usb_service_win.cc 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. // Copyright 2017 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_win.h"
  5. // windows.h must be included first.
  6. #include <windows.h>
  7. #define INITGUID
  8. #include <devpkey.h>
  9. #include <objbase.h>
  10. #include <setupapi.h>
  11. #include <stdint.h>
  12. #include <usbiodef.h>
  13. #include "base/bind.h"
  14. #include "base/containers/contains.h"
  15. #include "base/location.h"
  16. #include "base/memory/free_deleter.h"
  17. #include "base/memory/ptr_util.h"
  18. #include "base/scoped_generic.h"
  19. #include "base/strings/string_number_conversions.h"
  20. #include "base/strings/string_piece_forward.h"
  21. #include "base/strings/string_split.h"
  22. #include "base/strings/string_util.h"
  23. #include "base/strings/sys_string_conversions.h"
  24. #include "base/strings/utf_string_conversions.h"
  25. #include "base/threading/scoped_blocking_call.h"
  26. #include "base/threading/scoped_thread_priority.h"
  27. #include "base/threading/sequenced_task_runner_handle.h"
  28. #include "base/win/registry.h"
  29. #include "base/win/scoped_devinfo.h"
  30. #include "base/win/scoped_handle.h"
  31. #include "base/win/win_util.h"
  32. #include "components/device_event_log/device_event_log.h"
  33. #include "services/device/usb/usb_descriptors.h"
  34. #include "services/device/usb/usb_device_handle.h"
  35. #include "services/device/usb/webusb_descriptors.h"
  36. #include "third_party/re2/src/re2/re2.h"
  37. namespace device {
  38. namespace {
  39. bool IsCompositeDevice(const std::wstring& service_name) {
  40. // Windows built-in composite device driver
  41. return base::EqualsCaseInsensitiveASCII(service_name, L"usbccgp") ||
  42. // Samsung Mobile USB Composite device driver
  43. base::EqualsCaseInsensitiveASCII(service_name, L"dg_ssudbus");
  44. }
  45. std::ostream& operator<<(std::ostream& os, const DEVPROPKEY& value) {
  46. os << "{" << base::win::WStringFromGUID(value.fmtid) << ", " << value.pid
  47. << "}";
  48. return os;
  49. }
  50. absl::optional<uint32_t> GetDeviceUint32Property(HDEVINFO dev_info,
  51. SP_DEVINFO_DATA* dev_info_data,
  52. const DEVPROPKEY& property) {
  53. // SetupDiGetDeviceProperty() makes an RPC which may block.
  54. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  55. base::BlockingType::MAY_BLOCK);
  56. DEVPROPTYPE property_type;
  57. uint32_t buffer;
  58. if (!SetupDiGetDeviceProperty(
  59. dev_info, dev_info_data, &property, &property_type,
  60. reinterpret_cast<PBYTE>(&buffer), sizeof(buffer), nullptr, 0)) {
  61. USB_PLOG(ERROR) << "SetupDiGetDeviceProperty(" << property << ") failed";
  62. return absl::nullopt;
  63. }
  64. if (property_type != DEVPROP_TYPE_UINT32) {
  65. USB_LOG(ERROR) << "SetupDiGetDeviceProperty(" << property
  66. << ") returned unexpected type (" << property_type
  67. << " != " << DEVPROP_TYPE_UINT32 << ")";
  68. return absl::nullopt;
  69. }
  70. return buffer;
  71. }
  72. absl::optional<std::wstring> GetDeviceStringProperty(
  73. HDEVINFO dev_info,
  74. SP_DEVINFO_DATA* dev_info_data,
  75. const DEVPROPKEY& property) {
  76. // SetupDiGetDeviceProperty() makes an RPC which may block.
  77. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  78. base::BlockingType::MAY_BLOCK);
  79. DEVPROPTYPE property_type;
  80. DWORD required_size;
  81. if (SetupDiGetDeviceProperty(dev_info, dev_info_data, &property,
  82. &property_type, nullptr, 0, &required_size, 0)) {
  83. USB_LOG(ERROR) << "SetupDiGetDeviceProperty(" << property
  84. << ") unexpectedly succeeded";
  85. return absl::nullopt;
  86. }
  87. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  88. USB_PLOG(ERROR) << "SetupDiGetDeviceProperty(" << property << ") failed";
  89. return absl::nullopt;
  90. }
  91. if (property_type != DEVPROP_TYPE_STRING) {
  92. USB_LOG(ERROR) << "SetupDiGetDeviceProperty(" << property
  93. << ") returned unexpected type (" << property_type
  94. << " != " << DEVPROP_TYPE_STRING << ")";
  95. return absl::nullopt;
  96. }
  97. std::wstring buffer;
  98. if (!SetupDiGetDeviceProperty(
  99. dev_info, dev_info_data, &property, &property_type,
  100. reinterpret_cast<PBYTE>(base::WriteInto(&buffer, required_size)),
  101. required_size, nullptr, 0)) {
  102. USB_PLOG(ERROR) << "SetupDiGetDeviceProperty(" << property << ") failed";
  103. return absl::nullopt;
  104. }
  105. return buffer;
  106. }
  107. absl::optional<std::vector<std::wstring>> GetDeviceStringListProperty(
  108. HDEVINFO dev_info,
  109. SP_DEVINFO_DATA* dev_info_data,
  110. const DEVPROPKEY& property) {
  111. // SetupDiGetDeviceProperty() makes an RPC which may block.
  112. base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
  113. base::BlockingType::MAY_BLOCK);
  114. DEVPROPTYPE property_type;
  115. DWORD required_size;
  116. if (SetupDiGetDeviceProperty(dev_info, dev_info_data, &property,
  117. &property_type, nullptr, 0, &required_size, 0)) {
  118. USB_LOG(ERROR) << "SetupDiGetDeviceProperty(" << property
  119. << ") unexpectedly succeeded";
  120. return absl::nullopt;
  121. }
  122. if (GetLastError() == ERROR_NOT_FOUND) {
  123. // Simplify callers by returning empty list when the property isn't found.
  124. return std::vector<std::wstring>();
  125. }
  126. if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  127. USB_PLOG(ERROR) << "SetupDiGetDeviceProperty(" << property << ") failed";
  128. return absl::nullopt;
  129. }
  130. if (property_type != DEVPROP_TYPE_STRING_LIST) {
  131. USB_LOG(ERROR) << "SetupDiGetDeviceProperty(" << property
  132. << ") returned unexpected type (" << property_type
  133. << " != " << DEVPROP_TYPE_STRING_LIST << ")";
  134. return absl::nullopt;
  135. }
  136. std::wstring buffer;
  137. if (!SetupDiGetDeviceProperty(
  138. dev_info, dev_info_data, &property, &property_type,
  139. reinterpret_cast<PBYTE>(base::WriteInto(&buffer, required_size)),
  140. required_size, nullptr, 0)) {
  141. USB_PLOG(ERROR) << "SetupDiGetDeviceProperty(" << property << ") failed";
  142. return absl::nullopt;
  143. }
  144. // Windows string list properties use a NUL character as the delimiter.
  145. return base::SplitString(buffer, base::WStringPiece(L"\0", 1),
  146. base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  147. }
  148. std::wstring GetServiceName(HDEVINFO dev_info, SP_DEVINFO_DATA* dev_info_data) {
  149. absl::optional<std::wstring> property =
  150. GetDeviceStringProperty(dev_info, dev_info_data, DEVPKEY_Device_Service);
  151. if (!property.has_value())
  152. return std::wstring();
  153. // Windows pads this string with a variable number of NUL bytes for no
  154. // discernible reason.
  155. return std::wstring(base::TrimString(*property, base::WStringPiece(L"\0", 1),
  156. base::TRIM_TRAILING));
  157. }
  158. bool GetDeviceInterfaceDetails(HDEVINFO dev_info,
  159. SP_DEVICE_INTERFACE_DATA* device_interface_data,
  160. std::wstring* device_path,
  161. uint32_t* bus_number,
  162. uint32_t* port_number,
  163. std::wstring* instance_id,
  164. std::wstring* parent_instance_id,
  165. std::vector<std::wstring>* child_instance_ids,
  166. std::vector<std::wstring>* hardware_ids,
  167. std::wstring* service_name) {
  168. SP_DEVINFO_DATA dev_info_data = {};
  169. dev_info_data.cbSize = sizeof(dev_info_data);
  170. DWORD required_size = 0;
  171. std::unique_ptr<SP_DEVICE_INTERFACE_DETAIL_DATA, base::FreeDeleter>
  172. device_interface_detail_data;
  173. // Probing for the required size of the SP_DEVICE_INTERFACE_DETAIL_DATA
  174. // struct is only required if we are looking for the device path.
  175. // Otherwise all the necessary data can be queried from the SP_DEVINFO_DATA.
  176. if (device_path) {
  177. if (!SetupDiGetDeviceInterfaceDetail(dev_info, device_interface_data,
  178. /*DeviceInterfaceDetailData=*/nullptr,
  179. /*DeviceInterfaceDetailDataSize=*/0,
  180. &required_size,
  181. /*DeviceInfoData=*/nullptr) &&
  182. GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
  183. return false;
  184. }
  185. device_interface_detail_data.reset(
  186. static_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(malloc(required_size)));
  187. device_interface_detail_data->cbSize =
  188. sizeof(*device_interface_detail_data);
  189. }
  190. if (!SetupDiGetDeviceInterfaceDetail(
  191. dev_info, device_interface_data, device_interface_detail_data.get(),
  192. required_size, /*RequiredSize=*/nullptr, &dev_info_data) &&
  193. (device_path || GetLastError() != ERROR_INSUFFICIENT_BUFFER)) {
  194. USB_PLOG(ERROR) << "SetupDiGetDeviceInterfaceDetail";
  195. return false;
  196. }
  197. if (device_path)
  198. *device_path = std::wstring(device_interface_detail_data->DevicePath);
  199. if (bus_number) {
  200. auto result = GetDeviceUint32Property(dev_info, &dev_info_data,
  201. DEVPKEY_Device_BusNumber);
  202. if (!result.has_value())
  203. return false;
  204. *bus_number = result.value();
  205. }
  206. if (port_number) {
  207. auto result = GetDeviceUint32Property(dev_info, &dev_info_data,
  208. DEVPKEY_Device_Address);
  209. if (!result.has_value())
  210. return false;
  211. *port_number = result.value();
  212. }
  213. if (instance_id) {
  214. auto result = GetDeviceStringProperty(dev_info, &dev_info_data,
  215. DEVPKEY_Device_InstanceId);
  216. if (!result.has_value())
  217. return false;
  218. *instance_id = std::move(result.value());
  219. }
  220. if (parent_instance_id) {
  221. auto result = GetDeviceStringProperty(dev_info, &dev_info_data,
  222. DEVPKEY_Device_Parent);
  223. if (!result.has_value())
  224. return false;
  225. *parent_instance_id = std::move(result.value());
  226. }
  227. if (child_instance_ids) {
  228. auto result = GetDeviceStringListProperty(dev_info, &dev_info_data,
  229. DEVPKEY_Device_Children);
  230. if (!result.has_value())
  231. return false;
  232. *child_instance_ids = std::move(result.value());
  233. }
  234. if (hardware_ids) {
  235. auto result = GetDeviceStringListProperty(dev_info, &dev_info_data,
  236. DEVPKEY_Device_HardwareIds);
  237. if (!result.has_value())
  238. return false;
  239. *hardware_ids = std::move(result.value());
  240. }
  241. if (service_name) {
  242. *service_name = GetServiceName(dev_info, &dev_info_data);
  243. if (service_name->empty()) {
  244. return false;
  245. }
  246. }
  247. return true;
  248. }
  249. std::wstring GetDevicePath(const std::wstring& instance_id,
  250. const GUID& device_interface_guid) {
  251. base::win::ScopedDevInfo dev_info(
  252. SetupDiGetClassDevs(&device_interface_guid, instance_id.c_str(), 0,
  253. DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
  254. if (!dev_info.is_valid()) {
  255. USB_PLOG(ERROR) << "SetupDiGetClassDevs";
  256. return std::wstring();
  257. }
  258. SP_DEVICE_INTERFACE_DATA device_interface_data = {};
  259. device_interface_data.cbSize = sizeof(device_interface_data);
  260. if (!SetupDiEnumDeviceInterfaces(dev_info.get(), nullptr,
  261. &device_interface_guid, 0,
  262. &device_interface_data)) {
  263. USB_PLOG(ERROR) << "SetupDiEnumDeviceInterfaces";
  264. return std::wstring();
  265. }
  266. std::wstring device_path;
  267. if (!GetDeviceInterfaceDetails(
  268. dev_info.get(), &device_interface_data, &device_path,
  269. /*bus_number=*/nullptr, /*port_number=*/nullptr,
  270. /*instance_id=*/nullptr, /*parent_instance_id=*/nullptr,
  271. /*child_instance_ids=*/nullptr, /*hardware_ids=*/nullptr,
  272. /*service_name=*/nullptr)) {
  273. return std::wstring();
  274. }
  275. return device_path;
  276. }
  277. int GetInterfaceNumber(const std::wstring& instance_id,
  278. const std::vector<std::wstring>& hardware_ids) {
  279. // According to MSDN the instance IDs for the device nodes created by the
  280. // composite driver is in the form "USB\VID_vvvv&PID_dddd&MI_zz" where "zz"
  281. // is the interface number.
  282. //
  283. // https://docs.microsoft.com/en-us/windows-hardware/drivers/install/standard-usb-identifiers#multiple-interface-usb-devices
  284. RE2 pattern("MI_([0-9a-fA-F]{2})");
  285. std::string instance_id_ascii = base::WideToASCII(instance_id);
  286. std::string match;
  287. if (!RE2::PartialMatch(instance_id_ascii, pattern, &match)) {
  288. // Alternative composite drivers, such as the one used for Samsung devices,
  289. // don't use the standard format for the instance ID, but one of the
  290. // hardware IDs will still match the expected pattern.
  291. bool found = false;
  292. for (const std::wstring& hardware_id : hardware_ids) {
  293. std::string hardware_id_ascii = base::WideToASCII(hardware_id);
  294. if (RE2::PartialMatch(hardware_id_ascii, pattern, &match)) {
  295. found = true;
  296. break;
  297. }
  298. }
  299. if (!found)
  300. return -1;
  301. }
  302. int interface_number;
  303. if (!base::HexStringToInt(match, &interface_number))
  304. return -1;
  305. return interface_number;
  306. }
  307. UsbDeviceWin::FunctionInfo GetFunctionInfo(const std::wstring& instance_id) {
  308. UsbDeviceWin::FunctionInfo info;
  309. info.interface_number = -1;
  310. base::win::ScopedDevInfo dev_info(
  311. SetupDiCreateDeviceInfoList(nullptr, nullptr));
  312. if (!dev_info.is_valid()) {
  313. USB_PLOG(ERROR) << "SetupDiCreateDeviceInfoList";
  314. return info;
  315. }
  316. SP_DEVINFO_DATA dev_info_data = {};
  317. dev_info_data.cbSize = sizeof(dev_info_data);
  318. if (!SetupDiOpenDeviceInfo(dev_info.get(), instance_id.c_str(), nullptr, 0,
  319. &dev_info_data)) {
  320. USB_PLOG(ERROR) << "SetupDiOpenDeviceInfo";
  321. return info;
  322. }
  323. info.driver = GetServiceName(dev_info.get(), &dev_info_data);
  324. if (info.driver.empty()) {
  325. return info;
  326. }
  327. absl::optional<std::vector<std::wstring>> hardware_ids =
  328. GetDeviceStringListProperty(dev_info.get(), &dev_info_data,
  329. DEVPKEY_Device_HardwareIds);
  330. if (!hardware_ids.has_value()) {
  331. return info;
  332. }
  333. info.interface_number = GetInterfaceNumber(instance_id, *hardware_ids);
  334. if (info.interface_number == -1)
  335. return info;
  336. if (!base::EqualsCaseInsensitiveASCII(info.driver, L"winusb"))
  337. return info;
  338. // Boost priority while potentially loading Advapi32.dll on a background
  339. // thread for the registry functions used below.
  340. SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
  341. // There is no standard device interface GUID for USB functions and so we
  342. // must discover the set of GUIDs that have been set in the registry by
  343. // the INF file or Microsoft OS Compatibility descriptors before
  344. // SetupDiGetDeviceInterfaceDetail() can be used to get the device path.
  345. HKEY key = SetupDiOpenDevRegKey(dev_info.get(), &dev_info_data,
  346. DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ);
  347. if (key == INVALID_HANDLE_VALUE) {
  348. USB_PLOG(ERROR) << "Could not open device registry key";
  349. return info;
  350. }
  351. base::win::RegKey scoped_key(key);
  352. std::vector<std::wstring> device_interface_guids;
  353. LONG result =
  354. scoped_key.ReadValues(L"DeviceInterfaceGUIDs", &device_interface_guids);
  355. if (result != ERROR_SUCCESS) {
  356. USB_LOG(ERROR) << "Could not read device interface GUIDs: "
  357. << logging::SystemErrorCodeToString(result);
  358. return info;
  359. }
  360. for (const auto& guid_string : device_interface_guids) {
  361. // Boost priority while potentially loading Ole32.dll on a background
  362. // thread for CLSIDFromString().
  363. SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
  364. GUID guid;
  365. if (FAILED(CLSIDFromString(guid_string.c_str(), &guid))) {
  366. USB_LOG(ERROR) << "Failed to parse device interface GUID: "
  367. << guid_string;
  368. continue;
  369. }
  370. info.path = GetDevicePath(instance_id, guid);
  371. if (!info.path.empty())
  372. return info;
  373. }
  374. return info;
  375. }
  376. } // namespace
  377. class UsbServiceWin::BlockingTaskRunnerHelper {
  378. public:
  379. BlockingTaskRunnerHelper(
  380. base::WeakPtr<UsbServiceWin> service,
  381. scoped_refptr<base::SequencedTaskRunner> service_task_runner)
  382. : service_task_runner_(std::move(service_task_runner)),
  383. service_(std::move(service)) {
  384. // Boost priority while potentially loading SetupAPI.dll for the following
  385. // functions on a background thread.
  386. SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
  387. base::win::ScopedDevInfo dev_info(
  388. SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, nullptr, 0,
  389. DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
  390. if (!dev_info.is_valid()) {
  391. USB_PLOG(ERROR) << "Failed to set up device enumeration";
  392. service_task_runner_->PostTask(
  393. FROM_HERE, base::BindOnce(&UsbServiceWin::HelperStarted, service_));
  394. return;
  395. }
  396. SP_DEVICE_INTERFACE_DATA device_interface_data = {};
  397. device_interface_data.cbSize = sizeof(device_interface_data);
  398. for (DWORD i = 0; SetupDiEnumDeviceInterfaces(dev_info.get(), nullptr,
  399. &GUID_DEVINTERFACE_USB_DEVICE,
  400. i, &device_interface_data);
  401. ++i) {
  402. EnumerateDevice(dev_info.get(), &device_interface_data, absl::nullopt);
  403. }
  404. if (GetLastError() != ERROR_NO_MORE_ITEMS)
  405. USB_PLOG(ERROR) << "Failed to enumerate devices";
  406. service_task_runner_->PostTask(
  407. FROM_HERE, base::BindOnce(&UsbServiceWin::HelperStarted, service_));
  408. }
  409. ~BlockingTaskRunnerHelper() = default;
  410. void OnDeviceAdded(const GUID& guid, const std::wstring& device_path) {
  411. // Boost priority while potentially loading SetupAPI.dll and Ole32.dll on a
  412. // background thread for the following functions.
  413. SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
  414. base::win::ScopedDevInfo dev_info(SetupDiGetClassDevs(
  415. &guid, nullptr, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
  416. if (!dev_info.is_valid()) {
  417. USB_PLOG(ERROR) << "Failed to set up device enumeration";
  418. return;
  419. }
  420. SP_DEVICE_INTERFACE_DATA device_interface_data = {};
  421. device_interface_data.cbSize = sizeof(device_interface_data);
  422. if (!SetupDiOpenDeviceInterface(dev_info.get(), device_path.c_str(), 0,
  423. &device_interface_data)) {
  424. USB_PLOG(ERROR) << "Failed to add device interface: " << device_path;
  425. return;
  426. }
  427. if (IsEqualGUID(guid, GUID_DEVINTERFACE_USB_DEVICE)) {
  428. EnumerateDevice(dev_info.get(), &device_interface_data, device_path);
  429. } else {
  430. EnumeratePotentialFunction(dev_info.get(), &device_interface_data,
  431. device_path);
  432. }
  433. }
  434. private:
  435. void EnumerateDevice(HDEVINFO dev_info,
  436. SP_DEVICE_INTERFACE_DATA* device_interface_data,
  437. const absl::optional<std::wstring>& opt_device_path) {
  438. std::wstring device_path;
  439. std::wstring* device_path_ptr = &device_path;
  440. if (opt_device_path) {
  441. device_path = *opt_device_path;
  442. device_path_ptr = nullptr;
  443. }
  444. uint32_t bus_number;
  445. uint32_t port_number;
  446. std::wstring parent_instance_id;
  447. std::vector<std::wstring> child_instance_ids;
  448. std::wstring service_name;
  449. if (!GetDeviceInterfaceDetails(dev_info, device_interface_data,
  450. device_path_ptr, &bus_number, &port_number,
  451. /*instance_id=*/nullptr, &parent_instance_id,
  452. &child_instance_ids,
  453. /*hardware_ids=*/nullptr, &service_name)) {
  454. return;
  455. }
  456. auto driver_type = UsbDeviceWin::DriverType::kUnsupported;
  457. std::vector<std::pair<int, UsbDeviceWin::FunctionInfo>> functions;
  458. if (IsCompositeDevice(service_name)) {
  459. driver_type = UsbDeviceWin::DriverType::kComposite;
  460. // For composite devices Windows a composite device driver (usually the
  461. // built-in usbccgp.sys) creates child device nodes for each device
  462. // function. The device paths for these children must be opened in order
  463. // to communicate with the WinUSB driver.
  464. for (const std::wstring& instance_id : child_instance_ids) {
  465. UsbDeviceWin::FunctionInfo info = GetFunctionInfo(instance_id);
  466. if (info.interface_number != -1) {
  467. functions.emplace_back(info.interface_number, info);
  468. }
  469. }
  470. } else if (base::EqualsCaseInsensitiveASCII(service_name, L"winusb")) {
  471. driver_type = UsbDeviceWin::DriverType::kWinUSB;
  472. // A non-composite device has a single device node for all interfaces. It
  473. // may still include multiple functions but they will be ignored.
  474. UsbDeviceWin::FunctionInfo info;
  475. info.driver = service_name;
  476. info.path = device_path;
  477. functions.emplace_back(/*interface_number=*/0, info);
  478. }
  479. std::wstring& hub_path = hub_paths_[parent_instance_id];
  480. if (hub_path.empty()) {
  481. hub_path = GetDevicePath(parent_instance_id, GUID_DEVINTERFACE_USB_HUB);
  482. if (hub_path.empty())
  483. return;
  484. }
  485. service_task_runner_->PostTask(
  486. FROM_HERE, base::BindOnce(&UsbServiceWin::CreateDeviceObject, service_,
  487. std::move(device_path), std::move(hub_path),
  488. std::move(functions), bus_number, port_number,
  489. driver_type, service_name));
  490. }
  491. void EnumeratePotentialFunction(
  492. HDEVINFO dev_info,
  493. SP_DEVICE_INTERFACE_DATA* device_interface_data,
  494. const std::wstring& device_path) {
  495. std::wstring instance_id;
  496. std::wstring parent_instance_id;
  497. std::vector<std::wstring> hardware_ids;
  498. std::wstring service_name;
  499. if (!GetDeviceInterfaceDetails(
  500. dev_info, device_interface_data,
  501. /*device_path=*/nullptr, /*bus_number=*/nullptr,
  502. /*port_number=*/nullptr, &instance_id, &parent_instance_id,
  503. /*child_instance_ids=*/nullptr, &hardware_ids, &service_name)) {
  504. return;
  505. }
  506. int interface_number = GetInterfaceNumber(instance_id, hardware_ids);
  507. if (interface_number == -1)
  508. return;
  509. std::wstring parent_path =
  510. GetDevicePath(parent_instance_id, GUID_DEVINTERFACE_USB_DEVICE);
  511. if (parent_path.empty())
  512. return;
  513. UsbDeviceWin::FunctionInfo info;
  514. info.driver = service_name;
  515. info.path = device_path;
  516. service_task_runner_->PostTask(
  517. FROM_HERE,
  518. base::BindOnce(&UsbServiceWin::UpdateFunction, service_,
  519. std::move(parent_path), interface_number, info));
  520. }
  521. std::unordered_map<std::wstring, std::wstring> hub_paths_;
  522. // Calls back to |service_| must be posted to |service_task_runner_|, which
  523. // runs tasks on the thread where that object lives.
  524. scoped_refptr<base::SequencedTaskRunner> service_task_runner_;
  525. base::WeakPtr<UsbServiceWin> service_;
  526. };
  527. UsbServiceWin::UsbServiceWin()
  528. : blocking_task_runner_(CreateBlockingTaskRunner()) {
  529. DeviceMonitorWin* device_monitor = DeviceMonitorWin::GetForAllInterfaces();
  530. if (device_monitor)
  531. device_observation_.Observe(device_monitor);
  532. helper_ = base::SequenceBound<BlockingTaskRunnerHelper>(
  533. blocking_task_runner_, weak_factory_.GetWeakPtr(),
  534. base::SequencedTaskRunnerHandle::Get());
  535. }
  536. UsbServiceWin::~UsbServiceWin() {
  537. NotifyWillDestroyUsbService();
  538. }
  539. void UsbServiceWin::GetDevices(GetDevicesCallback callback) {
  540. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  541. if (enumeration_ready())
  542. UsbService::GetDevices(std::move(callback));
  543. else
  544. enumeration_callbacks_.push_back(std::move(callback));
  545. }
  546. void UsbServiceWin::OnDeviceAdded(const GUID& class_guid,
  547. const std::wstring& device_path) {
  548. helper_.AsyncCall(&BlockingTaskRunnerHelper::OnDeviceAdded)
  549. .WithArgs(class_guid, device_path);
  550. }
  551. void UsbServiceWin::OnDeviceRemoved(const GUID& class_guid,
  552. const std::wstring& device_path) {
  553. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  554. auto by_path_it = devices_by_path_.find(device_path);
  555. if (by_path_it == devices_by_path_.end())
  556. return;
  557. scoped_refptr<UsbDeviceWin> device = by_path_it->second;
  558. devices_by_path_.erase(by_path_it);
  559. device->OnDisconnect();
  560. auto by_guid_it = devices().find(device->guid());
  561. if (by_guid_it != devices().end() && enumeration_ready()) {
  562. USB_LOG(USER) << "USB device removed: path=" << device->device_path()
  563. << " guid=" << device->guid();
  564. devices().erase(by_guid_it);
  565. NotifyDeviceRemoved(device);
  566. }
  567. }
  568. void UsbServiceWin::HelperStarted() {
  569. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  570. helper_started_ = true;
  571. if (enumeration_ready()) {
  572. std::vector<scoped_refptr<UsbDevice>> result;
  573. result.reserve(devices().size());
  574. for (const auto& map_entry : devices())
  575. result.push_back(map_entry.second);
  576. for (auto& callback : enumeration_callbacks_)
  577. std::move(callback).Run(result);
  578. enumeration_callbacks_.clear();
  579. }
  580. }
  581. void UsbServiceWin::CreateDeviceObject(
  582. const std::wstring& device_path,
  583. const std::wstring& hub_path,
  584. const base::flat_map<int, UsbDeviceWin::FunctionInfo>& functions,
  585. uint32_t bus_number,
  586. uint32_t port_number,
  587. UsbDeviceWin::DriverType driver_type,
  588. const std::wstring& driver_name) {
  589. // Devices that appear during initial enumeration are gathered into the first
  590. // result returned by GetDevices() and prevent device add/remove notifications
  591. // from being sent.
  592. if (!enumeration_ready())
  593. ++first_enumeration_countdown_;
  594. auto device = base::MakeRefCounted<UsbDeviceWin>(
  595. device_path, hub_path, functions, bus_number, port_number, driver_type);
  596. devices_by_path_[device->device_path()] = device;
  597. device->ReadDescriptors(
  598. blocking_task_runner_,
  599. base::BindOnce(&UsbServiceWin::DeviceReady, weak_factory_.GetWeakPtr(),
  600. device, driver_name));
  601. }
  602. void UsbServiceWin::UpdateFunction(
  603. const std::wstring& device_path,
  604. int interface_number,
  605. const UsbDeviceWin::FunctionInfo& function_info) {
  606. auto it = devices_by_path_.find(device_path);
  607. if (it == devices_by_path_.end())
  608. return;
  609. const scoped_refptr<UsbDeviceWin>& device = it->second;
  610. USB_LOG(EVENT) << "USB device function updated: guid=" << device->guid()
  611. << ", interface_number=" << interface_number << ", path=\""
  612. << function_info.path << "\", driver=\""
  613. << function_info.driver << "\"";
  614. device->UpdateFunction(interface_number, function_info);
  615. }
  616. void UsbServiceWin::DeviceReady(scoped_refptr<UsbDeviceWin> device,
  617. const std::wstring& driver_name,
  618. bool success) {
  619. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  620. bool enumeration_became_ready = false;
  621. if (!enumeration_ready()) {
  622. DCHECK_GT(first_enumeration_countdown_, 0u);
  623. first_enumeration_countdown_--;
  624. if (enumeration_ready())
  625. enumeration_became_ready = true;
  626. }
  627. // If |device| was disconnected while descriptors were being read then it
  628. // will have been removed from |devices_by_path_|.
  629. auto it = devices_by_path_.find(device->device_path());
  630. if (it == devices_by_path_.end()) {
  631. success = false;
  632. } else if (success) {
  633. DCHECK(!base::Contains(devices(), device->guid()));
  634. devices()[device->guid()] = device;
  635. USB_LOG(USER) << "USB device added: path=" << device->device_path()
  636. << " vendor=" << device->vendor_id() << " \""
  637. << device->manufacturer_string()
  638. << "\", product=" << device->product_id() << " \""
  639. << device->product_string() << "\", serial=\""
  640. << device->serial_number() << "\", driver=\"" << driver_name
  641. << "\", guid=" << device->guid();
  642. } else {
  643. devices_by_path_.erase(it);
  644. }
  645. if (enumeration_became_ready) {
  646. std::vector<scoped_refptr<UsbDevice>> result;
  647. result.reserve(devices().size());
  648. for (const auto& map_entry : devices())
  649. result.push_back(map_entry.second);
  650. for (auto& callback : enumeration_callbacks_)
  651. std::move(callback).Run(result);
  652. enumeration_callbacks_.clear();
  653. } else if (success && enumeration_ready()) {
  654. NotifyDeviceAdded(device);
  655. }
  656. }
  657. } // namespace device