zoukankan      html  css  js  c++  java
  • 遍历 USB devcie,读取设备描述符 device descriptor【转】

    转自:http://blog.csdn.net/flyyyri/article/details/5480347

    理论:
        对于USB接口的设备,现在越来越多了。本篇我们就通过获取一个USB扫描仪设备中的序列号,来介绍如何获取usb设备的一些硬件信息。对于usb设备都是采用HCD0,HCD1,HCD2,HCD3等符号描述的。如下图:


    因此,有了这个名字,我们就可以使用CreateFile来打开usb设备。然后使用DeviceIoControl函数与usb设备通讯了。HCD是host controller driver的简写。需要了解详情的,还要仔细的阅读usb协议。
    usb的通讯基本步骤如下图所示:
     

    基本步骤:
        1)打开HCD%X
        2) 得到上面的USB root hub
        3) 遍历usb root hub上连接的usb 设备。获取信息
        4)如果有多个usb口,循环前3步。

    下面介绍通讯用的几个IOCTL:
    1)USB_HCD_DRIVERKEY_NAME ,用于获取USB设备驱动在注册表中的键名。相应的一个结构体是:
    typedef struct _USB_HCD_DRIVERKEY_NAME 
    {
       ULONG   ActualLength;
       WCHAR   DriverKeyName[1];
    } USB_HCD_DRIVERKEY_NAME, *PUSB_HCD_DRIVERKEY_NAME;

    2)IOCTL_USB_GET_ROOT_HUB_NAME,用于获取root hub 键名。使用的结构体,跟上面一样。
    typedef struct _USB_ROOT_HUB_NAME 
    {
        ULONG ActualLength; 
        WCHAR RootHubName[1]; 
    } USB_ROOT_HUB_NAME, *PUSB_ROOT_HUB_NAME;

    3)IOCTL_USB_GET_NODE_INFORMATION,用于获取连接在root hub上的节点设备信息。也就是我们接在usb口上的所有usb设备的信息,对应的结构体:
    typedef struct _USB_NODE_INFORMATION 
    {
        USB_HUB_NODE NodeType;    
        union {
            USB_HUB_INFORMATION HubInformation;
            USB_MI_PARENT_INFORMATION MiParentInformation;
        } u;
    } USB_NODE_INFORMATION, *PUSB_NODE_INFORMATION;

    typedef struct _USB_MI_PARENT_INFORMATION 
    {
        ULONG NumberOfInterfaces;
    } USB_MI_PARENT_INFORMATION, *PUSB_MI_PARENT_INFORMATION;

    typedef struct _USB_HUB_INFORMATION
    {
        USB_HUB_DESCRIPTOR HubDescriptor;

        BOOLEAN HubIsBusPowered;

    } USB_HUB_INFORMATION, *PUSB_HUB_INFORMATION;


    typedef struct _USB_HUB_DESCRIPTOR
    {
        UCHAR        bDescriptorLength;      // Length of this descriptor
        UCHAR        bDescriptorType;        // Hub configuration type
        UCHAR        bNumberOfPorts;         // number of ports on this hub
        USHORT       wHubCharacteristics;    // Hub Charateristics
        UCHAR        bPowerOnToPowerGood;    // port power on till power good in 2ms
        UCHAR        bHubControlCurrent;     // max current in mA
        //
        // room for 255 ports power control and removable bitmask
        UCHAR        bRemoveAndPowerMask[64];       
    } USB_HUB_DESCRIPTOR, *PUSB_HUB_DESCRIPTOR;

    4) IOCTL_USB_GET_NODE_CONNECTION_INFORMATION, 用于获取接在usb口上的单个usb设备的信息,对应的结构体:

    typedef struct _USB_NODE_CONNECTION_INFORMATION 
    {
        ULONG ConnectionIndex;
        USB_DEVICE_DESCRIPTOR DeviceDescriptor;
        UCHAR CurrentConfigurationValue;
        BOOLEAN LowSpeed;

        BOOLEAN DeviceIsHub;

        USHORT DeviceAddress;

        ULONG NumberOfOpenPipes;

        USB_CONNECTION_STATUS ConnectionStatus;
        USB_PIPE_INFO PipeList[0];
    } USB_NODE_CONNECTION_INFORMATION, *PUSB_NODE_CONNECTION_INFORMATION;

    4)IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION, 用于获取usb设备的描述信息。
    typedef struct _USB_DEVICE_DESCRIPTOR 
    {
        UCHAR bLength;
        UCHAR bDescriptorType;
        USHORT bcdUSB;
        UCHAR bDeviceClass;
        UCHAR bDeviceSubClass;
        UCHAR bDeviceProtocol;
        UCHAR bMaxPacketSize0;
        USHORT idVendor;
        USHORT idProduct;
        USHORT bcdDevice;
        UCHAR iManufacturer;
        UCHAR iProduct;
        UCHAR iSerialNumber;
        UCHAR bNumConfigurations;
    } USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;

    typedef struct _USB_DEVICE_DESCRIPTOR 
    {
        UCHAR bLength;
        UCHAR bDescriptorType;
        USHORT bcdUSB;
        UCHAR bDeviceClass;
        UCHAR bDeviceSubClass;
        UCHAR bDeviceProtocol;
        UCHAR bMaxPacketSize0;
        USHORT idVendor;
        USHORT idProduct;
        USHORT bcdDevice;
        UCHAR iManufacturer;
        UCHAR iProduct;
        UCHAR iSerialNumber;
        UCHAR bNumConfigurations;
    } USB_DEVICE_DESCRIPTOR, *PUSB_DEVICE_DESCRIPTOR;

    typedef enum _USB_CONNECTION_STATUS 
    {
        NoDeviceConnected,
        DeviceConnected,

        /* failure codes, these map to fail reasons */
        DeviceFailedEnumeration,
        DeviceGeneralFailure,
        DeviceCausedOvercurrent,
        DeviceNotEnoughPower,
        DeviceNotEnoughBandwidth,
        DeviceHubNestedTooDeeply,
        DeviceInLegacyHub
    } USB_CONNECTION_STATUS, *PUSB_CONNECTION_STATUS;

    typedef struct _USB_PIPE_INFO
    {
        USB_ENDPOINT_DESCRIPTOR EndpointDescriptor;
        ULONG ScheduleOffset;
    } USB_PIPE_INFO, *PUSB_PIPE_INFO;

    typedef struct _USB_ENDPOINT_DESCRIPTOR
    {
        UCHAR bLength;
        UCHAR bDescriptorType;
        UCHAR bEndpointAddress;
        UCHAR bmAttributes;
        USHORT wMaxPacketSize;
        UCHAR bInterval;
    } USB_ENDPOINT_DESCRIPTOR, *PUSB_ENDPOINT_DESCRIPTOR;

    需要注意一点,如果要得到pid,vid,则直接从USB_DEVICE_DESCRIPTOR结构中取出idVendor,idProduct这两项的值就行了。如果要得到序列号,则不是取出 iSerialNumber就可以的。这里的 iSerialNumber仅仅是一个索引值。如果想得到序列号,就需要定义一个结构,然后给设备发送个请求。请求的结构如下图:

    代码参照GetStringDescriptor函数。可以根据iSerialNumber偏移,取出其对应的字符串,存放在上图USB_STRING_DESCRIPTOR结构中。
    #include "windows.h"
    #include "PlkUsbIo.h"
    #include <malloc.h>

    #define NUM_HCS_TO_CHECK 10

    /******************************************************************/
    bool EnumUsbDevice();
    PCHAR GetDriverKeyName(HANDLE Hub, ULONG ConnectionIndex);
    PCHAR GetHCDDriverKeyName(HANDLE HCD);
    PCHAR GetRootHubName(HANDLE HostController);
    PCHAR WideStrToMultiStr(PWCHAR WideStr);
    bool GetStringDescriptor (
            HANDLE hHubDevice,
            ULONG   ConnectionIndex,
            UCHAR   DescriptorIndex    ,
            CHAR * outBuff);
        
    /******************************************************************/

    int main(int argc, char* argv[])
    {
        EnumUsbDevice();
        return 0;
    }

    bool EnumUsbDevice()
    {
        char        HCName[16];
        int         HCNum;
        HANDLE      hHCDev;
        PCHAR       rootHubName;

        ULONG       index;
        BOOL        success;

        PUSB_NODE_CONNECTION_INFORMATION    connectionInfo;
        HANDLE hHubDevice;

        for (HCNum = 0; HCNum < NUM_HCS_TO_CHECK; HCNum++)
        {
            wsprintf(HCName, "////.//HCD%d", HCNum);
            hHCDev = CreateFile(HCName,
                GENERIC_WRITE,
                FILE_SHARE_WRITE,
                NULL,
                OPEN_EXISTING,
                0,
                NULL);
            if (hHCDev == INVALID_HANDLE_VALUE)    
                break;
            
            PCHAR driverKeyName, deviceDesc;
            driverKeyName = GetHCDDriverKeyName(hHCDev);
            if(driverKeyName == NULL)
                goto end;    
            
        
            ULONG nBytes;
            rootHubName =(char*) GetRootHubName(hHCDev);
            if(rootHubName==NULL)
                goto end;
        
            PUSB_NODE_INFORMATION HubInfo;
            HubInfo = (PUSB_NODE_INFORMATION)malloc(sizeof(USB_NODE_INFORMATION));
            PCHAR deviceName;
            deviceName = (PCHAR)malloc(strlen(rootHubName) + sizeof("////.//"));
            if (rootHubName != NULL)
            {
                strcpy(deviceName, "////.//");
                strcpy(deviceName + sizeof("////.//") - 1, rootHubName);
                hHubDevice = CreateFile(deviceName,
                    GENERIC_WRITE,
                    FILE_SHARE_WRITE,
                    NULL,
                    OPEN_EXISTING,
                    0,
                    NULL);
                free(deviceName);
                if (hHubDevice == INVALID_HANDLE_VALUE)
                    goto end;
                
                success = DeviceIoControl(hHubDevice,
                    IOCTL_USB_GET_NODE_INFORMATION,
                    HubInfo,
                    sizeof(USB_NODE_INFORMATION),
                    HubInfo,
                    sizeof(USB_NODE_INFORMATION),
                    &nBytes,
                    NULL);
                if (!success)
                    goto end;
               

            }

            int port;
            port=HubInfo->u.HubInformation.HubDescriptor.bNumberOfPorts;
            for (index=1; index <= port; index++)
            {
                ULONG nBytes;
                nBytes = sizeof(USB_NODE_CONNECTION_INFORMATION) +
                    sizeof(USB_PIPE_INFO) * 30;
                connectionInfo = (PUSB_NODE_CONNECTION_INFORMATION)malloc(nBytes);
                if (connectionInfo == NULL)
                    goto end;
                
                connectionInfo->ConnectionIndex = index;
                success = DeviceIoControl(hHubDevice,
                    IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,
                    connectionInfo,
                    nBytes,
                    connectionInfo,
                    nBytes,
                    &nBytes,
                    NULL);
                if (!success)
                {
                    free(connectionInfo);
                    goto end;
                }
           

                deviceDesc = NULL;
                if (connectionInfo->ConnectionStatus != NoDeviceConnected)
                {
                    driverKeyName = GetDriverKeyName(hHubDevice,
                        index);
                    if (driverKeyName)
                    {
                        free(driverKeyName);
                    }
                }

                if (connectionInfo->ConnectionStatus == DeviceConnected)
                {
                    //取出序列号索引
                    UCHAR nSerialno = connectionInfo->DeviceDescriptor.iSerialNumber;
                    CHAR OutBuff[20] = {0};
                    GetStringDescriptor(hHubDevice,connectionInfo->ConnectionIndex,nSerialno,OutBuff);

                    //判断序列号是否有效
                    if(序列号是否有效)
                    {
                          CloseHandle(hHubDevice);
                          CloseHandle(hHCDev);
                         return true;
                    }
                }

            }
    end:; 
        }

        CloseHandle(hHubDevice);
        CloseHandle(hHCDev);
        return false;
    }

    PCHAR GetDriverKeyName(HANDLE Hub, ULONG ConnectionIndex)
    {
        BOOL                                success;
        ULONG                               nBytes;
        USB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyName;
        PUSB_NODE_CONNECTION_DRIVERKEY_NAME driverKeyNameW;
        PCHAR                               driverKeyNameA;

        driverKeyNameW = NULL;
        driverKeyNameA = NULL;

        driverKeyName.ConnectionIndex = ConnectionIndex;

        success = DeviceIoControl(Hub,
            IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
            &driverKeyName,
            sizeof(driverKeyName),
            &driverKeyName,
            sizeof(driverKeyName),
            &nBytes,
            NULL);

        if (!success)
        {
            goto GetDriverKeyNameError;
        }

        nBytes = driverKeyName.ActualLength;

        if (nBytes <= sizeof(driverKeyName))
        {
            goto GetDriverKeyNameError;
        }

        driverKeyNameW = (PUSB_NODE_CONNECTION_DRIVERKEY_NAME)malloc(nBytes);

        if (driverKeyNameW == NULL)
        {
            goto GetDriverKeyNameError;
        }

        driverKeyNameW->ConnectionIndex = ConnectionIndex;

        success = DeviceIoControl(Hub,
            IOCTL_USB_GET_NODE_CONNECTION_DRIVERKEY_NAME,
            driverKeyNameW,
            nBytes,
            driverKeyNameW,
            nBytes,
            &nBytes,
            NULL);

        if (!success)
        {
            goto GetDriverKeyNameError;
        }
        driverKeyNameA = WideStrToMultiStr(driverKeyNameW->DriverKeyName);
        free(driverKeyNameW);

        return driverKeyNameA;


    GetDriverKeyNameError:
        if (driverKeyNameW != NULL)
        {
            free(driverKeyNameW);
            driverKeyNameW = NULL;
        }

        return NULL;
    }
    PCHAR GetRootHubName(HANDLE HostController)
    {
        BOOL                success;
        ULONG               nBytes;
        USB_ROOT_HUB_NAME   rootHubName;
        PUSB_ROOT_HUB_NAME rootHubNameW;
        PCHAR               rootHubNameA;

        rootHubNameW = NULL;
        rootHubNameA = NULL;

        success = DeviceIoControl(HostController,
            IOCTL_USB_GET_ROOT_HUB_NAME,
            0,
            0,
            &rootHubName,
            sizeof(rootHubName),
            &nBytes,
            NULL);

        if (!success)
        {
            goto GetRootHubNameError;
        }

        nBytes = rootHubName.ActualLength;

        rootHubNameW =(PUSB_ROOT_HUB_NAME) malloc(nBytes);

        if (rootHubNameW == NULL)
        {

            goto GetRootHubNameError;
        }

        success = DeviceIoControl(HostController,
            IOCTL_USB_GET_ROOT_HUB_NAME,
            NULL,
            0,
            rootHubNameW,
            nBytes,
            &nBytes,
            NULL);

        if (!success)
        {
            goto GetRootHubNameError;
        }

        rootHubNameA = WideStrToMultiStr(rootHubNameW->RootHubName);
        free(rootHubNameW);

        return rootHubNameA;


    GetRootHubNameError:
        if (rootHubNameW != NULL)
        {
            free(rootHubNameW);
            rootHubNameW = NULL;
        }

        return NULL;
    }
    PCHAR GetHCDDriverKeyName(HANDLE HCD)
    {
        BOOL                    success;
        ULONG                   nBytes;
        USB_HCD_DRIVERKEY_NAME driverKeyName;
        PUSB_HCD_DRIVERKEY_NAME driverKeyNameW;
        PCHAR                   driverKeyNameA;

        driverKeyNameW = NULL;
        driverKeyNameA = NULL;

        success = DeviceIoControl(HCD,
            IOCTL_GET_HCD_DRIVERKEY_NAME,
            &driverKeyName,
            sizeof(driverKeyName),
            &driverKeyName,
            sizeof(driverKeyName),
            &nBytes,
            NULL);

        if (!success)
        {
            goto GetHCDDriverKeyNameError;
        }

        nBytes = driverKeyName.ActualLength;

        if (nBytes <= sizeof(driverKeyName))
        {
            goto GetHCDDriverKeyNameError;
        }

        driverKeyNameW =(PUSB_HCD_DRIVERKEY_NAME) malloc(nBytes);

        if (driverKeyNameW == NULL)
        {
            goto GetHCDDriverKeyNameError;
        }

        success = DeviceIoControl(HCD,
            IOCTL_GET_HCD_DRIVERKEY_NAME,
            driverKeyNameW,
            nBytes,
            driverKeyNameW,
            nBytes,
            &nBytes,
            NULL);

        if (!success)
        {
            goto GetHCDDriverKeyNameError;
        }

        driverKeyNameA = WideStrToMultiStr(driverKeyNameW->DriverKeyName);
        free(driverKeyNameW);

        return driverKeyNameA;


    GetHCDDriverKeyNameError:
        if (driverKeyNameW != NULL)
        {
            free(driverKeyNameW);
            driverKeyNameW = NULL;
        }

        return NULL;
    }

    PCHAR WideStrToMultiStr(PWCHAR WideStr)
    {
        ULONG nBytes;
        PCHAR MultiStr;
        nBytes = WideCharToMultiByte(
            CP_ACP,
            0,
            WideStr,
            -1,
            NULL,
            0,
            NULL,
            NULL);

        if (nBytes == 0)
        {
            return NULL;
        }
        MultiStr =(PCHAR) malloc(nBytes);

        if (MultiStr == NULL)
        {
            return NULL;
        }
        nBytes = WideCharToMultiByte(
            CP_ACP,
            0,
            WideStr,
            -1,
            MultiStr,
            nBytes,
            NULL,
            NULL);

        if (nBytes == 0)
        {
            free(MultiStr);
            return NULL;
        }

        return MultiStr;
    }


    bool    GetStringDescriptor (
            HANDLE hHubDevice,
            ULONG   ConnectionIndex,
            UCHAR   DescriptorIndex    ,
            CHAR * outBuff
            )
        {
            BOOL    success;
            ULONG   nBytes;
            ULONG   nBytesReturned;

            UCHAR   stringDescReqBuf[sizeof(USB_DESCRIPTOR_REQUEST) + MAXIMUM_USB_STRING_LENGTH];

            PUSB_DESCRIPTOR_REQUEST stringDescReq;
            PUSB_STRING_DESCRIPTOR stringDesc;

            nBytes = sizeof(stringDescReqBuf);

            stringDescReq = (PUSB_DESCRIPTOR_REQUEST)stringDescReqBuf;
            stringDesc = (PUSB_STRING_DESCRIPTOR)(stringDescReq+1);

        
            ::ZeroMemory(stringDescReq,nBytes);
            stringDescReq->ConnectionIndex = ConnectionIndex;
            stringDescReq->SetupPacket.wValue = (USB_STRING_DESCRIPTOR_TYPE << 8) | DescriptorIndex;
            stringDescReq->SetupPacket.wIndex = GetSystemDefaultLangID();
            stringDescReq->SetupPacket.wLength = (USHORT)(nBytes - sizeof(USB_DESCRIPTOR_REQUEST));

            success = DeviceIoControl(hHubDevice,IOCTL_USB_GET_DESCRIPTOR_FROM_NODE_CONNECTION,
                                    stringDescReq,nBytes,
                                    stringDescReq,nBytes,
                                    &nBytesReturned,NULL);

            if (!success || nBytesReturned < 2)
                return false;

            if (stringDesc->bDescriptorType != USB_STRING_DESCRIPTOR_TYPE)
                return false;

            if (stringDesc->bLength != nBytesReturned - sizeof(USB_DESCRIPTOR_REQUEST))
                return false;

            if (stringDesc->bLength % 2 != 0)
                return false;

            WCHAR * wChar = new WCHAR[stringDesc->bLength + 1];
            memcpy(wChar,stringDesc->bString,stringDesc->bLength);
            char *szTemp = WideStrToMultiStr(wChar);
            lstrcpy(outBuff, szTemp);
            
            if(szTemp)
            delete []szTemp;
            
            if(wChar)
            delete []wChar;
            return true;
        }

    分析:

    1)首先假定有10个usb接口
        #define NUM_HCS_TO_CHECK 10

    2)循环打开这10个usb端口,如果端口没有这么多,调用CreateFile,就会返回 INVALID_HANDLE_VALUE。
        for (HCNum = 0; HCNum < NUM_HCS_TO_CHECK; HCNum++)
        {
            wsprintf(HCName, "////.//HCD%d", HCNum);
            hHCDev = CreateFile(HCName,
                GENERIC_WRITE,
                FILE_SHARE_WRITE,
                NULL,
                OPEN_EXISTING,
                0,
                NULL);
            if (hHCDev == INVALID_HANDLE_VALUE)    
                break;

    3)获取root hub
           ULONG nBytes;
            rootHubName =(char*) GetRootHubName(hHCDev);
            if(rootHubName==NULL)
                goto end;

    4) 遍历连接在root hub上的节点
            int port;
            port=HubInfo->u.HubInformation.HubDescriptor.bNumberOfPorts;
            for (index=1; index <= port; index++)
            {
                ULONG nBytes;
                nBytes = sizeof(USB_NODE_CONNECTION_INFORMATION) +
                    sizeof(USB_PIPE_INFO) * 30;
                connectionInfo = (PUSB_NODE_CONNECTION_INFORMATION)malloc(nBytes);
                if (connectionInfo == NULL)
                    goto end;
                
                connectionInfo->ConnectionIndex = index;
                success = DeviceIoControl(hHubDevice,
                    IOCTL_USB_GET_NODE_CONNECTION_INFORMATION,
                    connectionInfo,
                    nBytes,
                    connectionInfo,
                    nBytes,
                    &nBytes,
                    NULL);
                if (!success)
                {
                    free(connectionInfo);
                    goto end;
                }

    5)根据节点的连接状态,获取节点信息,得到序列号。
        if (connectionInfo->ConnectionStatus == DeviceConnected)
                {
                    //取出序列号索引
                    UCHAR nSerialno = connectionInfo->DeviceDescriptor.iSerialNumber;
                    CHAR OutBuff[20] = {0};
                    GetStringDescriptor(hHubDevice,connectionInfo->ConnectionIndex,nSerialno,OutBuff);

    6)得到序列号的方法在理论部分已经详细说明了,对应的函数是GetStringDescriptor,这里不再重复。


    本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/jtujtujtu/archive/2009/11/19/4836900.aspx

  • 相关阅读:
    js中location.href的用法
    entityframework单例模式泛型用法
    [C#]从URL中获取路径的最简单方法-new Uri(url).AbsolutePath
    等到花儿也谢了的await
    ASP.NET MVC下的异步Action的定义和执行原理
    实际案例:在现有代码中通过async/await实现并行
    ASP.NET MVC Controllers and Actions
    扩展HtmlHelper
    iOS开发网络篇—XML数据的解析
    IOS学习:常用第三方库(GDataXMLNode:xml解析库)
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/5063298.html
Copyright © 2011-2022 走看看