device.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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. #include <utility>
  5. #include <vector>
  6. #include "base/bind.h"
  7. #include "base/callback_helpers.h"
  8. #include "base/memory/ptr_util.h"
  9. #include "base/strings/utf_string_conversions.h"
  10. #include "device/bluetooth/device.h"
  11. #include "device/bluetooth/public/mojom/gatt_result_type_converter.h"
  12. #include "mojo/public/cpp/bindings/self_owned_receiver.h"
  13. namespace bluetooth {
  14. Device::~Device() {
  15. adapter_->RemoveObserver(this);
  16. }
  17. // static
  18. void Device::Create(scoped_refptr<device::BluetoothAdapter> adapter,
  19. std::unique_ptr<device::BluetoothGattConnection> connection,
  20. mojo::PendingReceiver<mojom::Device> receiver) {
  21. auto device_impl =
  22. base::WrapUnique(new Device(adapter, std::move(connection)));
  23. auto* device_ptr = device_impl.get();
  24. device_ptr->receiver_ =
  25. mojo::MakeSelfOwnedReceiver(std::move(device_impl), std::move(receiver));
  26. }
  27. // static
  28. mojom::DeviceInfoPtr Device::ConstructDeviceInfoStruct(
  29. const device::BluetoothDevice* device) {
  30. mojom::DeviceInfoPtr device_info = mojom::DeviceInfo::New();
  31. device_info->name = device->GetName();
  32. device_info->name_for_display =
  33. base::UTF16ToUTF8(device->GetNameForDisplay());
  34. device_info->address = device->GetAddress();
  35. device_info->is_gatt_connected = device->IsGattConnected();
  36. if (device->GetInquiryRSSI()) {
  37. device_info->rssi = mojom::RSSIWrapper::New();
  38. device_info->rssi->value = device->GetInquiryRSSI().value();
  39. }
  40. std::vector<device::BluetoothUUID> service_uuids;
  41. for (auto& uuid : device->GetUUIDs())
  42. service_uuids.push_back(uuid);
  43. device_info->service_uuids = service_uuids;
  44. for (auto const& it : device->GetManufacturerData())
  45. device_info->manufacturer_data_map.insert_or_assign(it.first, it.second);
  46. for (auto const& it : device->GetServiceData())
  47. device_info->service_data_map.insert_or_assign(it.first, it.second);
  48. return device_info;
  49. }
  50. void Device::DeviceChanged(device::BluetoothAdapter* adapter,
  51. device::BluetoothDevice* device) {
  52. if (device->GetAddress() != GetAddress()) {
  53. return;
  54. }
  55. if (!device->IsGattConnected()) {
  56. receiver_->Close();
  57. }
  58. }
  59. void Device::GattServicesDiscovered(device::BluetoothAdapter* adapter,
  60. device::BluetoothDevice* device) {
  61. if (device->GetAddress() != GetAddress()) {
  62. return;
  63. }
  64. std::vector<base::OnceClosure> requests;
  65. requests.swap(pending_services_requests_);
  66. for (base::OnceClosure& request : requests) {
  67. std::move(request).Run();
  68. }
  69. }
  70. void Device::Disconnect() {
  71. receiver_->Close();
  72. }
  73. void Device::GetInfo(GetInfoCallback callback) {
  74. device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  75. DCHECK(device);
  76. std::move(callback).Run(ConstructDeviceInfoStruct(device));
  77. }
  78. void Device::GetServices(GetServicesCallback callback) {
  79. device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  80. DCHECK(device);
  81. if (device->IsGattServicesDiscoveryComplete()) {
  82. GetServicesImpl(std::move(callback));
  83. return;
  84. }
  85. // pending_services_requests_ is owned by Device, so base::Unretained is
  86. // safe.
  87. pending_services_requests_.push_back(base::BindOnce(
  88. &Device::GetServicesImpl, base::Unretained(this), std::move(callback)));
  89. }
  90. void Device::GetCharacteristics(const std::string& service_id,
  91. GetCharacteristicsCallback callback) {
  92. device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  93. DCHECK(device);
  94. device::BluetoothRemoteGattService* service =
  95. device->GetGattService(service_id);
  96. if (service == nullptr) {
  97. std::move(callback).Run(absl::nullopt);
  98. return;
  99. }
  100. std::vector<mojom::CharacteristicInfoPtr> characteristics;
  101. for (const auto* characteristic : service->GetCharacteristics()) {
  102. mojom::CharacteristicInfoPtr characteristic_info =
  103. mojom::CharacteristicInfo::New();
  104. characteristic_info->id = characteristic->GetIdentifier();
  105. characteristic_info->uuid = characteristic->GetUUID();
  106. characteristic_info->properties = characteristic->GetProperties();
  107. characteristics.push_back(std::move(characteristic_info));
  108. }
  109. std::move(callback).Run(std::move(characteristics));
  110. }
  111. void Device::ReadValueForCharacteristic(
  112. const std::string& service_id,
  113. const std::string& characteristic_id,
  114. ReadValueForCharacteristicCallback callback) {
  115. device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  116. DCHECK(device);
  117. device::BluetoothRemoteGattService* service =
  118. device->GetGattService(service_id);
  119. if (service == nullptr) {
  120. std::move(callback).Run(mojom::GattResult::SERVICE_NOT_FOUND,
  121. absl::nullopt /* value */);
  122. return;
  123. }
  124. device::BluetoothRemoteGattCharacteristic* characteristic =
  125. service->GetCharacteristic(characteristic_id);
  126. if (characteristic == nullptr) {
  127. std::move(callback).Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND,
  128. absl::nullopt /* value */);
  129. return;
  130. }
  131. characteristic->ReadRemoteCharacteristic(
  132. base::BindOnce(&Device::OnReadRemoteCharacteristic,
  133. weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
  134. }
  135. void Device::WriteValueForCharacteristic(
  136. const std::string& service_id,
  137. const std::string& characteristic_id,
  138. const std::vector<uint8_t>& value,
  139. WriteValueForCharacteristicCallback callback) {
  140. device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  141. DCHECK(device);
  142. device::BluetoothRemoteGattService* service =
  143. device->GetGattService(service_id);
  144. if (service == nullptr) {
  145. std::move(callback).Run(mojom::GattResult::SERVICE_NOT_FOUND);
  146. return;
  147. }
  148. device::BluetoothRemoteGattCharacteristic* characteristic =
  149. service->GetCharacteristic(characteristic_id);
  150. if (characteristic == nullptr) {
  151. std::move(callback).Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND);
  152. return;
  153. }
  154. auto split_callback = base::SplitOnceCallback(std::move(callback));
  155. characteristic->DeprecatedWriteRemoteCharacteristic(
  156. value,
  157. base::BindOnce(&Device::OnWriteRemoteCharacteristic,
  158. weak_ptr_factory_.GetWeakPtr(),
  159. std::move(split_callback.first)),
  160. base::BindOnce(&Device::OnWriteRemoteCharacteristicError,
  161. weak_ptr_factory_.GetWeakPtr(),
  162. std::move(split_callback.second)));
  163. }
  164. void Device::GetDescriptors(const std::string& service_id,
  165. const std::string& characteristic_id,
  166. GetDescriptorsCallback callback) {
  167. device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  168. if (!device) {
  169. std::move(callback).Run(absl::nullopt);
  170. return;
  171. }
  172. device::BluetoothRemoteGattService* service =
  173. device->GetGattService(service_id);
  174. if (!service) {
  175. std::move(callback).Run(absl::nullopt);
  176. return;
  177. }
  178. device::BluetoothRemoteGattCharacteristic* characteristic =
  179. service->GetCharacteristic(characteristic_id);
  180. if (!characteristic) {
  181. std::move(callback).Run(absl::nullopt);
  182. return;
  183. }
  184. std::vector<mojom::DescriptorInfoPtr> descriptors;
  185. for (const auto* descriptor : characteristic->GetDescriptors()) {
  186. mojom::DescriptorInfoPtr descriptor_info = mojom::DescriptorInfo::New();
  187. descriptor_info->id = descriptor->GetIdentifier();
  188. descriptor_info->uuid = descriptor->GetUUID();
  189. descriptor_info->last_known_value = descriptor->GetValue();
  190. descriptors.push_back(std::move(descriptor_info));
  191. }
  192. std::move(callback).Run(std::move(descriptors));
  193. }
  194. void Device::ReadValueForDescriptor(const std::string& service_id,
  195. const std::string& characteristic_id,
  196. const std::string& descriptor_id,
  197. ReadValueForDescriptorCallback callback) {
  198. device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  199. DCHECK(device);
  200. device::BluetoothRemoteGattService* service =
  201. device->GetGattService(service_id);
  202. if (!service) {
  203. std::move(callback).Run(mojom::GattResult::SERVICE_NOT_FOUND,
  204. absl::nullopt /* value */);
  205. return;
  206. }
  207. device::BluetoothRemoteGattCharacteristic* characteristic =
  208. service->GetCharacteristic(characteristic_id);
  209. if (!characteristic) {
  210. std::move(callback).Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND,
  211. absl::nullopt /* value */);
  212. return;
  213. }
  214. device::BluetoothRemoteGattDescriptor* descriptor =
  215. characteristic->GetDescriptor(descriptor_id);
  216. if (!descriptor) {
  217. std::move(callback).Run(mojom::GattResult::DESCRIPTOR_NOT_FOUND,
  218. absl::nullopt /* value */);
  219. return;
  220. }
  221. descriptor->ReadRemoteDescriptor(
  222. base::BindOnce(&Device::OnReadRemoteDescriptor,
  223. weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
  224. }
  225. void Device::WriteValueForDescriptor(const std::string& service_id,
  226. const std::string& characteristic_id,
  227. const std::string& descriptor_id,
  228. const std::vector<uint8_t>& value,
  229. WriteValueForDescriptorCallback callback) {
  230. device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  231. DCHECK(device);
  232. device::BluetoothRemoteGattService* service =
  233. device->GetGattService(service_id);
  234. if (!service) {
  235. std::move(callback).Run(mojom::GattResult::SERVICE_NOT_FOUND);
  236. return;
  237. }
  238. device::BluetoothRemoteGattCharacteristic* characteristic =
  239. service->GetCharacteristic(characteristic_id);
  240. if (!characteristic) {
  241. std::move(callback).Run(mojom::GattResult::CHARACTERISTIC_NOT_FOUND);
  242. return;
  243. }
  244. device::BluetoothRemoteGattDescriptor* descriptor =
  245. characteristic->GetDescriptor(descriptor_id);
  246. if (!descriptor) {
  247. std::move(callback).Run(mojom::GattResult::DESCRIPTOR_NOT_FOUND);
  248. return;
  249. }
  250. auto split_callback = base::SplitOnceCallback(std::move(callback));
  251. descriptor->WriteRemoteDescriptor(
  252. value,
  253. base::BindOnce(&Device::OnWriteRemoteDescriptor,
  254. weak_ptr_factory_.GetWeakPtr(),
  255. std::move(split_callback.first)),
  256. base::BindOnce(&Device::OnWriteRemoteDescriptorError,
  257. weak_ptr_factory_.GetWeakPtr(),
  258. std::move(split_callback.second)));
  259. }
  260. Device::Device(scoped_refptr<device::BluetoothAdapter> adapter,
  261. std::unique_ptr<device::BluetoothGattConnection> connection)
  262. : adapter_(std::move(adapter)), connection_(std::move(connection)) {
  263. adapter_->AddObserver(this);
  264. }
  265. void Device::GetServicesImpl(GetServicesCallback callback) {
  266. device::BluetoothDevice* device = adapter_->GetDevice(GetAddress());
  267. DCHECK(device);
  268. std::vector<mojom::ServiceInfoPtr> services;
  269. for (const device::BluetoothRemoteGattService* service :
  270. device->GetGattServices()) {
  271. services.push_back(ConstructServiceInfoStruct(*service));
  272. }
  273. std::move(callback).Run(std::move(services));
  274. }
  275. mojom::ServiceInfoPtr Device::ConstructServiceInfoStruct(
  276. const device::BluetoothRemoteGattService& service) {
  277. mojom::ServiceInfoPtr service_info = mojom::ServiceInfo::New();
  278. service_info->id = service.GetIdentifier();
  279. service_info->uuid = service.GetUUID();
  280. service_info->is_primary = service.IsPrimary();
  281. return service_info;
  282. }
  283. void Device::OnReadRemoteCharacteristic(
  284. ReadValueForCharacteristicCallback callback,
  285. absl::optional<device::BluetoothGattService::GattErrorCode> error_code,
  286. const std::vector<uint8_t>& value) {
  287. if (error_code.has_value()) {
  288. std::move(callback).Run(
  289. mojo::ConvertTo<mojom::GattResult>(error_code.value()),
  290. absl::nullopt /* value */);
  291. return;
  292. }
  293. std::move(callback).Run(mojom::GattResult::SUCCESS, std::move(value));
  294. }
  295. void Device::OnWriteRemoteCharacteristic(
  296. WriteValueForCharacteristicCallback callback) {
  297. std::move(callback).Run(mojom::GattResult::SUCCESS);
  298. }
  299. void Device::OnWriteRemoteCharacteristicError(
  300. WriteValueForCharacteristicCallback callback,
  301. device::BluetoothGattService::GattErrorCode error_code) {
  302. std::move(callback).Run(mojo::ConvertTo<mojom::GattResult>(error_code));
  303. }
  304. void Device::OnReadRemoteDescriptor(
  305. ReadValueForDescriptorCallback callback,
  306. absl::optional<device::BluetoothGattService::GattErrorCode> error_code,
  307. const std::vector<uint8_t>& value) {
  308. if (error_code.has_value()) {
  309. std::move(callback).Run(
  310. mojo::ConvertTo<mojom::GattResult>(error_code.value()),
  311. /*value=*/absl::nullopt);
  312. return;
  313. }
  314. std::move(callback).Run(mojom::GattResult::SUCCESS, std::move(value));
  315. }
  316. void Device::OnWriteRemoteDescriptor(WriteValueForDescriptorCallback callback) {
  317. std::move(callback).Run(mojom::GattResult::SUCCESS);
  318. }
  319. void Device::OnWriteRemoteDescriptorError(
  320. WriteValueForDescriptorCallback callback,
  321. device::BluetoothGattService::GattErrorCode error_code) {
  322. std::move(callback).Run(mojo::ConvertTo<mojom::GattResult>(error_code));
  323. }
  324. const std::string& Device::GetAddress() {
  325. return connection_->GetDeviceAddress();
  326. }
  327. } // namespace bluetooth