| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROMECAST_PUBLIC_BLUETOOTH_GATT_H_ |
| #define CHROMECAST_PUBLIC_BLUETOOTH_GATT_H_ |
| |
| #include <vector> |
| |
| #include "bluetooth_types.h" // NOLINT(build/include) |
| #include "chromecast_export.h" // NOLINT(build/include) |
| |
| namespace chromecast { |
| namespace bluetooth_v2_shlib { |
| |
| // GATT (Generic Attributes) is the primary mechanism in BLE (Bluetooth Low |
| // Energy) for transmiting data. |
| class CHROMECAST_EXPORT Gatt { |
| public: |
| // https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html |
| enum Permissions : uint16_t { |
| PERMISSION_NONE = 0, |
| PERMISSION_READ = 1 << 0, |
| PERMISSION_READ_ENCRYPTED = 1 << 1, |
| PERMISSION_READ_ENCRYPTED_MITM = 1 << 2, |
| PERMISSION_WRITE = 1 << 4, |
| PERMISSION_WRITE_ENCRYPTED = 1 << 5, |
| PERMISSION_WRITE_ENCRYPTED_MITM = 1 << 6, |
| PERMISSION_WRITE_SIGNED = 1 << 7, |
| PERMISSION_WRITE_SIGNED_MITM = 1 << 8, |
| }; |
| |
| // https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html |
| enum Properties : uint8_t { |
| PROPERTY_NONE = 0, |
| PROPERTY_BROADCAST = 1 << 0, |
| PROPERTY_READ = 1 << 1, |
| PROPERTY_WRITE_NO_RESPONSE = 1 << 2, |
| PROPERTY_WRITE = 1 << 3, |
| PROPERTY_NOTIFY = 1 << 4, |
| PROPERTY_INDICATE = 1 << 5, |
| PROPERTY_SIGNED_WRITE = 1 << 6, |
| PROPERTY_EXTENDED_PROPS = 1 << 7, |
| }; |
| |
| // https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html |
| enum WriteType : uint8_t { |
| WRITE_TYPE_NONE = 0, |
| WRITE_TYPE_NO_RESPONSE = 1 << 0, |
| WRITE_TYPE_DEFAULT = 1 << 1, |
| WRITE_TYPE_SIGNED = 1 << 2, |
| }; |
| |
| // Core 4.2 Vol3 part F 3.4.1.1 Error Response |
| enum class Status { |
| NONE = 0, |
| INVALID_HANDLE = 0x01, |
| READ_NOT_PERMITTED = 0x02, |
| WRITE_NOT_PERMITTED = 0x03, |
| INVALID_PDU = 0x04, |
| INSUFFICIENT_AUTHEN = 0x05, |
| REQUEST_NOT_SUPPORTED = 0x06, |
| INVALID_OFFSET = 0x07, |
| INSUFFICIENT_AUTHOR = 0x08, |
| PREP_QUEUE_FULL = 0x09, |
| ATTRIBUTE_NOT_FOUND = 0x0a, |
| ATTRIBUTE_NOT_LONG = 0x0b, |
| INSUFFICIENT_KEY_SIZE = 0x0c, |
| INVALID_ATTRIBUTE_LENGTH = 0x0d, |
| UNLIKELY = 0x0e, |
| INSUFFICIENT_ENCR = 0x0f, |
| UNSUPPORTED_GRP_TYPE = 0x10, |
| INSUFFICIENT_RESOURCES = 0x11, |
| CCCD_IMPROPERLY_CONFIGURED = 0xFD, |
| PROCEDURE_IN_PROGRESS = 0xFE, |
| OUT_OF_RANGE = 0xFF |
| }; |
| |
| // Attributes that describe a characteristic value. |
| struct Descriptor { |
| Uuid uuid; |
| uint16_t handle; |
| Permissions permissions; |
| }; |
| |
| // Attribute types that contain a single logical value. |
| struct Characteristic { |
| Characteristic(); |
| Characteristic(const Characteristic& other); |
| ~Characteristic(); |
| |
| Uuid uuid; |
| uint16_t handle; |
| Permissions permissions; |
| Properties properties; |
| std::vector<Descriptor> descriptors; |
| }; |
| |
| // Services are collections of characteristics and relationships to other |
| // services that encapsulate the behavior of part of a device. |
| struct Service { |
| Service(); |
| Service(const Service& other); |
| ~Service(); |
| Uuid uuid; |
| uint16_t handle; |
| bool primary; |
| std::vector<Characteristic> characteristics; |
| std::vector<Service> included_services; |
| }; |
| |
| // The GATT client role is when a device connects to a remote GATT server. |
| class Client { |
| public: |
| // See frameworks/base/core/java/android/bluetooth/BluetoothGatt.java |
| // AUTHENTICATION_{NONE,NO_MITM,MITM} |
| enum AuthReq : int32_t { |
| AUTH_REQ_INVALID = -1, |
| AUTH_REQ_NONE = 0, |
| AUTH_REQ_NO_MITM = 1, |
| AUTH_REQ_MITM = 2, |
| |
| AUTH_REQ_MAX = AUTH_REQ_MITM, |
| }; |
| |
| // These callbacks may be on any thead. |
| class Delegate { |
| public: |
| // Called when the connection changes. |
| virtual void OnConnectChanged(const Addr& addr, |
| bool status, |
| bool connected) = 0; |
| |
| // Called when the bonding state changes. |
| virtual void OnBondChanged(const Addr& addr, |
| bool status, |
| bool bonded) = 0; |
| |
| // Called on a Characteristic value notification. |
| virtual void OnNotification(const Addr& addr, |
| uint16_t handle, |
| const std::vector<uint8_t>& value) = 0; |
| |
| // Called in response to ReadCharacteristic. |
| virtual void OnCharacteristicReadResponse( |
| const Addr& addr, |
| bool status, |
| uint16_t handle, |
| const std::vector<uint8_t>& value) = 0; |
| |
| // Called in response to WriteCharacteristic. |
| virtual void OnCharacteristicWriteResponse(const Addr& addr, |
| bool status, |
| uint16_t handle) = 0; |
| |
| // Called in response to ReadDescriptor. |
| virtual void OnDescriptorReadResponse( |
| const Addr& addr, |
| bool status, |
| uint16_t handle, |
| const std::vector<uint8_t>& value) = 0; |
| |
| // Called in response to WriteDescriptor. |
| virtual void OnDescriptorWriteResponse(const Addr& addr, |
| bool status, |
| uint16_t handle) = 0; |
| |
| // Called in response to ReadRemoteRssi. |
| virtual void OnReadRemoteRssi(const Addr& addr, |
| bool status, |
| int rssi) = 0; |
| |
| // Called when the connection MTU changes. |
| virtual void OnMtuChanged(const Addr& addr, bool status, int mtu) = 0; |
| |
| // Called when the service list is obtained. |
| virtual void OnGetServices(const Addr& addr, |
| const std::vector<Service>& services) = 0; |
| |
| // Called when services are removed. |
| virtual void OnServicesRemoved(const Addr& addr, |
| uint16_t start_handle, |
| uint16_t end_handle) = 0; |
| |
| // Called when services are added. |
| virtual void OnServicesAdded(const Addr& addr, |
| const std::vector<Service>& services) = 0; |
| |
| virtual ~Delegate() = default; |
| }; |
| |
| // Returns true if GATT client profile is supported. |
| static bool IsSupported(); |
| static void SetDelegate(Delegate* delegate); |
| |
| // Create a connection to remote device |addr|. |
| static bool Connect(const Addr& addr); |
| |
| // Remove connection to remote device |addr|. |
| static bool Disconnect(const Addr& addr); |
| |
| // Create bond to remote device |addr|. |
| static bool CreateBond(const Addr& addr); |
| |
| // Remove bond to remote device |addr|. |
| static bool RemoveBond(const Addr& addr); |
| |
| // Read |characteristic| from remote device |addr|. If |auth_req| is |
| // AUTH_REQ_INVALID, this function will automatically retry stronger |
| // authentications on failure. |
| static bool ReadCharacteristic(const Addr& addr, |
| const Characteristic& characteristic, |
| AuthReq auth_req); |
| |
| // Write |characteristic| on remote device |addr|. If |auth_req| is |
| // AUTH_REQ_INVALID, this function will automatically retry stronger |
| // authentications on failure. |
| static bool WriteCharacteristic(const Addr& addr, |
| const Characteristic& characteristic, |
| AuthReq auth_req, |
| const std::vector<uint8_t>& value); |
| |
| // New version of above method where |write_type| can be specified. |
| // TODO(bcf): Replace old version in next API update. |
| static bool WriteCharacteristic2(const Addr& addr, |
| const Characteristic& characteristic, |
| AuthReq auth_req, |
| WriteType write_type, |
| const std::vector<uint8_t>& value) |
| __attribute__((__weak__)); |
| |
| // Read |descriptor| from remote device |addr|. If |auth_req| is |
| // AUTH_REQ_INVALID, this function will automatically retry stronger |
| // authentications on failure. |
| static bool ReadDescriptor(const Addr& addr, |
| const Descriptor& descriptor, |
| AuthReq auth_req); |
| |
| // Write |descriptor| on remote device |addr|. If |auth_req| is |
| // AUTH_REQ_INVALID, this function will automatically retry stronger |
| // authentications on failure. |
| static bool WriteDescriptor(const Addr& addr, |
| const Descriptor& descriptor, |
| AuthReq auth_req, |
| const std::vector<uint8_t>& value); |
| |
| // Register or deregister for notifications of |characteristic| on device |
| // |addr|. |
| static bool SetCharacteristicNotification( |
| const Addr& addr, |
| const Characteristic& characteristic, |
| bool enable); |
| |
| // Read the RSSI of remote device with |addr| |
| static bool ReadRemoteRssi(const Addr& addr); |
| |
| // Request |mtu| on the connection with device |addr|. |
| static bool RequestMtu(const Addr& addr, int mtu); |
| |
| // Update connection parameters with device |addr|. |
| static bool ConnectionParameterUpdate(const Addr& addr, |
| int min_interval, |
| int max_interval, |
| int latency, |
| int timeout); |
| |
| // Retrieve the list of services on device |addr|. They will be returned in |
| // the callback |OnGetServices|. |
| static bool GetServices(const Addr& addr); |
| }; |
| |
| // GATT Server role. Devices must implement the GATT server role in order to |
| // support Cast BLE setup. |
| class Server { |
| public: |
| class Delegate { |
| public: |
| // Called when a client connects or disconnects. |
| virtual void OnConnectionStateChanged(const Addr& addr, |
| bool connected) = 0; |
| |
| // Called when a service was added. |success| is false if it failed to add |
| // the service. |
| virtual void OnServiceAdded(bool success, const Service& service) = 0; |
| |
| // Called when a client requests a read on a characteristic. |
| virtual void OnCharacteristicReadRequest(const Addr& addr, |
| int request_id, |
| uint16_t handle, |
| int offset, |
| bool is_long) = 0; |
| |
| // Called when a client requests a write on a characteristic. |
| virtual void OnCharacteristicWriteRequest( |
| const Addr& addr, |
| int request_id, |
| uint16_t handle, |
| int offset, |
| bool is_prepare_write, |
| bool need_response, |
| const std::vector<uint8_t>& value) = 0; |
| |
| // Called when a client requests a read on a descriptor. |
| virtual void OnDescriptorReadRequest(const Addr& addr, |
| int request_id, |
| uint16_t handle, |
| int offset, |
| bool is_long) = 0; |
| |
| // Called when a client requests a write on a descriptor. |
| virtual void OnDescriptorWriteRequest( |
| const Addr& addr, |
| int request_id, |
| uint16_t handle, |
| int offset, |
| bool is_prepare_write, |
| bool need_response, |
| const std::vector<uint8_t>& value) = 0; |
| |
| // Called when a client performs a prepared write operation. If |
| // |is_execute| is false, then it clears the currently pending prepared |
| // write. |
| virtual void OnExecuteWriteRequest(const Addr& addr, |
| int request_id, |
| bool is_execute) = 0; |
| |
| // Called when SendNotification is complete. |success| is false if it |
| // failed. |
| virtual void OnNotificationSent(const Addr& addr, bool success) = 0; |
| |
| virtual ~Delegate() = default; |
| }; |
| |
| // Returns true if this interface is implemented. |
| static bool IsSupported(); |
| |
| static void SetDelegate(Delegate* delegate); |
| |
| // Add |Service| to this GATT Server. On completion, OnServiceAdded will be |
| // called. |
| static bool AddService(const Service& service); |
| |
| // Send a response to any of the callbacks with a |request_id| above. |
| static bool SendResponse(const Addr& addr, |
| int request_id, |
| Status status, |
| int offset, |
| const std::vector<uint8_t>& value); |
| |
| // Send a characteristic value notification. |
| static bool SendNotification(const Addr& addr, |
| int handle, |
| bool confirm, |
| const std::vector<uint8_t>& value); |
| }; |
| }; |
| |
| // Work around '[chromium-style] Complex class/struct needs an explicit |
| // out-of-line constructor.' |
| inline Gatt::Characteristic::Characteristic() = default; |
| inline Gatt::Characteristic::Characteristic(const Characteristic& other) = |
| default; |
| inline Gatt::Characteristic::~Characteristic() = default; |
| |
| inline Gatt::Service::Service() = default; |
| inline Gatt::Service::Service(const Service& other) = default; |
| inline Gatt::Service::~Service() = default; |
| |
| inline bool operator==(const Gatt::Descriptor& lhs, |
| const Gatt::Descriptor& rhs) { |
| return lhs.uuid == rhs.uuid && lhs.handle == rhs.handle && |
| lhs.permissions == rhs.permissions; |
| } |
| |
| inline bool operator==(const Gatt::Characteristic& lhs, |
| const Gatt::Characteristic& rhs) { |
| return lhs.uuid == rhs.uuid && lhs.handle == rhs.handle && |
| lhs.permissions == rhs.permissions && |
| lhs.properties == rhs.properties && lhs.descriptors == rhs.descriptors; |
| } |
| |
| } // namespace bluetooth_v2_shlib |
| } // namespace chromecast |
| |
| #endif // CHROMECAST_PUBLIC_BLUETOOTH_GATT_H_ |