VirtualBox

source: vbox/trunk/src/VBox/HostDrivers/VBoxUSB/win/USBLib-win.cpp@ 34306

Last change on this file since 34306 was 34306, checked in by vboxsync, 14 years ago

USBLib-win: unused function

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 88.5 KB
Line 
1/* $Id: USBLib-win.cpp 34306 2010-11-24 08:00:20Z vboxsync $ */
2/** @file
3 * USBLIB - USB support library interface, Windows.
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*******************************************************************************
20* Header Files *
21*******************************************************************************/
22#define LOG_GROUP LOG_GROUP_DRV_USBPROXY
23#include <windows.h>
24
25#include <VBox/sup.h>
26#include <VBox/types.h>
27#include <VBox/err.h>
28#include <VBox/param.h>
29#include <iprt/path.h>
30#include <iprt/assert.h>
31#include <iprt/alloc.h>
32#include <iprt/string.h>
33#include <iprt/thread.h>
34#include <VBox/log.h>
35#include <VBox/usblib.h>
36#include <VBox/usb.h>
37#include "../USBLibInternal.h"
38#include <stdio.h>
39#pragma warning (disable:4200) /* shuts up the empty array member warnings */
40#include <setupapi.h>
41#include <usbdi.h>
42#include <hidsdi.h>
43
44
45/*******************************************************************************
46* Global Variables *
47*******************************************************************************/
48/** Flags whether or not we started the service. */
49static bool g_fStartedService = false;
50static char completeDeviceName[256] = ""; //generated from the GUID registered by the driver itself
51
52typedef struct
53{
54 char szName[512];
55 char szDriverRegName[512];
56} USBDEV, *PUSBDEV;
57
58static PUSBDEV g_pUSBDev = NULL;
59static uint32_t g_cMaxDevices = 0;
60static uint32_t g_cUSBStateChange = 0;
61
62static HANDLE g_hUSBMonitor = INVALID_HANDLE_VALUE;
63
64
65/*******************************************************************************
66* Defined Constants And Macros *
67*******************************************************************************/
68/** @def VBOX_WITH_ANNOYING_USB_ASSERTIONS
69 * Enable this to get assertions on various failures.
70 */
71//#define VBOX_WITH_ANNOYING_USB_ASSERTIONS
72#ifdef DOXYGEN_RUNNING
73# define VBOX_WITH_ANNOYING_USB_ASSERTIONS
74#endif
75
76/*******************************************************************************
77* Internal Functions *
78*******************************************************************************/
79
80bool ValidateUSBDevice(char *pszName)
81{
82 HANDLE hOut = INVALID_HANDLE_VALUE;
83
84 hOut = CreateFile(pszName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
85 OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL);
86
87 if (INVALID_HANDLE_VALUE == hOut)
88 {
89 Log(( "USB: FAILED to open %s\n", pszName));
90 goto failure;
91 }
92 else
93 {
94 /*
95 * Check the version
96 */
97 USBSUP_VERSION version = {0};
98 DWORD cbReturned = 0;
99
100 if (!DeviceIoControl(hOut, SUPUSB_IOCTL_GET_VERSION, NULL, 0,&version, sizeof(version), &cbReturned, NULL))
101 {
102 Log(("DeviceIoControl SUPUSB_IOCTL_GET_VERSION failed with LastError=%Rwa\n", GetLastError()));
103 goto failure;
104 }
105
106 if (version.u32Major != USBDRV_MAJOR_VERSION ||
107 version.u32Minor < USBDRV_MINOR_VERSION)
108 {
109 Log(("USB: Invalid version %d:%d vs %d:%d\n", version.u32Major, version.u32Minor, USBDRV_MAJOR_VERSION, USBDRV_MINOR_VERSION));
110 goto failure;
111 }
112 if (!DeviceIoControl(hOut, SUPUSB_IOCTL_IS_OPERATIONAL, NULL, 0, NULL, NULL, &cbReturned, NULL))
113 {
114 Log(("DeviceIoControl SUPUSB_IOCTL_IS_OPERATIONAL failed with LastError=%Rwa\n", GetLastError()));
115 goto failure;
116 }
117
118 }
119 CloseHandle(hOut);
120 return true;
121
122failure:
123 if (hOut != INVALID_HANDLE_VALUE)
124 CloseHandle(hOut);
125
126 return false;
127}
128
129bool OpenOneDevice (HDEVINFO HardwareDeviceInfo,
130 PSP_DEVICE_INTERFACE_DATA DeviceInfoData,
131 USBDEV *pUsbDev)
132{
133 PSP_DEVICE_INTERFACE_DETAIL_DATA functionClassDeviceData = NULL;
134 ULONG predictedLength = 0;
135 ULONG requiredLength = 0;
136 SP_DEVINFO_DATA devInfo;
137
138 //
139 // allocate a function class device data structure to receive the
140 // goods about this particular device.
141 //
142 SetupDiGetDeviceInterfaceDetail (
143 HardwareDeviceInfo,
144 DeviceInfoData,
145 NULL, // probing so no output buffer yet
146 0, // probing so output buffer length of zero
147 &requiredLength,
148 NULL); // not interested in the specific dev-node
149
150 predictedLength = requiredLength;
151
152 functionClassDeviceData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) RTMemAllocZ(predictedLength);
153 if (NULL == functionClassDeviceData)
154 {
155 return false;
156 }
157 functionClassDeviceData->cbSize = sizeof (SP_DEVICE_INTERFACE_DETAIL_DATA);
158
159 //
160 // Retrieve the information from Plug and Play.
161 //
162 devInfo.cbSize = sizeof(devInfo);
163 if (! SetupDiGetDeviceInterfaceDetail(HardwareDeviceInfo, DeviceInfoData,
164 functionClassDeviceData, predictedLength,
165 &requiredLength, &devInfo))
166 {
167 goto failure;
168 }
169
170 strcpy(pUsbDev->szName, functionClassDeviceData->DevicePath) ;
171 Log(( "USB: Attempting to open %s\n", pUsbDev->szName));
172
173 /* Query the registry path of the associated driver */
174 requiredLength = 0;
175 SetupDiGetDeviceRegistryProperty(HardwareDeviceInfo, &devInfo, SPDRP_DRIVER, NULL, NULL, 0, &requiredLength);
176 Assert(sizeof(pUsbDev->szDriverRegName) >= requiredLength);
177 if (requiredLength && sizeof(pUsbDev->szDriverRegName) >= requiredLength)
178 {
179 predictedLength = requiredLength;
180
181 if (!SetupDiGetDeviceRegistryProperty(HardwareDeviceInfo, &devInfo, SPDRP_DRIVER, NULL, (PBYTE)pUsbDev->szDriverRegName, predictedLength, &requiredLength))
182 goto failure;
183
184 Log(("USB: Driver name %s\n", pUsbDev->szDriverRegName));
185 }
186
187 bool rc = ValidateUSBDevice(functionClassDeviceData->DevicePath);
188 RTMemFree(functionClassDeviceData);
189
190 return rc;
191
192failure:
193 if (functionClassDeviceData)
194 RTMemFree(functionClassDeviceData);
195
196 return false;
197}
198
199bool OpenUsbDevices(LPGUID pGuid, uint32_t *pcNumDevices)
200{
201 HDEVINFO hardwareDeviceInfo;
202 SP_DEVICE_INTERFACE_DATA deviceInfoData;
203 USBDEV usbDev;
204
205 //
206 // Open a handle to the plug and play dev node.
207 // SetupDiGetClassDevs() returns a device information set that contains info on all
208 // installed devices of a specified class.
209 //
210 hardwareDeviceInfo = SetupDiGetClassDevs (
211 pGuid,
212 NULL, // Define no enumerator (global)
213 NULL, // Define no
214 (DIGCF_PRESENT | // Only Devices present
215 DIGCF_DEVICEINTERFACE)); // Function class devices.
216
217 deviceInfoData.cbSize = sizeof (SP_DEVICE_INTERFACE_DATA);
218
219 int j = 0, i = 0;
220
221 while (true)
222 {
223 // SetupDiEnumDeviceInterfaces() returns information about device interfaces
224 // exposed by one or more devices. Each call returns information about one interface;
225 // the routine can be called repeatedly to get information about several interfaces
226 // exposed by one or more devices.
227
228 Log(("OpenUsbDevices: SetupDiEnumDeviceInterfaces\n"));
229 if (SetupDiEnumDeviceInterfaces (hardwareDeviceInfo,
230 0, // We don't care about specific PDOs
231 pGuid,
232 i,
233 &deviceInfoData))
234 {
235 if (OpenOneDevice (hardwareDeviceInfo, &deviceInfoData, &usbDev) == true)
236 {
237 uint32_t z;
238 for (z = 0; z < g_cMaxDevices; z++)
239 {
240 if (g_pUSBDev[z].szName[0] == 0)
241 {
242 memcpy(&g_pUSBDev[z], &usbDev, sizeof(usbDev));
243 Log(("Captured device %s\n", g_pUSBDev[z].szName));
244 j++;
245 break;
246 }
247 }
248 AssertMsg(z < g_cMaxDevices, ("z=%d g_cMaxDevices=%d\n", z, g_cMaxDevices));
249 }
250 }
251 else
252 {
253 if (ERROR_NO_MORE_ITEMS == GetLastError())
254 {
255 Log(("OpenUsbDevices: No more items\n"));
256 break;
257 }
258 }
259 i++;
260 }
261
262 *pcNumDevices = j;
263
264 // SetupDiDestroyDeviceInfoList() destroys a device information set
265 // and frees all associated memory.
266
267 SetupDiDestroyDeviceInfoList (hardwareDeviceInfo);
268 return true;
269}
270
271/**
272 * Initialize the OS specific part of the library.
273 * On Win32 this involves:
274 * - registering the device driver
275 * - start device driver.
276 * - open driver.
277 *
278 * @returns VBox status code
279 */
280static int usblibEnumDevices(uint32_t cNumNewDevices, uint32_t *pcNumDevices)
281{
282 if (g_pUSBDev)
283 RTMemFree(g_pUSBDev);
284 g_pUSBDev = NULL;
285 g_cMaxDevices = 0;
286 *pcNumDevices = 0;
287
288 if (cNumNewDevices == 0)
289 return 0; /* nothing to do */
290
291 g_pUSBDev = (PUSBDEV)RTMemAllocZ(cNumNewDevices*sizeof(USBDEV));
292 if (!g_pUSBDev)
293 {
294 AssertFailed();
295 return VERR_NO_MEMORY;
296 }
297 g_cMaxDevices = cNumNewDevices;
298
299 if (OpenUsbDevices((LPGUID)&GUID_CLASS_VBOXUSB, pcNumDevices) == false)
300 {
301 AssertFailed();
302 return VERR_INTERNAL_ERROR;
303 }
304 AssertMsg(*pcNumDevices <= cNumNewDevices, ("cNumDevices = %d, cNumNewDevices = %d\n", *pcNumDevices, cNumNewDevices));
305 return VINF_SUCCESS;
306}
307
308/**
309 * Returns the nth USB device name
310 *
311 * @returns NULL on failure, otherwise the requested name
312 */
313char *usblibQueryDeviceName(uint32_t idxDev)
314{
315 int j=0;
316
317 Assert(idxDev < g_cMaxDevices);
318 for (uint32_t i=0; i<g_cMaxDevices; i++)
319 {
320 if (g_pUSBDev[i].szName[0])
321 {
322 if (j == idxDev)
323 return g_pUSBDev[i].szName;
324 j++;
325 }
326 }
327
328 Log(("USB: usblibQueryHandle returned -1; g_cMaxDevices = %d\n", g_cMaxDevices));
329 return NULL;
330}
331
332/**
333 * Returns the nth USB device registry path
334 *
335 * @returns NULL on failure, otherwise the requested name
336 */
337char *usblibQueryDeviceRegPath(uint32_t idxDev)
338{
339 int j=0;
340
341 Assert(idxDev < g_cMaxDevices);
342 for (uint32_t i=0; i<g_cMaxDevices; i++)
343 {
344 if (g_pUSBDev[i].szName[0])
345 {
346 if (j == idxDev)
347 return g_pUSBDev[i].szDriverRegName;
348 j++;
349 }
350 }
351
352 Log(("USB: usblibQueryHandle returned -1; g_cMaxDevices = %d\n", g_cMaxDevices));
353 return NULL;
354}
355
356/**
357 * Converts a supdrv error code to an nt status code.
358 *
359 * @returns corresponding SUPDRV_ERR_*.
360 * @param rc Win32 error code.
361 */
362static int suplibConvertWin32Err(int rc)
363{
364 /* Conversion program (link with ntdll.lib from ddk):
365 #define _WIN32_WINNT 0x0501
366 #include <windows.h>
367 #include <ntstatus.h>
368 #include <winternl.h>
369 #include <stdio.h>
370
371 int main()
372 {
373 #define CONVERT(a) printf(#a " %#x -> %d\n", a, RtlNtStatusToDosError((a)))
374 CONVERT(STATUS_SUCCESS);
375 CONVERT(STATUS_NOT_SUPPORTED);
376 CONVERT(STATUS_INVALID_PARAMETER);
377 CONVERT(STATUS_ACCESS_DENIED);
378 CONVERT(STATUS_INVALID_HANDLE);
379 CONVERT(STATUS_INVALID_ADDRESS);
380 CONVERT(STATUS_NOT_LOCKED);
381 CONVERT(STATUS_IMAGE_ALREADY_LOADED);
382 return 0;
383 }
384 */
385
386 switch (rc)
387 {
388 //case 0: return STATUS_SUCCESS;
389 case 0: return 0;
390 //case SUPDRV_ERR_GENERAL_FAILURE: return STATUS_NOT_SUPPORTED;
391 case ERROR_NOT_SUPPORTED: return VERR_GENERAL_FAILURE;
392 //case SUPDRV_ERR_INVALID_PARAM: return STATUS_INVALID_PARAMETER;
393 case ERROR_INVALID_PARAMETER: return VERR_INVALID_PARAMETER;
394 //case SUPDRV_ERR_INVALID_MAGIC: return STATUS_ACCESS_DENIED;
395 case ERROR_ACCESS_DENIED: return VERR_INVALID_MAGIC;
396 //case SUPDRV_ERR_INVALID_HANDLE: return STATUS_INVALID_HANDLE;
397 case ERROR_INVALID_HANDLE: return VERR_INVALID_HANDLE;
398 //case SUPDRV_ERR_INVALID_POINTER: return STATUS_INVALID_ADDRESS;
399 case ERROR_UNEXP_NET_ERR: return VERR_INVALID_POINTER;
400 //case SUPDRV_ERR_LOCK_FAILED: return STATUS_NOT_LOCKED;
401 case ERROR_NOT_LOCKED: return VERR_LOCK_FAILED;
402 //case SUPDRV_ERR_ALREADY_LOADED: return STATUS_IMAGE_ALREADY_LOADED;
403 case ERROR_SERVICE_ALREADY_RUNNING: return VERR_ALREADY_LOADED;
404 }
405
406 return VERR_GENERAL_FAILURE;
407}
408
409
410
411//*****************************************************************************
412// D E F I N E S
413//*****************************************************************************
414
415#define NUM_HCS_TO_CHECK 10
416
417#include <cfgmgr32.h>
418#include "usbdesc.h"
419//
420// Structure used to build a linked list of String Descriptors
421// retrieved from a device.
422//
423
424typedef struct _STRING_DESCRIPTOR_NODE
425{
426 struct _STRING_DESCRIPTOR_NODE *Next;
427 UCHAR DescriptorIndex;
428 USHORT LanguageID;
429 USB_STRING_DESCRIPTOR StringDescriptor[0];
430} STRING_DESCRIPTOR_NODE, *PSTRING_DESCRIPTOR_NODE;
431
432//
433// Structures associated with TreeView items through the lParam. When an item
434// is selected, the lParam is retrieved and the structure it which it points
435// is used to display information in the edit control.
436//
437
438typedef struct
439{
440 PUSB_NODE_INFORMATION HubInfo; // NULL if not a HUB
441
442 PCHAR HubName; // NULL if not a HUB
443
444 PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo; // NULL if root HUB
445
446 PUSB_DESCRIPTOR_REQUEST ConfigDesc; // NULL if root HUB
447
448 PSTRING_DESCRIPTOR_NODE StringDescs;
449
450} USBDEVICEINFO, *PUSBDEVICEINFO;
451
452//*****************************************************************************
453// L O C A L F U N C T I O N P R O T O T Y P E S
454//*****************************************************************************
455
456VOID
457EnumerateHub (
458 PCHAR HubName,
459 PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo,
460 PUSB_DESCRIPTOR_REQUEST ConfigDesc,
461 PSTRING_DESCRIPTOR_NODE StringDescs,
462 PCHAR DeviceDesc
463);
464
465VOID
466EnumerateHubPorts (
467 HANDLE hHubDevice,
468 ULONG NumPorts,
469 const char *pszHubName
470);
471
472PCHAR GetRootHubName (
473 HANDLE HostController
474);
475
476PCHAR GetExternalHubName (
477 HANDLE Hub,
478 ULONG ConnectionIndex
479);
480
481PCHAR GetHCDDriverKeyName (
482 HANDLE HCD
483);
484
485PCHAR GetDriverKeyName (
486 HANDLE Hub,
487 ULONG ConnectionIndex
488);
489
490PUSB_DESCRIPTOR_REQUEST
491GetConfigDescriptor (
492 HANDLE hHubDevice,
493 ULONG ConnectionIndex,
494 UCHAR DescriptorIndex
495);
496
497BOOL
498AreThereStringDescriptors (
499 PUSB_DEVICE_DESCRIPTOR DeviceDesc,
500 PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc
501);
502
503PSTRING_DESCRIPTOR_NODE
504GetAllStringDescriptors (
505 HANDLE hHubDevice,
506 ULONG ConnectionIndex,
507 PUSB_DEVICE_DESCRIPTOR DeviceDesc,
508 PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc
509);
510
511PSTRING_DESCRIPTOR_NODE
512GetStringDescriptor (
513 HANDLE hHubDevice,
514 ULONG ConnectionIndex,
515 UCHAR DescriptorIndex,
516 USHORT LanguageID
517);
518
519PSTRING_DESCRIPTOR_NODE
520GetStringDescriptors (
521 HANDLE hHubDevice,
522 ULONG ConnectionIndex,
523 UCHAR DescriptorIndex,
524 ULONG NumLanguageIDs,
525 USHORT *LanguageIDs,
526 PSTRING_DESCRIPTOR_NODE StringDescNodeTail
527);
528
529PCHAR DriverNameToDeviceDesc (PCHAR DriverName);
530
531//*****************************************************************************
532// G L O B A L S P R I V A T E T O T H I S F I L E
533//*****************************************************************************
534
535PCHAR ConnectionStatuses[] =
536{
537 "NoDeviceConnected",
538 "DeviceConnected",
539 "DeviceFailedEnumeration",
540 "DeviceGeneralFailure",
541 "DeviceCausedOvercurrent",
542 "DeviceNotEnoughPower"
543};
544
545static ULONG g_TotalDevicesConnected;
546static BOOL g_DoConfigDesc = TRUE;
547static int g_TotalHubs;
548static PUSBDEVICE *g_ppDeviceList = NULL;
549
550PCHAR ConnectionStatuses[];
551
552VOID AddLeaf(PUSBDEVICEINFO info, PCHAR pszLeafName, PCHAR pszDriverKeyName, const char *pszHubName, ULONG iHubPort)
553{
554 Log3(("usbproxy:AddLeaf: pszDriverKeyName=%s pszLeafName=%s pszHubName=%s iHubPort=%d\n", pszDriverKeyName, pszLeafName, pszHubName, iHubPort));
555 PUSBDEVICE pDevice = (PUSBDEVICE)RTMemAllocZ(sizeof(USBDEVICE));
556
557 if (pDevice)
558 {
559 Assert(info->ConnectionInfo);
560
561 if (info->ConnectionInfo)
562 {
563 PSTRING_DESCRIPTOR_NODE pStrDesc;
564 char **pString;
565
566 pDevice->bcdUSB = info->ConnectionInfo->DeviceDescriptor.bcdUSB;
567 pDevice->bDeviceClass = info->ConnectionInfo->DeviceDescriptor.bDeviceClass;
568 pDevice->bDeviceSubClass = info->ConnectionInfo->DeviceDescriptor.bDeviceSubClass;
569 pDevice->bDeviceProtocol = info->ConnectionInfo->DeviceDescriptor.bDeviceProtocol;
570 pDevice->idVendor = info->ConnectionInfo->DeviceDescriptor.idVendor;
571 pDevice->idProduct = info->ConnectionInfo->DeviceDescriptor.idProduct;
572 pDevice->bcdDevice = info->ConnectionInfo->DeviceDescriptor.bcdDevice;
573 pDevice->bBus = 0; /** @todo figure out bBus on windows... */
574 pDevice->bPort = iHubPort;
575 /** @todo check which devices are used for primary input (keyboard & mouse) */
576 if (!pszDriverKeyName || *pszDriverKeyName == 0)
577 pDevice->enmState = USBDEVICESTATE_UNUSED;
578 else
579 pDevice->enmState = USBDEVICESTATE_USED_BY_HOST_CAPTURABLE;
580 pDevice->enmSpeed = USBDEVICESPEED_UNKNOWN;
581
582 pDevice->pszAddress = RTStrDup(pszDriverKeyName);
583 pDevice->pszHubName = RTStrDup(pszHubName);
584 pDevice->bNumConfigurations = 0;
585 pDevice->u64SerialHash = 0;
586 pStrDesc = info->StringDescs;
587 while (pStrDesc)
588 {
589 pString = NULL;
590 if ( info->ConnectionInfo->DeviceDescriptor.iManufacturer
591 && pStrDesc->DescriptorIndex == info->ConnectionInfo->DeviceDescriptor.iManufacturer)
592 {
593 pString = (char **)&pDevice->pszManufacturer;
594 }
595 else
596 if ( info->ConnectionInfo->DeviceDescriptor.iProduct
597 && pStrDesc->DescriptorIndex == info->ConnectionInfo->DeviceDescriptor.iProduct)
598 {
599 pString = (char **)&pDevice->pszProduct;
600 }
601 else
602 if ( info->ConnectionInfo->DeviceDescriptor.iSerialNumber
603 && pStrDesc->DescriptorIndex == info->ConnectionInfo->DeviceDescriptor.iSerialNumber)
604 {
605 pString = (char **)&pDevice->pszSerialNumber;
606 }
607 if (pString)
608 {
609 char *pStringUTF8 = NULL;
610 RTUtf16ToUtf8((PCRTUTF16)&pStrDesc->StringDescriptor->bString[0], &pStringUTF8);
611 RTStrUtf8ToCurrentCP(pString, pStringUTF8);
612 RTStrFree(pStringUTF8);
613 if (pStrDesc->DescriptorIndex == info->ConnectionInfo->DeviceDescriptor.iSerialNumber)
614 {
615 pDevice->u64SerialHash = USBLibHashSerial(pDevice->pszSerialNumber);
616 }
617 }
618
619 pStrDesc = pStrDesc->Next;
620 }
621 if (*g_ppDeviceList == NULL)
622 {
623 pDevice->pNext = NULL;
624 *g_ppDeviceList = pDevice;
625 }
626 else
627 {
628 pDevice->pNext = *g_ppDeviceList;
629 *g_ppDeviceList = pDevice;
630 }
631 }
632 return;
633 }
634 AssertFailed();
635}
636
637//*****************************************************************************
638//
639// EnumerateHostController()
640//
641// hTreeParent - Handle of the TreeView item under which host controllers
642// should be added.
643//
644//*****************************************************************************
645
646VOID
647EnumerateHostController (
648 HANDLE hHCDev,
649 PCHAR leafName
650)
651{
652 PCHAR driverKeyName;
653 PCHAR deviceDesc;
654 PCHAR rootHubName;
655
656 driverKeyName = GetHCDDriverKeyName(hHCDev);
657
658 if (driverKeyName)
659 {
660 deviceDesc = DriverNameToDeviceDesc(driverKeyName);
661
662 if (deviceDesc)
663 {
664 leafName = deviceDesc;
665 }
666
667 RTMemFree(driverKeyName);
668 }
669
670 rootHubName = GetRootHubName(hHCDev);
671
672 if (rootHubName != NULL)
673 {
674 EnumerateHub(rootHubName,
675 NULL, // ConnectionInfo
676 NULL, // ConfigDesc
677 NULL, // StringDescs
678 "RootHub" // DeviceDesc
679 );
680 }
681}
682
683
684//*****************************************************************************
685//
686// EnumerateHostControllers()
687//
688// hTreeParent - Handle of the TreeView item under which host controllers
689// should be added.
690//
691//*****************************************************************************
692
693void usbLibEnumerateHostControllers(PUSBDEVICE *ppDevices, uint32_t *DevicesConnected)
694{
695 char HCName[16];
696 int HCNum;
697 HANDLE hHCDev;
698 PCHAR leafName;
699
700 g_TotalDevicesConnected = 0;
701 g_TotalHubs = 0;
702 g_ppDeviceList = ppDevices;
703
704 // Iterate over some Host Controller names and try to open them.
705 //
706 for (HCNum = 0; HCNum < NUM_HCS_TO_CHECK; HCNum++)
707 {
708 sprintf(HCName, "\\\\.\\HCD%d", HCNum);
709
710 hHCDev = CreateFile(HCName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
711
712 // If the handle is valid, then we've successfully opened a Host
713 // Controller. Display some info about the Host Controller itself,
714 // then enumerate the Root Hub attached to the Host Controller.
715 //
716 if (hHCDev != INVALID_HANDLE_VALUE)
717 {
718 leafName = HCName + sizeof("\\\\.\\") - sizeof("");
719
720 EnumerateHostController(hHCDev,
721 leafName);
722
723 CloseHandle(hHCDev);
724 }
725 }
726
727 g_ppDeviceList = NULL;
728 *DevicesConnected = g_TotalDevicesConnected - g_TotalHubs;
729}
730
731//*****************************************************************************
732//
733// EnumerateHub()
734//
735// hTreeParent - Handle of the TreeView item under which this hub should be
736// added.
737//
738// HubName - Name of this hub. This pointer is kept so the caller can neither
739// free nor reuse this memory.
740//
741// ConnectionInfo - NULL if this is a root hub, else this is the connection
742// info for an external hub. This pointer is kept so the caller can neither
743// free nor reuse this memory.
744//
745// ConfigDesc - NULL if this is a root hub, else this is the Configuration
746// Descriptor for an external hub. This pointer is kept so the caller can
747// neither free nor reuse this memory.
748//
749//*****************************************************************************
750
751VOID
752EnumerateHub (
753 PCHAR HubName,
754 PUSB_NODE_CONNECTION_INFORMATION_EX ConnectionInfo,
755 PUSB_DESCRIPTOR_REQUEST ConfigDesc,
756 PSTRING_DESCRIPTOR_NODE StringDescs,
757 PCHAR DeviceDesc
758)
759{
760 HANDLE hHubDevice;
761 PCHAR deviceName;
762 BOOL success;
763 ULONG nBytes;
764 PUSBDEVICEINFO info;
765 CHAR leafName[512]; // XXXXX how big does this have to be?
766
767 Log3(("usbproxy::EnumerateHub: HubName=%s\n", HubName));
768
769 // Initialize locals to not allocated state so the error cleanup routine
770 // only tries to cleanup things that were successfully allocated.
771 //
772 info = NULL;
773 hHubDevice = INVALID_HANDLE_VALUE;
774
775 // Allocate some space for a USBDEVICEINFO structure to hold the
776 // hub info, hub name, and connection info pointers. GPTR zero
777 // initializes the structure for us.
778 //
779 info = (PUSBDEVICEINFO) RTMemAllocZ(sizeof(USBDEVICEINFO));
780
781 if (info == NULL)
782 {
783 AssertFailed();
784 goto EnumerateHubError;
785 }
786
787 // Keep copies of the Hub Name, Connection Info, and Configuration
788 // Descriptor pointers
789 //
790 info->HubName = HubName;
791
792 info->ConnectionInfo = ConnectionInfo;
793
794 info->ConfigDesc = ConfigDesc;
795
796 info->StringDescs = StringDescs;
797
798
799 // Allocate some space for a USB_NODE_INFORMATION structure for this Hub,
800 //
801 info->HubInfo = (PUSB_NODE_INFORMATION)RTMemAllocZ(sizeof(USB_NODE_INFORMATION));
802
803 if (info->HubInfo == NULL)
804 {
805 AssertFailed();
806 goto EnumerateHubError;
807 }
808
809 // Allocate a temp buffer for the full hub device name.
810 //
811 deviceName = (PCHAR)RTMemAllocZ(strlen(HubName) + sizeof("\\\\.\\"));
812
813 if (deviceName == NULL)
814 {
815 AssertFailed();
816 goto EnumerateHubError;
817 }
818
819 // Create the full hub device name
820 //
821 strcpy(deviceName, "\\\\.\\");
822 strcpy(deviceName + sizeof("\\\\.\\") - 1, info->HubName);
823
824 // Try to hub the open device
825 //
826 hHubDevice = CreateFile(deviceName, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
827
828 // Done with temp buffer for full hub device name
829 //
830 RTMemFree(deviceName);
831
832 if (hHubDevice == INVALID_HANDLE_VALUE)
833 {
834 AssertFailed();
835 goto EnumerateHubError;
836 }
837
838 //
839 // Now query USBHUB for the USB_NODE_INFORMATION structure for this hub.
840 // This will tell us the number of downstream ports to enumerate, among
841 // other things.
842 //
843 success = DeviceIoControl(hHubDevice,
844 IOCTL_USB_GET_NODE_INFORMATION,
845 info->HubInfo,
846 sizeof(USB_NODE_INFORMATION),
847 info->HubInfo,
848 sizeof(USB_NODE_INFORMATION),
849 &nBytes,
850 NULL);
851
852 if (!success)
853 {
854 AssertFailed();
855 goto EnumerateHubError;
856 }
857
858 // Build the leaf name from the port number and the device description
859 //
860 if (ConnectionInfo)
861 {
862 sprintf(leafName, "[Port%d] ", ConnectionInfo->ConnectionIndex);
863 strcat(leafName, ConnectionStatuses[ConnectionInfo->ConnectionStatus]);
864 strcat(leafName, " : ");
865 }
866 else
867 {
868 leafName[0] = 0;
869 }
870
871 if (DeviceDesc)
872 {
873
874 strcat(leafName, DeviceDesc);
875 }
876 else
877 {
878 strcat(leafName, info->HubName);
879 }
880
881 // Now recursively enumerate the ports of this hub.
882 //
883 EnumerateHubPorts(
884 hHubDevice,
885 info->HubInfo->u.HubInformation.HubDescriptor.bNumberOfPorts,
886 HubName
887 );
888
889
890 CloseHandle(hHubDevice);
891 return;
892
893EnumerateHubError:
894 //
895 // Clean up any stuff that got allocated
896 //
897
898 if (hHubDevice != INVALID_HANDLE_VALUE)
899 {
900 CloseHandle(hHubDevice);
901 hHubDevice = INVALID_HANDLE_VALUE;
902 }
903
904 if (info != NULL)
905 {
906 if (info->HubName != NULL)
907 {
908 RTMemFree(info->HubName);
909 info->HubName = NULL;
910 }
911
912 if (info->HubInfo != NULL)
913 {
914 RTMemFree(info->HubInfo);
915 info->HubInfo;
916 }
917
918 RTMemFree(info);
919 info = NULL;
920 }
921
922 if (ConnectionInfo)
923 {
924 RTMemFree(ConnectionInfo);
925 }
926
927 if (ConfigDesc)
928 {
929 RTMemFree(ConfigDesc);
930 }
931
932 if (StringDescs != NULL)
933 {
934 PSTRING_DESCRIPTOR_NODE Next;
935
936 do {
937
938 Next = StringDescs->Next;
939 RTMemFree(StringDescs);
940 StringDescs = Next;
941
942 } while (StringDescs != NULL);
943 }
944}
945
946//*****************************************************************************
947//
948// EnumerateHubPorts()
949//
950// hTreeParent - Handle of the TreeView item under which the hub port should
951// be added.
952//
953// hHubDevice - Handle of the hub device to enumerate.
954//
955// NumPorts - Number of ports on the hub.
956//
957//*****************************************************************************
958
959VOID
960EnumerateHubPorts (
961 HANDLE hHubDevice,
962 ULONG NumPorts,
963 const char *pszHubName
964)
965{
966 ULONG index;
967 BOOL success;
968
969 PUSB_NODE_CONNECTION_INFORMATION_EX connectionInfo;
970 PUSB_DESCRIPTOR_REQUEST configDesc;
971 PSTRING_DESCRIPTOR_NODE stringDescs;
972 PUSBDEVICEINFO info;
973
974 PCHAR pszDriverKeyName;
975 PCHAR deviceDesc;
976 CHAR leafName[512]; // XXXXX how big does this have to be?
977 CHAR szDriverKeyName[512];
978
979
980 // Loop over all ports of the hub.
981 //
982 // Port indices are 1 based, not 0 based.
983 //
984 for (index = 1; index <= NumPorts; index++)
985 {
986 ULONG nBytes;
987
988 // Allocate space to hold the connection info for this port.
989 // For now, allocate it big enough to hold info for 30 pipes.
990 //
991 // Endpoint numbers are 0-15. Endpoint number 0 is the standard
992 // control endpoint which is not explicitly listed in the Configuration
993 // Descriptor. There can be an IN endpoint and an OUT endpoint at
994 // endpoint numbers 1-15 so there can be a maximum of 30 endpoints
995 // per device configuration.
996 //
997 // Should probably size this dynamically at some point.
998 //
999 nBytes = sizeof(USB_NODE_CONNECTION_INFORMATION_EX) +
1000 sizeof(USB_PIPE_INFO) * 30;
1001
1002 connectionInfo = (PUSB_NODE_CONNECTION_INFORMATION_EX)RTMemAllocZ(nBytes);
1003
1004 if (connectionInfo == NULL)
1005 {
1006 AssertFailed();
1007 break;
1008 }
1009
1010 //
1011 // Now query USBHUB for the USB_NODE_CONNECTION_INFORMATION_EX structure
1012 // for this port. This will tell us if a device is attached to this
1013 // port, among other things.
1014 //
1015 connectionInfo->ConnectionIndex = index;
1016
1017 success = DeviceIoControl(hHubDevice,
1018 IOCTL_USB_GET_NODE_CONNECTION_INFORMATION_EX,
1019 connectionInfo,
1020 nBytes,
1021 connectionInfo,
1022 nBytes,
1023 &nBytes,
1024 NULL);
1025
1026 if (!success)
1027 {
1028 RTMemFree(connectionInfo);
1029 continue;
1030 }
1031
1032 // Update the count of connected devices
1033 //
1034 if (connectionInfo->ConnectionStatus == DeviceConnected)
1035 g_TotalDevicesConnected++;
1036 else
1037 {
1038 RTMemFree(connectionInfo);
1039 continue;
1040 }
1041
1042 if (connectionInfo->DeviceIsHub)
1043 g_TotalHubs++;
1044
1045 // If there is a device connected, get the Device Description
1046 //
1047 deviceDesc = NULL;
1048 szDriverKeyName[0] = 0;
1049 if (connectionInfo->ConnectionStatus != NoDeviceConnected)
1050 {
1051 pszDriverKeyName = GetDriverKeyName(hHubDevice,
1052 index);
1053
1054 if (pszDriverKeyName)
1055 {
1056 Log(("Attached driver %s [port=%d]%s\n", pszDriverKeyName, index, connectionInfo->DeviceIsHub ? " DeviceIsHub" : ""));
1057 deviceDesc = DriverNameToDeviceDesc(pszDriverKeyName);
1058 Assert(strlen(pszDriverKeyName)+1 < sizeof(szDriverKeyName));
1059 if (strlen(pszDriverKeyName)+1 < sizeof(szDriverKeyName))
1060 strcpy(szDriverKeyName, pszDriverKeyName);
1061
1062 RTMemFree(pszDriverKeyName);
1063 }
1064 }
1065
1066 // If there is a device connected to the port, try to retrieve the
1067 // Configuration Descriptor from the device.
1068 //
1069 if (g_DoConfigDesc &&
1070 connectionInfo->ConnectionStatus == DeviceConnected)
1071 {
1072 configDesc = GetConfigDescriptor(hHubDevice,
1073 index,
1074 0);
1075 }
1076 else
1077 {
1078 configDesc = NULL;
1079 }
1080
1081 if (configDesc != NULL &&
1082 AreThereStringDescriptors(&connectionInfo->DeviceDescriptor,
1083 (PUSB_CONFIGURATION_DESCRIPTOR)(configDesc+1)))
1084 {
1085 stringDescs = GetAllStringDescriptors(
1086 hHubDevice,
1087 index,
1088 &connectionInfo->DeviceDescriptor,
1089 (PUSB_CONFIGURATION_DESCRIPTOR)(configDesc+1));
1090 }
1091 else
1092 {
1093 stringDescs = NULL;
1094 }
1095
1096 // If the device connected to the port is an external hub, get the
1097 // name of the external hub and recursively enumerate it.
1098 //
1099 if (connectionInfo->DeviceIsHub)
1100 {
1101 PCHAR extHubName;
1102
1103 extHubName = GetExternalHubName(hHubDevice,
1104 index);
1105
1106 if (extHubName != NULL)
1107 {
1108 EnumerateHub(extHubName,
1109 connectionInfo,
1110 configDesc,
1111 stringDescs,
1112 deviceDesc);
1113
1114 // On to the next port
1115 //
1116 continue;
1117 }
1118 }
1119
1120 // Allocate some space for a USBDEVICEINFO structure to hold the
1121 // hub info, hub name, and connection info pointers. GPTR zero
1122 // initializes the structure for us.
1123 //
1124 info = (PUSBDEVICEINFO) RTMemAllocZ(sizeof(USBDEVICEINFO));
1125
1126 if (info == NULL)
1127 {
1128 AssertFailed();
1129 if (configDesc != NULL)
1130 {
1131 RTMemFree(configDesc);
1132 }
1133 RTMemFree(connectionInfo);
1134 break;
1135 }
1136
1137 info->ConnectionInfo = connectionInfo;
1138
1139 info->ConfigDesc = configDesc;
1140
1141 info->StringDescs = stringDescs;
1142
1143 sprintf(leafName, "[Port%d] ", index);
1144
1145 strcat(leafName, ConnectionStatuses[connectionInfo->ConnectionStatus]);
1146
1147 if (deviceDesc)
1148 {
1149 strcat(leafName, " : ");
1150 strcat(leafName, deviceDesc);
1151 }
1152
1153 AddLeaf(info, leafName, szDriverKeyName, pszHubName, index);
1154 }
1155}
1156
1157
1158//*****************************************************************************
1159//
1160// WideStrToMultiStr()
1161//
1162//*****************************************************************************
1163
1164PCHAR WideStrToMultiStr (PWCHAR WideStr)
1165{
1166 ULONG nBytes;
1167 PCHAR MultiStr;
1168
1169 // Get the length of the converted string
1170 //
1171 nBytes = WideCharToMultiByte(
1172 CP_ACP,
1173 0,
1174 WideStr,
1175 -1,
1176 NULL,
1177 0,
1178 NULL,
1179 NULL);
1180
1181 if (nBytes == 0)
1182 {
1183 return NULL;
1184 }
1185
1186 // Allocate space to hold the converted string
1187 //
1188 MultiStr = (PCHAR)RTMemAllocZ(nBytes);
1189
1190 if (MultiStr == NULL)
1191 {
1192 return NULL;
1193 }
1194
1195 // Convert the string
1196 //
1197 nBytes = WideCharToMultiByte(
1198 CP_ACP,
1199 0,
1200 WideStr,
1201 -1,
1202 MultiStr,
1203 nBytes,
1204 NULL,
1205 NULL);
1206
1207 if (nBytes == 0)
1208 {
1209 RTMemFree(MultiStr);
1210 return NULL;
1211 }
1212
1213 return MultiStr;
1214}
1215
1216
1217//*****************************************************************************
1218//
1219// GetRootHubName()
1220//
1221//*****************************************************************************
1222
1223PCHAR GetRootHubName (
1224 HANDLE HostController
1225)
1226{
1227 BOOL success;
1228 ULONG nBytes;
1229 USB_ROOT_HUB_NAME rootHubName;
1230 PUSB_ROOT_HUB_NAME rootHubNameW;
1231 PCHAR rootHubNameA;
1232
1233 rootHubNameW = NULL;
1234 rootHubNameA = NULL;
1235
1236 // Get the length of the name of the Root Hub attached to the
1237 // Host Controller
1238 //
1239 success = DeviceIoControl(HostController,
1240 IOCTL_USB_GET_ROOT_HUB_NAME,
1241 0,
1242 0,
1243 &rootHubName,
1244 sizeof(rootHubName),
1245 &nBytes,
1246 NULL);
1247
1248 if (!success)
1249 {
1250 AssertFailed();
1251 goto GetRootHubNameError;
1252 }
1253
1254 // Allocate space to hold the Root Hub name
1255 //
1256 nBytes = rootHubName.ActualLength;
1257
1258 rootHubNameW = (PUSB_ROOT_HUB_NAME)RTMemAllocZ(nBytes);
1259
1260 if (rootHubNameW == NULL)
1261 {
1262 AssertFailed();
1263 goto GetRootHubNameError;
1264 }
1265
1266 // Get the name of the Root Hub attached to the Host Controller
1267 //
1268 success = DeviceIoControl(HostController,
1269 IOCTL_USB_GET_ROOT_HUB_NAME,
1270 NULL,
1271 0,
1272 rootHubNameW,
1273 nBytes,
1274 &nBytes,
1275 NULL);
1276
1277 if (!success)
1278 {
1279 AssertFailed();
1280 goto GetRootHubNameError;
1281 }
1282
1283 // Convert the Root Hub name
1284 //
1285 rootHubNameA = WideStrToMultiStr(rootHubNameW->RootHubName);
1286
1287 // All done, free the uncoverted Root Hub name and return the
1288 // converted Root Hub name
1289 //
1290 RTMemFree(rootHubNameW);
1291
1292 return rootHubNameA;
1293
1294
1295GetRootHubNameError:
1296 // There was an error, free anything that was allocated
1297 //
1298 if (rootHubNameW != NULL)
1299 {
1300 RTMemFree(rootHubNameW);
1301 rootHubNameW = NULL;
1302 }
1303
1304 return NULL;
1305}
1306
1307
1308//*****************************************************************************
1309//
1310// GetExternalHubName()
1311//
1312//*****************************************************************************
1313
1314PCHAR GetExternalHubName (
1315 HANDLE Hub,
1316 ULONG ConnectionIndex
1317)
1318{
1319 BOOL success;
1320 ULONG nBytes;
1321 USB_NODE_CONNECTION_NAME extHubName;
1322 PUSB_NODE_CONNECTION_NAME extHubNameW;
1323 PCHAR extHubNameA;
1324
1325 extHubNameW = NULL;
1326 extHubNameA = NULL;
1327
1328 // Get the length of the name of the external hub attached to the
1329 // specified port.
1330 //
1331 extHubName.ConnectionIndex = ConnectionIndex;
1332
1333 success = DeviceIoControl(Hub,
1334 IOCTL_USB_GET_NODE_CONNECTION_NAME,
1335 &extHubName,
1336 sizeof(extHubName),
1337 &extHubName,
1338 sizeof(extHubName),
1339 &nBytes,
1340 NULL);
1341
1342 if (!success)
1343 {
1344 AssertFailed();
1345 goto GetExternalHubNameError;
1346 }
1347
1348 // Allocate space to hold the external hub name
1349 //
1350 nBytes = extHubName.ActualLength;
1351
1352 if (nBytes <= sizeof(extHubName))
1353 {
1354 AssertFailed();
1355 goto GetExternalHubNameError;
1356 }
1357
1358 extHubNameW = (PUSB_NODE_CONNECTION_NAME)RTMemAllocZ(nBytes);
1359
1360 if (extHubNameW == NULL)
1361 {
1362 AssertFailed();
1363 goto GetExternalHubNameError;
1364 }
1365
1366 // Get the name of the external hub attached to the specified port
1367 //
1368 extHubNameW->ConnectionIndex = ConnectionIndex;
1369
1370 success = DeviceIoControl(Hub,
1371 IOCTL_USB_GET_NODE_CONNECTION_NAME,
1372 extHubNameW,
1373 nBytes,
1374 extHubNameW,
1375 nBytes,
1376 &nBytes,
1377 NULL);
1378
1379 if (!success)
1380 {
1381 AssertFailed();
1382 goto GetExternalHubNameError;
1383 }
1384
1385 // Convert the External Hub name
1386 //
1387 extHubNameA = WideStrToMultiStr(extHubNameW->NodeName);
1388
1389 // All done, free the uncoverted external hub name and return the
1390 // converted external hub name
1391 //
1392 RTMemFree(extHubNameW);
1393
1394 return extHubNameA;
1395
1396
1397GetExternalHubNameError:
1398 // There was an error, free anything that was allocated
1399 //
1400 if (extHubNameW != NULL)
1401 {
1402 RTMemFree(extHubNameW);
1403 extHubNameW = NULL;
1404 }
1405
1406 return NULL;
1407}
1408
1409
1410//*****************************************************************************
1411//
1412// GetDriverKeyName()
1413//
1414//*****************************************************************************
1415
1416PCHAR GetDriverKeyName (
1417 HANDLE Hub,
1418 ULONG ConnectionIndex
1419)
1420{
1421 BOOL success;
1422 ULONG nBytes;
1423 USB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyName;
1424 PUSB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyNameW;
1425 PCHAR driverKeyNameA;
1426
1427 driverKeyNameW = NULL;
1428 driverKeyNameA = NULL;
1429
1430 // Get the length of the name of the driver key of the device attached to
1431 // the specified port.
1432 //
1433 driverKeyName.ConnectionIndex = ConnectionIndex;
1434
1435 success = DeviceIoControl(Hub,
1436 IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
1437 &driverKeyName,
1438 sizeof(driverKeyName),
1439 &driverKeyName,
1440 sizeof(driverKeyName),
1441 &nBytes,
1442 NULL);
1443
1444 if (!success)
1445 {
1446 goto GetDriverKeyNameError;
1447 }
1448
1449 // Allocate space to hold the driver key name
1450 //
1451 nBytes = driverKeyName.ActualLength;
1452
1453 if (nBytes <= sizeof(driverKeyName))
1454 {
1455 AssertFailed();
1456 goto GetDriverKeyNameError;
1457 }
1458
1459 driverKeyNameW = (PUSB_NODE_CONNECTION_DRIVERKEY_NAME)RTMemAllocZ(nBytes);
1460
1461 if (driverKeyNameW == NULL)
1462 {
1463 AssertFailed();
1464 goto GetDriverKeyNameError;
1465 }
1466
1467 // Get the name of the driver key of the device attached to
1468 // the specified port.
1469 //
1470 driverKeyNameW->ConnectionIndex = ConnectionIndex;
1471
1472 success = DeviceIoControl(Hub,
1473 IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
1474 driverKeyNameW,
1475 nBytes,
1476 driverKeyNameW,
1477 nBytes,
1478 &nBytes,
1479 NULL);
1480
1481 if (!success)
1482 {
1483 AssertFailed();
1484 goto GetDriverKeyNameError;
1485 }
1486
1487 // Convert the driver key name
1488 //
1489 driverKeyNameA = WideStrToMultiStr(driverKeyNameW->DriverKeyName);
1490
1491 // All done, free the uncoverted driver key name and return the
1492 // converted driver key name
1493 //
1494 RTMemFree(driverKeyNameW);
1495
1496 return driverKeyNameA;
1497
1498
1499GetDriverKeyNameError:
1500 // There was an error, free anything that was allocated
1501 //
1502 if (driverKeyNameW != NULL)
1503 {
1504 RTMemFree(driverKeyNameW);
1505 driverKeyNameW = NULL;
1506 }
1507
1508 return NULL;
1509}
1510
1511
1512//*****************************************************************************
1513//
1514// GetHCDDriverKeyName()
1515//
1516//*****************************************************************************
1517
1518PCHAR GetHCDDriverKeyName (
1519 HANDLE HCD
1520)
1521{
1522 BOOL success;
1523 ULONG nBytes;
1524 USB_HCD_DRIVERKEY_NAME driverKeyName;
1525 PUSB_HCD_DRIVERKEY_NAME driverKeyNameW;
1526 PCHAR driverKeyNameA;
1527
1528 driverKeyNameW = NULL;
1529 driverKeyNameA = NULL;
1530
1531 // Get the length of the name of the driver key of the HCD
1532 //
1533 success = DeviceIoControl(HCD,
1534 IOCTL_GET_HCD_DRIVERKEY_NAME,
1535 &driverKeyName,
1536 sizeof(driverKeyName),
1537 &driverKeyName,
1538 sizeof(driverKeyName),
1539 &nBytes,
1540 NULL);
1541
1542 if (!success)
1543 {
1544 AssertFailed();
1545 goto GetHCDDriverKeyNameError;
1546 }
1547
1548 // Allocate space to hold the driver key name
1549 //
1550 nBytes = driverKeyName.ActualLength;
1551
1552 if (nBytes <= sizeof(driverKeyName))
1553 {
1554 AssertFailed();
1555 goto GetHCDDriverKeyNameError;
1556 }
1557
1558 driverKeyNameW = (PUSB_HCD_DRIVERKEY_NAME)RTMemAllocZ(nBytes);
1559
1560 if (driverKeyNameW == NULL)
1561 {
1562 AssertFailed();
1563 goto GetHCDDriverKeyNameError;
1564 }
1565
1566 // Get the name of the driver key of the device attached to
1567 // the specified port.
1568 //
1569 success = DeviceIoControl(HCD,
1570 IOCTL_GET_HCD_DRIVERKEY_NAME,
1571 driverKeyNameW,
1572 nBytes,
1573 driverKeyNameW,
1574 nBytes,
1575 &nBytes,
1576 NULL);
1577
1578 if (!success)
1579 {
1580 AssertFailed();
1581 goto GetHCDDriverKeyNameError;
1582 }
1583
1584 // Convert the driver key name
1585 //
1586 driverKeyNameA = WideStrToMultiStr(driverKeyNameW->DriverKeyName);
1587
1588 // All done, free the uncoverted driver key name and return the
1589 // converted driver key name
1590 //
1591 RTMemFree(driverKeyNameW);
1592
1593 return driverKeyNameA;
1594
1595
1596GetHCDDriverKeyNameError:
1597 // There was an error, free anything that was allocated
1598 //
1599 if (driverKeyNameW != NULL)
1600 {
1601 RTMemFree(driverKeyNameW);
1602 driverKeyNameW = NULL;
1603 }
1604
1605 return NULL;
1606}
1607
1608
1609//*****************************************************************************
1610//
1611// GetConfigDescriptor()
1612//
1613// hHubDevice - Handle of the hub device containing the port from which the
1614// Configuration Descriptor will be requested.
1615//
1616// ConnectionIndex - Identifies the port on the hub to which a device is
1617// attached from which the Configuration Descriptor will be requested.
1618//
1619// DescriptorIndex - Configuration Descriptor index, zero based.
1620//
1621//*****************************************************************************
1622
1623PUSB_DESCRIPTOR_REQUEST
1624GetConfigDescriptor (
1625 HANDLE hHubDevice,
1626 ULONG ConnectionIndex,
1627 UCHAR DescriptorIndex
1628)
1629{
1630 BOOL success;
1631 ULONG nBytes;
1632 ULONG nBytesReturned;
1633
1634 UCHAR configDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) +
1635 sizeof(USB_CONFIGURATION_DESCRIPTOR)];
1636
1637 PUSB_DESCRIPTOR_REQUEST configDescReq;
1638 PUSB_CONFIGURATION_DESCRIPTOR configDesc;
1639
1640
1641 // Request the Configuration Descriptor the first time using our
1642 // local buffer, which is just big enough for the Cofiguration
1643 // Descriptor itself.
1644 //
1645 nBytes = sizeof(configDescReqBuf);
1646
1647 configDescReq = (PUSB_DESCRIPTOR_REQUEST)configDescReqBuf;
1648 configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(configDescReq+1);
1649
1650 // Zero fill the entire request structure
1651 //
1652 memset(configDescReq, 0, nBytes);
1653
1654 // Indicate the port from which the descriptor will be requested
1655 //
1656 configDescReq->ConnectionIndex = ConnectionIndex;
1657
1658 //
1659 // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this
1660 // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request.
1661 //
1662 // USBD will automatically initialize these fields:
1663 // bmRequest = 0x80
1664 // bRequest = 0x06
1665 //
1666 // We must initialize these fields:
1667 // wValue = Descriptor Type (high) and Descriptor Index (low byte)
1668 // wIndex = Zero (or Language ID for String Descriptors)
1669 // wLength = Length of descriptor buffer
1670 //
1671 configDescReq->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8)
1672 | DescriptorIndex;
1673
1674 configDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST));
1675
1676 // Now issue the get descriptor request.
1677 //
1678 success = DeviceIoControl(hHubDevice,
1679 IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
1680 configDescReq,
1681 nBytes,
1682 configDescReq,
1683 nBytes,
1684 &nBytesReturned,
1685 NULL);
1686
1687 if (!success)
1688 {
1689#ifdef VBOX_WITH_ANNOYING_USB_ASSERTIONS
1690 AssertMsgFailed(("DeviceIoControl IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION failed with LastError=%Rwa\n", GetLastError()));
1691#else
1692 LogRel(("DeviceIoControl IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION failed with LastError=%Rwa\n", GetLastError()));
1693#endif
1694 return NULL;
1695 }
1696
1697 if (nBytes != nBytesReturned)
1698 {
1699 AssertFailed();
1700 return NULL;
1701 }
1702
1703 if (configDesc->wTotalLength < sizeof(USB_CONFIGURATION_DESCRIPTOR))
1704 {
1705 AssertFailed();
1706 return NULL;
1707 }
1708
1709 // Now request the entire Configuration Descriptor using a dynamically
1710 // allocated buffer which is sized big enough to hold the entire descriptor
1711 //
1712 nBytes = sizeof(USB_DESCRIPTOR_REQUEST) + configDesc->wTotalLength;
1713
1714 configDescReq = (PUSB_DESCRIPTOR_REQUEST)RTMemAllocZ(nBytes);
1715
1716 if (configDescReq == NULL)
1717 {
1718 AssertFailed();
1719 return NULL;
1720 }
1721
1722 configDesc = (PUSB_CONFIGURATION_DESCRIPTOR)(configDescReq+1);
1723
1724 // Indicate the port from which the descriptor will be requested
1725 //
1726 configDescReq->ConnectionIndex = ConnectionIndex;
1727
1728 //
1729 // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this
1730 // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request.
1731 //
1732 // USBD will automatically initialize these fields:
1733 // bmRequest = 0x80
1734 // bRequest = 0x06
1735 //
1736 // We must initialize these fields:
1737 // wValue = Descriptor Type (high) and Descriptor Index (low byte)
1738 // wIndex = Zero (or Language ID for String Descriptors)
1739 // wLength = Length of descriptor buffer
1740 //
1741 configDescReq->SetupPacket.wValue = (USB_CONFIGURATION_DESCRIPTOR_TYPE << 8)
1742 | DescriptorIndex;
1743
1744 configDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST));
1745
1746 // Now issue the get descriptor request.
1747 //
1748 success = DeviceIoControl(hHubDevice,
1749 IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
1750 configDescReq,
1751 nBytes,
1752 configDescReq,
1753 nBytes,
1754 &nBytesReturned,
1755 NULL);
1756
1757 if (!success)
1758 {
1759#ifdef VBOX_WITH_ANNOYING_USB_ASSERTIONS
1760 AssertMsgFailed(("DeviceIoControl IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION failed with LastError=%Rwa\n", GetLastError()));
1761#else
1762 LogRel(("DeviceIoControl IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION failed with LastError=%Rwa\n", GetLastError()));
1763#endif
1764 RTMemFree(configDescReq);
1765 return NULL;
1766 }
1767
1768 if (nBytes != nBytesReturned)
1769 {
1770#ifdef VBOX_WITH_ANNOYING_USB_ASSERTIONS
1771 AssertMsgFailed(("DeviceIoControl IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION %d != %d\n", nBytes, nBytesReturned));
1772#else
1773 LogRel(("DeviceIoControl IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION %d != %d\n", nBytes, nBytesReturned));
1774#endif
1775 RTMemFree(configDescReq);
1776 return NULL;
1777 }
1778
1779 if (configDesc->wTotalLength != (nBytes - sizeof(USB_DESCRIPTOR_REQUEST)))
1780 {
1781#ifdef VBOX_WITH_ANNOYING_USB_ASSERTIONS
1782 AssertMsgFailed(("DeviceIoControl IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION %d != %d\n", configDesc->wTotalLength, (nBytes - sizeof(USB_DESCRIPTOR_REQUEST))));
1783#else
1784 LogRel(("DeviceIoControl IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION %d != %d\n", configDesc->wTotalLength, (nBytes - sizeof(USB_DESCRIPTOR_REQUEST)) ));
1785#endif
1786 RTMemFree(configDescReq);
1787 return NULL;
1788 }
1789
1790 return configDescReq;
1791}
1792
1793
1794//*****************************************************************************
1795//
1796// AreThereStringDescriptors()
1797//
1798// DeviceDesc - Device Descriptor for which String Descriptors should be
1799// checked.
1800//
1801// ConfigDesc - Configuration Descriptor (also containing Interface Descriptor)
1802// for which String Descriptors should be checked.
1803//
1804//*****************************************************************************
1805
1806BOOL
1807AreThereStringDescriptors (
1808 PUSB_DEVICE_DESCRIPTOR DeviceDesc,
1809 PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc
1810)
1811{
1812 PUCHAR descEnd;
1813 PUSB_COMMON_DESCRIPTOR commonDesc;
1814
1815 //
1816 // Check Device Descriptor strings
1817 //
1818
1819 if (DeviceDesc->iManufacturer ||
1820 DeviceDesc->iProduct ||
1821 DeviceDesc->iSerialNumber
1822 )
1823 {
1824 return TRUE;
1825 }
1826
1827
1828 //
1829 // Check the Configuration and Interface Descriptor strings
1830 //
1831
1832 descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength;
1833
1834 commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc;
1835
1836 while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd &&
1837 (PUCHAR)commonDesc + commonDesc->bLength <= descEnd)
1838 {
1839 switch (commonDesc->bDescriptorType)
1840 {
1841 case USB_CONFIGURATION_DESCRIPTOR_TYPE:
1842 if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR))
1843 {
1844 AssertFailed();
1845 break;
1846 }
1847 if (((PUSB_CONFIGURATION_DESCRIPTOR)commonDesc)->iConfiguration)
1848 {
1849 return TRUE;
1850 }
1851 commonDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)commonDesc + commonDesc->bLength);
1852 continue;
1853
1854 case USB_INTERFACE_DESCRIPTOR_TYPE:
1855 if (commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR) &&
1856 commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR2))
1857 {
1858 AssertFailed();
1859 break;
1860 }
1861 if (((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->iInterface)
1862 {
1863 return TRUE;
1864 }
1865 commonDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)commonDesc + commonDesc->bLength);
1866 continue;
1867
1868 default:
1869 commonDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)commonDesc + commonDesc->bLength);
1870 continue;
1871 }
1872 break;
1873 }
1874
1875 return FALSE;
1876}
1877
1878
1879//*****************************************************************************
1880//
1881// GetAllStringDescriptors()
1882//
1883// hHubDevice - Handle of the hub device containing the port from which the
1884// String Descriptors will be requested.
1885//
1886// ConnectionIndex - Identifies the port on the hub to which a device is
1887// attached from which the String Descriptors will be requested.
1888//
1889// DeviceDesc - Device Descriptor for which String Descriptors should be
1890// requested.
1891//
1892// ConfigDesc - Configuration Descriptor (also containing Interface Descriptor)
1893// for which String Descriptors should be requested.
1894//
1895//*****************************************************************************
1896
1897PSTRING_DESCRIPTOR_NODE
1898GetAllStringDescriptors (
1899 HANDLE hHubDevice,
1900 ULONG ConnectionIndex,
1901 PUSB_DEVICE_DESCRIPTOR DeviceDesc,
1902 PUSB_CONFIGURATION_DESCRIPTOR ConfigDesc
1903)
1904{
1905 PSTRING_DESCRIPTOR_NODE supportedLanguagesString;
1906 PSTRING_DESCRIPTOR_NODE stringDescNodeTail;
1907 ULONG numLanguageIDs;
1908 USHORT *languageIDs;
1909
1910 PUCHAR descEnd;
1911 PUSB_COMMON_DESCRIPTOR commonDesc;
1912
1913 //
1914 // Get the array of supported Language IDs, which is returned
1915 // in String Descriptor 0
1916 //
1917 supportedLanguagesString = GetStringDescriptor(hHubDevice,
1918 ConnectionIndex,
1919 0,
1920 0);
1921
1922 if (supportedLanguagesString == NULL)
1923 {
1924 return NULL;
1925 }
1926
1927 numLanguageIDs = (supportedLanguagesString->StringDescriptor->bLength - 2) / 2;
1928
1929 languageIDs = (PUSHORT)&supportedLanguagesString->StringDescriptor->bString[0];
1930
1931 stringDescNodeTail = supportedLanguagesString;
1932
1933 //
1934 // Get the Device Descriptor strings
1935 //
1936
1937 if (DeviceDesc->iManufacturer)
1938 {
1939 stringDescNodeTail = GetStringDescriptors(hHubDevice,
1940 ConnectionIndex,
1941 DeviceDesc->iManufacturer,
1942 numLanguageIDs,
1943 languageIDs,
1944 stringDescNodeTail);
1945 }
1946
1947 if (DeviceDesc->iProduct)
1948 {
1949 stringDescNodeTail = GetStringDescriptors(hHubDevice,
1950 ConnectionIndex,
1951 DeviceDesc->iProduct,
1952 numLanguageIDs,
1953 languageIDs,
1954 stringDescNodeTail);
1955 }
1956
1957 if (DeviceDesc->iSerialNumber)
1958 {
1959 stringDescNodeTail = GetStringDescriptors(hHubDevice,
1960 ConnectionIndex,
1961 DeviceDesc->iSerialNumber,
1962 numLanguageIDs,
1963 languageIDs,
1964 stringDescNodeTail);
1965 }
1966
1967
1968 //
1969 // Get the Configuration and Interface Descriptor strings
1970 //
1971
1972 descEnd = (PUCHAR)ConfigDesc + ConfigDesc->wTotalLength;
1973
1974 commonDesc = (PUSB_COMMON_DESCRIPTOR)ConfigDesc;
1975
1976 while ((PUCHAR)commonDesc + sizeof(USB_COMMON_DESCRIPTOR) < descEnd &&
1977 (PUCHAR)commonDesc + commonDesc->bLength <= descEnd)
1978 {
1979 switch (commonDesc->bDescriptorType)
1980 {
1981 case USB_CONFIGURATION_DESCRIPTOR_TYPE:
1982 if (commonDesc->bLength != sizeof(USB_CONFIGURATION_DESCRIPTOR))
1983 {
1984 AssertFailed();
1985 break;
1986 }
1987 if (((PUSB_CONFIGURATION_DESCRIPTOR)commonDesc)->iConfiguration)
1988 {
1989 stringDescNodeTail = GetStringDescriptors(
1990 hHubDevice,
1991 ConnectionIndex,
1992 ((PUSB_CONFIGURATION_DESCRIPTOR)commonDesc)->iConfiguration,
1993 numLanguageIDs,
1994 languageIDs,
1995 stringDescNodeTail);
1996 }
1997 commonDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)commonDesc + commonDesc->bLength);
1998 continue;
1999
2000 case USB_INTERFACE_DESCRIPTOR_TYPE:
2001 if (commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR) &&
2002 commonDesc->bLength != sizeof(USB_INTERFACE_DESCRIPTOR2))
2003 {
2004 AssertFailed();
2005 break;
2006 }
2007 if (((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->iInterface)
2008 {
2009 stringDescNodeTail = GetStringDescriptors(
2010 hHubDevice,
2011 ConnectionIndex,
2012 ((PUSB_INTERFACE_DESCRIPTOR)commonDesc)->iInterface,
2013 numLanguageIDs,
2014 languageIDs,
2015 stringDescNodeTail);
2016 }
2017 commonDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)commonDesc + commonDesc->bLength);
2018 continue;
2019
2020 default:
2021 commonDesc = (PUSB_COMMON_DESCRIPTOR)((PUCHAR)commonDesc + commonDesc->bLength);
2022 continue;
2023 }
2024 break;
2025 }
2026
2027 return supportedLanguagesString;
2028}
2029
2030
2031//*****************************************************************************
2032//
2033// GetStringDescriptor()
2034//
2035// hHubDevice - Handle of the hub device containing the port from which the
2036// String Descriptor will be requested.
2037//
2038// ConnectionIndex - Identifies the port on the hub to which a device is
2039// attached from which the String Descriptor will be requested.
2040//
2041// DescriptorIndex - String Descriptor index.
2042//
2043// LanguageID - Language in which the string should be requested.
2044//
2045//*****************************************************************************
2046
2047PSTRING_DESCRIPTOR_NODE
2048GetStringDescriptor (
2049 HANDLE hHubDevice,
2050 ULONG ConnectionIndex,
2051 UCHAR DescriptorIndex,
2052 USHORT LanguageID
2053)
2054{
2055 BOOL success;
2056 ULONG nBytes;
2057 ULONG nBytesReturned;
2058
2059 UCHAR stringDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) +
2060 MAXIMUM_USB_STRING_LENGTH];
2061
2062 PUSB_DESCRIPTOR_REQUEST stringDescReq;
2063 PUSB_STRING_DESCRIPTOR stringDesc;
2064 PSTRING_DESCRIPTOR_NODE stringDescNode;
2065
2066 nBytes = sizeof(stringDescReqBuf);
2067
2068 stringDescReq = (PUSB_DESCRIPTOR_REQUEST)stringDescReqBuf;
2069 stringDesc = (PUSB_STRING_DESCRIPTOR)(stringDescReq+1);
2070
2071 // Zero fill the entire request structure
2072 //
2073 memset(stringDescReq, 0, nBytes);
2074
2075 // Indicate the port from which the descriptor will be requested
2076 //
2077 stringDescReq->ConnectionIndex = ConnectionIndex;
2078
2079 //
2080 // USBHUB uses URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE to process this
2081 // IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION request.
2082 //
2083 // USBD will automatically initialize these fields:
2084 // bmRequest = 0x80
2085 // bRequest = 0x06
2086 //
2087 // We must initialize these fields:
2088 // wValue = Descriptor Type (high) and Descriptor Index (low byte)
2089 // wIndex = Zero (or Language ID for String Descriptors)
2090 // wLength = Length of descriptor buffer
2091 //
2092 stringDescReq->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8)
2093 | DescriptorIndex;
2094
2095 stringDescReq->SetupPacket.wIndex = LanguageID;
2096
2097 stringDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST));
2098
2099 // Now issue the get descriptor request.
2100 //
2101 success = DeviceIoControl(hHubDevice,
2102 IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
2103 stringDescReq,
2104 nBytes,
2105 stringDescReq,
2106 nBytes,
2107 &nBytesReturned,
2108 NULL);
2109
2110 //
2111 // Do some sanity checks on the return from the get descriptor request.
2112 //
2113
2114 if (!success)
2115 {
2116#ifdef VBOX_WITH_ANNOYING_USB_ASSERTIONS
2117 AssertMsgFailed(("DeviceIoControl IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION failed with LastError=%Rwa\n", GetLastError()));
2118#else
2119 LogRel(("DeviceIoControl IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION failed with LastError=%Rwa\n", GetLastError()));
2120#endif
2121 return NULL;
2122 }
2123
2124 if (nBytesReturned < 2)
2125 {
2126 AssertFailed();
2127 return NULL;
2128 }
2129
2130 if (stringDesc->bDescriptorType != USB_STRING_DESCRIPTOR_TYPE)
2131 {
2132 AssertFailed();
2133 return NULL;
2134 }
2135
2136 if (stringDesc->bLength != nBytesReturned - sizeof(USB_DESCRIPTOR_REQUEST))
2137 {
2138 AssertFailed();
2139 return NULL;
2140 }
2141
2142 if (stringDesc->bLength % 2 != 0)
2143 {
2144 AssertFailed();
2145 return NULL;
2146 }
2147
2148 //
2149 // Looks good, allocate some (zero filled) space for the string descriptor
2150 // node and copy the string descriptor to it.
2151 //
2152
2153 stringDescNode = (PSTRING_DESCRIPTOR_NODE)RTMemAllocZ(sizeof(STRING_DESCRIPTOR_NODE) +
2154 stringDesc->bLength + 2);
2155
2156 if (stringDescNode == NULL)
2157 {
2158 AssertFailed();
2159 return NULL;
2160 }
2161
2162 stringDescNode->DescriptorIndex = DescriptorIndex;
2163 stringDescNode->LanguageID = LanguageID;
2164
2165 memcpy(stringDescNode->StringDescriptor,
2166 stringDesc,
2167 stringDesc->bLength);
2168
2169 return stringDescNode;
2170}
2171
2172
2173//*****************************************************************************
2174//
2175// GetStringDescriptors()
2176//
2177// hHubDevice - Handle of the hub device containing the port from which the
2178// String Descriptor will be requested.
2179//
2180// ConnectionIndex - Identifies the port on the hub to which a device is
2181// attached from which the String Descriptor will be requested.
2182//
2183// DescriptorIndex - String Descriptor index.
2184//
2185// NumLanguageIDs - Number of languages in which the string should be
2186// requested.
2187//
2188// LanguageIDs - Languages in which the string should be requested.
2189//
2190//*****************************************************************************
2191
2192PSTRING_DESCRIPTOR_NODE
2193GetStringDescriptors (
2194 HANDLE hHubDevice,
2195 ULONG ConnectionIndex,
2196 UCHAR DescriptorIndex,
2197 ULONG NumLanguageIDs,
2198 USHORT *LanguageIDs,
2199 PSTRING_DESCRIPTOR_NODE StringDescNodeTail
2200)
2201{
2202 ULONG i;
2203
2204 for (i = 0; i < NumLanguageIDs; i++)
2205 {
2206 StringDescNodeTail->Next = GetStringDescriptor(hHubDevice,
2207 ConnectionIndex,
2208 DescriptorIndex,
2209 *LanguageIDs);
2210
2211 if (StringDescNodeTail->Next)
2212 {
2213 StringDescNodeTail = StringDescNodeTail->Next;
2214 }
2215
2216 LanguageIDs++;
2217 }
2218
2219 return StringDescNodeTail;
2220}
2221
2222
2223//*****************************************************************************
2224//
2225// DriverNameToDeviceDesc()
2226//
2227// Returns the Device Description of the DevNode with the matching DriverName.
2228// Returns NULL if the matching DevNode is not found.
2229//
2230// The caller should copy the returned string buffer instead of just saving
2231// the pointer value. XXXXX Dynamically allocate return buffer?
2232//
2233//*****************************************************************************
2234CHAR buf[512]; // XXXXX How big does this have to be? Dynamically size it?
2235
2236PCHAR DriverNameToDeviceDesc (PCHAR DriverName)
2237{
2238 DEVINST devInst;
2239 DEVINST devInstNext;
2240 CONFIGRET cr;
2241 ULONG walkDone = 0;
2242 ULONG len;
2243
2244 // Get Root DevNode
2245 //
2246 cr = CM_Locate_DevNode(&devInst,
2247 NULL,
2248 0);
2249
2250 if (cr != CR_SUCCESS)
2251 {
2252 return NULL;
2253 }
2254
2255 // Do a depth first search for the DevNode with a matching
2256 // DriverName value
2257 //
2258 while (!walkDone)
2259 {
2260 // Get the DriverName value
2261 //
2262 len = sizeof(buf);
2263 cr = CM_Get_DevNode_Registry_Property(devInst,
2264 CM_DRP_DRIVER,
2265 NULL,
2266 buf,
2267 &len,
2268 0);
2269
2270 // If the DriverName value matches, return the DeviceDescription
2271 //
2272 if (cr == CR_SUCCESS && _stricmp(DriverName, buf) == 0)
2273 {
2274 len = sizeof(buf);
2275 cr = CM_Get_DevNode_Registry_Property(devInst,
2276 CM_DRP_DEVICEDESC,
2277 NULL,
2278 buf,
2279 &len,
2280 0);
2281
2282 if (cr == CR_SUCCESS)
2283 {
2284 return buf;
2285 }
2286 else
2287 {
2288 return NULL;
2289 }
2290 }
2291
2292 // This DevNode didn't match, go down a level to the first child.
2293 //
2294 cr = CM_Get_Child(&devInstNext,
2295 devInst,
2296 0);
2297
2298 if (cr == CR_SUCCESS)
2299 {
2300 devInst = devInstNext;
2301 continue;
2302 }
2303
2304 // Can't go down any further, go across to the next sibling. If
2305 // there are no more siblings, go back up until there is a sibling.
2306 // If we can't go up any further, we're back at the root and we're
2307 // done.
2308 //
2309 for (;;)
2310 {
2311 cr = CM_Get_Sibling(&devInstNext,
2312 devInst,
2313 0);
2314
2315 if (cr == CR_SUCCESS)
2316 {
2317 devInst = devInstNext;
2318 break;
2319 }
2320
2321 cr = CM_Get_Parent(&devInstNext,
2322 devInst,
2323 0);
2324
2325
2326 if (cr == CR_SUCCESS)
2327 {
2328 devInst = devInstNext;
2329 }
2330 else
2331 {
2332 walkDone = 1;
2333 break;
2334 }
2335 }
2336 }
2337
2338 return NULL;
2339}
2340
2341
2342/**
2343 * Attempts to start the service, creating it if necessary.
2344 *
2345 * @returns 0 on success.
2346 * @returns -1 on failure.
2347 * @param fRetry Indicates retry call.
2348 */
2349int usbMonStartService(void)
2350{
2351 /*
2352 * Check if the driver service is there.
2353 */
2354 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_QUERY_STATUS | SERVICE_START);
2355 if (hSMgr == NULL)
2356 {
2357 AssertMsgFailed(("couldn't open service manager in SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS mode!\n"));
2358 return -1;
2359 }
2360
2361 /*
2362 * Try open our service to check it's status.
2363 */
2364 SC_HANDLE hService = OpenService(hSMgr, USBMON_SERVICE_NAME, SERVICE_QUERY_STATUS | SERVICE_START);
2365 if (!hService)
2366 return -1;
2367
2368 /*
2369 * Check if open and on demand create succeeded.
2370 */
2371 int rc = -1;
2372 if (hService)
2373 {
2374
2375 /*
2376 * Query service status to see if we need to start it or not.
2377 */
2378 SERVICE_STATUS Status;
2379 BOOL fRc = QueryServiceStatus(hService, &Status);
2380 Assert(fRc);
2381 if ( Status.dwCurrentState != SERVICE_RUNNING
2382 && Status.dwCurrentState != SERVICE_START_PENDING)
2383 {
2384 /*
2385 * Start it.
2386 */
2387 LogRel(("usbMonStartService -> start it\n"));
2388
2389 fRc = StartService(hService, 0, NULL);
2390 DWORD LastError = GetLastError(); NOREF(LastError);
2391 AssertMsg(fRc, ("StartService failed with LastError=%Rwa\n", LastError));
2392 if (fRc)
2393 g_fStartedService = true;
2394 }
2395
2396 /*
2397 * Wait for the service to finish starting.
2398 * We'll wait for 10 seconds then we'll give up.
2399 */
2400 QueryServiceStatus(hService, &Status);
2401 if (Status.dwCurrentState == SERVICE_START_PENDING)
2402 {
2403 int iWait;
2404 for (iWait = 100; iWait > 0 && Status.dwCurrentState == SERVICE_START_PENDING; iWait--)
2405 {
2406 Sleep(100);
2407 QueryServiceStatus(hService, &Status);
2408 }
2409 DWORD LastError = GetLastError(); NOREF(LastError);
2410 AssertMsg(Status.dwCurrentState != SERVICE_RUNNING,
2411 ("Failed to start. LastError=%Rwa iWait=%d status=%d\n",
2412 LastError, iWait, Status.dwCurrentState));
2413 }
2414
2415 if (Status.dwCurrentState == SERVICE_RUNNING)
2416 rc = 0;
2417
2418 /*
2419 * Close open handles.
2420 */
2421 CloseServiceHandle(hService);
2422 }
2423 else
2424 {
2425 DWORD LastError = GetLastError(); NOREF(LastError);
2426 AssertMsgFailed(("OpenService failed! LastError=%Rwa\n", LastError));
2427 }
2428 if (!CloseServiceHandle(hSMgr))
2429 AssertFailed();
2430
2431 return rc;
2432}
2433
2434/**
2435 * Stops a possibly running service.
2436 *
2437 * @returns 0 on success.
2438 * @returns -1 on failure.
2439 */
2440int usbMonStopService(void)
2441{
2442 LogRel(("usbMonStopService\n"));
2443 /*
2444 * Assume it didn't exist, so we'll create the service.
2445 */
2446 int rc = -1;
2447 SC_HANDLE hSMgr = OpenSCManager(NULL, NULL, SERVICE_STOP | SERVICE_QUERY_STATUS);
2448 DWORD LastError = GetLastError(); NOREF(LastError);
2449 AssertMsg(hSMgr, ("OpenSCManager(,,delete) failed rc=%d\n", LastError));
2450 if (hSMgr)
2451 {
2452 SC_HANDLE hService = OpenService(hSMgr, USBMON_SERVICE_NAME, SERVICE_STOP | SERVICE_QUERY_STATUS);
2453 if (hService)
2454 {
2455 /*
2456 * Stop the service.
2457 */
2458 SERVICE_STATUS Status;
2459 QueryServiceStatus(hService, &Status);
2460 if (Status.dwCurrentState == SERVICE_STOPPED)
2461 rc = 0;
2462 else if (ControlService(hService, SERVICE_CONTROL_STOP, &Status))
2463 {
2464 int iWait = 100;
2465 while (Status.dwCurrentState == SERVICE_STOP_PENDING && iWait-- > 0)
2466 {
2467 Sleep(100);
2468 QueryServiceStatus(hService, &Status);
2469 }
2470 if (Status.dwCurrentState == SERVICE_STOPPED)
2471 rc = 0;
2472 else
2473 AssertMsgFailed(("Failed to stop service. status=%d\n", Status.dwCurrentState));
2474 }
2475 else
2476 {
2477 DWORD LastError = GetLastError(); NOREF(LastError);
2478 AssertMsgFailed(("ControlService failed with LastError=%Rwa. status=%d\n", LastError, Status.dwCurrentState));
2479 }
2480 CloseServiceHandle(hService);
2481 }
2482 else if (GetLastError() == ERROR_SERVICE_DOES_NOT_EXIST)
2483 rc = 0;
2484 else
2485 {
2486 DWORD LastError = GetLastError(); NOREF(LastError);
2487 AssertMsgFailed(("OpenService failed with LastError=%Rwa\n", LastError));
2488 }
2489 CloseServiceHandle(hSMgr);
2490 }
2491 return rc;
2492}
2493
2494
2495/**
2496 * Initialize the USB library
2497 *
2498 * @returns VBox status code.
2499 */
2500USBLIB_DECL(int) USBLibInit(void)
2501{
2502 int rc;
2503 USBSUP_VERSION version = {0};
2504 DWORD cbReturned;
2505
2506 Log(("usbproxy: usbLibInit\n"));
2507
2508 g_hUSBMonitor = CreateFile(USBMON_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
2509 OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL);
2510
2511 if (g_hUSBMonitor == INVALID_HANDLE_VALUE)
2512 {
2513 usbMonStartService();
2514
2515 g_hUSBMonitor = CreateFile(USBMON_DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
2516 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL);
2517
2518 if (g_hUSBMonitor == INVALID_HANDLE_VALUE)
2519 {
2520 /* AssertFailed(); */
2521 LogRel(("usbproxy: Unable to open monitor driver!! LastError=%Rwa\n", GetLastError()));
2522 rc = VERR_FILE_NOT_FOUND;
2523 goto failure;
2524 }
2525 }
2526
2527 /*
2528 * Check the version
2529 */
2530 cbReturned = 0;
2531 if (!DeviceIoControl(g_hUSBMonitor, SUPUSBFLT_IOCTL_GET_VERSION, NULL, 0,&version, sizeof(version), &cbReturned, NULL))
2532 {
2533 LogRel(("usbproxy: Unable to query filter version!! LastError=%Rwa\n", GetLastError()));
2534 rc = VERR_VERSION_MISMATCH;
2535 goto failure;
2536 }
2537
2538 if (version.u32Major != USBMON_MAJOR_VERSION ||
2539 version.u32Minor < USBMON_MINOR_VERSION)
2540 {
2541 LogRel(("usbproxy: Filter driver version mismatch!!\n"));
2542 rc = VERR_VERSION_MISMATCH;
2543 goto failure;
2544 }
2545 return VINF_SUCCESS;
2546
2547failure:
2548 if (g_hUSBMonitor != INVALID_HANDLE_VALUE)
2549 {
2550 CloseHandle(g_hUSBMonitor);
2551 g_hUSBMonitor = INVALID_HANDLE_VALUE;
2552 }
2553 return rc;
2554}
2555
2556
2557/**
2558 * Terminate the USB library
2559 *
2560 * @returns VBox status code.
2561 */
2562USBLIB_DECL(int) USBLibTerm(void)
2563{
2564 if (g_hUSBMonitor != INVALID_HANDLE_VALUE)
2565 {
2566 CloseHandle(g_hUSBMonitor);
2567 g_hUSBMonitor = INVALID_HANDLE_VALUE;
2568 }
2569#if 0
2570 /*
2571 * If we started the service we might consider stopping it too.
2572 *
2573 * Since this won't work unless the process starting it is the
2574 * last user we might wanna skip this...
2575 */
2576 if (g_fStartedService)
2577 {
2578 usbMonStopService();
2579 g_fStartedService = false;
2580 }
2581#endif
2582
2583 return VINF_SUCCESS;
2584}
2585
2586/**
2587 * Capture specified USB device
2588 *
2589 * @returns VBox status code
2590 * @param usVendorId Vendor id
2591 * @param usProductId Product id
2592 * @param usRevision Revision
2593 */
2594USBLIB_DECL(int) USBLibCaptureDevice(uint16_t usVendorId, uint16_t usProductId, uint16_t usRevision)
2595{
2596 USBSUP_CAPTURE capture;
2597 DWORD cbReturned = 0;
2598
2599 Log(("usbLibCaptureDevice %x %x %x\n", usVendorId, usProductId, usRevision));
2600
2601 if (g_hUSBMonitor == INVALID_HANDLE_VALUE)
2602 return VERR_NOT_SUPPORTED;
2603
2604 capture.usVendorId = usVendorId;
2605 capture.usProductId = usProductId;
2606 capture.usRevision = usRevision;
2607
2608 if (!DeviceIoControl(g_hUSBMonitor, SUPUSBFLT_IOCTL_CAPTURE_DEVICE, &capture, sizeof(capture), NULL, 0, &cbReturned, NULL))
2609 {
2610 AssertMsgFailed(("DeviceIoControl failed with LastError=%Rwa\n", GetLastError()));
2611 return RTErrConvertFromWin32(GetLastError());
2612 }
2613
2614 return VINF_SUCCESS;
2615}
2616
2617/**
2618 * Release specified USB device to the host.
2619 *
2620 * @returns VBox status code
2621 * @param usVendorId Vendor id
2622 * @param usProductId Product id
2623 * @param usRevision Revision
2624 */
2625USBLIB_DECL(int) USBLibReleaseDevice(uint16_t usVendorId, uint16_t usProductId, uint16_t usRevision)
2626{
2627 USBSUP_RELEASE release;
2628 DWORD cbReturned = 0;
2629
2630 Log(("usbLibReleaseDevice %x %x %x\n", usVendorId, usProductId, usRevision));
2631
2632 if (g_hUSBMonitor == INVALID_HANDLE_VALUE)
2633 return VERR_NOT_SUPPORTED;
2634
2635 release.usVendorId = usVendorId;
2636 release.usProductId = usProductId;
2637 release.usRevision = usRevision;
2638
2639 if (!DeviceIoControl(g_hUSBMonitor, SUPUSBFLT_IOCTL_RELEASE_DEVICE, &release, sizeof(release), NULL, 0, &cbReturned, NULL))
2640 {
2641 AssertMsgFailed(("DeviceIoControl failed with LastError=%Rwa\n", GetLastError()));
2642 return RTErrConvertFromWin32(GetLastError());
2643 }
2644
2645 return VINF_SUCCESS;
2646}
2647
2648
2649USBLIB_DECL(void *) USBLibAddFilter(PCUSBFILTER pFilter)
2650{
2651 USBSUP_FLTADDOUT add_out;
2652 DWORD cbReturned = 0;
2653
2654 if (g_hUSBMonitor == INVALID_HANDLE_VALUE)
2655 return NULL;
2656
2657 Log(("usblibInsertFilter: Manufacturer=%s Product=%s Serial=%s\n",
2658 USBFilterGetString(pFilter, USBFILTERIDX_MANUFACTURER_STR) ? USBFilterGetString(pFilter, USBFILTERIDX_MANUFACTURER_STR) : "<null>",
2659 USBFilterGetString(pFilter, USBFILTERIDX_PRODUCT_STR) ? USBFilterGetString(pFilter, USBFILTERIDX_PRODUCT_STR) : "<null>",
2660 USBFilterGetString(pFilter, USBFILTERIDX_SERIAL_NUMBER_STR) ? USBFilterGetString(pFilter, USBFILTERIDX_SERIAL_NUMBER_STR) : "<null>"));
2661
2662 if (!DeviceIoControl(g_hUSBMonitor, SUPUSBFLT_IOCTL_ADD_FILTER, (LPVOID)pFilter, sizeof(*pFilter), &add_out, sizeof(add_out), &cbReturned, NULL))
2663 {
2664 AssertMsgFailed(("DeviceIoControl failed with LastError=%Rwa\n", GetLastError()));
2665 return NULL;
2666 }
2667 if (RT_FAILURE(add_out.rc))
2668 {
2669 AssertMsgFailed(("Adding filter failed with %d\n", add_out.rc));
2670 return NULL;
2671 }
2672 return (void *)add_out.uId;
2673}
2674
2675
2676USBLIB_DECL(void) USBLibRemoveFilter(void *pvId)
2677{
2678 uintptr_t uId;
2679 DWORD cbReturned = 0;
2680
2681 if (g_hUSBMonitor == INVALID_HANDLE_VALUE)
2682 return;
2683
2684 Log(("usblibRemoveFilter %p\n", pvId));
2685
2686 uId = (uintptr_t)pvId;
2687 if (!DeviceIoControl(g_hUSBMonitor, SUPUSBFLT_IOCTL_REMOVE_FILTER, &uId, sizeof(uId), NULL, 0,&cbReturned, NULL))
2688 AssertMsgFailed(("DeviceIoControl failed with LastError=%Rwa\n", GetLastError()));
2689}
2690
2691
2692static void usbLibLogHostDevices(PUSBDEVICE pDevice)
2693{
2694#ifdef LOG_ENABLED
2695 int iDevice = 0;
2696 while (pDevice)
2697 {
2698 iDevice++;
2699 Log(("Detected device: #%d\n", iDevice));
2700 Log((" Vendor Id: 0x%04X\n", pDevice->idVendor));
2701 Log((" Product Id: 0x%04X\n", pDevice->idProduct));
2702 Log((" Revision: 0x%04X\n", pDevice->bcdDevice));
2703 Log((" Address: %s\n", pDevice->pszAddress));
2704 Log((" AltAddress: %s\n", pDevice->pszAltAddress));
2705 Log((" HubName: %s\n", pDevice->pszHubName));
2706 Log((" Port: %u\n", pDevice->bPort));
2707 Log((" Manufacturer: %s\n", pDevice->pszManufacturer));
2708 Log((" Product: %s\n", pDevice->pszProduct));
2709 if (pDevice->pszSerialNumber)
2710 Log((" Serial Nr.: %s\n", pDevice->pszSerialNumber));
2711
2712 switch(pDevice->enmState)
2713 {
2714 case USBDEVICESTATE_UNSUPPORTED:
2715 Log((" State USBDEVICESTATE_UNSUPPORTED\n"));
2716 break;
2717 case USBDEVICESTATE_USED_BY_HOST:
2718 Log((" State USBDEVICESTATE_USED_BY_HOST\n"));
2719 break;
2720 case USBDEVICESTATE_USED_BY_HOST_CAPTURABLE:
2721 Log((" State USBDEVICESTATE_USED_BY_HOST_CAPTURABLE\n"));
2722 break;
2723 case USBDEVICESTATE_UNUSED:
2724 Log((" State USBDEVICESTATE_UNUSED\n"));
2725 break;
2726 case USBDEVICESTATE_HELD_BY_PROXY:
2727 Log((" State USBDEVICESTATE_HELD_BY_PROXY\n"));
2728 break;
2729 case USBDEVICESTATE_USED_BY_GUEST:
2730 Log((" State USBDEVICESTATE_USED_BY_GUEST\n"));
2731 break;
2732 }
2733 pDevice = pDevice->pNext;
2734 }
2735#endif
2736}
2737
2738
2739/**
2740 * Return all attached USB devices that are captured by the filter
2741 *
2742 * @returns VBox status code
2743 * @param ppDevices Receives pointer to list of devices
2744 * @param pcDevices Number of USB devices in the list
2745 */
2746USBLIB_DECL(int) USBLibGetDevices(PUSBDEVICE *ppDevices, uint32_t *pcDevices)
2747{
2748 Log(("usbLibGetDevices: enter\n"));
2749 int rc = VINF_SUCCESS;
2750
2751 if (g_hUSBMonitor == INVALID_HANDLE_VALUE)
2752 return VERR_NOT_SUPPORTED;
2753
2754 /*
2755 * 1: Enumerate all USB devices attached to the host.
2756 */
2757 PUSBDEVICE pHostDevices = NULL;
2758 uint32_t cHostDevices = 0;
2759 usbLibEnumerateHostControllers(&pHostDevices, &cHostDevices);
2760
2761 Log(("usbLibGetDevices: Detected %d host devices\n", cHostDevices));
2762 usbLibLogHostDevices(pHostDevices);
2763
2764 /*
2765 * Get the return data. Note that we might be called a bit too early here.
2766 * Give Windows time to register the new USB driver/device. It's no problem
2767 * to block here as we're in the async usb detection thread (not EMT).
2768 */
2769 USBSUP_GETNUMDEV numdev;
2770 *ppDevices = NULL;
2771 *pcDevices = 0;
2772 for (uint32_t i = 0; i < 100; i++)
2773 {
2774 /*
2775 * Get the number of USB devices.
2776 */
2777 DWORD cbReturned = 0;
2778 if (!DeviceIoControl(g_hUSBMonitor, SUPUSBFLT_IOCTL_GET_NUM_DEVICES, NULL, 0, &numdev, sizeof(numdev), &cbReturned, NULL))
2779 {
2780 DWORD LastError = GetLastError();
2781 AssertMsgFailed(("DeviceIoControl failed with LastError=%Rwa\n", LastError));
2782 /* Free the host devices */
2783 PUSBDEVICE pDevice = pHostDevices;
2784 while (pDevice)
2785 {
2786 PUSBDEVICE pNext = pDevice->pNext;
2787
2788 RTStrFree((char*)pDevice->pszAddress);
2789 RTStrFree(pDevice->pszAltAddress);
2790 RTStrFree(pDevice->pszHubName);
2791 RTStrFree((char*)pDevice->pszManufacturer);
2792 RTStrFree((char*)pDevice->pszProduct);
2793 RTStrFree((char*)pDevice->pszSerialNumber);
2794 RTMemFree(pDevice);
2795
2796 pDevice = pNext;
2797 }
2798
2799 *ppDevices = NULL;
2800 int rc = RTErrConvertFromWin32(LastError);
2801 Log(("usbLibGetDevices: returns %Rrc\n", rc));
2802 return rc;
2803 }
2804
2805 AssertMsg((int32_t)numdev.cUSBDevices >= 0, ("%d", numdev.cUSBDevices));
2806 /* This can be < 0 when detaching a captured device which hadn't yet been
2807 * opened by a VM process. */
2808 if ((int32_t)numdev.cUSBDevices <= 0)
2809 break;
2810
2811 Log(("Monitor detected %d captured devices\n", numdev.cUSBDevices));
2812
2813 usblibEnumDevices(numdev.cUSBDevices, pcDevices);
2814 Log(("usblibEnumDevices detected %d devices\n", *pcDevices));
2815
2816 if (numdev.cUSBDevices == *pcDevices)
2817 break;
2818 RTThreadSleep(100);
2819 }
2820 Assert(numdev.cUSBDevices == *pcDevices);
2821
2822 if ((int32_t)numdev.cUSBDevices <= 0 || *pcDevices == 0)
2823 {
2824 /* Only return the host devices */
2825 *ppDevices = pHostDevices;
2826 *pcDevices = cHostDevices;
2827 Log(("usbLibGetDevices: returns %d host devices - no captured devices\n", cHostDevices));
2828 return VINF_SUCCESS;
2829 }
2830
2831 /*
2832 * 2: Get all the USB devices that the filter has captured for us. Then
2833 * update the corresponding device information in the host devices.
2834 */
2835 uint32_t cCaptured = 0;
2836 for (uint32_t i = 0; i < numdev.cUSBDevices; i++)
2837 {
2838 USBSUP_GETDEV dev = {0};
2839 HANDLE hDev;
2840
2841 char *pszDevName = usblibQueryDeviceName(i);
2842 hDev = CreateFile(pszDevName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL,
2843 OPEN_EXISTING, FILE_ATTRIBUTE_SYSTEM, NULL);
2844
2845 if (hDev != INVALID_HANDLE_VALUE)
2846 {
2847 DWORD cbReturned = 0;
2848 if (!DeviceIoControl(hDev, SUPUSB_IOCTL_GET_DEVICE, &dev, sizeof(dev), &dev, sizeof(dev), &cbReturned, NULL))
2849 {
2850 DWORD LastError = GetLastError();
2851 /* ERROR_DEVICE_NOT_CONNECTED -> device was removed just now */
2852 AssertMsg(LastError == ERROR_DEVICE_NOT_CONNECTED, ("DeviceIoControl %d failed with LastError=%Rwa\n", i, LastError));
2853 Log(("SUPUSB_IOCTL_GET_DEVICE: DeviceIoControl %d no longer connected\n", i));
2854 }
2855 else
2856 {
2857 /* Now search the captured device in the host list and update
2858 * the information there */
2859 char *pszDeviceRegPath = usblibQueryDeviceRegPath(i);
2860 if (pszDeviceRegPath)
2861 {
2862 PUSBDEVICE pDevice = pHostDevices;
2863 uint32_t j;
2864 for (j = 0; j < cHostDevices; j++)
2865 {
2866 if (!strcmp(pszDeviceRegPath, pDevice->pszAddress))
2867 {
2868 Log(("usbLibGetDevices: Found captured device in host list %s (%s)\n", pszDeviceRegPath, pszDevName));
2869
2870 pDevice->enmState = USBDEVICESTATE_HELD_BY_PROXY;
2871 /* The following is not 100% accurate but we only care about high-speed vs. non-high-speed */
2872 pDevice->enmSpeed = dev.fHiSpeed ? USBDEVICESPEED_HIGH : USBDEVICESPEED_FULL;
2873 RTStrFree(pDevice->pszAltAddress);
2874 pDevice->pszAltAddress = (char *)pDevice->pszAddress;
2875 pDevice->pszAddress = RTStrDup(pszDevName);
2876 cCaptured++;
2877 }
2878 pDevice = pDevice->pNext;
2879 }
2880
2881 if (j == cHostDevices)
2882 {
2883 Assert(!pDevice);
2884
2885 /* Probably in the process of being reattached */
2886 Log(("usbLibGetDevices: Captured device %s not found in host device list\n", pszDeviceRegPath));
2887 /* do nothing */
2888 }
2889 }
2890 else
2891 Log(("usbLibGetDevices: Cannot determine the path to %s\n", pszDevName));
2892 }
2893 CloseHandle(hDev);
2894 }
2895 else
2896 AssertMsgFailed(("Unexpected failure to open %s. LastError=%Rwa\n", pszDevName, GetLastError()));
2897 }
2898
2899 if (!cCaptured)
2900 {
2901 /* Only return the host devices */
2902 *ppDevices = pHostDevices;
2903 *pcDevices = cHostDevices;
2904 Log(("usbLibGetDevices: returns %d host devices - no captured devices after all\n", cHostDevices));
2905 return VINF_SUCCESS;
2906 }
2907
2908 *pcDevices = cHostDevices;
2909
2910 Log(("usbLibGetDevices: returns %d devices (%d captured)\n", *pcDevices, cCaptured));
2911 usbLibLogHostDevices(pHostDevices);
2912
2913 *ppDevices = pHostDevices;
2914 return VINF_SUCCESS;
2915}
2916
2917
2918/**
2919 * Check for USB device arrivals or removals
2920 *
2921 * @returns boolean
2922 */
2923USBLIB_DECL(bool) USBLibHasPendingDeviceChanges(void)
2924{
2925 USBSUP_USB_CHANGE out;
2926 DWORD cbReturned;
2927
2928 if (g_hUSBMonitor == INVALID_HANDLE_VALUE)
2929 return false;
2930 cbReturned = 0;
2931 if ( DeviceIoControl(g_hUSBMonitor, SUPUSBFLT_IOCTL_USB_CHANGE, NULL, 0, &out, sizeof(out), &cbReturned, NULL)
2932 && out.cUSBStateChange != g_cUSBStateChange)
2933 {
2934 g_cUSBStateChange = out.cUSBStateChange;
2935 Log(("usbLibHasPendingDeviceChanges: Detected USB state change!!\n"));
2936 return true;
2937 }
2938 return false;
2939}
2940
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette