bluetooth_remote_gatt_characteristic.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_H_
  5. #define DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_H_
  6. #include <stdint.h>
  7. #include <memory>
  8. #include <set>
  9. #include <string>
  10. #include <vector>
  11. #include "base/callback.h"
  12. #include "base/callback_forward.h"
  13. #include "base/containers/flat_map.h"
  14. #include "base/containers/queue.h"
  15. #include "base/memory/weak_ptr.h"
  16. #include "base/sequence_checker.h"
  17. #include "device/bluetooth/bluetooth_export.h"
  18. #include "device/bluetooth/bluetooth_gatt_characteristic.h"
  19. #include "device/bluetooth/bluetooth_remote_gatt_service.h"
  20. #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
  21. #include "third_party/abseil-cpp/absl/types/optional.h"
  22. namespace device {
  23. class BluetoothGattNotifySession;
  24. class BluetoothRemoteGattDescriptor;
  25. // BluetoothRemoteGattCharacteristic represents a remote GATT characteristic.
  26. // This class is used to represent GATT characteristics that belong to a service
  27. // hosted by a remote device. In this case the characteristic will be
  28. // constructed by the subsystem.
  29. //
  30. // Note: We use virtual inheritance on the GATT characteristic since it will be
  31. // inherited by platform specific versions of the GATT characteristic classes
  32. // also. The platform specific remote GATT characteristic classes will inherit
  33. // both this class and their GATT characteristic class, hence causing an
  34. // inheritance diamond.
  35. class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristic
  36. : public virtual BluetoothGattCharacteristic {
  37. public:
  38. // Parameter for WriteRemoteCharacteristic
  39. enum class WriteType {
  40. kWithResponse,
  41. kWithoutResponse,
  42. };
  43. // The ValueCallback is used to return the value of a remote characteristic
  44. // upon a read request. Upon successful completion |error_code| will not
  45. // have a value and |value| may be used. When unsuccessful |error_code| will
  46. // have a value and |value| must be ignored.
  47. using ValueCallback = base::OnceCallback<void(
  48. absl::optional<BluetoothGattService::GattErrorCode> error_code,
  49. const std::vector<uint8_t>& value)>;
  50. // The NotifySessionCallback is used to return sessions after they have
  51. // been successfully started.
  52. using NotifySessionCallback =
  53. base::OnceCallback<void(std::unique_ptr<BluetoothGattNotifySession>)>;
  54. BluetoothRemoteGattCharacteristic(const BluetoothRemoteGattCharacteristic&) =
  55. delete;
  56. BluetoothRemoteGattCharacteristic& operator=(
  57. const BluetoothRemoteGattCharacteristic&) = delete;
  58. ~BluetoothRemoteGattCharacteristic() override;
  59. // Returns the value of the characteristic. For remote characteristics, this
  60. // is the most recently cached value. For local characteristics, this is the
  61. // most recently updated value or the value retrieved from the delegate.
  62. virtual const std::vector<uint8_t>& GetValue() const = 0;
  63. // Returns a pointer to the GATT service this characteristic belongs to.
  64. virtual BluetoothRemoteGattService* GetService() const = 0;
  65. // Returns the list of GATT characteristic descriptors that provide more
  66. // information about this characteristic.
  67. virtual std::vector<BluetoothRemoteGattDescriptor*> GetDescriptors() const;
  68. // Returns the GATT characteristic descriptor with identifier |identifier| if
  69. // it belongs to this GATT characteristic.
  70. virtual BluetoothRemoteGattDescriptor* GetDescriptor(
  71. const std::string& identifier) const;
  72. // Returns the GATT characteristic descriptors that match |uuid|. There may be
  73. // multiple, as illustrated by Core Bluetooth Specification [V4.2 Vol 3 Part G
  74. // 3.3.3.5 Characteristic Presentation Format].
  75. virtual std::vector<BluetoothRemoteGattDescriptor*> GetDescriptorsByUUID(
  76. const BluetoothUUID& uuid) const;
  77. // Get a weak pointer to the characteristic.
  78. base::WeakPtr<BluetoothRemoteGattCharacteristic> GetWeakPtr();
  79. // Returns whether or not this characteristic is currently sending value
  80. // updates in the form of a notification or indication.
  81. //
  82. // If your code wants to receive notifications, you MUST call
  83. // StartNotifySession and hold on to the resulting session object for as long
  84. // as you want to keep receiving notifications. Even if this method returns
  85. // true, and you are able to see the notifications coming in, you have no
  86. // guarantee that the notifications will keep flowing for as long as you
  87. // need, unless you open your own session.
  88. virtual bool IsNotifying() const;
  89. // Starts a notify session for the remote characteristic, if it supports
  90. // notifications/indications. On success, the characteristic starts sending
  91. // value notifications and |callback| is called with a session object whose
  92. // ownership belongs to the caller. |error_callback| is called on errors.
  93. //
  94. // This method handles all logic regarding multiple sessions so that
  95. // specific platform implementations of the remote characteristic class
  96. // do not have to. Rather than overriding this method, it is recommended
  97. // to override the SubscribeToNotifications method below.
  98. //
  99. // The code in SubscribeToNotifications writes to the Client Characteristic
  100. // Configuration descriptor to enable notifications/indications. Core
  101. // Bluetooth Specification [V4.2 Vol 3 Part G Section 3.3.1.1. Characteristic
  102. // Properties] requires this descriptor to be present when
  103. // notifications/indications are supported. If the descriptor is not present
  104. // |error_callback| will be run.
  105. //
  106. // Writing a non-zero value to the remote characteristic's Client
  107. // Characteristic Configuration descriptor, causes the remote characteristic
  108. // to start sending us notifications whenever the characteristic's value
  109. // changes. When a new notification is received,
  110. // BluetoothAdapterObserver::GattCharacteristicValueChanged is called with
  111. // the characteristic's new value.
  112. //
  113. // To stop the flow of notifications, simply call the Stop method on the
  114. // BluetoothGattNotifySession object that you received in |callback|.
  115. virtual void StartNotifySession(NotifySessionCallback callback,
  116. ErrorCallback error_callback);
  117. #if BUILDFLAG(IS_CHROMEOS)
  118. // TODO(https://crbug.com/849359): This method should also be implemented on
  119. // Android and Windows.
  120. // macOS does not support specifying a notification type. According to macOS
  121. // documentation if the characteristic supports both notify and indicate, only
  122. // notifications will be enabled.
  123. // https://developer.apple.com/documentation/corebluetooth/cbperipheral/1518949-setnotifyvalue?language=objc#discussion
  124. virtual void StartNotifySession(NotificationType notification_type,
  125. NotifySessionCallback callback,
  126. ErrorCallback error_callback);
  127. #endif // BUILDFLAG(IS_CHROMEOS)
  128. // Sends a read request to a remote characteristic to read its value.
  129. // |callback| is called to return the read value or error.
  130. virtual void ReadRemoteCharacteristic(ValueCallback callback) = 0;
  131. // Sends a write request to a remote characteristic with the value |value|
  132. // using the specified |write_type|. |callback| is called to signal success
  133. // and |error_callback| for failures. This method only applies to remote
  134. // characteristics and will fail for those that are locally hosted.
  135. virtual void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
  136. WriteType write_type,
  137. base::OnceClosure callback,
  138. ErrorCallback error_callback) = 0;
  139. // DEPRECATED: Use WriteRemoteCharacteristic instead. This method remains
  140. // for backward compatibility.
  141. // Sends a write request to a remote characteristic with the value |value|.
  142. // |callback| is called to signal success and |error_callback| for failures.
  143. // This method only applies to remote characteristics and will fail for those
  144. // that are locally hosted.
  145. virtual void DeprecatedWriteRemoteCharacteristic(
  146. const std::vector<uint8_t>& value,
  147. base::OnceClosure callback,
  148. ErrorCallback error_callback) = 0;
  149. #if BUILDFLAG(IS_CHROMEOS)
  150. // Sends a prepare write request to a remote characteristic with the value
  151. // |value|. |callback| is called to signal success and |error_callback| for
  152. // failures. This method only applies to remote characteristics and will fail
  153. // for those that are locally hosted.
  154. // Callers should use BluetoothDevice::ExecuteWrite() to commit or
  155. // BluetoothDevice::AbortWrite() to abort the change.
  156. virtual void PrepareWriteRemoteCharacteristic(
  157. const std::vector<uint8_t>& value,
  158. base::OnceClosure callback,
  159. ErrorCallback error_callback) = 0;
  160. #endif // BUILDFLAG(IS_CHROMEOS)
  161. protected:
  162. using DescriptorMap =
  163. base::flat_map<std::string,
  164. std::unique_ptr<BluetoothRemoteGattDescriptor>>;
  165. BluetoothRemoteGattCharacteristic();
  166. // Writes to the Client Characteristic Configuration descriptor to enable
  167. // notifications/indications. This method is meant to be called from
  168. // StartNotifySession and should contain only the code necessary to start
  169. // listening to characteristic notifications on a particular platform.
  170. #if BUILDFLAG(IS_CHROMEOS)
  171. // |notification_type| specifies the type of notifications that will be
  172. // enabled: notifications or indications.
  173. // TODO(https://crbug.com/849359): This method should also be implemented on
  174. // Android and Windows.
  175. virtual void SubscribeToNotifications(
  176. BluetoothRemoteGattDescriptor* ccc_descriptor,
  177. NotificationType notification_type,
  178. base::OnceClosure callback,
  179. ErrorCallback error_callback) = 0;
  180. #else
  181. virtual void SubscribeToNotifications(
  182. BluetoothRemoteGattDescriptor* ccc_descriptor,
  183. base::OnceClosure callback,
  184. ErrorCallback error_callback) = 0;
  185. #endif // BUILDFLAG(IS_CHROMEOS)
  186. // Writes to the Client Characteristic Configuration descriptor to disable
  187. // notifications/indications. This method is meant to be called from
  188. // StopNotifySession and should contain only the code necessary to stop
  189. // listening to characteristic notifications on a particular platform.
  190. virtual void UnsubscribeFromNotifications(
  191. BluetoothRemoteGattDescriptor* ccc_descriptor,
  192. base::OnceClosure callback,
  193. ErrorCallback error_callback) = 0;
  194. // Utility function to add a |descriptor| to the map of |descriptors_|.
  195. bool AddDescriptor(std::unique_ptr<BluetoothRemoteGattDescriptor> descriptor);
  196. // Descriptors owned by the chracteristic. The descriptors' identifiers serve
  197. // as keys.
  198. DescriptorMap descriptors_;
  199. private:
  200. friend class BluetoothGattNotifySession;
  201. enum class CommandType { kNone, kStart, kStop };
  202. struct CommandStatus {
  203. explicit CommandStatus(CommandType type = CommandType::kNone,
  204. absl::optional<BluetoothGattService::GattErrorCode>
  205. error_code = absl::nullopt);
  206. CommandStatus(CommandStatus&& other);
  207. CommandType type;
  208. absl::optional<BluetoothGattService::GattErrorCode> error_code;
  209. };
  210. // Stops an active notify session for the remote characteristic. On success,
  211. // the characteristic removes this session from the list of active sessions.
  212. // If there are no more active sessions, notifications/indications are
  213. // turned off.
  214. //
  215. // This method is, and should only be, called from
  216. // BluetoothGattNotifySession::Stop().
  217. //
  218. // The code in UnsubscribeFromNotifications writes to the Client
  219. // Characteristic Configuration descriptor to disable
  220. // notifications/indications. Core Bluetooth Specification [V4.2 Vol 3 Part G
  221. // Section 3.3.1.1. Characteristic Properties] requires this descriptor to be
  222. // present when notifications/indications are supported.
  223. virtual void StopNotifySession(BluetoothGattNotifySession* session,
  224. base::OnceClosure callback);
  225. class NotifySessionCommand {
  226. public:
  227. using ExecuteCallback = base::OnceCallback<void(CommandStatus)>;
  228. NotifySessionCommand(ExecuteCallback execute_callback,
  229. base::OnceClosure cancel_callback);
  230. NotifySessionCommand(NotifySessionCommand&& other);
  231. ~NotifySessionCommand();
  232. bool IsExecuted() const;
  233. void Execute();
  234. void Execute(CommandStatus previous_command);
  235. void Cancel();
  236. private:
  237. ExecuteCallback execute_callback_;
  238. base::OnceClosure cancel_callback_;
  239. };
  240. void StartNotifySessionInternal(
  241. const absl::optional<NotificationType>& notification_type,
  242. NotifySessionCallback callback,
  243. ErrorCallback error_callback);
  244. void ExecuteStartNotifySession(
  245. const absl::optional<NotificationType>& notification_type,
  246. NotifySessionCallback callback,
  247. ErrorCallback error_callback,
  248. CommandStatus previous_command);
  249. void CancelStartNotifySession(base::OnceClosure callback);
  250. void OnStartNotifySessionSuccess(NotifySessionCallback callback);
  251. void OnStartNotifySessionError(ErrorCallback error_callback,
  252. BluetoothGattService::GattErrorCode error);
  253. void ExecuteStopNotifySession(BluetoothGattNotifySession* session,
  254. base::OnceClosure callback,
  255. CommandStatus previous_command);
  256. void CancelStopNotifySession(base::OnceClosure callback);
  257. void OnStopNotifySessionSuccess(BluetoothGattNotifySession* session,
  258. base::OnceClosure callback);
  259. void OnStopNotifySessionError(BluetoothGattNotifySession* session,
  260. base::OnceClosure callback,
  261. BluetoothGattService::GattErrorCode error);
  262. bool IsNotificationTypeSupported(
  263. const absl::optional<NotificationType>& notification_type);
  264. // Pending StartNotifySession / StopNotifySession calls.
  265. // The front will either be awaiting execution, or in the process of being
  266. // executed. Items are popped upon completion (success or error) of the
  267. // currently executing command.
  268. base::queue<NotifySessionCommand> pending_notify_commands_;
  269. // Is there a NotifySessionCommand currently executing?
  270. bool notify_command_running_ = false;
  271. // Set of active notify sessions.
  272. std::set<BluetoothGattNotifySession*> notify_sessions_;
  273. SEQUENCE_CHECKER(sequence_checker_);
  274. base::WeakPtrFactory<BluetoothRemoteGattCharacteristic> weak_ptr_factory_{
  275. this};
  276. };
  277. } // namespace device
  278. #endif // DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_CHARACTERISTIC_H_