VirtualBox

Ignore:
Timestamp:
Dec 10, 2019 1:00:06 PM (5 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
135403
Message:

USB/Win: Use a different method of obtaining the port number in VBoxUSBMon.sys.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/VBoxUSB/win/mon/VBoxUsbFlt.cpp

    r82446 r82538  
    111111    uint16_t        idProduct;
    112112    uint16_t        bcdDevice;
    113     uint16_t        wPort;
     113    uint16_t        bPort;
    114114    uint8_t         bClass;
    115115    uint8_t         bSubClass;
     
    380380
    381381    /* If the port number looks valid, add it to the filter. */
    382     if (pDevice->wPort < 256)
    383     {
    384         LOG(("Setting filter port %04X\n", pDevice->wPort));
    385         USBFilterSetNumExact(&DevFlt, USBFILTERIDX_PORT, pDevice->wPort, true);
     382    if (pDevice->bPort)
     383    {
     384        LOG(("Setting filter port %04X\n", pDevice->bPort));
     385        USBFilterSetNumExact(&DevFlt, USBFILTERIDX_PORT, pDevice->bPort, true);
    386386    }
    387387    else
     
    535535}
    536536
    537 static bool vboxUsbParseLocation(WCHAR *pchLocStr, uint16_t *pHub, uint16_t *pPort)
    538 {
    539 #define PORT_PREFIX L"Port_#"
    540 #define BUS_PREFIX  L".Hub_#"
    541 
    542     *pHub = *pPort = 0xFFFF;
    543 
    544     /* The Location Information is in the format Port_#xxxx.Hub_#xxxx, with 'xxxx'
    545      * being 16-bit hexadecimal numbers. It should be reliable on Windows Vista and
    546      * later. Note that while the port corresponds to the port number aka address,
    547      * the hub number has no discernible relationship to how Windows enumerates hubs.
    548      */
    549 
    550     if (wcsncmp(pchLocStr, PORT_PREFIX, wcslen(PORT_PREFIX)))
    551         return false;
    552 
    553     /* Point to the start of the port number and parse it. */
    554     pchLocStr += wcslen(PORT_PREFIX);
    555     *pPort = vboxUsbParseHexNumU16(&pchLocStr);
    556 
    557     if (wcsncmp(pchLocStr, BUS_PREFIX, wcslen(BUS_PREFIX)))
    558         return false;
    559 
    560     /* Point to the start of the hub/bus number and parse it. */
    561     pchLocStr += wcslen(BUS_PREFIX);
    562     *pHub = vboxUsbParseHexNumU16(&pchLocStr);
    563 
    564     return true;
    565 #undef PORT_PREFIX
    566 #undef BUS_PREFIX
    567 }
    568 
    569537#define VBOXUSBMON_POPULATE_REQUEST_TIMEOUT_MS 10000
    570538
     
    572540{
    573541    NTSTATUS                Status;
     542    USB_TOPOLOGY_ADDRESS    TopoAddr;
    574543    PUSB_DEVICE_DESCRIPTOR  pDevDr = 0;
    575544    ULONG                   ulResultLen;
    576545    DEVPROPTYPE             type;
    577546    WCHAR                   wchPropBuf[256];
    578     uint16_t                port, hub;
     547    uint16_t                port;
    579548    bool                    rc;
    580549
     
    667636        }
    668637
    669         /* Query the location information. The hub number is iffy because the numbering is
    670          * non-obvious and not necessarily stable, but the port number is well defined and useful.
     638        // Disabled, but could be used as a fallback instead of IoGetDevicePropertyData; it should work even
     639        // when this code is entered from the PnP IRP processing path.
     640#if 0
     641        {
     642            HUB_DEVICE_CONFIG_INFO  HubInfo;
     643
     644            memset(&HubInfo, 0, sizeof(HubInfo));
     645            HubInfo.Version = 1;
     646            HubInfo.Length  = sizeof(HubInfo);
     647
     648            NTSTATUS Status = VBoxUsbToolIoInternalCtlSendSync(pDo, IOCTL_INTERNAL_USB_GET_DEVICE_CONFIG_INFO, &HubInfo, NULL);
     649            ASSERT_WARN(Status == STATUS_SUCCESS, ("GET_DEVICE_CONFIG_INFO for PDO(0x%p) failed Status(0x%x)", pDo, Status));
     650            LOG(("Querying hub device config info for PDO(0x%p) done with Status(0x%x)", pDo, Status));
     651
     652            if (Status == STATUS_SUCCESS)
     653            {
     654                uint16_t    vid, pid, rev;
     655                uint8_t     cls, sub, prt;
     656
     657                LOG(("Hub flags: %X\n", HubInfo.HubFlags));
     658                LOG_STRW(HubInfo.HardwareIds.Buffer);
     659                LOG_STRW(HubInfo.CompatibleIds.Buffer);
     660                if (HubInfo.DeviceDescription.Buffer)
     661                    LOG_STRW(HubInfo.DeviceDescription.Buffer);
     662
     663                rc = vboxUsbParseHardwareID(HubInfo.HardwareIds.Buffer, &pid, &vid, &rev);
     664                if (!rc)
     665                {
     666                    /* This *really* should not happen. */
     667                    WARN(("Failed to parse Hardware ID"));
     668                }
     669
     670                rc = vboxUsbParseCompatibleIDs(HubInfo.CompatibleIds.Buffer, &cls, &sub, &prt);
     671                if (!rc)
     672                {
     673                    /* This *really* should not happen. */
     674                    WARN(("Failed to parse Hardware ID"));
     675                    break;
     676                }
     677                LOG(("Parsed HardwareID from IOCTL: vid=%04X, pid=%04X, rev=%04X, class=%02X, subcls=%02X, prot=%02X", vid, pid, rev, cls, sub, prt));
     678
     679                ExFreePool(HubInfo.HardwareIds.Buffer);
     680                ExFreePool(HubInfo.CompatibleIds.Buffer);
     681                if (HubInfo.DeviceDescription.Buffer)
     682                    ExFreePool(HubInfo.DeviceDescription.Buffer);
     683            }
     684        }
     685#endif
     686
     687        /* Query the topology address from the hub driver. This is not trivial to translate to the location
     688         * path, but at least we can get the port number this way.
    671689         */
    672         Status = IoGetDevicePropertyData(pDo, &DEVPKEY_Device_LocationInfo, LOCALE_NEUTRAL, 0, sizeof(wchPropBuf), wchPropBuf, &ulResultLen, &type);
    673         if (!NT_SUCCESS(Status))
    674         {
    675             /* This is useful but not critical. On Windows 7, we may get STATUS_OBJECT_NAME_NOT_FOUND. */
    676             WARN(("IoGetDevicePropertyData failed for DEVPKEY_Device_LocationInfo, Status (0x%x)", Status));
    677             hub = port = 0xffff;
    678             Status = STATUS_SUCCESS;    /* Need to override the IoGetDevicePropertyData return. */
    679         }
    680         else
    681         {
    682             LOG_STRW(wchPropBuf);
    683             rc = vboxUsbParseLocation(wchPropBuf, &hub, &port);
    684             if (!rc)
    685             {
    686                 /* This *really* should not happen but it's not fatal. */
    687                 WARN(("Failed to parse Location Info"));
    688             }
     690        memset(&TopoAddr, 0, sizeof(TopoAddr));
     691        Status = VBoxUsbToolIoInternalCtlSendSync(pDo, IOCTL_INTERNAL_USB_GET_TOPOLOGY_ADDRESS, &TopoAddr, NULL);
     692        ASSERT_WARN(Status == STATUS_SUCCESS, ("GET_TOPOLOGY_ADDRESS for PDO(0x%p) failed Status(0x%x)", pDo, Status));
     693        LOG(("Querying topology address for PDO(0x%p) done with Status(0x%x)", pDo, Status));
     694
     695        port = 0;
     696        if (Status == STATUS_SUCCESS)
     697        {
     698            uint16_t    *pPort = &TopoAddr.RootHubPortNumber;
     699
     700            /* The last non-zero port number is the one we're looking for. It might be on the
     701             * root hub directly, or on some downstream hub.
     702             */
     703            for (int i = 0; i < RT_ELEMENTS(TopoAddr.HubPortNumber) + 1; ++i) {
     704                if (*pPort)
     705                    port = *pPort;
     706                pPort++;
     707            }
     708            LOG(("PCI bus/dev/fn: %02X:%02X:%02X, parsed port: %u\n", TopoAddr.PciBusNumber, TopoAddr.PciDeviceNumber, TopoAddr.PciFunctionNumber, port));
     709            LOG(("RH port: %u, hub ports: %u/%u/%u/%u/%u/%u\n", TopoAddr.RootHubPortNumber, TopoAddr.HubPortNumber[0],
     710                 TopoAddr.HubPortNumber[1], TopoAddr.HubPortNumber[2], TopoAddr.HubPortNumber[3], TopoAddr.HubPortNumber[4], TopoAddr.HubPortNumber[5]));
     711
     712            /* In the extremely unlikely case that the port number does not fit into 8 bits, force
     713             * it to zero to indicate that we can't use it.
     714             */
     715            if (port > 255)
     716                port = 0;
    689717        }
    690718
     
    697725
    698726        LOG(("Device pid=%x vid=%x rev=%x port=%x", pDevDr->idVendor, pDevDr->idProduct, pDevDr->bcdDevice, port));
    699         pDevice->wPort        = port;
     727        pDevice->bPort        = port;
    700728        pDevice->idVendor     = pDevDr->idVendor;
    701729        pDevice->idProduct    = pDevDr->idProduct;
Note: See TracChangeset for help on using the changeset viewer.

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