low_energy_client.cc 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. //
  2. // Copyright 2015 Google, Inc.
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at:
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. #include "service/low_energy_client.h"
  17. #include <base/logging.h>
  18. #include "service/adapter.h"
  19. #include "service/logging_helpers.h"
  20. #include "stack/include/bt_types.h"
  21. #include "stack/include/hcidefs.h"
  22. using std::lock_guard;
  23. using std::mutex;
  24. namespace bluetooth {
  25. // LowEnergyClient implementation
  26. // ========================================================
  27. LowEnergyClient::LowEnergyClient(Adapter& adapter, const Uuid& uuid,
  28. int client_id)
  29. : adapter_(adapter),
  30. app_identifier_(uuid),
  31. client_id_(client_id),
  32. delegate_(nullptr) {}
  33. LowEnergyClient::~LowEnergyClient() {
  34. // Automatically unregister the client.
  35. VLOG(1) << "LowEnergyClient unregistering client: " << client_id_;
  36. // Unregister as observer so we no longer receive any callbacks.
  37. hal::BluetoothGattInterface::Get()->RemoveClientObserver(this);
  38. hal::BluetoothGattInterface::Get()
  39. ->GetClientHALInterface()
  40. ->unregister_client(client_id_);
  41. }
  42. bool LowEnergyClient::Connect(const std::string& address, bool is_direct) {
  43. VLOG(2) << __func__ << "Address: " << address << " is_direct: " << is_direct;
  44. RawAddress bda;
  45. RawAddress::FromString(address, bda);
  46. bt_status_t status =
  47. hal::BluetoothGattInterface::Get()->GetClientHALInterface()->connect(
  48. client_id_, bda, is_direct, BT_TRANSPORT_LE, false, PHY_LE_1M_MASK);
  49. if (status != BT_STATUS_SUCCESS) {
  50. LOG(ERROR) << "HAL call to connect failed";
  51. return false;
  52. }
  53. return true;
  54. }
  55. bool LowEnergyClient::Disconnect(const std::string& address) {
  56. VLOG(2) << __func__ << "Address: " << address;
  57. RawAddress bda;
  58. RawAddress::FromString(address, bda);
  59. std::map<const RawAddress, int>::iterator conn_id;
  60. {
  61. lock_guard<mutex> lock(connection_fields_lock_);
  62. conn_id = connection_ids_.find(bda);
  63. if (conn_id == connection_ids_.end()) {
  64. LOG(WARNING) << "Can't disconnect, no existing connection to " << address;
  65. return false;
  66. }
  67. }
  68. bt_status_t status =
  69. hal::BluetoothGattInterface::Get()->GetClientHALInterface()->disconnect(
  70. client_id_, bda, conn_id->second);
  71. if (status != BT_STATUS_SUCCESS) {
  72. LOG(ERROR) << "HAL call to disconnect failed";
  73. return false;
  74. }
  75. return true;
  76. }
  77. bool LowEnergyClient::SetMtu(const std::string& address, int mtu) {
  78. VLOG(2) << __func__ << "Address: " << address << " MTU: " << mtu;
  79. RawAddress bda;
  80. RawAddress::FromString(address, bda);
  81. std::map<const RawAddress, int>::iterator conn_id;
  82. {
  83. lock_guard<mutex> lock(connection_fields_lock_);
  84. conn_id = connection_ids_.find(bda);
  85. if (conn_id == connection_ids_.end()) {
  86. LOG(WARNING) << "Can't set MTU, no existing connection to " << address;
  87. return false;
  88. }
  89. }
  90. bt_status_t status = hal::BluetoothGattInterface::Get()
  91. ->GetClientHALInterface()
  92. ->configure_mtu(conn_id->second, mtu);
  93. if (status != BT_STATUS_SUCCESS) {
  94. LOG(ERROR) << "HAL call to set MTU failed";
  95. return false;
  96. }
  97. return true;
  98. }
  99. void LowEnergyClient::SetDelegate(Delegate* delegate) {
  100. lock_guard<mutex> lock(delegate_mutex_);
  101. delegate_ = delegate;
  102. }
  103. const Uuid& LowEnergyClient::GetAppIdentifier() const {
  104. return app_identifier_;
  105. }
  106. int LowEnergyClient::GetInstanceId() const { return client_id_; }
  107. void LowEnergyClient::ConnectCallback(hal::BluetoothGattInterface* gatt_iface,
  108. int conn_id, int status, int client_id,
  109. const RawAddress& bda) {
  110. if (client_id != client_id_) return;
  111. VLOG(1) << __func__ << "client_id: " << client_id << " status: " << status;
  112. {
  113. lock_guard<mutex> lock(connection_fields_lock_);
  114. auto success = connection_ids_.emplace(bda, conn_id);
  115. if (!success.second) {
  116. LOG(ERROR) << __func__ << " Insertion into connection_ids_ failed!";
  117. }
  118. }
  119. if (delegate_)
  120. delegate_->OnConnectionState(this, status, BtAddrString(&bda).c_str(),
  121. true);
  122. }
  123. void LowEnergyClient::DisconnectCallback(
  124. hal::BluetoothGattInterface* gatt_iface, int conn_id, int status,
  125. int client_id, const RawAddress& bda) {
  126. if (client_id != client_id_) return;
  127. VLOG(1) << __func__ << " client_id: " << client_id << " status: " << status;
  128. {
  129. lock_guard<mutex> lock(connection_fields_lock_);
  130. if (!connection_ids_.erase(bda)) {
  131. LOG(ERROR) << __func__ << " Erasing from connection_ids_ failed!";
  132. }
  133. }
  134. if (delegate_)
  135. delegate_->OnConnectionState(this, status, BtAddrString(&bda).c_str(),
  136. false);
  137. }
  138. void LowEnergyClient::MtuChangedCallback(
  139. hal::BluetoothGattInterface* gatt_iface, int conn_id, int status, int mtu) {
  140. VLOG(1) << __func__ << " conn_id: " << conn_id << " status: " << status
  141. << " mtu: " << mtu;
  142. const RawAddress* bda = nullptr;
  143. {
  144. lock_guard<mutex> lock(connection_fields_lock_);
  145. for (auto& connection : connection_ids_) {
  146. if (connection.second == conn_id) {
  147. bda = &connection.first;
  148. break;
  149. }
  150. }
  151. }
  152. if (!bda) return;
  153. std::string addr = BtAddrString(bda);
  154. if (delegate_) delegate_->OnMtuChanged(this, status, addr.c_str(), mtu);
  155. }
  156. // LowEnergyClientFactory implementation
  157. // ========================================================
  158. LowEnergyClientFactory::LowEnergyClientFactory(Adapter& adapter)
  159. : adapter_(adapter) {
  160. hal::BluetoothGattInterface::Get()->AddClientObserver(this);
  161. }
  162. LowEnergyClientFactory::~LowEnergyClientFactory() {
  163. hal::BluetoothGattInterface::Get()->RemoveClientObserver(this);
  164. }
  165. bool LowEnergyClientFactory::RegisterInstance(
  166. const Uuid& uuid, const RegisterCallback& callback) {
  167. VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
  168. lock_guard<mutex> lock(pending_calls_lock_);
  169. if (pending_calls_.find(uuid) != pending_calls_.end()) {
  170. LOG(ERROR) << "Low-Energy client with given Uuid already registered - "
  171. << "Uuid: " << uuid.ToString();
  172. return false;
  173. }
  174. const btgatt_client_interface_t* hal_iface =
  175. hal::BluetoothGattInterface::Get()->GetClientHALInterface();
  176. if (hal_iface->register_client(uuid) != BT_STATUS_SUCCESS) return false;
  177. pending_calls_[uuid] = callback;
  178. return true;
  179. }
  180. void LowEnergyClientFactory::RegisterClientCallback(
  181. hal::BluetoothGattInterface* gatt_iface, int status, int client_id,
  182. const bluetooth::Uuid& app_uuid) {
  183. Uuid uuid(app_uuid);
  184. VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
  185. lock_guard<mutex> lock(pending_calls_lock_);
  186. auto iter = pending_calls_.find(uuid);
  187. if (iter == pending_calls_.end()) {
  188. VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
  189. return;
  190. }
  191. // No need to construct a client if the call wasn't successful.
  192. std::unique_ptr<LowEnergyClient> client;
  193. BLEStatus result = BLE_STATUS_FAILURE;
  194. if (status == BT_STATUS_SUCCESS) {
  195. client.reset(new LowEnergyClient(adapter_, uuid, client_id));
  196. gatt_iface->AddClientObserver(client.get());
  197. result = BLE_STATUS_SUCCESS;
  198. }
  199. // Notify the result via the result callback.
  200. iter->second(result, uuid, std::move(client));
  201. pending_calls_.erase(iter);
  202. }
  203. } // namespace bluetooth