Loading system/service/example/heart_rate/heart_rate_server.cpp +22 −0 Original line number Diff line number Diff line Loading @@ -188,4 +188,26 @@ void HeartRateServer::OnDescriptorReadRequest( // TODO(armansito): Implement. } void HeartRateServer::OnCharacteristicWriteRequest( const std::string& device_address, int request_id, int offset, bool is_prepare_write, bool need_response, const std::vector<uint8_t>& value, const bluetooth::GattIdentifier& characteristic_id) { // TODO(armansito): Implement. } void HeartRateServer::OnDescriptorWriteRequest( const std::string& device_address, int request_id, int offset, bool is_prepare_write, bool need_response, const std::vector<uint8_t>& value, const bluetooth::GattIdentifier& descriptor_id) { // TODO(armansito): Implement. } void HeartRateServer::OnExecuteWriteRequest( const std::string& device_address, int request_id, bool is_execute) { // TODO(armansito): Implement. } } // namespace heart_rate system/service/example/heart_rate/heart_rate_server.h +13 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,19 @@ class HeartRateServer : public ipc::binder::BnBluetoothGattServerCallback { const std::string& device_address, int request_id, int offset, bool is_long, const bluetooth::GattIdentifier& descriptor_id) override; void OnCharacteristicWriteRequest( const std::string& device_address, int request_id, int offset, bool is_prepare_write, bool need_response, const std::vector<uint8_t>& value, const bluetooth::GattIdentifier& characteristic_id) override; void OnDescriptorWriteRequest( const std::string& device_address, int request_id, int offset, bool is_prepare_write, bool need_response, const std::vector<uint8_t>& value, const bluetooth::GattIdentifier& descriptor_id) override; void OnExecuteWriteRequest( const std::string& device_address, int request_id, bool is_execute) override; std::mutex mutex_; Loading system/service/gatt_server.cpp +114 −5 Original line number Diff line number Diff line Loading @@ -342,11 +342,16 @@ bool GattServer::SendResponse( btgatt_response_t response; memset(&response, 0, sizeof(response)); response.handle = connection->request_id_to_handle[request_id]; // We keep -1 as the handle for "Execute Write Request". In that case, // there is no need to populate the response data. Just send zeros back. int handle = connection->request_id_to_handle[request_id]; response.handle = handle; response.attr_value.handle = handle; if (handle != -1) { memcpy(response.attr_value.value, value.data(), value.size()); response.attr_value.handle = response.handle; response.attr_value.offset = offset; response.attr_value.len = value.size(); } bt_status_t result = hal::BluetoothGattInterface::Get()-> GetServerHALInterface()->send_response( Loading Loading @@ -602,6 +607,110 @@ void GattServer::RequestReadCallback( } } void GattServer::RequestWriteCallback( hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id, const bt_bdaddr_t& bda, int attr_handle, int offset, int length, bool need_rsp, bool is_prep, uint8_t* value) { lock_guard<mutex> lock(mutex_); if (length < 0) { LOG(WARNING) << "Negative length value received"; return; } // Check to see if we know about this connection. Otherwise ignore the // request. auto conn = GetConnection(conn_id, bda, trans_id); if (!conn) return; std::string device_address = BtAddrString(&bda); VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle << " offset: " << offset << " length: " << length << " need_rsp: " << need_rsp << " is_prep: " << is_prep; // Make sure that the handle is valid. auto iter = handle_to_id_map_.find(attr_handle); if (iter == handle_to_id_map_.end()) { LOG(ERROR) << "Request received for unknown handle: " << attr_handle; return; } // Store the request ID only if this is not a write-without-response. If // another request occurs after this with the same request ID, then we'll // simply process it normally, though that shouldn't ever happen. if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle; // If there is no delegate then there is nobody to handle request. The request // will eventually timeout and we should get a connection update that // terminates the connection. if (!delegate_) { // TODO(armansito): Require a delegate at server registration so that this // is never possible. LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request " << "will time out."; return; } std::vector<uint8_t> value_vec(value, value + length); if (iter->second.IsCharacteristic()) { delegate_->OnCharacteristicWriteRequest( this, device_address, trans_id, offset, is_prep, need_rsp, value_vec, iter->second); } else if (iter->second.IsDescriptor()) { delegate_->OnDescriptorWriteRequest( this, device_address, trans_id, offset, is_prep, need_rsp, value_vec, iter->second); } else { // Our API only delegates to applications those read requests for // characteristic value and descriptor attributes. Everything else should be // handled by the stack. LOG(WARNING) << "Write request received for unsupported attribute"; } } void GattServer::RequestExecWriteCallback( hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id, const bt_bdaddr_t& bda, int exec_write) { lock_guard<mutex> lock(mutex_); // Check to see if we know about this connection. Otherwise ignore the // request. auto conn = GetConnection(conn_id, bda, trans_id); if (!conn) return; std::string device_address = BtAddrString(&bda); VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id << " BD_ADDR: " << device_address << " exec_write: " << exec_write; // Just store a dummy invalid handle as this request doesn't apply to a // specific handle. conn->request_id_to_handle[trans_id] = -1; // If there is no delegate then there is nobody to handle request. The request // will eventually timeout and we should get a connection update that // terminates the connection. if (!delegate_) { // TODO(armansito): Require a delegate at server registration so that this // is never possible. LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request " << "will time out."; return; } delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write); } void GattServer::NotifyEndCallbackAndClearData( BLEStatus status, const GattIdentifier& id) { VLOG(1) << __func__ << " status: " << status; Loading system/service/gatt_server.h +51 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,47 @@ class GattServer : public BluetoothClientInstance, int request_id, int offset, bool is_long, const bluetooth::GattIdentifier& descriptor_id) = 0; // Called when there is an incoming write request for the characteristic // with ID |characteristic_id| from a remote device with address // |device_address|. |request_id| can be used to respond to this request by // calling SendResponse, if the |need_response| parameter is true. Otherwise // this is a "Write Without Reponse" procedure and SendResponse will fail. // If |is_prepare_write| is true, then the write should not be committed // immediately as this is a "Prepared Write Request". Instead, the Delegate // should hold on to the value and either discard it or complete the write // when it receives the OnExecuteWriteRequest event. virtual void OnCharacteristicWriteRequest( GattServer* gatt_server, const std::string& device_address, int request_id, int offset, bool is_prepare_write, bool need_response, const std::vector<uint8_t>& value, const bluetooth::GattIdentifier& characteristic_id) = 0; // Called when there is an incoming write request for the descriptor // with ID |descriptor_id| from a remote device with address // |device_address|. |request_id| can be used to respond to this request by // calling SendResponse, if the |need_response| parameter is true. Otherwise // this is a "Write Without Response" procedure and SendResponse will fail. // If |is_prepare_write| is true, then the write should not be committed // immediately as this is a "Prepared Write Request". Instead, the Delegate // should hold on to the value and either discard it or complete the write // when it receives the OnExecuteWriteRequest event. virtual void OnDescriptorWriteRequest( GattServer* gatt_server, const std::string& device_address, int request_id, int offset, bool is_prepare_write, bool need_response, const std::vector<uint8_t>& value, const bluetooth::GattIdentifier& descriptor_id) = 0; // Called when there is an incoming "Execute Write Request". If |is_execute| // is true, then the Delegate should commit all previously prepared writes. // Otherwise, all prepared writes should be aborted. The Delegate should // call "SendResponse" to complete the procedure. virtual void OnExecuteWriteRequest( GattServer* gatt_server, const std::string& device_address, int request_id, bool is_execute) = 0; private: DISALLOW_COPY_AND_ASSIGN(Delegate); }; Loading Loading @@ -223,6 +264,16 @@ class GattServer : public BluetoothClientInstance, const bt_bdaddr_t& bda, int attribute_handle, int offset, bool is_long) override; void RequestWriteCallback( hal::BluetoothGattInterface* gatt_iface, int conn_id, int trans_id, const bt_bdaddr_t& bda, int attr_handle, int offset, int length, bool need_rsp, bool is_prep, uint8_t* value) override; void RequestExecWriteCallback( hal::BluetoothGattInterface* gatt_iface, int conn_id, int trans_id, const bt_bdaddr_t& bda, int exec_write) override; // Helper function that notifies and clears the pending callback. void NotifyEndCallbackAndClearData(BLEStatus status, Loading system/service/hal/bluetooth_gatt_interface.cpp +54 −2 Original line number Diff line number Diff line Loading @@ -204,6 +204,35 @@ void RequestReadCallback(int conn_id, int trans_id, bt_bdaddr_t* bda, g_interface, conn_id, trans_id, *bda, attr_handle, offset, is_long)); } void RequestWriteCallback(int conn_id, int trans_id, bt_bdaddr_t* bda, int attr_handle, int offset, int length, bool need_rsp, bool is_prep, uint8_t* value) { lock_guard<mutex> lock(g_instance_lock); VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id << " attr_handle: " << attr_handle << " offset: " << offset << " length: " << length << " need_rsp: " << need_rsp << " is_prep: " << is_prep; VERIFY_INTERFACE_OR_RETURN(); CHECK(bda); FOR_EACH_SERVER_OBSERVER(RequestWriteCallback( g_interface, conn_id, trans_id, *bda, attr_handle, offset, length, need_rsp, is_prep, value)); } void RequestExecWriteCallback(int conn_id, int trans_id, bt_bdaddr_t* bda, int exec_write) { lock_guard<mutex> lock(g_instance_lock); VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id << " exec_write: " << exec_write; VERIFY_INTERFACE_OR_RETURN(); CHECK(bda); FOR_EACH_SERVER_OBSERVER(RequestExecWriteCallback( g_interface, conn_id, trans_id, *bda, exec_write)); } // The HAL Bluetooth GATT client interface callbacks. These signal a mixture of // GATT client-role and GAP events. const btgatt_client_callbacks_t gatt_client_callbacks = { Loading Loading @@ -253,8 +282,8 @@ const btgatt_server_callbacks_t gatt_server_callbacks = { ServiceStoppedCallback, nullptr, // service_deleted_cb, RequestReadCallback, nullptr, // request_write_cb, nullptr, // request_exec_write_cb, RequestWriteCallback, RequestExecWriteCallback, nullptr, // response_confirmation_cb, nullptr, // indication_sent_cb nullptr, // congestion_cb Loading Loading @@ -498,6 +527,29 @@ void BluetoothGattInterface::ServerObserver::RequestReadCallback( // Do nothing. } void BluetoothGattInterface::ServerObserver::RequestWriteCallback( BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, int /* trans_id */, const bt_bdaddr_t& /* bda */, int /* attr_handle */, int /* offset */, int /* length */, bool /* need_rsp */, bool /* is_prep */, uint8_t* /* value */) { // Do nothing. } void BluetoothGattInterface::ServerObserver::RequestExecWriteCallback( BluetoothGattInterface* gatt_iface, int /* conn_id */, int /* trans_id */, const bt_bdaddr_t& /* bda */, int /* exec_write */) { // Do nothing. } // static bool BluetoothGattInterface::Initialize() { lock_guard<mutex> lock(g_instance_lock); Loading Loading
system/service/example/heart_rate/heart_rate_server.cpp +22 −0 Original line number Diff line number Diff line Loading @@ -188,4 +188,26 @@ void HeartRateServer::OnDescriptorReadRequest( // TODO(armansito): Implement. } void HeartRateServer::OnCharacteristicWriteRequest( const std::string& device_address, int request_id, int offset, bool is_prepare_write, bool need_response, const std::vector<uint8_t>& value, const bluetooth::GattIdentifier& characteristic_id) { // TODO(armansito): Implement. } void HeartRateServer::OnDescriptorWriteRequest( const std::string& device_address, int request_id, int offset, bool is_prepare_write, bool need_response, const std::vector<uint8_t>& value, const bluetooth::GattIdentifier& descriptor_id) { // TODO(armansito): Implement. } void HeartRateServer::OnExecuteWriteRequest( const std::string& device_address, int request_id, bool is_execute) { // TODO(armansito): Implement. } } // namespace heart_rate
system/service/example/heart_rate/heart_rate_server.h +13 −0 Original line number Diff line number Diff line Loading @@ -51,6 +51,19 @@ class HeartRateServer : public ipc::binder::BnBluetoothGattServerCallback { const std::string& device_address, int request_id, int offset, bool is_long, const bluetooth::GattIdentifier& descriptor_id) override; void OnCharacteristicWriteRequest( const std::string& device_address, int request_id, int offset, bool is_prepare_write, bool need_response, const std::vector<uint8_t>& value, const bluetooth::GattIdentifier& characteristic_id) override; void OnDescriptorWriteRequest( const std::string& device_address, int request_id, int offset, bool is_prepare_write, bool need_response, const std::vector<uint8_t>& value, const bluetooth::GattIdentifier& descriptor_id) override; void OnExecuteWriteRequest( const std::string& device_address, int request_id, bool is_execute) override; std::mutex mutex_; Loading
system/service/gatt_server.cpp +114 −5 Original line number Diff line number Diff line Loading @@ -342,11 +342,16 @@ bool GattServer::SendResponse( btgatt_response_t response; memset(&response, 0, sizeof(response)); response.handle = connection->request_id_to_handle[request_id]; // We keep -1 as the handle for "Execute Write Request". In that case, // there is no need to populate the response data. Just send zeros back. int handle = connection->request_id_to_handle[request_id]; response.handle = handle; response.attr_value.handle = handle; if (handle != -1) { memcpy(response.attr_value.value, value.data(), value.size()); response.attr_value.handle = response.handle; response.attr_value.offset = offset; response.attr_value.len = value.size(); } bt_status_t result = hal::BluetoothGattInterface::Get()-> GetServerHALInterface()->send_response( Loading Loading @@ -602,6 +607,110 @@ void GattServer::RequestReadCallback( } } void GattServer::RequestWriteCallback( hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id, const bt_bdaddr_t& bda, int attr_handle, int offset, int length, bool need_rsp, bool is_prep, uint8_t* value) { lock_guard<mutex> lock(mutex_); if (length < 0) { LOG(WARNING) << "Negative length value received"; return; } // Check to see if we know about this connection. Otherwise ignore the // request. auto conn = GetConnection(conn_id, bda, trans_id); if (!conn) return; std::string device_address = BtAddrString(&bda); VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id << " BD_ADDR: " << device_address << " attr_handle: " << attr_handle << " offset: " << offset << " length: " << length << " need_rsp: " << need_rsp << " is_prep: " << is_prep; // Make sure that the handle is valid. auto iter = handle_to_id_map_.find(attr_handle); if (iter == handle_to_id_map_.end()) { LOG(ERROR) << "Request received for unknown handle: " << attr_handle; return; } // Store the request ID only if this is not a write-without-response. If // another request occurs after this with the same request ID, then we'll // simply process it normally, though that shouldn't ever happen. if (need_rsp) conn->request_id_to_handle[trans_id] = attr_handle; // If there is no delegate then there is nobody to handle request. The request // will eventually timeout and we should get a connection update that // terminates the connection. if (!delegate_) { // TODO(armansito): Require a delegate at server registration so that this // is never possible. LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request " << "will time out."; return; } std::vector<uint8_t> value_vec(value, value + length); if (iter->second.IsCharacteristic()) { delegate_->OnCharacteristicWriteRequest( this, device_address, trans_id, offset, is_prep, need_rsp, value_vec, iter->second); } else if (iter->second.IsDescriptor()) { delegate_->OnDescriptorWriteRequest( this, device_address, trans_id, offset, is_prep, need_rsp, value_vec, iter->second); } else { // Our API only delegates to applications those read requests for // characteristic value and descriptor attributes. Everything else should be // handled by the stack. LOG(WARNING) << "Write request received for unsupported attribute"; } } void GattServer::RequestExecWriteCallback( hal::BluetoothGattInterface* /* gatt_iface */, int conn_id, int trans_id, const bt_bdaddr_t& bda, int exec_write) { lock_guard<mutex> lock(mutex_); // Check to see if we know about this connection. Otherwise ignore the // request. auto conn = GetConnection(conn_id, bda, trans_id); if (!conn) return; std::string device_address = BtAddrString(&bda); VLOG(1) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id << " BD_ADDR: " << device_address << " exec_write: " << exec_write; // Just store a dummy invalid handle as this request doesn't apply to a // specific handle. conn->request_id_to_handle[trans_id] = -1; // If there is no delegate then there is nobody to handle request. The request // will eventually timeout and we should get a connection update that // terminates the connection. if (!delegate_) { // TODO(armansito): Require a delegate at server registration so that this // is never possible. LOG(WARNING) << "No delegate was assigned to GattServer. Incoming request " << "will time out."; return; } delegate_->OnExecuteWriteRequest(this, device_address, trans_id, exec_write); } void GattServer::NotifyEndCallbackAndClearData( BLEStatus status, const GattIdentifier& id) { VLOG(1) << __func__ << " status: " << status; Loading
system/service/gatt_server.h +51 −0 Original line number Diff line number Diff line Loading @@ -65,6 +65,47 @@ class GattServer : public BluetoothClientInstance, int request_id, int offset, bool is_long, const bluetooth::GattIdentifier& descriptor_id) = 0; // Called when there is an incoming write request for the characteristic // with ID |characteristic_id| from a remote device with address // |device_address|. |request_id| can be used to respond to this request by // calling SendResponse, if the |need_response| parameter is true. Otherwise // this is a "Write Without Reponse" procedure and SendResponse will fail. // If |is_prepare_write| is true, then the write should not be committed // immediately as this is a "Prepared Write Request". Instead, the Delegate // should hold on to the value and either discard it or complete the write // when it receives the OnExecuteWriteRequest event. virtual void OnCharacteristicWriteRequest( GattServer* gatt_server, const std::string& device_address, int request_id, int offset, bool is_prepare_write, bool need_response, const std::vector<uint8_t>& value, const bluetooth::GattIdentifier& characteristic_id) = 0; // Called when there is an incoming write request for the descriptor // with ID |descriptor_id| from a remote device with address // |device_address|. |request_id| can be used to respond to this request by // calling SendResponse, if the |need_response| parameter is true. Otherwise // this is a "Write Without Response" procedure and SendResponse will fail. // If |is_prepare_write| is true, then the write should not be committed // immediately as this is a "Prepared Write Request". Instead, the Delegate // should hold on to the value and either discard it or complete the write // when it receives the OnExecuteWriteRequest event. virtual void OnDescriptorWriteRequest( GattServer* gatt_server, const std::string& device_address, int request_id, int offset, bool is_prepare_write, bool need_response, const std::vector<uint8_t>& value, const bluetooth::GattIdentifier& descriptor_id) = 0; // Called when there is an incoming "Execute Write Request". If |is_execute| // is true, then the Delegate should commit all previously prepared writes. // Otherwise, all prepared writes should be aborted. The Delegate should // call "SendResponse" to complete the procedure. virtual void OnExecuteWriteRequest( GattServer* gatt_server, const std::string& device_address, int request_id, bool is_execute) = 0; private: DISALLOW_COPY_AND_ASSIGN(Delegate); }; Loading Loading @@ -223,6 +264,16 @@ class GattServer : public BluetoothClientInstance, const bt_bdaddr_t& bda, int attribute_handle, int offset, bool is_long) override; void RequestWriteCallback( hal::BluetoothGattInterface* gatt_iface, int conn_id, int trans_id, const bt_bdaddr_t& bda, int attr_handle, int offset, int length, bool need_rsp, bool is_prep, uint8_t* value) override; void RequestExecWriteCallback( hal::BluetoothGattInterface* gatt_iface, int conn_id, int trans_id, const bt_bdaddr_t& bda, int exec_write) override; // Helper function that notifies and clears the pending callback. void NotifyEndCallbackAndClearData(BLEStatus status, Loading
system/service/hal/bluetooth_gatt_interface.cpp +54 −2 Original line number Diff line number Diff line Loading @@ -204,6 +204,35 @@ void RequestReadCallback(int conn_id, int trans_id, bt_bdaddr_t* bda, g_interface, conn_id, trans_id, *bda, attr_handle, offset, is_long)); } void RequestWriteCallback(int conn_id, int trans_id, bt_bdaddr_t* bda, int attr_handle, int offset, int length, bool need_rsp, bool is_prep, uint8_t* value) { lock_guard<mutex> lock(g_instance_lock); VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id << " attr_handle: " << attr_handle << " offset: " << offset << " length: " << length << " need_rsp: " << need_rsp << " is_prep: " << is_prep; VERIFY_INTERFACE_OR_RETURN(); CHECK(bda); FOR_EACH_SERVER_OBSERVER(RequestWriteCallback( g_interface, conn_id, trans_id, *bda, attr_handle, offset, length, need_rsp, is_prep, value)); } void RequestExecWriteCallback(int conn_id, int trans_id, bt_bdaddr_t* bda, int exec_write) { lock_guard<mutex> lock(g_instance_lock); VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id << " exec_write: " << exec_write; VERIFY_INTERFACE_OR_RETURN(); CHECK(bda); FOR_EACH_SERVER_OBSERVER(RequestExecWriteCallback( g_interface, conn_id, trans_id, *bda, exec_write)); } // The HAL Bluetooth GATT client interface callbacks. These signal a mixture of // GATT client-role and GAP events. const btgatt_client_callbacks_t gatt_client_callbacks = { Loading Loading @@ -253,8 +282,8 @@ const btgatt_server_callbacks_t gatt_server_callbacks = { ServiceStoppedCallback, nullptr, // service_deleted_cb, RequestReadCallback, nullptr, // request_write_cb, nullptr, // request_exec_write_cb, RequestWriteCallback, RequestExecWriteCallback, nullptr, // response_confirmation_cb, nullptr, // indication_sent_cb nullptr, // congestion_cb Loading Loading @@ -498,6 +527,29 @@ void BluetoothGattInterface::ServerObserver::RequestReadCallback( // Do nothing. } void BluetoothGattInterface::ServerObserver::RequestWriteCallback( BluetoothGattInterface* /* gatt_iface */, int /* conn_id */, int /* trans_id */, const bt_bdaddr_t& /* bda */, int /* attr_handle */, int /* offset */, int /* length */, bool /* need_rsp */, bool /* is_prep */, uint8_t* /* value */) { // Do nothing. } void BluetoothGattInterface::ServerObserver::RequestExecWriteCallback( BluetoothGattInterface* gatt_iface, int /* conn_id */, int /* trans_id */, const bt_bdaddr_t& /* bda */, int /* exec_write */) { // Do nothing. } // static bool BluetoothGattInterface::Initialize() { lock_guard<mutex> lock(g_instance_lock); Loading