zoukankan      html  css  js  c++  java
  • MSDN WinUSB Example

    The WinUSB user-mode library uses device interface classes to communicate with the kernel-mode USB stack. The INF file that loads winusb.sys specifies a device interface class GUID in the registry. When winusb.sys loads, it calls IoRegisterDeviceInterface to register a device interface that belongs to the device interface class that is specified in the registry.

    User-mode software must call SetupDiGetClassDevs to enumerate the registered device interfaces that are associated with one of these device interface classes. The user-mode software must then pass the symbolic link of a device interface to the WinUsb_Initialize routine to obtain a WinUSB handle for the device interface.

    The code example in this topic illustrates how user-mode software can enumerate device interfaces and obtain a WinUSB handle. For this example, assume that the INF file stores a device interface class GUID in the registry as follows.

    HKR,,DeviceInterfaceGUIDs, 0x10000,"{058815B2-9805-47d3-B7D5-ABC464D3CA06}"

    The example user-mode software calls SetupDiGetClassDevs to query for information about all of the registered device interfaces in the device interface class that is associated with this GUID. SetupDiGetClassDevs then returns a handle to a device information set that contains information about the device interfaces.

    #include initguid.h
    #include setupapi.h

    // Example GUID definition. This GUID must match 
    // the GUID that was specified in the INF file 
    // that loaded winusb.sys. 

    DEFINE_GUID(InterfaceClassGuidConstant,0x058815B2, 0x9805, 0x47d3, 0xB7, 0xD5, 0xAB, 0xC4, 0x64, 0xD3, 0xCA, 0x06);
    GUID InterfaceClassGuid = InterfaceClassGuidConstant;

    // Define a handle to a device information set.
    HDEVINFO  hdevClassInfo; 

    // Retrieve a device information set.
    hdevClassInfo = SetupDiGetClassDevs
            (&InterfaceClassGuid, NULL, NULL,
            DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
    if (hdevClassInfo == INVALID_HANDLE_VALUE) { 
            // ERROR }

    The call to SetupDiGetClassDevs in the preceding code example requests registered device interfaces (DIGCF_DEVICEINTERFACE) for the device interface class that the InterfaceClassGuid variable specifies. Only device interfaces for presently installed devices (DIGCF_PRESENT) are returned.

    Next, the example application must iteratively call SetupDiEnumDeviceInterfaces to determine how many elements are in the device information set.

    // Initialize variables.
    SP_DEVICE_INTERFACE_DATA  DeviceData;
    DeviceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);

    for (nMemberIndex = 0; TRUE; nMemberIndex++) {
        nStatus = SetupDiEnumDeviceInterfaces (hdevClassInfo, NULL,
        (LPGUID)&InterfaceGuid, nMemberIndex,
        &DeviceData);
        if (nStatus != TRUE) break;
    }

    Now, the example application must enumerate the registered device interfaces that are associated with the device interface class. The example application calls SetupDiEnumDeviceInterfaces iteratively, once again; but now it retrieves hardware identifiers (IDs) and symbolic links for each registered interface. The application will use the symbolic links to obtain a WinUSB device interface handle.

    // Allocate array that will hold information about the devices that
    // are associated with this interface class.
    struct DeviceData {
      TCHAR  *HardwareId;
      TCHAR  *Path; // symbolic link
      TCHAR  *FriendlyName;
      DWORD  DeviceInstance;
    } *DeviceList;
    DeviceList = (struct DeviceData *) malloc 
        ((nMemberIndex + 1) * sizeof(struct DeviceData));
    if (DeviceList == NULL) { // ERROR }

    // Enumerate devices that are associated with the interface.
    for (i = 0; i < nMemberIndex; i++) {
        nStatus = SetupDiEnumDeviceInterfaces
                     (hdevClassInfo, NULL,
                     (LPGUID)&InterfaceGuid, i,
                     &DeviceData);
        if (nStatus != TRUE) break;

        // Retrieve the size of the device data.
        nStatus = SetupDiGetDeviceInterfaceDetail
                     (hdevClassInfo, &DeviceData, 
                     NULL, 0, &nSize, NULL);                  
        if (nStatus != TRUE) break;

        // Allocate memory for the device detail buffer. 
        SP_DEVICE_INTERFACE_DATA  pBuffer;
        pBuffer = (PSP_INTERFACE_DEVICE_DETAIL_DATA)
                  malloc (nSize));
        if (pBuffer == NULL) { // ERROR }

        // Initialize variables.
        DeviceData.cbSize =
            sizeof(SP_INTERFACE_DEVICE_DATA);
        nStatus = SetupDiGetDeviceInterfaceDetail
                     (hdevClassInfo, &DeviceData,
                     pBuffer, nSize, NULL,&DeviceData));
        if (nStatus = FALSE)) { // ERROR }


        //****************************************
        // Save the device interface path: 
        //           This path can be used to open 
        //           the interface with CreateFile.
        //****************************************

        // Calculate the length of the path string. 
        // Add 1 for the terminating NULL character.
        nLen = strlen(DeviceData.DevicePath) + 1; 
        DeviceList[i].Path = 
           (TCHAR *) malloc (nLen * sizeof(TCHAR));
        StringCchCopy(DeviceList[i].Path, nLen, 
           DeviceData.DevicePath);

        // Save the device instance.
        DeviceList[i].DeviceInstance = 
           DeviceInfoData.DevInst;

        //****************************************
        // Retrieve registry values.
        //****************************************

        // Initialize variables that are used in registry
        // operations.
        SP_DEVINFO_DATA DevInfoData;

        //****************************************
        // Retrieve the device friendly name.
        //****************************************

        // Query for the size of the friendly name.
        nStatus = SetupDiGetDeviceRegistryProperty
                    (hdevClassInfo, &DevnfoData,
                    SPDRP_FRIENDLYNAME, &dwRegType,
                    NULL, 0, &dwRegSize);
        if (nStatus == FALSE) { // ERROR }

        // Allocate buffer for the friendly name.
        pBuffer = (TCHAR *) malloc 
                      (dwRegSize * sizeof(TCHAR));
        if (pBuffer =  == NULL) { // ERROR }

        // Retrieve the friendly name.
        nStatus = SetupDiGetDeviceRegistryProperty
                    (hdevClassInfo, &DevInfoData,
                    SPDRP_FRIENDLYNAME, NULL,
                    (PBYTE) *pBuffer, dwRegSize, NULL);
        if (nStatus == FALSE) { // ERROR }

        // Store the friendly name for this device.
        DeviceList[i].FriendlyName = pBuffer;

        // ************************************
        // Retrieve the hardware ID.
        // ************************************

        // Query for the size of the hardware ID.
        nStatus = SetupDiGetDeviceRegistryProperty
                    (hdevClassInfo, &DevnfoData,
                    SPDRP_HARDWAREID, &dwRegType,
                    NULL, 0, &dwRegSize);
        if (nStatus == FALSE) { // ERROR }

        // Allocate a buffer for the hardware ID.
        pBuffer = (TCHAR *) malloc 
           (dwRegSize * sizeof(TCHAR));
        if (pBuffer =  == NULL) { // ERROR }

        // Retrieve the hardware ID.
        nStatus = SetupDiGetDeviceRegistryProperty
                    (hdevClassInfo, &DevInfoData,
                    SPDRP_HARDWAREID, NULL,
                    (PBYTE) *pBuffer, dwRegSize, NULL);
        if (nStatus == FALSE) { // ERROR }

        // Store the hardware ID for this device.
        DeviceList[i].HardwareId = pBuffer;
    }

    The example software next opens the first device interface in the device interface list. The device interface must be opened with the overlapped flag.

    // Create a symbolic link to device interface
    LPCTSTR Path; 
    HANDLE DeviceInterfaceHandle;

    Path = DeviceList[0].Path;
    DeviceInterfaceHandle = CreateFile (Path,
                            GENERIC_READ | GENERIC_WRITE,
                            FILE_SHARE_READ |
                            FILE_SHARE_WRITE,
                            NULL,
                            OPEN_EXISTING,
                            FILE_FLAG_OVERLAPPED,
                            NULL);
    if (DeviceInterfaceHandle == INVALID_HANDLE_VALUE) { // ERROR }

    After the example software opens the device interface, the application must call WinUsb_Initialize to obtain a WinUSB handle.

    WINUSB_INTERFACE_HANDLE WinUSBHandle;
    nStatus = WinUsb_Initialize (DeviceInterfaceHandle, &WinUSBHandle);
    if (nStatus = FALSE) { // ERROR }

    The example software manages a composite USB device, whose first interface (interface 0) contains bulk transfer endpoints. In the following code example, the example software:

    1. Calls WinUsb_QueryInterfaceSettings to retrieve the interface descriptor (USB_INTERFACE_DESCRIPTOR) for interface 0.
    2. Calls WinUsb_QueryPipe to query for information (WINUSB_PIPE_INFORMATION) about the pipe for endpoint 0.
    3. Verifies that the pipe is a bulk transfer pipe.
    4. Calls WinUsb_SetPipePolicy to set the time-out interval for the pipe.


    // ********************************************
    // The first interface is for bulk transfers.
    // ********************************************

    USB_INTERFACE_DESCRIPTOR interface;
    nStatus = WinUsb_QueryInterfaceSettings
                (WinUSBHandle, 0, &interface);
    if (nStatus = FALSE) { // ERROR }

    WINUSB_PIPE_INFORMATION pipe;
    nStatus = WinUsb_QueryPipe (WinUSBHandle, 0, 
                (UCHAR) 0, &pipe);
    if (nStatus == FALSE) { // ERROR }

    Verify that the pipe type is set to the correct USBD_PIPE_TYPE enumeration value before calling WinUsb_SetPipePolicy.

    if (pipe.PipeType != UsbdPipeTypeBulk) { // ERROR }

    // Set the transfer time-out interval for endpoint 0
    // to 10000 milliseconds.
    UCHAR timeout = 10000;
    nStatus = WinUsb_SetPipePolicy (WinUSBHandle,
                pipe.PipeId, PIPE_TRANSFER_TIMEOUT,
                sizeof (timeout), &timeout);
    if (nStatus == FALSE) { // ERROR }

    The second interface (interface 1) contains interrupt transfer endpoints. In the following code example, the example software

    1. Calls WinUsb_GetAssociatedInterface to obtain a handle to interface 1.
    2. Calls WinUsb_QueryInterfaceSettings to retrieve the interface descriptor for interface 1.
    3. Calls WinUsb_QueryPipe to query for information about the pipe for endpoint 0.
    4. Verifies that the pipe is an interrupt transfer pipe.


    // *************************************************
    // The second interface is for interrupt transfers
    // *************************************************

    WINUSB_INTERFACE_HANDLE WinUSBHandleAlt;
    nStatus = WinUsb_GetAssociatedInterface (WinUSBHandle, 0, 
                            &WinUSBHandleAlt);
    if (nStatus == FALSE) { // ERROR }

    nStatus = WinUsb_QueryInterfaceSettings (WinUSBHandleAlt, 0,
                            &interface);
    if (nStatus == FALSE) { // ERROR }

    nStatus = WinUsb_QueryPipe (WinUSBHandleAlt, 0, (UCHAR) 0, &pipe);
    if (nStatus == FALSE) { // ERROR }

    if (pipe.PipeType != UsbdPipeTypeInterrupt) { // ERROR } 

  • 相关阅读:
    剑指offer--26.顺时针打印矩阵
    剑指offer--25.二叉树的镜像
    剑指offer--24.树的子结构
    剑指offer--23.合并两个排序的链表
    剑指offer--22.反转链表
    剑指offer--21.链表中倒数第k个结点
    剑指offer--20.矩形覆盖
    剑指offer--19.重建二叉树
    剑指offer--18.从尾到头打印链表
    剑指offer--17.第一个只出现一次的字符
  • 原文地址:https://www.cnblogs.com/shangdawei/p/4662223.html
Copyright © 2011-2022 走看看