Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1471 lines
45 KiB

  1. /*******************************************************************************
  2. *
  3. * (C) COPYRIGHT MICROSOFT CORP., 1993-1995
  4. * TITLE: ITEMENUM.CPP
  5. * VERSION: 1.0
  6. * AUTHOR: jsenior
  7. * DATE: 10/28/1998
  8. *
  9. ********************************************************************************
  10. *
  11. * CHANGE LOG:
  12. *
  13. * DATE REV DESCRIPTION
  14. * ---------- ------- ----------------------------------------------------------
  15. * 10/28/1998 jsenior Original implementation.
  16. *
  17. *******************************************************************************/
  18. #define INITGUID
  19. #include "UsbItem.h"
  20. #include "debug.h"
  21. #include "resource.h"
  22. extern HINSTANCE gHInst;
  23. #define NUM_HCS_TO_CHECK 10
  24. UINT
  25. UsbItem::TotalTreeBandwidth()
  26. {
  27. UINT bw = 0;
  28. if (sibling) {
  29. bw += sibling->TotalTreeBandwidth();
  30. }
  31. if (child) {
  32. bw += child->TotalTreeBandwidth();
  33. }
  34. if (ComputeBandwidth()) {
  35. bw += bandwidth;
  36. }
  37. return bw;
  38. }
  39. DEVINST FindTopmostUSBDevInst(DEVINST DevInst)
  40. {
  41. TCHAR buf[512];
  42. CONFIGRET cr = CR_SUCCESS;
  43. DEVINST devInst, lastUsbDevInst;
  44. DWORD len = 0;
  45. if (!DevInst)
  46. return 0;
  47. devInst = lastUsbDevInst = DevInst;
  48. cr = CM_Get_Parent(&devInst,
  49. devInst,
  50. 0);
  51. while (cr == CR_SUCCESS) {
  52. len = sizeof(buf);
  53. cr = CM_Get_DevNode_Registry_Property(devInst,
  54. CM_DRP_CLASS,
  55. NULL,
  56. buf,
  57. &len,
  58. 0);
  59. if (cr == CR_SUCCESS) {
  60. if (_tcscmp(_T("USB"), buf) == 0)
  61. lastUsbDevInst = devInst;
  62. }
  63. cr = CM_Get_Parent(&devInst,
  64. devInst,
  65. 0);
  66. }
  67. return lastUsbDevInst;
  68. }
  69. //
  70. // Find all USB Host controllers in the system and enumerate them
  71. //
  72. BOOL
  73. UsbItem::EnumerateAll(UsbImageList* ClassImageList)
  74. {
  75. String HCName;
  76. WCHAR number[5];
  77. BOOL ControllerFound = FALSE;
  78. int HCNum;
  79. HANDLE hHCDev;
  80. UsbItem *usbItem = NULL;
  81. UsbItem *iter;
  82. #if 0
  83. HDEVINFO deviceInfo;
  84. SP_INTERFACE_DEVICE_DATA deviceInfoData;
  85. PSP_INTERFACE_DEVICE_DETAIL_DATA deviceDetailData;
  86. ULONG index;
  87. ULONG requiredLength;
  88. #endif
  89. //
  90. // Iterate over some Host Controller names and try to open them.
  91. // If successful in opening, create a new UsbItem and add it to the chain
  92. //
  93. for (HCNum = 0; HCNum < NUM_HCS_TO_CHECK; HCNum++)
  94. {
  95. HCName = L"\\\\.\\HCD";
  96. _itow(HCNum, number, 10);
  97. HCName += number;
  98. hHCDev = GetHandleForDevice(HCName);
  99. // If the handle is valid, then we've successfully opened a Host
  100. // Controller. Display some info about the Host Controller itself,
  101. // then enumerate the Root Hub attached to the Host Controller.
  102. //
  103. if (hHCDev != INVALID_HANDLE_VALUE)
  104. {
  105. ControllerFound = TRUE;
  106. CloseHandle(hHCDev);
  107. //
  108. // Create a new UsbItem for the found controller
  109. //
  110. usbItem = new UsbItem();
  111. if (!usbItem) {
  112. USBERROR((_T("Out of memory!\n")));
  113. return FALSE;
  114. }
  115. AddChunk(usbItem);
  116. //
  117. // Add this controller to the chain
  118. //
  119. if (!child) {
  120. child = usbItem;
  121. } else {
  122. for (iter = child; iter->sibling != NULL; iter = iter->sibling) { ; }
  123. iter->sibling = usbItem;
  124. }
  125. //
  126. // Enumerate the controller
  127. //
  128. usbItem->EnumerateController(this, HCName, ClassImageList, 0);
  129. }
  130. }
  131. #if 0
  132. // Now iterate over host controllers using the new GUID based interface
  133. //
  134. deviceInfo = SetupDiGetClassDevs((LPGUID)&GUID_CLASS_USB_HOST_CONTROLLER,
  135. NULL,
  136. NULL,
  137. (DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
  138. deviceInfoData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);
  139. for (index=0;
  140. SetupDiEnumDeviceInterfaces(deviceInfo,
  141. 0,
  142. (LPGUID)&GUID_CLASS_USB_HOST_CONTROLLER,
  143. index,
  144. &deviceInfoData);
  145. index++)
  146. {
  147. SetupDiGetInterfaceDeviceDetail(deviceInfo,
  148. &deviceInfoData,
  149. NULL,
  150. 0,
  151. &requiredLength,
  152. NULL);
  153. deviceDetailData = (PSP_INTERFACE_DEVICE_DETAIL_DATA) GlobalAlloc(GPTR, requiredLength);
  154. deviceDetailData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
  155. SetupDiGetInterfaceDeviceDetail(deviceInfo,
  156. &deviceInfoData,
  157. deviceDetailData,
  158. requiredLength,
  159. &requiredLength,
  160. NULL);
  161. hHCDev = GetHandleForDevice(deviceDetailData->DevicePath);
  162. // If the handle is valid, then we've successfully opened a Host
  163. // Controller. Display some info about the Host Controller itself,
  164. // then enumerate the Root Hub attached to the Host Controller.
  165. //
  166. if (hHCDev != INVALID_HANDLE_VALUE)
  167. {
  168. ControllerFound = TRUE;
  169. CloseHandle(hHCDev);
  170. //
  171. // Create a new UsbItem for the found controller
  172. //
  173. usbItem = new UsbItem();
  174. if (!usbItem) {
  175. USBERROR((_T("Out of memory!\n")));
  176. return FALSE;
  177. }
  178. AddChunk(usbItem);
  179. //
  180. // Add this controller to the chain
  181. //
  182. if (!child) {
  183. child = usbItem;
  184. } else {
  185. for (iter = child; iter->sibling != NULL; iter = iter->sibling) { ; }
  186. iter->sibling = usbItem;
  187. }
  188. //
  189. // Enumerate the controller
  190. //
  191. usbItem->EnumerateController(this, deviceDetailData->DevicePath, ClassImageList, 0);
  192. }
  193. GlobalFree(deviceDetailData);
  194. }
  195. SetupDiDestroyDeviceInfoList(deviceInfo);
  196. #endif
  197. return ControllerFound;
  198. }
  199. BOOL
  200. UsbItem::EnumerateController(UsbItem *Parent,
  201. const String &RootName,
  202. UsbImageList* ClassImageList,
  203. DEVINST DevInst)
  204. {
  205. CONFIGRET cr = CR_SUCCESS;
  206. HANDLE hController= INVALID_HANDLE_VALUE;
  207. String rootHubName, driverKeyName;
  208. UsbConfigInfo *hubConfigInfo = 0, *configInfo = 0;
  209. UsbDeviceInfo *hubDeviceInfo = 0;
  210. DWORD len = 0;
  211. TCHAR usbBuf[MAX_PATH];
  212. hController = GetHandleForDevice(RootName);
  213. //
  214. // If the handle is valid, then we've successfully opened a Host
  215. // Controller. Display some info about the Host Controller itself,
  216. // then enumerate the Root Hub attached to the Host Controller.
  217. //
  218. if (hController == INVALID_HANDLE_VALUE) {
  219. goto EnumerateWholeError;
  220. }
  221. driverKeyName = GetHCDDriverKeyName(hController);
  222. if (driverKeyName.empty()) {
  223. // the devinst really wasn't the controller
  224. goto EnumerateWholeError;
  225. }
  226. configInfo = new UsbConfigInfo();
  227. if (!configInfo) {
  228. USBERROR((_T("Out of memory!\n")));
  229. goto EnumerateWholeError;
  230. }
  231. AddChunk(configInfo);
  232. if (DevInst) {
  233. configInfo->devInst = DevInst;
  234. len = sizeof(usbBuf);
  235. if (CM_Get_DevNode_Registry_Property(DevInst,
  236. CM_DRP_CLASS,
  237. NULL,
  238. usbBuf,
  239. &len,
  240. 0) == CR_SUCCESS) {
  241. configInfo->deviceClass = usbBuf;
  242. }
  243. len = sizeof(usbBuf);
  244. if (CM_Get_DevNode_Registry_Property(DevInst,
  245. CM_DRP_DEVICEDESC,
  246. NULL,
  247. usbBuf,
  248. &len,
  249. 0) == CR_SUCCESS) {
  250. configInfo->deviceDesc = usbBuf;
  251. }
  252. else {
  253. LoadString(gHInst, IDS_UNKNOWNCONTROLLER, usbBuf, MAX_PATH);
  254. configInfo->deviceDesc = usbBuf;
  255. }
  256. }
  257. else {
  258. GetConfigMgrInfo(driverKeyName, configInfo);
  259. if (configInfo->deviceDesc.empty()) {
  260. LoadString(gHInst, IDS_UNKNOWNCONTROLLER, usbBuf, MAX_PATH);
  261. configInfo->deviceDesc = usbBuf;
  262. configInfo->deviceClass = TEXT("USB");
  263. }
  264. }
  265. //
  266. // No leaf info for host controllers, so parent is 0
  267. //
  268. if (AddLeaf(0,
  269. 0,
  270. UsbItem::UsbItemType::HCD,
  271. configInfo,
  272. ClassImageList)) {
  273. rootHubName = GetRootHubName(hController);
  274. if (!rootHubName.empty()) {
  275. EnumerateHub(rootHubName,
  276. ClassImageList,
  277. 0,
  278. this,
  279. UsbItem::UsbItemType::RootHub);
  280. }
  281. }
  282. CloseHandle(hController);
  283. return TRUE;
  284. EnumerateWholeError:
  285. if (hController != INVALID_HANDLE_VALUE) {
  286. CloseHandle(hController);
  287. }
  288. if (hubConfigInfo) {
  289. }
  290. return FALSE;
  291. }
  292. //
  293. // This form of EnumerateHub should only ever be called if enumerating directly
  294. // from this specific hub as the root. It should not be called from within
  295. // another enumeration call.
  296. //
  297. BOOL
  298. UsbItem::EnumerateHub(const String &HubName,
  299. UsbImageList* ClassImageList,
  300. DEVINST DevInst,
  301. UsbItem *Parent,
  302. UsbItem::UsbItemType itemType)
  303. {
  304. CONFIGRET cr = CR_SUCCESS;
  305. HANDLE hHub= INVALID_HANDLE_VALUE;
  306. UsbConfigInfo *configInfo = 0;
  307. DWORD len = 0;
  308. // TCHAR buf[MAX_PATH];
  309. UsbDeviceInfo *info = 0;
  310. TCHAR usbBuf[MAX_PATH];
  311. UsbItem *item;
  312. //
  313. // If the handle is valid, then we've successfully opened a Hub.
  314. // Display some info about the Hub itself, then enumerate the Hub.
  315. //
  316. if (INVALID_HANDLE_VALUE == (hHub = GetHandleForDevice(HubName)))
  317. {
  318. USBERROR((_T("Invalid handle returned for hub\n")));
  319. goto EnumerateHubError;
  320. }
  321. configInfo = new UsbConfigInfo();
  322. if (!configInfo) {
  323. USBERROR((_T("Out of memory!\n")));
  324. goto EnumerateHubError;
  325. }
  326. AddChunk(configInfo);
  327. configInfo->deviceClass = TEXT("USB");
  328. if (itemType == UsbItem::UsbItemType::RootHub) {
  329. configInfo->deviceDesc = TEXT("USB Root Hub");
  330. } else {
  331. configInfo->deviceDesc = TEXT("USB Hub");
  332. }
  333. if (DevInst) {
  334. configInfo->devInst = DevInst;
  335. len = sizeof(usbBuf);
  336. if (CM_Get_DevNode_Registry_Property(DevInst,
  337. CM_DRP_CLASS,
  338. NULL,
  339. usbBuf,
  340. &len,
  341. 0) == CR_SUCCESS) {
  342. configInfo->deviceClass = usbBuf;
  343. }
  344. len = sizeof(usbBuf);
  345. if (CM_Get_DevNode_Registry_Property(DevInst,
  346. CM_DRP_DEVICEDESC,
  347. NULL,
  348. usbBuf,
  349. &len,
  350. 0) == CR_SUCCESS) {
  351. configInfo->deviceDesc = usbBuf;
  352. }
  353. else {
  354. LoadString(gHInst, IDS_UNKNOWNHUB, usbBuf, MAX_PATH);
  355. configInfo->deviceDesc = usbBuf;
  356. }
  357. }
  358. info = new UsbDeviceInfo();
  359. if (!info) {
  360. USBERROR((_T("Out of memory!\n")));
  361. goto EnumerateHubError;
  362. }
  363. AddChunk(info);
  364. info->hubName = HubName;
  365. //
  366. // No leaf info for this hub, so parent is 0
  367. //
  368. if (NULL == (item = AddLeaf(Parent,
  369. info,
  370. itemType,
  371. configInfo, ClassImageList))) {
  372. goto EnumerateHubError;
  373. }
  374. if (item->GetHubInfo(hHub)) {
  375. item->EnumerateHubPorts(hHub,
  376. info->hubInfo.u.HubInformation.HubDescriptor.bNumberOfPorts,
  377. ClassImageList);
  378. }
  379. CloseHandle(hHub);
  380. return TRUE;
  381. EnumerateHubError:
  382. if (hHub != INVALID_HANDLE_VALUE) {
  383. CloseHandle(hHub);
  384. }
  385. if (info) {
  386. DeleteChunk(info);
  387. delete info;
  388. }
  389. if (configInfo) {
  390. DeleteChunk(configInfo);
  391. delete configInfo;
  392. }
  393. return FALSE;
  394. }
  395. BOOL
  396. UsbItem::GetPortAttributes(
  397. HANDLE HHubDevice,
  398. PUSB_NODE_CONNECTION_ATTRIBUTES connectionAttributes,
  399. ULONG index)
  400. {
  401. ULONG nBytes;
  402. //
  403. // Now query USBHUB for the USB_NODE_CONNECTION_INFORMATION structure
  404. // for this port. This will tell us if a device is attached to this
  405. // port, among other things.
  406. //
  407. nBytes = sizeof(USB_NODE_CONNECTION_ATTRIBUTES);
  408. ZeroMemory(connectionAttributes, nBytes);
  409. connectionAttributes->ConnectionIndex = index;
  410. if ( !DeviceIoControl(HHubDevice,
  411. IOCTL_USB_GET_NODE_CONNECTION_ATTRIBUTES,
  412. connectionAttributes,
  413. nBytes,
  414. connectionAttributes,
  415. nBytes,
  416. &nBytes,
  417. NULL)) {
  418. USBERROR((_T("Couldn't get connection attributes for hub port\n")));
  419. return FALSE;
  420. }
  421. return TRUE;
  422. }
  423. PUSB_NODE_CONNECTION_INFORMATION
  424. UsbItem::GetConnectionInformation(HANDLE HHubDevice,
  425. ULONG index)
  426. {
  427. PUSB_NODE_CONNECTION_INFORMATION connectionInfo = 0;
  428. USB_NODE_CONNECTION_INFORMATION connectionInfoStruct;
  429. ULONG nBytes;
  430. nBytes = sizeof(USB_NODE_CONNECTION_INFORMATION);
  431. ZeroMemory(&connectionInfoStruct, nBytes);
  432. connectionInfoStruct.ConnectionIndex = index;
  433. if ( !DeviceIoControl(HHubDevice,
  434. IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,
  435. &connectionInfoStruct,
  436. nBytes,
  437. &connectionInfoStruct,
  438. nBytes,
  439. &nBytes,
  440. NULL)) {
  441. return NULL;
  442. }
  443. //
  444. // Allocate space to hold the connection info for this port.
  445. // Should probably size this dynamically at some point.
  446. //
  447. nBytes = sizeof(USB_NODE_CONNECTION_INFORMATION) +
  448. connectionInfoStruct.NumberOfOpenPipes*sizeof(USB_PIPE_INFO);
  449. connectionInfo = (PUSB_NODE_CONNECTION_INFORMATION) LocalAlloc(LPTR, nBytes);
  450. if (!connectionInfo) {
  451. USBERROR((_T("Out of memory!\n")));
  452. return NULL;
  453. }
  454. //
  455. // Now query USBHUB for the USB_NODE_CONNECTION_INFORMATION structure
  456. // for this port. This will tell us if a device is attached to this
  457. // port, among other things.
  458. //
  459. connectionInfo->ConnectionIndex = index;
  460. if ( !DeviceIoControl(HHubDevice,
  461. IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,
  462. connectionInfo,
  463. nBytes,
  464. connectionInfo,
  465. nBytes,
  466. &nBytes,
  467. NULL)) {
  468. LocalFree(connectionInfo);
  469. USBERROR((_T("Couldn't get connection information for hub port\n")));
  470. return NULL;
  471. }
  472. return connectionInfo;
  473. }
  474. //*****************************************************************************
  475. //
  476. // EnumerateHubPorts()
  477. //
  478. // hTreeParent - Handle of the TreeView item under which the hub port should
  479. // be added.
  480. //
  481. // hHubDevice - Handle of the hub device to enumerate.
  482. //
  483. // NumPorts - Number of ports on the hub.
  484. //
  485. //*****************************************************************************
  486. void UsbItem::EnumerateHubPorts(HANDLE HHubDevice,
  487. ULONG NPorts,
  488. UsbImageList* ClassImageList)
  489. {
  490. UsbItem* item = 0;
  491. UsbDeviceInfo* info= 0;
  492. UsbConfigInfo* cfgInfo= 0;
  493. PUSB_NODE_CONNECTION_INFORMATION connectionInfo = 0;
  494. USB_NODE_CONNECTION_ATTRIBUTES cxnAttributes;
  495. String extHubName, driverKeyName;
  496. DWORD numDevices = 0;
  497. ULONG index;
  498. UsbItem::UsbItemType itemType;
  499. TCHAR buf[MAX_PATH];
  500. //
  501. // Loop over all ports of the hub. If a hub or device exists on the port,
  502. // add it to the tree. If it's a hub, recursively enumerate it. Add a leaf to
  503. // indicate the number of unused ports.
  504. // Port indices are 1 based, not 0 based.
  505. //
  506. for (index=1; index <= NPorts; index++) {
  507. if (!GetPortAttributes(HHubDevice, &cxnAttributes, index)) {
  508. USBWARN((_T("Couldn't get connection attribs for port %x!\n"),index));
  509. continue;
  510. }
  511. if (cxnAttributes.PortAttributes & USB_PORTATTR_NO_CONNECTOR) {
  512. USBWARN((_T("Detected port with no connector!\n")));
  513. continue;
  514. }
  515. if (NULL == (connectionInfo = GetConnectionInformation(HHubDevice, index))) {
  516. continue;
  517. }
  518. //
  519. // Allocate configuration information structure
  520. //
  521. cfgInfo = new UsbConfigInfo();
  522. if (!cfgInfo) {
  523. // leak.
  524. USBERROR((_T("Out of memory!\n")));
  525. break;
  526. }
  527. AddChunk(cfgInfo);
  528. //
  529. // If there is a device connected, get the Device Description
  530. //
  531. if (connectionInfo->ConnectionStatus != NoDeviceConnected) {
  532. numDevices++;
  533. //
  534. // Get config mgr info
  535. //
  536. driverKeyName = GetDriverKeyName(HHubDevice,index);
  537. if (!driverKeyName.empty()) {
  538. GetConfigMgrInfo(driverKeyName, cfgInfo);
  539. }
  540. if (connectionInfo->DeviceIsHub) {
  541. itemType = UsbItem::UsbItemType::Hub;
  542. if (cfgInfo->deviceDesc.empty()) {
  543. LoadString(gHInst, IDS_UNKNOWNHUB, buf, MAX_PATH);
  544. cfgInfo->deviceDesc = buf;
  545. }
  546. if (cfgInfo->deviceClass.empty()) {
  547. cfgInfo->deviceClass = TEXT("USB");
  548. }
  549. } else {
  550. itemType = UsbItem::UsbItemType::Device;
  551. if (cfgInfo->deviceDesc.empty()) {
  552. LoadString(gHInst, IDS_UNKNOWNDEVICE, buf, MAX_PATH);
  553. cfgInfo->deviceDesc = buf;
  554. }
  555. if (cfgInfo->deviceClass.empty()) {
  556. cfgInfo->deviceClass = TEXT("Unknown");
  557. }
  558. }
  559. //
  560. // Get device specific info
  561. //
  562. info = new UsbDeviceInfo();
  563. if (!info) {
  564. USBERROR((_T("Out of memory!\n")));
  565. break;
  566. }
  567. AddChunk(info);
  568. if (NULL != (info->configDescReq =
  569. GetConfigDescriptor(HHubDevice, index))) {
  570. info->configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(info->configDescReq+1);
  571. }
  572. info->connectionInfo = connectionInfo;
  573. //
  574. // Add the item into the tree
  575. //
  576. if (NULL != (item = UsbItem::AddLeaf(this,
  577. info,
  578. itemType,
  579. cfgInfo,
  580. ClassImageList))) {
  581. item->cxnAttributes = cxnAttributes;
  582. }
  583. if (connectionInfo->DeviceIsHub) {
  584. //
  585. // The device connected to the port is an external hub; get
  586. // the techie name of the hub and recursively enumerate it.
  587. //
  588. extHubName = GetExternalHubName(HHubDevice, index);
  589. if (!extHubName.empty()) {
  590. HANDLE hNewHub = INVALID_HANDLE_VALUE;
  591. info->hubName = extHubName;
  592. if (INVALID_HANDLE_VALUE != (hNewHub = GetHandleForDevice(extHubName))) {
  593. //
  594. // Recursively enumerate the ports of this hub.
  595. //
  596. if (item->GetHubInfo(hNewHub)) {
  597. item->EnumerateHubPorts(hNewHub,
  598. info->hubInfo.u.HubInformation.HubDescriptor.bNumberOfPorts,
  599. ClassImageList);
  600. }
  601. CloseHandle(hNewHub);
  602. }
  603. }
  604. }
  605. } else {
  606. LocalFree(connectionInfo);
  607. //
  608. // Empty port.
  609. //
  610. if (cxnAttributes.PortAttributes & USB_PORTATTR_OEM_CONNECTOR) {
  611. USBWARN((_T("Detected an OEM connector with nothing on it. Not reporting!\n"),index));
  612. DeleteChunk(cfgInfo);
  613. delete cfgInfo;
  614. } else {
  615. //
  616. // Add "Port n"
  617. //
  618. if (cxnAttributes.PortAttributes & USB_PORTATTR_MINI_CONNECTOR) {
  619. LoadString(gHInst, IDS_UNUSEDMINIPORT, buf, MAX_PATH);
  620. } else {
  621. LoadString(gHInst, IDS_UNUSEDPORT, buf, MAX_PATH);
  622. }
  623. cfgInfo->deviceDesc = buf;
  624. cfgInfo->deviceClass = TEXT("USB");
  625. if (NULL != (item = UsbItem::AddLeaf(this,
  626. NULL,
  627. UsbItem::UsbItemType::Empty,
  628. cfgInfo,
  629. ClassImageList
  630. ))) {
  631. item->UnusedPort = TRUE;
  632. item->cxnAttributes = cxnAttributes;
  633. }
  634. }
  635. }
  636. }
  637. //
  638. // Add the number of ports to the name of the hub
  639. //
  640. TCHAR szPorts[30];
  641. LoadString(gHInst, IDS_PORTS, szPorts, 30);
  642. wsprintf(buf, szPorts, NumPorts());
  643. configInfo->deviceDesc += buf;
  644. }
  645. BOOL
  646. UsbItem::GetHubInfo(HANDLE HHubDevice)
  647. {
  648. ULONG nBytes = 0;
  649. //
  650. // Query USBHUB for the USB_NODE_INFORMATION structure for this hub.
  651. // This will tell us the number of downstream ports to enumerate, among
  652. // other things.
  653. //
  654. if(!DeviceIoControl(HHubDevice,
  655. IOCTL_USB_GET_NODE_INFORMATION,
  656. &deviceInfo->hubInfo,
  657. sizeof(USB_NODE_INFORMATION),
  658. &deviceInfo->hubInfo,
  659. sizeof(USB_NODE_INFORMATION),
  660. &nBytes,
  661. NULL)) {
  662. return FALSE;
  663. }
  664. #ifdef HUB_CAPS
  665. nBytes = 0;
  666. if(!DeviceIoControl(HHubDevice,
  667. IOCTL_USB_GET_HUB_CAPABILITIES,
  668. &hubCaps,
  669. sizeof(USB_HUB_CAPABILITIES),
  670. &hubCaps,
  671. sizeof(USB_HUB_CAPABILITIES),
  672. &nBytes,
  673. NULL)) {
  674. return FALSE;
  675. }
  676. #endif
  677. return TRUE;
  678. }
  679. /*
  680. BOOL
  681. UsbItem::EnumerateDevice(DEVINST DevInst)
  682. {
  683. HANDLE hDevice;
  684. if (INVALID_HANDLE_VALUE == (hDevice = GetHandleForDevice(DevInst)))
  685. {
  686. return FALSE;
  687. }
  688. return TRUE;
  689. }
  690. */
  691. String UsbItem::GetHCDDriverKeyName(HANDLE HController)
  692. //*****************************************************************************
  693. //
  694. // Given a handle to a host controller,
  695. // return the Driver entry in its registry key.
  696. //
  697. //*****************************************************************************
  698. {
  699. BOOL success = FALSE;
  700. ULONG nBytes = 0;
  701. USB_HCD_DRIVERKEY_NAME driverKeyName;
  702. PUSB_HCD_DRIVERKEY_NAME driverKeyNameW = 0;
  703. String name;
  704. driverKeyNameW = NULL;
  705. // Get the length of the name of the driver key of the HCD
  706. //
  707. success = DeviceIoControl(HController,
  708. IOCTL_GET_HCD_DRIVERKEY_NAME,
  709. &driverKeyName,
  710. sizeof(driverKeyName),
  711. &driverKeyName,
  712. sizeof(driverKeyName),
  713. &nBytes,
  714. NULL);
  715. if (!success) {
  716. USBWARN((_T("Failed to get driver key name for controller.\n")));
  717. goto GetHCDDriverKeyNameError;
  718. }
  719. // Allocate space to hold the driver key name
  720. //
  721. nBytes = driverKeyName.ActualLength;
  722. if (nBytes <= sizeof(driverKeyName))
  723. {
  724. USBERROR((_T("Driver key name is wrong length\n")));
  725. goto GetHCDDriverKeyNameError;
  726. }
  727. driverKeyNameW = (PUSB_HCD_DRIVERKEY_NAME) LocalAlloc(LPTR, nBytes);
  728. if (!driverKeyNameW)
  729. {
  730. USBERROR((_T("Out of memory\n")));
  731. goto GetHCDDriverKeyNameError;
  732. }
  733. driverKeyNameW->ActualLength = nBytes;
  734. // Get the name of the driver key of the device attached to
  735. // the specified port.
  736. //
  737. success = DeviceIoControl(HController,
  738. IOCTL_GET_HCD_DRIVERKEY_NAME,
  739. driverKeyNameW,
  740. nBytes,
  741. driverKeyNameW,
  742. nBytes,
  743. &nBytes,
  744. NULL);
  745. if (!success)
  746. {
  747. USBWARN((_T("Failed to get driver key name for controller\n")));
  748. goto GetHCDDriverKeyNameError;
  749. }
  750. // Convert the driver key name
  751. //
  752. name = driverKeyNameW->DriverKeyName;
  753. // All done, free the uncoverted driver key name and return the
  754. // converted driver key name
  755. //
  756. LocalFree(driverKeyNameW);
  757. return name;
  758. GetHCDDriverKeyNameError:
  759. // There was an error, free anything that was allocated
  760. //
  761. if (driverKeyNameW)
  762. {
  763. LocalFree(driverKeyNameW);
  764. }
  765. return String();
  766. }
  767. String UsbItem::GetExternalHubName (HANDLE Hub, ULONG ConnectionIndex)
  768. {
  769. BOOL success = FALSE;
  770. ULONG nBytes = 0;
  771. USB_NODE_CONNECTION_NAME extHubName;
  772. PUSB_NODE_CONNECTION_NAME extHubNameW = 0;
  773. String name;
  774. extHubNameW = NULL;
  775. // Get the length of the name of the external hub attached to the
  776. // specified port.
  777. //
  778. extHubName.ConnectionIndex = ConnectionIndex;
  779. success = DeviceIoControl(Hub,
  780. IOCTL_USB_GET_NODE_CONNECTION_NAME,
  781. &extHubName,
  782. sizeof(extHubName),
  783. &extHubName,
  784. sizeof(extHubName),
  785. &nBytes,
  786. NULL);
  787. if (!success) {
  788. USBWARN((_T("Failed to retrieve external hub name\n")));
  789. goto GetExternalHubNameError;
  790. }
  791. // Allocate space to hold the external hub name
  792. //
  793. nBytes = extHubName.ActualLength;
  794. if (nBytes <= sizeof(extHubName)) {
  795. USBERROR((_T("Get node connection name returned invalid data size: %d\n"),
  796. nBytes));
  797. goto GetExternalHubNameError;
  798. }
  799. extHubNameW = (PUSB_NODE_CONNECTION_NAME) LocalAlloc(LPTR, nBytes);
  800. if (!extHubNameW) {
  801. USBERROR((_T("External hub name alloc failed.")));
  802. goto GetExternalHubNameError;
  803. }
  804. extHubNameW->ActualLength = nBytes;
  805. //
  806. // Get the name of the external hub attached to the specified port
  807. //
  808. extHubNameW->ConnectionIndex = ConnectionIndex;
  809. success = DeviceIoControl(Hub,
  810. IOCTL_USB_GET_NODE_CONNECTION_NAME,
  811. extHubNameW,
  812. nBytes,
  813. extHubNameW,
  814. nBytes,
  815. &nBytes,
  816. NULL);
  817. if (!success) {
  818. USBERROR((_T("Failed to get external hub name\n")));
  819. goto GetExternalHubNameError;
  820. }
  821. // Convert the External Hub name
  822. name = extHubNameW->NodeName;
  823. LocalFree(extHubNameW);
  824. // All done, free the uncoverted external hub name and return the
  825. // converted external hub name
  826. //
  827. return name;
  828. GetExternalHubNameError:
  829. // There was an error, free anything that was allocated
  830. //
  831. if (extHubNameW)
  832. {
  833. LocalFree(extHubNameW);
  834. }
  835. return String();
  836. }
  837. String GetDriverKeyName(HANDLE Hub, ULONG ConnectionIndex)
  838. {
  839. BOOL success = FALSE;
  840. ULONG nBytes = 0;
  841. USB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyName;
  842. PUSB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyNameW = 0;
  843. String name;
  844. driverKeyNameW = NULL;
  845. // Get the length of the name of the driver key of the device attached to
  846. // the specified port.
  847. //
  848. driverKeyName.ConnectionIndex = ConnectionIndex;
  849. success = DeviceIoControl(Hub,
  850. IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
  851. &driverKeyName,
  852. sizeof(driverKeyName),
  853. &driverKeyName,
  854. sizeof(driverKeyName),
  855. &nBytes,
  856. NULL);
  857. if (!success) {
  858. USBWARN((_T("Couldn't retrieve driver key name\n")));
  859. goto GetDriverKeyNameError;
  860. }
  861. // Allocate space to hold the driver key name
  862. //
  863. nBytes = driverKeyName.ActualLength;
  864. if (nBytes <= sizeof(driverKeyName))
  865. {
  866. USBERROR((_T("Driver key name wrong length\n")));
  867. goto GetDriverKeyNameError;
  868. }
  869. driverKeyNameW = (PUSB_NODE_CONNECTION_DRIVERKEY_NAME) LocalAlloc(LPTR, nBytes);
  870. if (!driverKeyNameW) {
  871. USBERROR((_T("Driver key name alloc failed.")));
  872. goto GetDriverKeyNameError;
  873. }
  874. driverKeyNameW->ActualLength = nBytes;
  875. // Get the name of the driver key of the device attached to
  876. // the specified port.
  877. //
  878. driverKeyNameW->ConnectionIndex = ConnectionIndex;
  879. success = DeviceIoControl(Hub,
  880. IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
  881. driverKeyNameW,
  882. nBytes,
  883. driverKeyNameW,
  884. nBytes,
  885. &nBytes,
  886. NULL);
  887. if (!success) {
  888. USBERROR((_T("Failed to get driver key name for port")));
  889. goto GetDriverKeyNameError;
  890. }
  891. // Convert the driver key name
  892. //
  893. name = driverKeyNameW->DriverKeyName;
  894. // All done, free the uncoverted driver key name and return the
  895. // converted driver key name
  896. //
  897. LocalFree(driverKeyNameW);
  898. return name;
  899. GetDriverKeyNameError:
  900. // There was an error, free anything that was allocated
  901. //
  902. if (driverKeyNameW)
  903. {
  904. LocalFree(driverKeyNameW);
  905. }
  906. return String();
  907. }
  908. void GetConfigMgrInfo(const String &DriverName, UsbConfigInfo *ConfigInfo)
  909. /*++
  910. Returns the Device Description of the DevNode with the matching DriverName.
  911. Returns NULL if the matching DevNode is not found.
  912. The caller should copy the returned string buffer instead of just saving
  913. the pointer value. Dynamically allocate the return buffer.
  914. --*/
  915. {
  916. DEVINST devInst;
  917. DEVINST devInstNext;
  918. CONFIGRET cr;
  919. BOOL walkDone = FALSE;
  920. ULONG len = 0;
  921. ULONG status = 0, problemNumber = 0;
  922. HKEY devKey;
  923. DWORD failID = 0;
  924. TCHAR buf[MAX_PATH];
  925. //
  926. // Get Root DevNode
  927. //
  928. cr = CM_Locate_DevNode(&devInst, NULL, 0);
  929. if (cr != CR_SUCCESS) {
  930. return;
  931. }
  932. //
  933. // Do a depth first search for the DevNode with a matching
  934. // DriverName value
  935. //
  936. while (!walkDone)
  937. {
  938. //
  939. // Get the DriverName value
  940. //
  941. len = sizeof(buf);
  942. cr = CM_Get_DevNode_Registry_Property(devInst,
  943. CM_DRP_DRIVER,
  944. NULL,
  945. buf,
  946. &len,
  947. 0);
  948. #ifndef WINNT
  949. WCHAR compareBuf[MAX_PATH];
  950. if (!MultiByteToWideChar(CP_ACP,
  951. MB_PRECOMPOSED,
  952. buf,
  953. -1,
  954. compareBuf,
  955. MAX_PATH)) {
  956. return;
  957. }
  958. if (cr == CR_SUCCESS && (DriverName == compareBuf)) {
  959. #else
  960. //
  961. // If the DriverName value matches, return the DeviceDescription
  962. //
  963. if (cr == CR_SUCCESS && (DriverName == buf)) {
  964. #endif
  965. //
  966. // Save the devnode
  967. //
  968. ConfigInfo->devInst = devInst;
  969. ConfigInfo->driverName = DriverName;
  970. //
  971. // Get the device description
  972. //
  973. TCHAR usbBuf[MAX_PATH];
  974. len = sizeof(usbBuf);
  975. cr = CM_Get_DevNode_Registry_Property(devInst,
  976. CM_DRP_DEVICEDESC,
  977. NULL,
  978. usbBuf,
  979. &len,
  980. 0);
  981. if (cr == CR_SUCCESS) {
  982. ConfigInfo->deviceDesc = usbBuf;
  983. }
  984. //
  985. // Get the device class
  986. //
  987. len = sizeof(buf);
  988. cr = CM_Get_DevNode_Registry_Property(devInst,
  989. CM_DRP_CLASS,
  990. NULL,
  991. buf,
  992. &len,
  993. 0);
  994. if (cr == CR_SUCCESS) {
  995. ConfigInfo->deviceClass = buf;
  996. }
  997. len = sizeof(buf);
  998. cr = CM_Get_DevNode_Registry_Property(devInst,
  999. CM_DRP_BUSTYPEGUID,
  1000. NULL,
  1001. buf,
  1002. &len,
  1003. 0);
  1004. if (cr == CR_SUCCESS) {
  1005. GUID guid = *((LPGUID) buf);
  1006. }
  1007. len = sizeof(buf);
  1008. cr = CM_Get_DevNode_Registry_Property(devInst,
  1009. CM_DRP_PHYSICAL_DEVICE_OBJECT_NAME,
  1010. NULL,
  1011. buf,
  1012. &len,
  1013. 0);
  1014. //
  1015. // Get the failed reason
  1016. //
  1017. ConfigInfo->usbFailure = 0;
  1018. if (CM_Open_DevNode_Key(devInst,
  1019. KEY_QUERY_VALUE,
  1020. CM_REGISTRY_HARDWARE,
  1021. RegDisposition_OpenExisting,
  1022. &devKey,
  1023. 0) == CR_SUCCESS) {
  1024. len = sizeof(DWORD);
  1025. if (RegQueryValueEx(devKey,
  1026. _T("FailReasonID"),
  1027. NULL,
  1028. NULL,
  1029. (LPBYTE) &failID,
  1030. &len) == ERROR_SUCCESS) {
  1031. ConfigInfo->usbFailure = failID;
  1032. }
  1033. RegCloseKey(devKey);
  1034. }
  1035. //
  1036. // Get the config manager status for this device
  1037. //
  1038. cr = CM_Get_DevNode_Status(&status,
  1039. &problemNumber,
  1040. devInst,
  1041. 0);
  1042. if (cr == CR_SUCCESS) {
  1043. ConfigInfo->status = status;
  1044. ConfigInfo->problemNumber = problemNumber;
  1045. }
  1046. return; // (Don't search the rest of the device tree)
  1047. }
  1048. //
  1049. // This DevNode didn't match, go down a level to the first child.
  1050. //
  1051. cr = CM_Get_Child(&devInstNext,
  1052. devInst,
  1053. 0);
  1054. if (cr == CR_SUCCESS)
  1055. {
  1056. devInst = devInstNext;
  1057. continue;
  1058. }
  1059. //
  1060. // Can't go down any further, go across to the next sibling. If
  1061. // there are no more siblings, go back up until there is a sibling.
  1062. // If we can't go up any further, we're back at the root and we're
  1063. // done.
  1064. //
  1065. for (;;)
  1066. {
  1067. cr = CM_Get_Sibling(&devInstNext,
  1068. devInst,
  1069. 0);
  1070. if (cr == CR_SUCCESS) {
  1071. devInst = devInstNext;
  1072. break;
  1073. }
  1074. cr = CM_Get_Parent(&devInstNext,
  1075. devInst,
  1076. 0);
  1077. if (cr == CR_SUCCESS) {
  1078. devInst = devInstNext;
  1079. }
  1080. else {
  1081. walkDone = TRUE;
  1082. break;
  1083. }
  1084. }
  1085. }
  1086. return;
  1087. }
  1088. String UsbItem::GetRootHubName(HANDLE HostController)
  1089. {
  1090. BOOL success = FALSE;
  1091. ULONG nBytes = 0;
  1092. USB_ROOT_HUB_NAME rootHubName;
  1093. PUSB_ROOT_HUB_NAME rootHubNameW = 0;
  1094. String name;
  1095. // Get the length of the name of the Root Hub attached to the
  1096. // Host Controller
  1097. //
  1098. success = DeviceIoControl(HostController,
  1099. IOCTL_USB_GET_ROOT_HUB_NAME,
  1100. 0,
  1101. 0,
  1102. &rootHubName,
  1103. sizeof(rootHubName),
  1104. &nBytes,
  1105. NULL);
  1106. if (!success) {
  1107. USBERROR((_T("Failed to get root hub name\n")));
  1108. goto GetRootHubNameError;
  1109. }
  1110. // Allocate space to hold the Root Hub name
  1111. //
  1112. nBytes = rootHubName.ActualLength;
  1113. // rootHubNameW = ALLOC(nBytes);
  1114. rootHubNameW = (PUSB_ROOT_HUB_NAME) LocalAlloc(LPTR, nBytes);
  1115. if (!rootHubNameW) {
  1116. USBERROR((_T("Root hub name alloc failed.")));
  1117. goto GetRootHubNameError;
  1118. }
  1119. rootHubNameW->ActualLength = nBytes;
  1120. // Get the name of the Root Hub attached to the Host Controller
  1121. //
  1122. success = DeviceIoControl(HostController,
  1123. IOCTL_USB_GET_ROOT_HUB_NAME,
  1124. NULL,
  1125. 0,
  1126. rootHubNameW,
  1127. nBytes,
  1128. &nBytes,
  1129. NULL);
  1130. if (!success) {
  1131. USBERROR((_T("Failed to get root hub name\n")));
  1132. goto GetRootHubNameError;
  1133. }
  1134. name = rootHubNameW->RootHubName;
  1135. LocalFree(rootHubNameW);
  1136. return name;
  1137. GetRootHubNameError:
  1138. // There was an error, free anything that was allocated
  1139. //
  1140. if (rootHubNameW != NULL)
  1141. {
  1142. LocalFree(rootHubNameW);
  1143. }
  1144. return String();
  1145. }
  1146. PUSB_DESCRIPTOR_REQUEST
  1147. UsbItem::GetConfigDescriptor(
  1148. HANDLE hHubDevice,
  1149. ULONG ConnectionIndex
  1150. )
  1151. {
  1152. BOOL success;
  1153. ULONG nBytes;
  1154. ULONG nBytesReturned;
  1155. PUSB_DESCRIPTOR_REQUEST configDescReq = 0;
  1156. nBytes = sizeof(USB_DESCRIPTOR_REQUEST) + sizeof(USB_CONFIGURATION_DESCRIPTOR);
  1157. configDescReq = (PUSB_DESCRIPTOR_REQUEST) LocalAlloc(LPTR, nBytes);
  1158. if (!configDescReq) {
  1159. USBERROR((_T("Out of memory!\n")));
  1160. return NULL;
  1161. }
  1162. // Indicate the port from which the descriptor will be requested
  1163. //
  1164. configDescReq->ConnectionIndex = ConnectionIndex;
  1165. //
  1166. // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this
  1167. // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request.
  1168. //
  1169. // USBD will automatically initialize these fields:
  1170. // bmRequest = 0x80
  1171. // bRequest = 0x06
  1172. //
  1173. // We must inititialize these fields:
  1174. // wValue = Descriptor Type (high) and Descriptor Index (low byte)
  1175. // wIndex = Zero (or Language ID for String Descriptors)
  1176. // wLength = Length of descriptor buffer
  1177. //
  1178. configDescReq->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8)
  1179. | 0;
  1180. configDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST));
  1181. // Now issue the get descriptor request.
  1182. //
  1183. success = DeviceIoControl(hHubDevice,
  1184. IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
  1185. configDescReq,
  1186. nBytes,
  1187. configDescReq,
  1188. nBytes,
  1189. &nBytesReturned,
  1190. NULL);
  1191. if (!success ||
  1192. nBytes != nBytesReturned) {
  1193. // OOPS();
  1194. LocalFree(configDescReq);
  1195. return NULL;
  1196. }
  1197. return configDescReq;
  1198. }
  1199. BOOL
  1200. SearchAndReplace(LPCWSTR FindThis,
  1201. LPCWSTR FindWithin,
  1202. LPCWSTR ReplaceWith,
  1203. String &NewString)
  1204. {
  1205. BOOL success = FALSE;
  1206. size_t i=0, j=0;
  1207. for (i=0; i < wcslen(FindWithin); i++ ) {
  1208. if (FindWithin[i] == *FindThis) {
  1209. //
  1210. // The first character matched. See if we got more.
  1211. //
  1212. for (j=0;
  1213. j < wcslen(FindThis) && j+i < wcslen(FindWithin);
  1214. j++ ) {
  1215. if (FindWithin[j+i] != FindThis[j]) {
  1216. // No match, get out
  1217. break;
  1218. }
  1219. }
  1220. if (j == wcslen(FindThis)) {
  1221. //
  1222. // Since j reached the end of the substring to find, we must
  1223. // have succeeded.
  1224. //
  1225. success = TRUE;
  1226. break;
  1227. }
  1228. }
  1229. }
  1230. if (success) {
  1231. //
  1232. // Replace the string with the new one. Copy the first part and then
  1233. // append the rest.
  1234. //
  1235. WCHAR temp[MAX_PATH];
  1236. wcsncpy(temp, FindWithin, i);
  1237. temp[i] = '\0';
  1238. NewString = temp;
  1239. String s1= ReplaceWith;
  1240. String s2 = (LPWSTR) &FindWithin[j+i];
  1241. NewString += s1;
  1242. NewString += s2; //(LPTSTR) ReplaceWith + (LPTSTR) &FindWithin[j+i-1];
  1243. }
  1244. return success;
  1245. }
  1246. HANDLE GetHandleForDevice(const String &DeviceName)
  1247. {
  1248. HANDLE hHCDev;
  1249. String realDeviceName;
  1250. //
  1251. // We have to replace \DosDevices\ and \??\ prefixes on device names with
  1252. // \\.\ because they don't work.
  1253. //
  1254. if (!SearchAndReplace (L"\\DosDevices\\",
  1255. DeviceName.c_str(),
  1256. L"\\\\.\\",
  1257. realDeviceName)) {
  1258. if (!SearchAndReplace (L"\\??\\",
  1259. DeviceName.c_str(),
  1260. L"\\\\.\\",
  1261. realDeviceName)) {
  1262. if (!SearchAndReplace (L"\\\\.\\",
  1263. DeviceName.c_str(),
  1264. L"\\\\.\\",
  1265. realDeviceName)) {
  1266. if (!SearchAndReplace (L"\\\\?\\",
  1267. DeviceName.c_str(),
  1268. L"\\\\.\\",
  1269. realDeviceName)) {
  1270. //
  1271. // It doesn't have anything on the front, put the "\\.\" there
  1272. //
  1273. realDeviceName = L"\\\\.\\";
  1274. realDeviceName += DeviceName;
  1275. }
  1276. }
  1277. }
  1278. }
  1279. hHCDev = UsbCreateFile(realDeviceName.c_str(),
  1280. GENERIC_WRITE,
  1281. FILE_SHARE_WRITE,
  1282. NULL,
  1283. OPEN_EXISTING,
  1284. 0,
  1285. NULL);
  1286. return hHCDev;
  1287. }