usb_descriptors.cc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  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_descriptors.h"
  5. #include <stddef.h>
  6. #include <algorithm>
  7. #include <memory>
  8. #include <string>
  9. #include <utility>
  10. #include <vector>
  11. #include "base/barrier_closure.h"
  12. #include "base/bind.h"
  13. #include "base/memory/ref_counted_memory.h"
  14. #include "services/device/public/cpp/usb/usb_utils.h"
  15. #include "services/device/usb/usb_device_handle.h"
  16. namespace device {
  17. using mojom::UsbAlternateInterfaceInfoPtr;
  18. using mojom::UsbConfigurationInfoPtr;
  19. using mojom::UsbControlTransferRecipient;
  20. using mojom::UsbControlTransferType;
  21. using mojom::UsbDeviceInfoPtr;
  22. using mojom::UsbEndpointInfoPtr;
  23. using mojom::UsbInterfaceInfoPtr;
  24. using mojom::UsbSynchronizationType;
  25. using mojom::UsbTransferDirection;
  26. using mojom::UsbTransferStatus;
  27. using mojom::UsbTransferType;
  28. using mojom::UsbUsageType;
  29. namespace {
  30. using IndexMap = std::map<uint8_t, std::u16string>;
  31. using IndexMapPtr = std::unique_ptr<IndexMap>;
  32. // Standard USB requests and descriptor types:
  33. const uint8_t kGetDescriptorRequest = 0x06;
  34. const uint8_t kDeviceDescriptorType = 0x01;
  35. const uint8_t kConfigurationDescriptorType = 0x02;
  36. const uint8_t kStringDescriptorType = 0x03;
  37. const uint8_t kInterfaceDescriptorType = 0x04;
  38. const uint8_t kEndpointDescriptorType = 0x05;
  39. const uint8_t kInterfaceAssociationDescriptorType = 11;
  40. const uint8_t kDeviceDescriptorLength = 18;
  41. const uint8_t kConfigurationDescriptorLength = 9;
  42. const uint8_t kInterfaceDescriptorLength = 9;
  43. const uint8_t kEndpointDescriptorLength = 7;
  44. const uint8_t kInterfaceAssociationDescriptorLength = 8;
  45. const int kControlTransferTimeoutMs = 2000; // 2 seconds
  46. struct UsbInterfaceAssociationDescriptor {
  47. UsbInterfaceAssociationDescriptor(uint8_t first_interface,
  48. uint8_t interface_count)
  49. : first_interface(first_interface), interface_count(interface_count) {}
  50. bool operator<(const UsbInterfaceAssociationDescriptor& other) const {
  51. return first_interface < other.first_interface;
  52. }
  53. uint8_t first_interface;
  54. uint8_t interface_count;
  55. };
  56. void ParseInterfaceAssociationDescriptors(
  57. const std::vector<uint8_t>& buffer,
  58. std::vector<UsbInterfaceAssociationDescriptor>* functions) {
  59. auto it = buffer.begin();
  60. while (it != buffer.end()) {
  61. // All descriptors must be at least 2 byte which means the length and type
  62. // are safe to read.
  63. if (std::distance(it, buffer.end()) < 2)
  64. return;
  65. uint8_t length = it[0];
  66. if (length > std::distance(it, buffer.end()))
  67. return;
  68. if (it[1] == kInterfaceAssociationDescriptorType &&
  69. length == kInterfaceAssociationDescriptorLength) {
  70. functions->push_back(UsbInterfaceAssociationDescriptor(it[2], it[3]));
  71. }
  72. std::advance(it, length);
  73. }
  74. }
  75. void OnDoneReadingConfigDescriptors(
  76. scoped_refptr<UsbDeviceHandle> device_handle,
  77. std::unique_ptr<UsbDeviceDescriptor> desc,
  78. base::OnceCallback<void(std::unique_ptr<UsbDeviceDescriptor>)> callback) {
  79. if (desc->num_configurations == desc->device_info->configurations.size()) {
  80. std::move(callback).Run(std::move(desc));
  81. } else {
  82. LOG(ERROR) << "Failed to read all configuration descriptors. Expected "
  83. << static_cast<int>(desc->num_configurations) << ", got "
  84. << desc->device_info->configurations.size() << ".";
  85. std::move(callback).Run(nullptr);
  86. }
  87. }
  88. void OnReadConfigDescriptor(UsbDeviceDescriptor* desc,
  89. base::OnceClosure closure,
  90. UsbTransferStatus status,
  91. scoped_refptr<base::RefCountedBytes> buffer,
  92. size_t length) {
  93. if (status == UsbTransferStatus::COMPLETED) {
  94. if (!desc->Parse(base::make_span(buffer->front(), length))) {
  95. LOG(ERROR) << "Failed to parse configuration descriptor.";
  96. }
  97. } else {
  98. LOG(ERROR) << "Failed to read configuration descriptor.";
  99. }
  100. std::move(closure).Run();
  101. }
  102. void OnReadConfigDescriptorHeader(scoped_refptr<UsbDeviceHandle> device_handle,
  103. UsbDeviceDescriptor* desc,
  104. uint8_t index,
  105. base::OnceClosure closure,
  106. UsbTransferStatus status,
  107. scoped_refptr<base::RefCountedBytes> header,
  108. size_t length) {
  109. if (status == UsbTransferStatus::COMPLETED &&
  110. length == kConfigurationDescriptorLength) {
  111. const uint8_t* data = header->front();
  112. uint16_t total_length = data[2] | data[3] << 8;
  113. auto buffer = base::MakeRefCounted<base::RefCountedBytes>(total_length);
  114. device_handle->ControlTransfer(
  115. UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD,
  116. UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest,
  117. kConfigurationDescriptorType << 8 | index, 0, buffer,
  118. kControlTransferTimeoutMs,
  119. base::BindOnce(&OnReadConfigDescriptor, desc, std::move(closure)));
  120. } else {
  121. LOG(ERROR) << "Failed to read length for configuration "
  122. << static_cast<int>(index) << ".";
  123. std::move(closure).Run();
  124. }
  125. }
  126. void OnReadDeviceDescriptor(
  127. scoped_refptr<UsbDeviceHandle> device_handle,
  128. base::OnceCallback<void(std::unique_ptr<UsbDeviceDescriptor>)> callback,
  129. UsbTransferStatus status,
  130. scoped_refptr<base::RefCountedBytes> buffer,
  131. size_t length) {
  132. if (status != UsbTransferStatus::COMPLETED) {
  133. LOG(ERROR) << "Failed to read device descriptor.";
  134. std::move(callback).Run(nullptr);
  135. return;
  136. }
  137. std::unique_ptr<UsbDeviceDescriptor> desc(new UsbDeviceDescriptor());
  138. if (!desc->Parse(base::make_span(buffer->front(), length))) {
  139. LOG(ERROR) << "Device descriptor parsing error.";
  140. std::move(callback).Run(nullptr);
  141. return;
  142. }
  143. if (desc->num_configurations == 0) {
  144. std::move(callback).Run(std::move(desc));
  145. return;
  146. }
  147. uint8_t num_configurations = desc->num_configurations;
  148. UsbDeviceDescriptor* desc_ptr = desc.get();
  149. base::RepeatingClosure closure = base::BarrierClosure(
  150. num_configurations,
  151. base::BindOnce(OnDoneReadingConfigDescriptors, device_handle,
  152. std::move(desc), std::move(callback)));
  153. for (uint8_t i = 0; i < num_configurations; ++i) {
  154. auto header = base::MakeRefCounted<base::RefCountedBytes>(
  155. kConfigurationDescriptorLength);
  156. device_handle->ControlTransfer(
  157. UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD,
  158. UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest,
  159. kConfigurationDescriptorType << 8 | i, 0, header,
  160. kControlTransferTimeoutMs,
  161. base::BindOnce(&OnReadConfigDescriptorHeader, device_handle, desc_ptr,
  162. i, closure));
  163. }
  164. }
  165. void StoreStringDescriptor(IndexMap::iterator it,
  166. base::OnceClosure callback,
  167. const std::u16string& string) {
  168. it->second = string;
  169. std::move(callback).Run();
  170. }
  171. void OnReadStringDescriptor(
  172. base::OnceCallback<void(const std::u16string&)> callback,
  173. UsbTransferStatus status,
  174. scoped_refptr<base::RefCountedBytes> buffer,
  175. size_t length) {
  176. std::u16string string;
  177. if (status == UsbTransferStatus::COMPLETED &&
  178. ParseUsbStringDescriptor(
  179. std::vector<uint8_t>(buffer->front(), buffer->front() + length),
  180. &string)) {
  181. std::move(callback).Run(string);
  182. } else {
  183. std::move(callback).Run(std::u16string());
  184. }
  185. }
  186. void ReadStringDescriptor(
  187. scoped_refptr<UsbDeviceHandle> device_handle,
  188. uint8_t index,
  189. uint16_t language_id,
  190. base::OnceCallback<void(const std::u16string&)> callback) {
  191. auto buffer = base::MakeRefCounted<base::RefCountedBytes>(255);
  192. device_handle->ControlTransfer(
  193. UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD,
  194. UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest,
  195. kStringDescriptorType << 8 | index, language_id, buffer,
  196. kControlTransferTimeoutMs,
  197. base::BindOnce(&OnReadStringDescriptor, std::move(callback)));
  198. }
  199. void OnReadLanguageIds(scoped_refptr<UsbDeviceHandle> device_handle,
  200. IndexMapPtr index_map,
  201. base::OnceCallback<void(IndexMapPtr)> callback,
  202. const std::u16string& languages) {
  203. // Default to English unless the device provides a language and then just pick
  204. // the first one.
  205. uint16_t language_id = languages.empty() ? 0x0409 : languages[0];
  206. std::map<uint8_t, IndexMap::iterator> iterator_map;
  207. for (auto it = index_map->begin(); it != index_map->end(); ++it)
  208. iterator_map[it->first] = it;
  209. base::RepeatingClosure barrier = base::BarrierClosure(
  210. static_cast<int>(iterator_map.size()),
  211. base::BindOnce(std::move(callback), std::move(index_map)));
  212. for (const auto& map_entry : iterator_map) {
  213. ReadStringDescriptor(
  214. device_handle, map_entry.first, language_id,
  215. base::BindOnce(&StoreStringDescriptor, map_entry.second, barrier));
  216. }
  217. }
  218. } // namespace
  219. CombinedInterfaceInfo::CombinedInterfaceInfo(
  220. const mojom::UsbInterfaceInfo* interface,
  221. const mojom::UsbAlternateInterfaceInfo* alternate)
  222. : interface(interface), alternate(alternate) {}
  223. bool CombinedInterfaceInfo::IsValid() const {
  224. return interface && alternate;
  225. }
  226. UsbDeviceDescriptor::UsbDeviceDescriptor()
  227. : device_info(mojom::UsbDeviceInfo::New()) {}
  228. UsbDeviceDescriptor::~UsbDeviceDescriptor() = default;
  229. bool UsbDeviceDescriptor::Parse(base::span<const uint8_t> buffer) {
  230. mojom::UsbConfigurationInfo* last_config = nullptr;
  231. mojom::UsbInterfaceInfo* last_interface = nullptr;
  232. mojom::UsbEndpointInfo* last_endpoint = nullptr;
  233. for (auto it = buffer.begin(); it != buffer.end();
  234. /* incremented internally */) {
  235. const uint8_t* data = &it[0];
  236. uint8_t length = data[0];
  237. if (length < 2 || length > std::distance(it, buffer.end()))
  238. return false;
  239. it += length;
  240. switch (data[1] /* bDescriptorType */) {
  241. case kDeviceDescriptorType:
  242. if (device_info->configurations.size() > 0 ||
  243. length < kDeviceDescriptorLength) {
  244. return false;
  245. }
  246. device_info->usb_version_minor = data[2] >> 4 & 0xf;
  247. device_info->usb_version_subminor = data[2] & 0xf;
  248. device_info->usb_version_major = data[3];
  249. device_info->class_code = data[4];
  250. device_info->subclass_code = data[5];
  251. device_info->protocol_code = data[6];
  252. device_info->vendor_id = data[8] | data[9] << 8;
  253. device_info->product_id = data[10] | data[11] << 8;
  254. device_info->device_version_minor = data[12] >> 4 & 0xf;
  255. device_info->device_version_subminor = data[12] & 0xf;
  256. device_info->device_version_major = data[13];
  257. i_manufacturer = data[14];
  258. i_product = data[15];
  259. i_serial_number = data[16];
  260. num_configurations = data[17];
  261. break;
  262. case kConfigurationDescriptorType:
  263. if (length < kConfigurationDescriptorLength)
  264. return false;
  265. if (last_config) {
  266. AssignFirstInterfaceNumbers(last_config);
  267. AggregateInterfacesForConfig(last_config);
  268. }
  269. device_info->configurations.push_back(
  270. BuildUsbConfigurationInfoPtr(data));
  271. last_config = device_info->configurations.back().get();
  272. last_interface = nullptr;
  273. last_endpoint = nullptr;
  274. break;
  275. case kInterfaceDescriptorType:
  276. if (!last_config || length < kInterfaceDescriptorLength)
  277. return false;
  278. last_config->interfaces.push_back(BuildUsbInterfaceInfoPtr(data));
  279. last_interface = last_config->interfaces.back().get();
  280. last_endpoint = nullptr;
  281. break;
  282. case kEndpointDescriptorType:
  283. if (!last_interface || length < kEndpointDescriptorLength)
  284. return false;
  285. last_interface->alternates[0]->endpoints.push_back(
  286. BuildUsbEndpointInfoPtr(data));
  287. last_endpoint = last_interface->alternates[0]->endpoints.back().get();
  288. break;
  289. default:
  290. // Append unknown descriptor types to the |extra_data| field of the last
  291. // descriptor.
  292. if (last_endpoint) {
  293. last_endpoint->extra_data.insert(last_endpoint->extra_data.end(),
  294. data, data + length);
  295. } else if (last_interface) {
  296. DCHECK_EQ(1u, last_interface->alternates.size());
  297. last_interface->alternates[0]->extra_data.insert(
  298. last_interface->alternates[0]->extra_data.end(), data,
  299. data + length);
  300. } else if (last_config) {
  301. last_config->extra_data.insert(last_config->extra_data.end(), data,
  302. data + length);
  303. }
  304. }
  305. }
  306. if (last_config) {
  307. AssignFirstInterfaceNumbers(last_config);
  308. AggregateInterfacesForConfig(last_config);
  309. }
  310. return true;
  311. }
  312. void ReadUsbDescriptors(
  313. scoped_refptr<UsbDeviceHandle> device_handle,
  314. base::OnceCallback<void(std::unique_ptr<UsbDeviceDescriptor>)> callback) {
  315. auto buffer =
  316. base::MakeRefCounted<base::RefCountedBytes>(kDeviceDescriptorLength);
  317. device_handle->ControlTransfer(
  318. UsbTransferDirection::INBOUND, UsbControlTransferType::STANDARD,
  319. UsbControlTransferRecipient::DEVICE, kGetDescriptorRequest,
  320. kDeviceDescriptorType << 8, 0, buffer, kControlTransferTimeoutMs,
  321. base::BindOnce(&OnReadDeviceDescriptor, device_handle,
  322. std::move(callback)));
  323. }
  324. bool ParseUsbStringDescriptor(const std::vector<uint8_t>& descriptor,
  325. std::u16string* output) {
  326. if (descriptor.size() < 2 || descriptor[1] != kStringDescriptorType)
  327. return false;
  328. // Let the device return a buffer larger than the actual string but prefer the
  329. // length reported inside the descriptor.
  330. size_t length = descriptor[0];
  331. length = std::min(length, descriptor.size());
  332. if (length < 2)
  333. return false;
  334. // The string is returned by the device in UTF-16LE.
  335. *output =
  336. std::u16string(reinterpret_cast<const char16_t*>(descriptor.data() + 2),
  337. (length - 2) / sizeof(char16_t));
  338. return true;
  339. }
  340. // For each key in |index_map| this function reads that string descriptor from
  341. // |device_handle| and updates the value in in |index_map|.
  342. void ReadUsbStringDescriptors(scoped_refptr<UsbDeviceHandle> device_handle,
  343. IndexMapPtr index_map,
  344. base::OnceCallback<void(IndexMapPtr)> callback) {
  345. if (index_map->empty()) {
  346. std::move(callback).Run(std::move(index_map));
  347. return;
  348. }
  349. ReadStringDescriptor(
  350. device_handle, 0, 0,
  351. base::BindOnce(&OnReadLanguageIds, device_handle, std::move(index_map),
  352. std::move(callback)));
  353. }
  354. UsbEndpointInfoPtr BuildUsbEndpointInfoPtr(const uint8_t* data) {
  355. DCHECK_GE(data[0], kEndpointDescriptorLength);
  356. DCHECK_EQ(data[1], kEndpointDescriptorType);
  357. return BuildUsbEndpointInfoPtr(
  358. data[2] /* bEndpointAddress */, data[3] /* bmAttributes */,
  359. data[4] + (data[5] << 8) /* wMaxPacketSize */, data[6] /* bInterval */);
  360. }
  361. UsbEndpointInfoPtr BuildUsbEndpointInfoPtr(uint8_t address,
  362. uint8_t attributes,
  363. uint16_t maximum_packet_size,
  364. uint8_t polling_interval) {
  365. UsbEndpointInfoPtr endpoint = mojom::UsbEndpointInfo::New();
  366. endpoint->endpoint_number = ConvertEndpointAddressToNumber(address);
  367. // These fields are defined in Table 9-24 of the USB 3.1 Specification.
  368. switch (address & 0x80) {
  369. case 0x00:
  370. endpoint->direction = UsbTransferDirection::OUTBOUND;
  371. break;
  372. case 0x80:
  373. endpoint->direction = UsbTransferDirection::INBOUND;
  374. break;
  375. }
  376. switch (attributes & 0x03) {
  377. case 0x00:
  378. endpoint->type = UsbTransferType::CONTROL;
  379. break;
  380. case 0x01:
  381. endpoint->type = UsbTransferType::ISOCHRONOUS;
  382. break;
  383. case 0x02:
  384. endpoint->type = UsbTransferType::BULK;
  385. break;
  386. case 0x03:
  387. endpoint->type = UsbTransferType::INTERRUPT;
  388. break;
  389. }
  390. switch (attributes & 0x0F) {
  391. // Isochronous endpoints only.
  392. case 0x05:
  393. endpoint->synchronization_type = UsbSynchronizationType::ASYNCHRONOUS;
  394. break;
  395. case 0x09:
  396. endpoint->synchronization_type = UsbSynchronizationType::ADAPTIVE;
  397. break;
  398. case 0x0D:
  399. endpoint->synchronization_type = UsbSynchronizationType::SYNCHRONOUS;
  400. break;
  401. default:
  402. endpoint->synchronization_type = UsbSynchronizationType::NONE;
  403. }
  404. switch (attributes & 0x33) {
  405. // Isochronous endpoint usages.
  406. case 0x01:
  407. endpoint->usage_type = UsbUsageType::DATA;
  408. break;
  409. case 0x11:
  410. endpoint->usage_type = UsbUsageType::FEEDBACK;
  411. break;
  412. case 0x21:
  413. endpoint->usage_type = UsbUsageType::EXPLICIT_FEEDBACK;
  414. break;
  415. // Interrupt endpoint usages.
  416. case 0x03:
  417. endpoint->usage_type = UsbUsageType::PERIODIC;
  418. break;
  419. case 0x13:
  420. endpoint->usage_type = UsbUsageType::NOTIFICATION;
  421. break;
  422. default:
  423. endpoint->usage_type = UsbUsageType::RESERVED;
  424. }
  425. endpoint->packet_size = static_cast<uint32_t>(maximum_packet_size);
  426. endpoint->polling_interval = polling_interval;
  427. return endpoint;
  428. }
  429. UsbInterfaceInfoPtr BuildUsbInterfaceInfoPtr(const uint8_t* data) {
  430. DCHECK_GE(data[0], kInterfaceDescriptorLength);
  431. DCHECK_EQ(data[1], kInterfaceDescriptorType);
  432. return BuildUsbInterfaceInfoPtr(
  433. data[2] /* bInterfaceNumber */, data[3] /* bAlternateSetting */,
  434. data[5] /* bInterfaceClass */, data[6] /* bInterfaceSubClass */,
  435. data[7] /* bInterfaceProtocol */);
  436. }
  437. UsbInterfaceInfoPtr BuildUsbInterfaceInfoPtr(uint8_t interface_number,
  438. uint8_t alternate_setting,
  439. uint8_t interface_class,
  440. uint8_t interface_subclass,
  441. uint8_t interface_protocol) {
  442. UsbInterfaceInfoPtr interface_info = mojom::UsbInterfaceInfo::New();
  443. interface_info->interface_number = interface_number;
  444. interface_info->first_interface = interface_number;
  445. UsbAlternateInterfaceInfoPtr alternate =
  446. mojom::UsbAlternateInterfaceInfo::New();
  447. alternate->alternate_setting = alternate_setting;
  448. alternate->class_code = interface_class;
  449. alternate->subclass_code = interface_subclass;
  450. alternate->protocol_code = interface_protocol;
  451. interface_info->alternates.push_back(std::move(alternate));
  452. return interface_info;
  453. }
  454. // Aggregate each alternate setting into an InterfaceInfo corresponding to its
  455. // interface number.
  456. void AggregateInterfacesForConfig(mojom::UsbConfigurationInfo* config) {
  457. std::map<uint8_t, device::mojom::UsbInterfaceInfo*> interface_map;
  458. std::vector<device::mojom::UsbInterfaceInfoPtr> interfaces =
  459. std::move(config->interfaces);
  460. config->interfaces.clear();
  461. for (size_t i = 0; i < interfaces.size(); ++i) {
  462. // As interfaces should appear in order, this map could be unnecessary,
  463. // but this errs on the side of caution.
  464. auto iter = interface_map.find(interfaces[i]->interface_number);
  465. if (iter == interface_map.end()) {
  466. // This is the first time we're seeing an alternate with this interface
  467. // number, so add a new InterfaceInfo to the array and map the number.
  468. config->interfaces.push_back(std::move(interfaces[i]));
  469. interface_map.insert(
  470. std::make_pair(config->interfaces.back()->interface_number,
  471. config->interfaces.back().get()));
  472. } else {
  473. DCHECK_EQ(1u, interfaces[i]->alternates.size());
  474. iter->second->alternates.push_back(
  475. std::move(interfaces[i]->alternates[0]));
  476. }
  477. }
  478. }
  479. CombinedInterfaceInfo FindInterfaceInfoFromConfig(
  480. const mojom::UsbConfigurationInfo* config,
  481. uint8_t interface_number,
  482. uint8_t alternate_setting) {
  483. CombinedInterfaceInfo interface_info;
  484. if (!config) {
  485. return interface_info;
  486. }
  487. for (const auto& iface : config->interfaces) {
  488. if (iface->interface_number == interface_number) {
  489. interface_info.interface = iface.get();
  490. for (const auto& alternate : iface->alternates) {
  491. if (alternate->alternate_setting == alternate_setting) {
  492. interface_info.alternate = alternate.get();
  493. break;
  494. }
  495. }
  496. }
  497. }
  498. return interface_info;
  499. }
  500. UsbConfigurationInfoPtr BuildUsbConfigurationInfoPtr(const uint8_t* data) {
  501. DCHECK_GE(data[0], kConfigurationDescriptorLength);
  502. DCHECK_EQ(data[1], kConfigurationDescriptorType);
  503. return BuildUsbConfigurationInfoPtr(data[5] /* bConfigurationValue */,
  504. (data[7] & 0x02) != 0 /* bmAttributes */,
  505. (data[7] & 0x04) != 0 /* bmAttributes */,
  506. data[8] /* bMaxPower */);
  507. }
  508. UsbConfigurationInfoPtr BuildUsbConfigurationInfoPtr(
  509. uint8_t configuration_value,
  510. bool self_powered,
  511. bool remote_wakeup,
  512. uint8_t maximum_power) {
  513. UsbConfigurationInfoPtr config = mojom::UsbConfigurationInfo::New();
  514. config->configuration_value = configuration_value;
  515. config->self_powered = self_powered;
  516. config->remote_wakeup = remote_wakeup;
  517. config->maximum_power = maximum_power;
  518. return config;
  519. }
  520. void AssignFirstInterfaceNumbers(mojom::UsbConfigurationInfo* config) {
  521. std::vector<UsbInterfaceAssociationDescriptor> functions;
  522. ParseInterfaceAssociationDescriptors(config->extra_data, &functions);
  523. for (const auto& interface : config->interfaces) {
  524. DCHECK_EQ(1u, interface->alternates.size());
  525. ParseInterfaceAssociationDescriptors(interface->alternates[0]->extra_data,
  526. &functions);
  527. for (auto& endpoint : interface->alternates[0]->endpoints)
  528. ParseInterfaceAssociationDescriptors(endpoint->extra_data, &functions);
  529. }
  530. // libusb has collected interface association descriptors in the |extra_data|
  531. // fields of other descriptor types. This may have disturbed their order
  532. // but sorting by the bFirstInterface should fix it.
  533. std::sort(functions.begin(), functions.end());
  534. uint8_t remaining_interfaces = 0;
  535. auto function_it = functions.cbegin();
  536. auto interface_it = config->interfaces.begin();
  537. while (interface_it != config->interfaces.end()) {
  538. if (remaining_interfaces > 0) {
  539. // Continuation of a previous function. Tag all alternate interfaces
  540. // (which are guaranteed to be contiguous).
  541. for (uint8_t interface_number = (*interface_it)->interface_number;
  542. interface_it != config->interfaces.end() &&
  543. (*interface_it)->interface_number == interface_number;
  544. ++interface_it) {
  545. (*interface_it)->first_interface = function_it->first_interface;
  546. }
  547. if (--remaining_interfaces == 0)
  548. ++function_it;
  549. } else if (function_it != functions.end() &&
  550. (*interface_it)->interface_number ==
  551. function_it->first_interface) {
  552. // Start of a new function.
  553. (*interface_it)->first_interface = function_it->first_interface;
  554. if (function_it->interface_count > 1)
  555. remaining_interfaces = function_it->interface_count - 1;
  556. else
  557. ++function_it;
  558. ++interface_it;
  559. } else {
  560. // Unassociated interfaces already have |first_interface| set to
  561. // |interface_number|.
  562. ++interface_it;
  563. }
  564. }
  565. }
  566. } // namespace device