usb_device_handle_impl.cc 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074
  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_device_handle_impl.h"
  5. #include <algorithm>
  6. #include <memory>
  7. #include <numeric>
  8. #include <string>
  9. #include <utility>
  10. #include <vector>
  11. #include "base/bind.h"
  12. #include "base/containers/contains.h"
  13. #include "base/location.h"
  14. #include "base/memory/ref_counted_memory.h"
  15. #include "base/sequence_checker.h"
  16. #include "base/task/single_thread_task_runner.h"
  17. #include "base/threading/scoped_blocking_call.h"
  18. #include "base/threading/thread_task_runner_handle.h"
  19. #include "components/device_event_log/device_event_log.h"
  20. #include "services/device/public/cpp/usb/usb_utils.h"
  21. #include "services/device/usb/usb_context.h"
  22. #include "services/device/usb/usb_descriptors.h"
  23. #include "services/device/usb/usb_device_impl.h"
  24. #include "services/device/usb/usb_error.h"
  25. #include "services/device/usb/usb_service.h"
  26. #include "third_party/libusb/src/libusb/libusb.h"
  27. namespace device {
  28. using mojom::UsbControlTransferRecipient;
  29. using mojom::UsbControlTransferType;
  30. using mojom::UsbIsochronousPacketPtr;
  31. using mojom::UsbTransferDirection;
  32. using mojom::UsbTransferStatus;
  33. using mojom::UsbTransferType;
  34. void HandleTransferCompletion(PlatformUsbTransferHandle transfer);
  35. namespace {
  36. uint8_t ConvertTransferDirection(UsbTransferDirection direction) {
  37. switch (direction) {
  38. case UsbTransferDirection::INBOUND:
  39. return LIBUSB_ENDPOINT_IN;
  40. case UsbTransferDirection::OUTBOUND:
  41. return LIBUSB_ENDPOINT_OUT;
  42. }
  43. NOTREACHED();
  44. return 0;
  45. }
  46. uint8_t CreateRequestType(UsbTransferDirection direction,
  47. UsbControlTransferType request_type,
  48. UsbControlTransferRecipient recipient) {
  49. uint8_t result = ConvertTransferDirection(direction);
  50. switch (request_type) {
  51. case UsbControlTransferType::STANDARD:
  52. result |= LIBUSB_REQUEST_TYPE_STANDARD;
  53. break;
  54. case UsbControlTransferType::CLASS:
  55. result |= LIBUSB_REQUEST_TYPE_CLASS;
  56. break;
  57. case UsbControlTransferType::VENDOR:
  58. result |= LIBUSB_REQUEST_TYPE_VENDOR;
  59. break;
  60. case UsbControlTransferType::RESERVED:
  61. result |= LIBUSB_REQUEST_TYPE_RESERVED;
  62. break;
  63. }
  64. switch (recipient) {
  65. case UsbControlTransferRecipient::DEVICE:
  66. result |= LIBUSB_RECIPIENT_DEVICE;
  67. break;
  68. case UsbControlTransferRecipient::INTERFACE:
  69. result |= LIBUSB_RECIPIENT_INTERFACE;
  70. break;
  71. case UsbControlTransferRecipient::ENDPOINT:
  72. result |= LIBUSB_RECIPIENT_ENDPOINT;
  73. break;
  74. case UsbControlTransferRecipient::OTHER:
  75. result |= LIBUSB_RECIPIENT_OTHER;
  76. break;
  77. }
  78. return result;
  79. }
  80. static UsbTransferStatus ConvertTransferStatus(
  81. const libusb_transfer_status status) {
  82. switch (status) {
  83. case LIBUSB_TRANSFER_COMPLETED:
  84. return UsbTransferStatus::COMPLETED;
  85. case LIBUSB_TRANSFER_ERROR:
  86. return UsbTransferStatus::TRANSFER_ERROR;
  87. case LIBUSB_TRANSFER_TIMED_OUT:
  88. return UsbTransferStatus::TIMEOUT;
  89. case LIBUSB_TRANSFER_STALL:
  90. return UsbTransferStatus::STALLED;
  91. case LIBUSB_TRANSFER_NO_DEVICE:
  92. return UsbTransferStatus::DISCONNECT;
  93. case LIBUSB_TRANSFER_OVERFLOW:
  94. return UsbTransferStatus::BABBLE;
  95. case LIBUSB_TRANSFER_CANCELLED:
  96. return UsbTransferStatus::CANCELLED;
  97. }
  98. NOTREACHED();
  99. return UsbTransferStatus::TRANSFER_ERROR;
  100. }
  101. } // namespace
  102. class UsbDeviceHandleImpl::InterfaceClaimer
  103. : public base::RefCountedThreadSafe<UsbDeviceHandleImpl::InterfaceClaimer> {
  104. public:
  105. InterfaceClaimer(scoped_refptr<UsbDeviceHandleImpl> handle,
  106. int interface_number,
  107. scoped_refptr<base::SequencedTaskRunner> task_runner);
  108. InterfaceClaimer(const InterfaceClaimer&) = delete;
  109. InterfaceClaimer& operator=(const InterfaceClaimer&) = delete;
  110. int interface_number() const { return interface_number_; }
  111. int alternate_setting() const { return alternate_setting_; }
  112. void set_alternate_setting(const int alternate_setting) {
  113. alternate_setting_ = alternate_setting;
  114. }
  115. void set_release_callback(ResultCallback callback) {
  116. release_callback_ = std::move(callback);
  117. }
  118. private:
  119. friend class base::RefCountedThreadSafe<InterfaceClaimer>;
  120. ~InterfaceClaimer();
  121. const scoped_refptr<UsbDeviceHandleImpl> handle_;
  122. const int interface_number_;
  123. int alternate_setting_;
  124. const scoped_refptr<base::SequencedTaskRunner> task_runner_;
  125. ResultCallback release_callback_;
  126. base::SequenceChecker sequence_checker_;
  127. };
  128. UsbDeviceHandleImpl::InterfaceClaimer::InterfaceClaimer(
  129. scoped_refptr<UsbDeviceHandleImpl> handle,
  130. int interface_number,
  131. scoped_refptr<base::SequencedTaskRunner> task_runner)
  132. : handle_(handle),
  133. interface_number_(interface_number),
  134. alternate_setting_(0),
  135. task_runner_(task_runner) {}
  136. UsbDeviceHandleImpl::InterfaceClaimer::~InterfaceClaimer() {
  137. DCHECK(sequence_checker_.CalledOnValidSequence());
  138. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  139. base::BlockingType::MAY_BLOCK);
  140. int rc = libusb_release_interface(handle_->handle(), interface_number_);
  141. if (rc != LIBUSB_SUCCESS) {
  142. USB_LOG(DEBUG) << "Failed to release interface: "
  143. << ConvertPlatformUsbErrorToString(rc);
  144. }
  145. if (!release_callback_.is_null()) {
  146. task_runner_->PostTask(
  147. FROM_HERE,
  148. base::BindOnce(std::move(release_callback_), rc == LIBUSB_SUCCESS));
  149. }
  150. }
  151. // This inner class owns the underlying libusb_transfer and may outlast
  152. // the UsbDeviceHandle that created it.
  153. class UsbDeviceHandleImpl::Transfer {
  154. public:
  155. // These functions takes |*callback| if they successfully create Transfer
  156. // instance, otherwise |*callback| left unchanged.
  157. static std::unique_ptr<Transfer> CreateControlTransfer(
  158. scoped_refptr<UsbDeviceHandleImpl> device_handle,
  159. uint8_t type,
  160. uint8_t request,
  161. uint16_t value,
  162. uint16_t index,
  163. uint16_t length,
  164. scoped_refptr<base::RefCountedBytes> buffer,
  165. unsigned int timeout,
  166. TransferCallback* callback);
  167. static std::unique_ptr<Transfer> CreateBulkTransfer(
  168. scoped_refptr<UsbDeviceHandleImpl> device_handle,
  169. uint8_t endpoint,
  170. scoped_refptr<base::RefCountedBytes> buffer,
  171. int length,
  172. unsigned int timeout,
  173. TransferCallback* callback);
  174. static std::unique_ptr<Transfer> CreateInterruptTransfer(
  175. scoped_refptr<UsbDeviceHandleImpl> device_handle,
  176. uint8_t endpoint,
  177. scoped_refptr<base::RefCountedBytes> buffer,
  178. int length,
  179. unsigned int timeout,
  180. TransferCallback* callback);
  181. static std::unique_ptr<Transfer> CreateIsochronousTransfer(
  182. scoped_refptr<UsbDeviceHandleImpl> device_handle,
  183. uint8_t endpoint,
  184. scoped_refptr<base::RefCountedBytes> buffer,
  185. size_t length,
  186. const std::vector<uint32_t>& packet_lengths,
  187. unsigned int timeout,
  188. IsochronousTransferCallback* callback);
  189. ~Transfer();
  190. void Submit();
  191. void Cancel();
  192. void ProcessCompletion();
  193. void TransferComplete(UsbTransferStatus status, size_t bytes_transferred);
  194. const UsbDeviceHandleImpl::InterfaceClaimer* claimed_interface() const {
  195. return claimed_interface_.get();
  196. }
  197. private:
  198. Transfer(scoped_refptr<UsbDeviceHandleImpl> device_handle,
  199. scoped_refptr<InterfaceClaimer> claimed_interface,
  200. UsbTransferType transfer_type,
  201. scoped_refptr<base::RefCountedBytes> buffer,
  202. size_t length,
  203. TransferCallback callback);
  204. Transfer(scoped_refptr<UsbDeviceHandleImpl> device_handle,
  205. scoped_refptr<InterfaceClaimer> claimed_interface,
  206. scoped_refptr<base::RefCountedBytes> buffer,
  207. IsochronousTransferCallback callback);
  208. static void LIBUSB_CALL PlatformCallback(PlatformUsbTransferHandle handle);
  209. void IsochronousTransferComplete();
  210. UsbTransferType transfer_type_;
  211. scoped_refptr<UsbDeviceHandleImpl> device_handle_;
  212. PlatformUsbTransferHandle platform_transfer_ = nullptr;
  213. scoped_refptr<base::RefCountedBytes> buffer_;
  214. scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer> claimed_interface_;
  215. size_t length_;
  216. bool cancelled_ = false;
  217. TransferCallback callback_;
  218. IsochronousTransferCallback iso_callback_;
  219. scoped_refptr<base::SequencedTaskRunner> task_runner_;
  220. };
  221. // static
  222. std::unique_ptr<UsbDeviceHandleImpl::Transfer>
  223. UsbDeviceHandleImpl::Transfer::CreateControlTransfer(
  224. scoped_refptr<UsbDeviceHandleImpl> device_handle,
  225. uint8_t type,
  226. uint8_t request,
  227. uint16_t value,
  228. uint16_t index,
  229. uint16_t length,
  230. scoped_refptr<base::RefCountedBytes> buffer,
  231. unsigned int timeout,
  232. TransferCallback* callback) {
  233. std::unique_ptr<Transfer> transfer(
  234. new Transfer(device_handle, nullptr, UsbTransferType::CONTROL, buffer,
  235. length + LIBUSB_CONTROL_SETUP_SIZE, std::move(*callback)));
  236. transfer->platform_transfer_ = libusb_alloc_transfer(0);
  237. if (!transfer->platform_transfer_) {
  238. USB_LOG(ERROR) << "Failed to allocate control transfer.";
  239. *callback = std::move(transfer->callback_);
  240. return nullptr;
  241. }
  242. libusb_fill_control_setup(buffer->front(), type, request, value, index,
  243. length);
  244. libusb_fill_control_transfer(transfer->platform_transfer_,
  245. device_handle->handle(), buffer->front(),
  246. &UsbDeviceHandleImpl::Transfer::PlatformCallback,
  247. transfer.get(), timeout);
  248. return transfer;
  249. }
  250. // static
  251. std::unique_ptr<UsbDeviceHandleImpl::Transfer>
  252. UsbDeviceHandleImpl::Transfer::CreateBulkTransfer(
  253. scoped_refptr<UsbDeviceHandleImpl> device_handle,
  254. uint8_t endpoint,
  255. scoped_refptr<base::RefCountedBytes> buffer,
  256. int length,
  257. unsigned int timeout,
  258. TransferCallback* callback) {
  259. std::unique_ptr<Transfer> transfer(new Transfer(
  260. device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
  261. UsbTransferType::BULK, buffer, length, std::move(*callback)));
  262. transfer->platform_transfer_ = libusb_alloc_transfer(0);
  263. if (!transfer->platform_transfer_) {
  264. USB_LOG(ERROR) << "Failed to allocate bulk transfer.";
  265. *callback = std::move(transfer->callback_);
  266. return nullptr;
  267. }
  268. libusb_fill_bulk_transfer(
  269. transfer->platform_transfer_, device_handle->handle(), endpoint,
  270. buffer->front(), length, &UsbDeviceHandleImpl::Transfer::PlatformCallback,
  271. transfer.get(), timeout);
  272. return transfer;
  273. }
  274. // static
  275. std::unique_ptr<UsbDeviceHandleImpl::Transfer>
  276. UsbDeviceHandleImpl::Transfer::CreateInterruptTransfer(
  277. scoped_refptr<UsbDeviceHandleImpl> device_handle,
  278. uint8_t endpoint,
  279. scoped_refptr<base::RefCountedBytes> buffer,
  280. int length,
  281. unsigned int timeout,
  282. TransferCallback* callback) {
  283. std::unique_ptr<Transfer> transfer(new Transfer(
  284. device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
  285. UsbTransferType::INTERRUPT, buffer, length, std::move(*callback)));
  286. transfer->platform_transfer_ = libusb_alloc_transfer(0);
  287. if (!transfer->platform_transfer_) {
  288. USB_LOG(ERROR) << "Failed to allocate interrupt transfer.";
  289. *callback = std::move(transfer->callback_);
  290. return nullptr;
  291. }
  292. libusb_fill_interrupt_transfer(
  293. transfer->platform_transfer_, device_handle->handle(), endpoint,
  294. buffer->front(), length, &UsbDeviceHandleImpl::Transfer::PlatformCallback,
  295. transfer.get(), timeout);
  296. return transfer;
  297. }
  298. // static
  299. std::unique_ptr<UsbDeviceHandleImpl::Transfer>
  300. UsbDeviceHandleImpl::Transfer::CreateIsochronousTransfer(
  301. scoped_refptr<UsbDeviceHandleImpl> device_handle,
  302. uint8_t endpoint,
  303. scoped_refptr<base::RefCountedBytes> buffer,
  304. size_t length,
  305. const std::vector<uint32_t>& packet_lengths,
  306. unsigned int timeout,
  307. IsochronousTransferCallback* callback) {
  308. std::unique_ptr<Transfer> transfer(new Transfer(
  309. device_handle, device_handle->GetClaimedInterfaceForEndpoint(endpoint),
  310. buffer, std::move(*callback)));
  311. int num_packets = static_cast<int>(packet_lengths.size());
  312. transfer->platform_transfer_ = libusb_alloc_transfer(num_packets);
  313. if (!transfer->platform_transfer_) {
  314. USB_LOG(ERROR) << "Failed to allocate isochronous transfer.";
  315. *callback = std::move(transfer->iso_callback_);
  316. return nullptr;
  317. }
  318. libusb_fill_iso_transfer(
  319. transfer->platform_transfer_, device_handle->handle(), endpoint,
  320. buffer->front(), static_cast<int>(length), num_packets,
  321. &Transfer::PlatformCallback, transfer.get(), timeout);
  322. for (size_t i = 0; i < packet_lengths.size(); ++i)
  323. transfer->platform_transfer_->iso_packet_desc[i].length = packet_lengths[i];
  324. return transfer;
  325. }
  326. UsbDeviceHandleImpl::Transfer::Transfer(
  327. scoped_refptr<UsbDeviceHandleImpl> device_handle,
  328. scoped_refptr<InterfaceClaimer> claimed_interface,
  329. UsbTransferType transfer_type,
  330. scoped_refptr<base::RefCountedBytes> buffer,
  331. size_t length,
  332. TransferCallback callback)
  333. : transfer_type_(transfer_type),
  334. device_handle_(device_handle),
  335. buffer_(buffer),
  336. claimed_interface_(claimed_interface),
  337. length_(length),
  338. callback_(std::move(callback)),
  339. task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
  340. UsbDeviceHandleImpl::Transfer::Transfer(
  341. scoped_refptr<UsbDeviceHandleImpl> device_handle,
  342. scoped_refptr<InterfaceClaimer> claimed_interface,
  343. scoped_refptr<base::RefCountedBytes> buffer,
  344. IsochronousTransferCallback callback)
  345. : transfer_type_(UsbTransferType::ISOCHRONOUS),
  346. device_handle_(device_handle),
  347. buffer_(buffer),
  348. claimed_interface_(claimed_interface),
  349. iso_callback_(std::move(callback)),
  350. task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
  351. UsbDeviceHandleImpl::Transfer::~Transfer() {
  352. if (platform_transfer_) {
  353. libusb_free_transfer(platform_transfer_);
  354. }
  355. }
  356. void UsbDeviceHandleImpl::Transfer::Submit() {
  357. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  358. base::BlockingType::MAY_BLOCK);
  359. const int rv = libusb_submit_transfer(platform_transfer_);
  360. if (rv != LIBUSB_SUCCESS) {
  361. USB_LOG(EVENT) << "Failed to submit transfer: "
  362. << ConvertPlatformUsbErrorToString(rv);
  363. TransferComplete(UsbTransferStatus::TRANSFER_ERROR, 0);
  364. }
  365. }
  366. void UsbDeviceHandleImpl::Transfer::Cancel() {
  367. if (!cancelled_) {
  368. libusb_cancel_transfer(platform_transfer_);
  369. claimed_interface_ = nullptr;
  370. }
  371. cancelled_ = true;
  372. }
  373. void UsbDeviceHandleImpl::Transfer::ProcessCompletion() {
  374. DCHECK_GE(platform_transfer_->actual_length, 0)
  375. << "Negative actual length received";
  376. size_t actual_length =
  377. static_cast<size_t>(std::max(platform_transfer_->actual_length, 0));
  378. DCHECK(length_ >= actual_length)
  379. << "data too big for our buffer (libusb failure?)";
  380. switch (transfer_type_) {
  381. case UsbTransferType::CONTROL:
  382. // If the transfer is a control transfer we do not expose the control
  383. // setup header to the caller. This logic strips off the header if
  384. // present before invoking the callback provided with the transfer.
  385. if (actual_length > 0) {
  386. CHECK(length_ >= LIBUSB_CONTROL_SETUP_SIZE)
  387. << "buffer was not correctly set: too small for the control header";
  388. if (length_ >= (LIBUSB_CONTROL_SETUP_SIZE + actual_length)) {
  389. auto resized_buffer =
  390. base::MakeRefCounted<base::RefCountedBytes>(actual_length);
  391. memcpy(resized_buffer->front(),
  392. buffer_->front() + LIBUSB_CONTROL_SETUP_SIZE, actual_length);
  393. buffer_ = resized_buffer;
  394. }
  395. }
  396. [[fallthrough]];
  397. case UsbTransferType::BULK:
  398. case UsbTransferType::INTERRUPT:
  399. TransferComplete(ConvertTransferStatus(platform_transfer_->status),
  400. actual_length);
  401. break;
  402. case UsbTransferType::ISOCHRONOUS:
  403. IsochronousTransferComplete();
  404. break;
  405. default:
  406. NOTREACHED() << "Invalid usb transfer type";
  407. break;
  408. }
  409. }
  410. /* static */
  411. void LIBUSB_CALL UsbDeviceHandleImpl::Transfer::PlatformCallback(
  412. PlatformUsbTransferHandle platform_transfer) {
  413. Transfer* transfer =
  414. reinterpret_cast<Transfer*>(platform_transfer->user_data);
  415. DCHECK(transfer->platform_transfer_ == platform_transfer);
  416. transfer->ProcessCompletion();
  417. }
  418. void UsbDeviceHandleImpl::Transfer::TransferComplete(UsbTransferStatus status,
  419. size_t bytes_transferred) {
  420. base::OnceClosure closure;
  421. if (transfer_type_ == UsbTransferType::ISOCHRONOUS) {
  422. DCHECK_NE(LIBUSB_TRANSFER_COMPLETED, platform_transfer_->status);
  423. std::vector<UsbIsochronousPacketPtr> packets(
  424. platform_transfer_->num_iso_packets);
  425. for (size_t i = 0; i < packets.size(); ++i) {
  426. packets[i] = mojom::UsbIsochronousPacket::New();
  427. packets[i]->length = platform_transfer_->iso_packet_desc[i].length;
  428. packets[i]->transferred_length = 0;
  429. packets[i]->status = status;
  430. }
  431. closure =
  432. base::BindOnce(std::move(iso_callback_), buffer_, std::move(packets));
  433. } else {
  434. closure = base::BindOnce(std::move(callback_), status, buffer_,
  435. bytes_transferred);
  436. }
  437. task_runner_->PostTask(
  438. FROM_HERE,
  439. base::BindOnce(&UsbDeviceHandleImpl::TransferComplete, device_handle_,
  440. base::Unretained(this), std::move(closure)));
  441. }
  442. void UsbDeviceHandleImpl::Transfer::IsochronousTransferComplete() {
  443. std::vector<UsbIsochronousPacketPtr> packets(
  444. platform_transfer_->num_iso_packets);
  445. for (size_t i = 0; i < packets.size(); ++i) {
  446. packets[i] = mojom::UsbIsochronousPacket::New();
  447. packets[i]->length = platform_transfer_->iso_packet_desc[i].length;
  448. packets[i]->transferred_length =
  449. platform_transfer_->iso_packet_desc[i].actual_length;
  450. packets[i]->status =
  451. ConvertTransferStatus(platform_transfer_->iso_packet_desc[i].status);
  452. }
  453. task_runner_->PostTask(
  454. FROM_HERE, base::BindOnce(&UsbDeviceHandleImpl::TransferComplete,
  455. device_handle_, base::Unretained(this),
  456. base::BindOnce(std::move(iso_callback_),
  457. buffer_, std::move(packets))));
  458. }
  459. scoped_refptr<UsbDevice> UsbDeviceHandleImpl::GetDevice() const {
  460. return device_;
  461. }
  462. void UsbDeviceHandleImpl::Close() {
  463. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  464. if (!device_)
  465. return;
  466. // Cancel all the transfers, their callbacks will be called some time later.
  467. for (Transfer* transfer : transfers_)
  468. transfer->Cancel();
  469. // Release all remaining interfaces once their transfers have completed.
  470. // This loop must ensure that what may be the final reference is released on
  471. // the right thread.
  472. for (auto& map_entry : claimed_interfaces_) {
  473. blocking_task_runner_->ReleaseSoon(FROM_HERE, std::move(map_entry.second));
  474. }
  475. device_->HandleClosed(this);
  476. device_ = nullptr;
  477. // The device handle cannot be closed here. When libusb_cancel_transfer is
  478. // finished the last references to this device will be released and the
  479. // destructor will close the handle.
  480. }
  481. void UsbDeviceHandleImpl::SetConfiguration(int configuration_value,
  482. ResultCallback callback) {
  483. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  484. if (!device_) {
  485. std::move(callback).Run(false);
  486. return;
  487. }
  488. for (Transfer* transfer : transfers_) {
  489. transfer->Cancel();
  490. }
  491. claimed_interfaces_.clear();
  492. blocking_task_runner_->PostTask(
  493. FROM_HERE,
  494. base::BindOnce(&UsbDeviceHandleImpl::SetConfigurationBlocking, this,
  495. configuration_value, std::move(callback)));
  496. }
  497. void UsbDeviceHandleImpl::ClaimInterface(int interface_number,
  498. ResultCallback callback) {
  499. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  500. if (!device_) {
  501. std::move(callback).Run(false);
  502. return;
  503. }
  504. if (base::Contains(claimed_interfaces_, interface_number)) {
  505. std::move(callback).Run(true);
  506. return;
  507. }
  508. blocking_task_runner_->PostTask(
  509. FROM_HERE, base::BindOnce(&UsbDeviceHandleImpl::ClaimInterfaceBlocking,
  510. this, interface_number, std::move(callback)));
  511. }
  512. void UsbDeviceHandleImpl::ReleaseInterface(int interface_number,
  513. ResultCallback callback) {
  514. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  515. if (!device_ || !base::Contains(claimed_interfaces_, interface_number)) {
  516. task_runner_->PostTask(FROM_HERE,
  517. base::BindOnce(std::move(callback), false));
  518. return;
  519. }
  520. // Cancel all the transfers on that interface.
  521. InterfaceClaimer* interface_claimer =
  522. claimed_interfaces_[interface_number].get();
  523. for (Transfer* transfer : transfers_) {
  524. if (transfer->claimed_interface() == interface_claimer) {
  525. transfer->Cancel();
  526. }
  527. }
  528. interface_claimer->set_release_callback(std::move(callback));
  529. blocking_task_runner_->ReleaseSoon(
  530. FROM_HERE, std::move(claimed_interfaces_[interface_number]));
  531. claimed_interfaces_.erase(interface_number);
  532. RefreshEndpointMap();
  533. }
  534. void UsbDeviceHandleImpl::SetInterfaceAlternateSetting(
  535. int interface_number,
  536. int alternate_setting,
  537. ResultCallback callback) {
  538. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  539. if (!device_ || !base::Contains(claimed_interfaces_, interface_number)) {
  540. std::move(callback).Run(false);
  541. return;
  542. }
  543. blocking_task_runner_->PostTask(
  544. FROM_HERE,
  545. base::BindOnce(&UsbDeviceHandleImpl::SetInterfaceAlternateSettingBlocking,
  546. this, interface_number, alternate_setting,
  547. std::move(callback)));
  548. }
  549. void UsbDeviceHandleImpl::ResetDevice(ResultCallback callback) {
  550. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  551. if (!device_) {
  552. std::move(callback).Run(false);
  553. return;
  554. }
  555. blocking_task_runner_->PostTask(
  556. FROM_HERE, base::BindOnce(&UsbDeviceHandleImpl::ResetDeviceBlocking, this,
  557. std::move(callback)));
  558. }
  559. void UsbDeviceHandleImpl::ClearHalt(UsbTransferDirection direction,
  560. uint8_t endpoint_number,
  561. ResultCallback callback) {
  562. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  563. if (!device_) {
  564. std::move(callback).Run(false);
  565. return;
  566. }
  567. uint8_t endpoint_address =
  568. ConvertTransferDirection(direction) | endpoint_number;
  569. InterfaceClaimer* interface_claimer =
  570. GetClaimedInterfaceForEndpoint(endpoint_address).get();
  571. for (Transfer* transfer : transfers_) {
  572. if (transfer->claimed_interface() == interface_claimer) {
  573. transfer->Cancel();
  574. }
  575. }
  576. blocking_task_runner_->PostTask(
  577. FROM_HERE, base::BindOnce(&UsbDeviceHandleImpl::ClearHaltBlocking, this,
  578. endpoint_address, std::move(callback)));
  579. }
  580. void UsbDeviceHandleImpl::ControlTransfer(
  581. UsbTransferDirection direction,
  582. UsbControlTransferType request_type,
  583. UsbControlTransferRecipient recipient,
  584. uint8_t request,
  585. uint16_t value,
  586. uint16_t index,
  587. scoped_refptr<base::RefCountedBytes> buffer,
  588. unsigned int timeout,
  589. TransferCallback callback) {
  590. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  591. if (!device_) {
  592. task_runner_->PostTask(
  593. FROM_HERE, base::BindOnce(std::move(callback),
  594. UsbTransferStatus::DISCONNECT, buffer, 0));
  595. return;
  596. }
  597. if (!base::IsValueInRangeForNumericType<uint16_t>(buffer->size())) {
  598. USB_LOG(USER) << "Transfer too long.";
  599. task_runner_->PostTask(
  600. FROM_HERE,
  601. base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR,
  602. buffer, 0));
  603. return;
  604. }
  605. const size_t resized_length = LIBUSB_CONTROL_SETUP_SIZE + buffer->size();
  606. auto resized_buffer =
  607. base::MakeRefCounted<base::RefCountedBytes>(resized_length);
  608. memcpy(resized_buffer->front() + LIBUSB_CONTROL_SETUP_SIZE, buffer->front(),
  609. buffer->size());
  610. std::unique_ptr<Transfer> transfer = Transfer::CreateControlTransfer(
  611. this, CreateRequestType(direction, request_type, recipient), request,
  612. value, index, static_cast<uint16_t>(buffer->size()), resized_buffer,
  613. timeout, &callback);
  614. if (!transfer) {
  615. DCHECK(callback);
  616. task_runner_->PostTask(
  617. FROM_HERE,
  618. base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR,
  619. buffer, 0));
  620. return;
  621. }
  622. SubmitTransfer(std::move(transfer));
  623. }
  624. void UsbDeviceHandleImpl::IsochronousTransferIn(
  625. uint8_t endpoint_number,
  626. const std::vector<uint32_t>& packet_lengths,
  627. unsigned int timeout,
  628. IsochronousTransferCallback callback) {
  629. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  630. if (!device_) {
  631. ReportIsochronousTransferError(std::move(callback), packet_lengths,
  632. UsbTransferStatus::DISCONNECT);
  633. return;
  634. }
  635. uint8_t endpoint_address =
  636. ConvertTransferDirection(UsbTransferDirection::INBOUND) | endpoint_number;
  637. size_t length =
  638. std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u);
  639. auto buffer = base::MakeRefCounted<base::RefCountedBytes>(length);
  640. std::unique_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer(
  641. this, endpoint_address, buffer, length, packet_lengths, timeout,
  642. &callback);
  643. DCHECK(transfer);
  644. SubmitTransfer(std::move(transfer));
  645. }
  646. void UsbDeviceHandleImpl::IsochronousTransferOut(
  647. uint8_t endpoint_number,
  648. scoped_refptr<base::RefCountedBytes> buffer,
  649. const std::vector<uint32_t>& packet_lengths,
  650. unsigned int timeout,
  651. IsochronousTransferCallback callback) {
  652. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  653. if (!device_) {
  654. ReportIsochronousTransferError(std::move(callback), packet_lengths,
  655. UsbTransferStatus::DISCONNECT);
  656. return;
  657. }
  658. uint8_t endpoint_address =
  659. ConvertTransferDirection(UsbTransferDirection::OUTBOUND) |
  660. endpoint_number;
  661. size_t length =
  662. std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u);
  663. std::unique_ptr<Transfer> transfer = Transfer::CreateIsochronousTransfer(
  664. this, endpoint_address, buffer, length, packet_lengths, timeout,
  665. &callback);
  666. DCHECK(transfer);
  667. SubmitTransfer(std::move(transfer));
  668. }
  669. void UsbDeviceHandleImpl::GenericTransfer(
  670. UsbTransferDirection direction,
  671. uint8_t endpoint_number,
  672. scoped_refptr<base::RefCountedBytes> buffer,
  673. unsigned int timeout,
  674. TransferCallback callback) {
  675. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  676. if (!device_) {
  677. task_runner_->PostTask(
  678. FROM_HERE, base::BindOnce(std::move(callback),
  679. UsbTransferStatus::DISCONNECT, buffer, 0));
  680. return;
  681. }
  682. uint8_t endpoint_address =
  683. ConvertTransferDirection(direction) | endpoint_number;
  684. const auto endpoint_it = endpoint_map_.find(endpoint_address);
  685. if (endpoint_it == endpoint_map_.end()) {
  686. USB_LOG(DEBUG) << "Failed to submit transfer because endpoint "
  687. << static_cast<int>(endpoint_address)
  688. << " not part of a claimed interface.";
  689. task_runner_->PostTask(
  690. FROM_HERE,
  691. base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR,
  692. buffer, 0));
  693. return;
  694. }
  695. if (!base::IsValueInRangeForNumericType<int>(buffer->size())) {
  696. USB_LOG(DEBUG) << "Transfer too long.";
  697. task_runner_->PostTask(
  698. FROM_HERE,
  699. base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR,
  700. buffer, 0));
  701. return;
  702. }
  703. std::unique_ptr<Transfer> transfer;
  704. UsbTransferType transfer_type = endpoint_it->second.endpoint->type;
  705. if (transfer_type == UsbTransferType::BULK) {
  706. transfer = Transfer::CreateBulkTransfer(this, endpoint_address, buffer,
  707. static_cast<int>(buffer->size()),
  708. timeout, &callback);
  709. } else if (transfer_type == UsbTransferType::INTERRUPT) {
  710. transfer = Transfer::CreateInterruptTransfer(
  711. this, endpoint_address, buffer, static_cast<int>(buffer->size()),
  712. timeout, &callback);
  713. } else {
  714. USB_LOG(DEBUG) << "Endpoint " << static_cast<int>(endpoint_address)
  715. << " is not a bulk or interrupt endpoint.";
  716. task_runner_->PostTask(
  717. FROM_HERE,
  718. base::BindOnce(std::move(callback), UsbTransferStatus::TRANSFER_ERROR,
  719. buffer, 0));
  720. return;
  721. }
  722. DCHECK(transfer);
  723. SubmitTransfer(std::move(transfer));
  724. }
  725. const mojom::UsbInterfaceInfo* UsbDeviceHandleImpl::FindInterfaceByEndpoint(
  726. uint8_t endpoint_address) {
  727. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  728. const auto endpoint_it = endpoint_map_.find(endpoint_address);
  729. if (endpoint_it != endpoint_map_.end())
  730. return endpoint_it->second.interface;
  731. return nullptr;
  732. }
  733. UsbDeviceHandleImpl::UsbDeviceHandleImpl(
  734. scoped_refptr<UsbDeviceImpl> device,
  735. ScopedLibusbDeviceHandle handle,
  736. scoped_refptr<base::SequencedTaskRunner> blocking_task_runner)
  737. : device_(std::move(device)),
  738. handle_(std::move(handle)),
  739. task_runner_(base::SequencedTaskRunnerHandle::Get()),
  740. blocking_task_runner_(blocking_task_runner) {
  741. DCHECK(handle_.IsValid()) << "Cannot create device with an invalid handle.";
  742. }
  743. UsbDeviceHandleImpl::~UsbDeviceHandleImpl() {
  744. DCHECK(!device_) << "UsbDeviceHandle must be closed before it is destroyed.";
  745. // This class is RefCountedThreadSafe and so the destructor may be called on
  746. // any thread. libusb is not safe to reentrancy so be sure not to try to close
  747. // the device from inside a transfer completion callback.
  748. if (blocking_task_runner_->RunsTasksInCurrentSequence()) {
  749. handle_.Reset();
  750. } else {
  751. blocking_task_runner_->PostTask(
  752. FROM_HERE,
  753. base::BindOnce([](ScopedLibusbDeviceHandle) {}, std::move(handle_)));
  754. }
  755. }
  756. void UsbDeviceHandleImpl::SetConfigurationBlocking(int configuration_value,
  757. ResultCallback callback) {
  758. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  759. base::BlockingType::MAY_BLOCK);
  760. int rv = libusb_set_configuration(handle(), configuration_value);
  761. if (rv != LIBUSB_SUCCESS) {
  762. USB_LOG(EVENT) << "Failed to set configuration " << configuration_value
  763. << ": " << ConvertPlatformUsbErrorToString(rv);
  764. }
  765. task_runner_->PostTask(
  766. FROM_HERE,
  767. base::BindOnce(&UsbDeviceHandleImpl::SetConfigurationComplete, this,
  768. rv == LIBUSB_SUCCESS, std::move(callback)));
  769. }
  770. void UsbDeviceHandleImpl::SetConfigurationComplete(bool success,
  771. ResultCallback callback) {
  772. if (!device_) {
  773. std::move(callback).Run(false);
  774. return;
  775. }
  776. if (success) {
  777. device_->RefreshActiveConfiguration();
  778. RefreshEndpointMap();
  779. }
  780. std::move(callback).Run(success);
  781. }
  782. void UsbDeviceHandleImpl::ClaimInterfaceBlocking(int interface_number,
  783. ResultCallback callback) {
  784. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  785. base::BlockingType::MAY_BLOCK);
  786. int rv = libusb_claim_interface(handle(), interface_number);
  787. scoped_refptr<InterfaceClaimer> interface_claimer;
  788. if (rv == LIBUSB_SUCCESS) {
  789. interface_claimer =
  790. new InterfaceClaimer(this, interface_number, task_runner_);
  791. } else {
  792. USB_LOG(EVENT) << "Failed to claim interface: "
  793. << ConvertPlatformUsbErrorToString(rv);
  794. }
  795. task_runner_->PostTask(
  796. FROM_HERE, base::BindOnce(&UsbDeviceHandleImpl::ClaimInterfaceComplete,
  797. this, interface_claimer, std::move(callback)));
  798. }
  799. void UsbDeviceHandleImpl::ClaimInterfaceComplete(
  800. scoped_refptr<InterfaceClaimer> interface_claimer,
  801. ResultCallback callback) {
  802. if (!device_) {
  803. if (interface_claimer) {
  804. // Ensure that the InterfaceClaimer is released on the blocking thread.
  805. blocking_task_runner_->ReleaseSoon(FROM_HERE,
  806. std::move(interface_claimer));
  807. }
  808. std::move(callback).Run(false);
  809. return;
  810. }
  811. if (interface_claimer) {
  812. claimed_interfaces_[interface_claimer->interface_number()] =
  813. interface_claimer;
  814. RefreshEndpointMap();
  815. }
  816. std::move(callback).Run(interface_claimer != nullptr);
  817. }
  818. void UsbDeviceHandleImpl::SetInterfaceAlternateSettingBlocking(
  819. int interface_number,
  820. int alternate_setting,
  821. ResultCallback callback) {
  822. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  823. base::BlockingType::MAY_BLOCK);
  824. int rv = libusb_set_interface_alt_setting(handle(), interface_number,
  825. alternate_setting);
  826. if (rv != LIBUSB_SUCCESS) {
  827. USB_LOG(EVENT) << "Failed to set interface " << interface_number
  828. << " to alternate setting " << alternate_setting << ": "
  829. << ConvertPlatformUsbErrorToString(rv);
  830. }
  831. task_runner_->PostTask(
  832. FROM_HERE,
  833. base::BindOnce(&UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete,
  834. this, interface_number, alternate_setting,
  835. rv == LIBUSB_SUCCESS, std::move(callback)));
  836. }
  837. void UsbDeviceHandleImpl::SetInterfaceAlternateSettingComplete(
  838. int interface_number,
  839. int alternate_setting,
  840. bool success,
  841. ResultCallback callback) {
  842. if (!device_) {
  843. std::move(callback).Run(false);
  844. return;
  845. }
  846. if (success) {
  847. claimed_interfaces_[interface_number]->set_alternate_setting(
  848. alternate_setting);
  849. RefreshEndpointMap();
  850. }
  851. std::move(callback).Run(success);
  852. }
  853. void UsbDeviceHandleImpl::ResetDeviceBlocking(ResultCallback callback) {
  854. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  855. base::BlockingType::MAY_BLOCK);
  856. int rv = libusb_reset_device(handle());
  857. if (rv != LIBUSB_SUCCESS) {
  858. USB_LOG(EVENT) << "Failed to reset device: "
  859. << ConvertPlatformUsbErrorToString(rv);
  860. }
  861. task_runner_->PostTask(
  862. FROM_HERE, base::BindOnce(std::move(callback), rv == LIBUSB_SUCCESS));
  863. }
  864. void UsbDeviceHandleImpl::ClearHaltBlocking(uint8_t endpoint_address,
  865. ResultCallback callback) {
  866. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  867. base::BlockingType::MAY_BLOCK);
  868. int rv = libusb_clear_halt(handle(), endpoint_address);
  869. if (rv != LIBUSB_SUCCESS) {
  870. USB_LOG(EVENT) << "Failed to clear halt: "
  871. << ConvertPlatformUsbErrorToString(rv);
  872. }
  873. task_runner_->PostTask(
  874. FROM_HERE, base::BindOnce(std::move(callback), rv == LIBUSB_SUCCESS));
  875. }
  876. void UsbDeviceHandleImpl::RefreshEndpointMap() {
  877. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  878. DCHECK(device_);
  879. endpoint_map_.clear();
  880. const mojom::UsbConfigurationInfo* config = device_->GetActiveConfiguration();
  881. if (!config)
  882. return;
  883. for (const auto& map_entry : claimed_interfaces_) {
  884. CombinedInterfaceInfo interface_info = FindInterfaceInfoFromConfig(
  885. config, map_entry.first, map_entry.second->alternate_setting());
  886. if (!interface_info.IsValid())
  887. return;
  888. for (const auto& endpoint : interface_info.alternate->endpoints) {
  889. endpoint_map_[ConvertEndpointNumberToAddress(*endpoint)] = {
  890. interface_info.interface, endpoint.get()};
  891. }
  892. }
  893. }
  894. scoped_refptr<UsbDeviceHandleImpl::InterfaceClaimer>
  895. UsbDeviceHandleImpl::GetClaimedInterfaceForEndpoint(uint8_t endpoint_address) {
  896. const auto endpoint_it = endpoint_map_.find(endpoint_address);
  897. if (endpoint_it != endpoint_map_.end())
  898. return claimed_interfaces_[endpoint_it->second.interface->interface_number];
  899. return nullptr;
  900. }
  901. void UsbDeviceHandleImpl::ReportIsochronousTransferError(
  902. UsbDeviceHandle::IsochronousTransferCallback callback,
  903. const std::vector<uint32_t> packet_lengths,
  904. UsbTransferStatus status) {
  905. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  906. std::vector<UsbIsochronousPacketPtr> packets(packet_lengths.size());
  907. for (size_t i = 0; i < packet_lengths.size(); ++i) {
  908. packets[i] = mojom::UsbIsochronousPacket::New();
  909. packets[i]->length = packet_lengths[i];
  910. packets[i]->transferred_length = 0;
  911. packets[i]->status = status;
  912. }
  913. task_runner_->PostTask(FROM_HERE, base::BindOnce(std::move(callback), nullptr,
  914. std::move(packets)));
  915. }
  916. void UsbDeviceHandleImpl::SubmitTransfer(std::unique_ptr<Transfer> transfer) {
  917. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  918. DCHECK(transfer);
  919. // Transfer is owned by libusb until its completion callback is run. This
  920. // object holds a weak reference.
  921. transfers_.insert(transfer.get());
  922. blocking_task_runner_->PostTask(
  923. FROM_HERE,
  924. base::BindOnce(&Transfer::Submit, base::Unretained(transfer.release())));
  925. }
  926. void UsbDeviceHandleImpl::TransferComplete(Transfer* transfer,
  927. base::OnceClosure callback) {
  928. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  929. DCHECK(base::Contains(transfers_, transfer)) << "Missing transfer completed";
  930. transfers_.erase(transfer);
  931. std::move(callback).Run();
  932. // libusb_free_transfer races with libusb_submit_transfer and only work-
  933. // around is to make sure to call them on the same thread.
  934. blocking_task_runner_->DeleteSoon(FROM_HERE, transfer);
  935. }
  936. } // namespace device