blob: d1f10f2ba06c91f88a3c6a0c1c4f34a62f981ab8 [file] [log] [blame]
// 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| with |write_type|. 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,
WriteType write_type,
const std::vector<uint8_t>& value);
// 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);
// Clear pending connect request of remote device with |addr|.
static bool ClearPendingConnect(const Addr& addr)
__attribute__((__weak__));
// Clear pending disconnect request of remote device with |addr|.
static bool ClearPendingDisconnect(const Addr& addr)
__attribute__((__weak__));
};
// 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_