usb_service_impl.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. // Copyright 2014 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 "services/device/usb/usb_service_impl.h"
  5. #include <stdint.h>
  6. #include <list>
  7. #include <memory>
  8. #include <set>
  9. #include <utility>
  10. #include "base/barrier_closure.h"
  11. #include "base/bind.h"
  12. #include "base/callback_helpers.h"
  13. #include "base/containers/contains.h"
  14. #include "base/location.h"
  15. #include "base/memory/ref_counted_memory.h"
  16. #include "base/memory/weak_ptr.h"
  17. #include "base/strings/string_number_conversions.h"
  18. #include "base/strings/utf_string_conversions.h"
  19. #include "base/task/sequenced_task_runner.h"
  20. #include "base/task/single_thread_task_runner.h"
  21. #include "base/task/thread_pool.h"
  22. #include "base/threading/scoped_blocking_call.h"
  23. #include "build/build_config.h"
  24. #include "components/device_event_log/device_event_log.h"
  25. #include "services/device/usb/usb_device_handle.h"
  26. #include "services/device/usb/usb_error.h"
  27. #include "services/device/usb/webusb_descriptors.h"
  28. #include "third_party/libusb/src/libusb/libusb.h"
  29. namespace device {
  30. namespace {
  31. // Standard USB requests and descriptor types:
  32. const uint16_t kUsbVersion2_1 = 0x0210;
  33. scoped_refptr<UsbContext> InitializeUsbContextBlocking() {
  34. PlatformUsbContext platform_context = nullptr;
  35. int rv = libusb_init(&platform_context);
  36. if (rv == LIBUSB_SUCCESS && platform_context) {
  37. return base::MakeRefCounted<UsbContext>(platform_context);
  38. }
  39. USB_LOG(DEBUG) << "Failed to initialize libusb: "
  40. << ConvertPlatformUsbErrorToString(rv);
  41. return nullptr;
  42. }
  43. absl::optional<std::vector<ScopedLibusbDeviceRef>> GetDeviceListBlocking(
  44. scoped_refptr<UsbContext> usb_context) {
  45. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  46. base::BlockingType::MAY_BLOCK);
  47. libusb_device** platform_devices = NULL;
  48. const ssize_t device_count =
  49. libusb_get_device_list(usb_context->context(), &platform_devices);
  50. if (device_count < 0) {
  51. USB_LOG(ERROR) << "Failed to get device list: "
  52. << ConvertPlatformUsbErrorToString(device_count);
  53. return absl::nullopt;
  54. }
  55. std::vector<ScopedLibusbDeviceRef> scoped_devices;
  56. scoped_devices.reserve(device_count);
  57. for (ssize_t i = 0; i < device_count; ++i)
  58. scoped_devices.emplace_back(platform_devices[i], usb_context);
  59. // Free the list but don't unref the devices because ownership has been
  60. // been transfered to the elements of |scoped_devices|.
  61. libusb_free_device_list(platform_devices, false);
  62. return scoped_devices;
  63. }
  64. void CloseHandleAndRunContinuation(scoped_refptr<UsbDeviceHandle> device_handle,
  65. base::OnceClosure continuation) {
  66. device_handle->Close();
  67. std::move(continuation).Run();
  68. }
  69. void SaveStringsAndRunContinuation(
  70. scoped_refptr<UsbDeviceImpl> device,
  71. uint8_t manufacturer,
  72. uint8_t product,
  73. uint8_t serial_number,
  74. base::OnceClosure continuation,
  75. std::unique_ptr<std::map<uint8_t, std::u16string>> string_map) {
  76. if (manufacturer != 0)
  77. device->set_manufacturer_string((*string_map)[manufacturer]);
  78. if (product != 0)
  79. device->set_product_string((*string_map)[product]);
  80. if (serial_number != 0)
  81. device->set_serial_number((*string_map)[serial_number]);
  82. std::move(continuation).Run();
  83. }
  84. void OnReadBosDescriptor(scoped_refptr<UsbDeviceHandle> device_handle,
  85. base::OnceClosure barrier,
  86. const GURL& landing_page) {
  87. scoped_refptr<UsbDeviceImpl> device =
  88. static_cast<UsbDeviceImpl*>(device_handle->GetDevice().get());
  89. if (landing_page.is_valid())
  90. device->set_webusb_landing_page(landing_page);
  91. std::move(barrier).Run();
  92. }
  93. void RunSuccessAndCompletionClosure(base::OnceClosure success_closure,
  94. base::OnceClosure completion_closure) {
  95. std::move(success_closure).Run();
  96. std::move(completion_closure).Run();
  97. }
  98. void OnDeviceOpenedReadDescriptors(
  99. uint8_t manufacturer,
  100. uint8_t product,
  101. uint8_t serial_number,
  102. bool read_bos_descriptors,
  103. base::OnceClosure success_closure,
  104. base::OnceClosure failure_closure,
  105. base::OnceClosure completion_closure,
  106. scoped_refptr<UsbDeviceHandle> device_handle) {
  107. if (device_handle) {
  108. std::unique_ptr<std::map<uint8_t, std::u16string>> string_map(
  109. new std::map<uint8_t, std::u16string>());
  110. if (manufacturer != 0)
  111. (*string_map)[manufacturer] = std::u16string();
  112. if (product != 0)
  113. (*string_map)[product] = std::u16string();
  114. if (serial_number != 0)
  115. (*string_map)[serial_number] = std::u16string();
  116. int count = 0;
  117. if (!string_map->empty())
  118. count++;
  119. if (read_bos_descriptors)
  120. count++;
  121. DCHECK_GT(count, 0);
  122. base::OnceClosure success_and_completion_closure = base::BindOnce(
  123. &RunSuccessAndCompletionClosure, std::move(success_closure),
  124. std::move(completion_closure));
  125. base::RepeatingClosure barrier = base::BarrierClosure(
  126. count, base::BindOnce(&CloseHandleAndRunContinuation, device_handle,
  127. std::move(success_and_completion_closure)));
  128. if (!string_map->empty()) {
  129. scoped_refptr<UsbDeviceImpl> device =
  130. static_cast<UsbDeviceImpl*>(device_handle->GetDevice().get());
  131. ReadUsbStringDescriptors(
  132. device_handle, std::move(string_map),
  133. base::BindOnce(&SaveStringsAndRunContinuation, device, manufacturer,
  134. product, serial_number, barrier));
  135. }
  136. if (read_bos_descriptors) {
  137. ReadWebUsbDescriptors(
  138. device_handle,
  139. base::BindOnce(&OnReadBosDescriptor, device_handle, barrier));
  140. }
  141. } else {
  142. std::move(failure_closure).Run();
  143. std::move(completion_closure).Run();
  144. }
  145. }
  146. } // namespace
  147. UsbServiceImpl::UsbServiceImpl()
  148. : task_runner_(base::SequencedTaskRunnerHandle::Get()) {
  149. weak_self_ = weak_factory_.GetWeakPtr();
  150. base::ThreadPool::PostTaskAndReplyWithResult(
  151. FROM_HERE, kBlockingTaskTraits,
  152. base::BindOnce(&InitializeUsbContextBlocking),
  153. base::BindOnce(&UsbServiceImpl::OnUsbContext,
  154. weak_factory_.GetWeakPtr()));
  155. }
  156. UsbServiceImpl::~UsbServiceImpl() {
  157. NotifyWillDestroyUsbService();
  158. if (context_)
  159. libusb_hotplug_deregister_callback(context_->context(), hotplug_handle_);
  160. }
  161. void UsbServiceImpl::GetDevices(GetDevicesCallback callback) {
  162. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  163. if (usb_unavailable_) {
  164. task_runner_->PostTask(
  165. FROM_HERE, base::BindOnce(std::move(callback),
  166. std::vector<scoped_refptr<UsbDevice>>()));
  167. return;
  168. }
  169. if (enumeration_in_progress_) {
  170. pending_enumeration_callbacks_.push_back(std::move(callback));
  171. return;
  172. }
  173. UsbService::GetDevices(std::move(callback));
  174. }
  175. void UsbServiceImpl::OnUsbContext(scoped_refptr<UsbContext> context) {
  176. if (!context) {
  177. usb_unavailable_ = true;
  178. return;
  179. }
  180. context_ = std::move(context);
  181. int rv = libusb_hotplug_register_callback(
  182. context_->context(),
  183. static_cast<libusb_hotplug_event>(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED |
  184. LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
  185. static_cast<libusb_hotplug_flag>(0), LIBUSB_HOTPLUG_MATCH_ANY,
  186. LIBUSB_HOTPLUG_MATCH_ANY, LIBUSB_HOTPLUG_MATCH_ANY,
  187. &UsbServiceImpl::HotplugCallback, this, &hotplug_handle_);
  188. if (rv != LIBUSB_SUCCESS) {
  189. usb_unavailable_ = true;
  190. context_.reset();
  191. return;
  192. }
  193. // This will call any enumeration callbacks queued while initializing.
  194. RefreshDevices();
  195. }
  196. void UsbServiceImpl::RefreshDevices() {
  197. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  198. DCHECK(context_);
  199. DCHECK(!enumeration_in_progress_);
  200. enumeration_in_progress_ = true;
  201. DCHECK(devices_being_enumerated_.empty());
  202. base::ThreadPool::PostTaskAndReplyWithResult(
  203. FROM_HERE, kBlockingTaskTraits,
  204. base::BindOnce(&GetDeviceListBlocking, context_),
  205. base::BindOnce(&UsbServiceImpl::OnDeviceList,
  206. weak_factory_.GetWeakPtr()));
  207. }
  208. void UsbServiceImpl::OnDeviceList(
  209. absl::optional<std::vector<ScopedLibusbDeviceRef>> devices) {
  210. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  211. if (!devices) {
  212. RefreshDevicesComplete();
  213. return;
  214. }
  215. std::vector<ScopedLibusbDeviceRef> new_devices;
  216. // Look for new and existing devices.
  217. for (auto& device : *devices) {
  218. // Ignore devices that have failed enumeration previously.
  219. if (base::Contains(ignored_devices_, device.get()))
  220. continue;
  221. auto it = platform_devices_.find(device.get());
  222. if (it == platform_devices_.end()) {
  223. new_devices.push_back(std::move(device));
  224. } else {
  225. // Mark the existing device object visited and remove it from the list so
  226. // it will not be ignored.
  227. it->second->set_visited(true);
  228. device.Reset();
  229. }
  230. }
  231. // Remove devices not seen in this enumeration.
  232. for (PlatformDeviceMap::iterator it = platform_devices_.begin();
  233. it != platform_devices_.end();
  234. /* incremented internally */) {
  235. PlatformDeviceMap::iterator current = it++;
  236. const scoped_refptr<UsbDeviceImpl>& device = current->second;
  237. if (device->was_visited()) {
  238. device->set_visited(false);
  239. } else {
  240. RemoveDevice(device);
  241. }
  242. }
  243. // Remaining devices are being ignored. Clear the old list so that devices
  244. // that have been removed don't remain in |ignored_devices_| indefinitely.
  245. ignored_devices_.clear();
  246. for (auto& device : *devices) {
  247. if (device.IsValid())
  248. ignored_devices_.push_back(std::move(device));
  249. }
  250. // Enumerate new devices.
  251. base::RepeatingClosure refresh_complete = base::BarrierClosure(
  252. new_devices.size(),
  253. base::BindOnce(&UsbServiceImpl::RefreshDevicesComplete,
  254. weak_factory_.GetWeakPtr()));
  255. for (auto& device : new_devices)
  256. EnumerateDevice(std::move(device), refresh_complete);
  257. }
  258. void UsbServiceImpl::RefreshDevicesComplete() {
  259. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  260. DCHECK(enumeration_in_progress_);
  261. enumeration_ready_ = true;
  262. enumeration_in_progress_ = false;
  263. devices_being_enumerated_.clear();
  264. if (!pending_enumeration_callbacks_.empty()) {
  265. std::vector<scoped_refptr<UsbDevice>> result;
  266. result.reserve(devices().size());
  267. for (const auto& map_entry : devices())
  268. result.push_back(map_entry.second);
  269. std::vector<GetDevicesCallback> callbacks;
  270. callbacks.swap(pending_enumeration_callbacks_);
  271. for (GetDevicesCallback& callback : callbacks)
  272. std::move(callback).Run(result);
  273. }
  274. }
  275. void UsbServiceImpl::EnumerateDevice(ScopedLibusbDeviceRef platform_device,
  276. base::OnceClosure refresh_complete) {
  277. DCHECK(context_);
  278. libusb_device_descriptor descriptor;
  279. int rv = libusb_get_device_descriptor(platform_device.get(), &descriptor);
  280. if (rv != LIBUSB_SUCCESS) {
  281. USB_LOG(EVENT) << "Failed to get device descriptor: "
  282. << ConvertPlatformUsbErrorToString(rv);
  283. EnumerationFailed(std::move(platform_device));
  284. std::move(refresh_complete).Run();
  285. return;
  286. }
  287. if (descriptor.bDeviceClass == LIBUSB_CLASS_HUB) {
  288. // Don't try to enumerate hubs. We never want to connect to a hub.
  289. EnumerationFailed(std::move(platform_device));
  290. std::move(refresh_complete).Run();
  291. return;
  292. }
  293. devices_being_enumerated_.insert(platform_device.get());
  294. auto device = base::MakeRefCounted<UsbDeviceImpl>(std::move(platform_device),
  295. descriptor);
  296. base::OnceClosure add_device = base::BindOnce(
  297. &UsbServiceImpl::AddDevice, weak_factory_.GetWeakPtr(), device);
  298. bool read_bos_descriptors = descriptor.bcdUSB >= kUsbVersion2_1;
  299. if (descriptor.iManufacturer == 0 && descriptor.iProduct == 0 &&
  300. descriptor.iSerialNumber == 0 && !read_bos_descriptors) {
  301. // Don't bother disturbing the device if it has no descriptors to offer.
  302. std::move(add_device).Run();
  303. std::move(refresh_complete).Run();
  304. } else {
  305. // Take an additional reference to the libusb_device object that will be
  306. // owned by this callback.
  307. libusb_ref_device(device->platform_device());
  308. base::OnceClosure enumeration_failed = base::BindOnce(
  309. &UsbServiceImpl::EnumerationFailed, weak_factory_.GetWeakPtr(),
  310. ScopedLibusbDeviceRef(device->platform_device(), context_));
  311. device->Open(base::BindOnce(
  312. &OnDeviceOpenedReadDescriptors, descriptor.iManufacturer,
  313. descriptor.iProduct, descriptor.iSerialNumber, read_bos_descriptors,
  314. std::move(add_device), std::move(enumeration_failed),
  315. std::move(refresh_complete)));
  316. }
  317. }
  318. void UsbServiceImpl::AddDevice(scoped_refptr<UsbDeviceImpl> device) {
  319. if (!base::Contains(devices_being_enumerated_, device->platform_device())) {
  320. // Device was removed while being enumerated.
  321. return;
  322. }
  323. DCHECK(!base::Contains(platform_devices_, device->platform_device()));
  324. platform_devices_[device->platform_device()] = device;
  325. DCHECK(!base::Contains(devices(), device->guid()));
  326. devices()[device->guid()] = device;
  327. USB_LOG(USER) << "USB device added: vendor=" << device->vendor_id() << " \""
  328. << device->manufacturer_string()
  329. << "\", product=" << device->product_id() << " \""
  330. << device->product_string() << "\", serial=\""
  331. << device->serial_number() << "\", guid=" << device->guid();
  332. if (enumeration_ready_)
  333. NotifyDeviceAdded(device);
  334. }
  335. void UsbServiceImpl::RemoveDevice(scoped_refptr<UsbDeviceImpl> device) {
  336. platform_devices_.erase(device->platform_device());
  337. devices().erase(device->guid());
  338. USB_LOG(USER) << "USB device removed: guid=" << device->guid();
  339. NotifyDeviceRemoved(device);
  340. device->OnDisconnect();
  341. }
  342. // static
  343. int LIBUSB_CALL UsbServiceImpl::HotplugCallback(libusb_context* context,
  344. libusb_device* device_raw,
  345. libusb_hotplug_event event,
  346. void* user_data) {
  347. // It is safe to access the UsbServiceImpl* here because libusb takes a lock
  348. // around registering, deregistering and calling hotplug callback functions
  349. // and so guarantees that this function will not be called by the event
  350. // processing thread after it has been deregistered.
  351. UsbServiceImpl* self = reinterpret_cast<UsbServiceImpl*>(user_data);
  352. // libusb does not transfer ownership of |device_raw| to this function so a
  353. // reference must be taken here.
  354. libusb_ref_device(device_raw);
  355. ScopedLibusbDeviceRef device(device_raw, self->context_);
  356. switch (event) {
  357. case LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED:
  358. self->task_runner_->PostTask(
  359. FROM_HERE, base::BindOnce(&UsbServiceImpl::OnPlatformDeviceAdded,
  360. self->weak_self_, std::move(device)));
  361. break;
  362. case LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT:
  363. self->task_runner_->PostTask(
  364. FROM_HERE, base::BindOnce(&UsbServiceImpl::OnPlatformDeviceRemoved,
  365. self->weak_self_, std::move(device)));
  366. break;
  367. default:
  368. NOTREACHED();
  369. }
  370. return 0;
  371. }
  372. void UsbServiceImpl::OnPlatformDeviceAdded(
  373. ScopedLibusbDeviceRef platform_device) {
  374. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  375. DCHECK(!base::Contains(platform_devices_, platform_device.get()));
  376. EnumerateDevice(std::move(platform_device), base::DoNothing());
  377. }
  378. void UsbServiceImpl::OnPlatformDeviceRemoved(
  379. ScopedLibusbDeviceRef platform_device) {
  380. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  381. auto it = platform_devices_.find(platform_device.get());
  382. if (it == platform_devices_.end())
  383. devices_being_enumerated_.erase(platform_device.get());
  384. else
  385. RemoveDevice(it->second);
  386. }
  387. void UsbServiceImpl::EnumerationFailed(ScopedLibusbDeviceRef platform_device) {
  388. ignored_devices_.push_back(std::move(platform_device));
  389. }
  390. } // namespace device