首页 文章

需要为USB外围设备编写驱动程序吗?

提问于
浏览
1

我正在设计一个USB外围设备,偶尔会连接到Windows PC,并在每个方向传输几KB的数据 . 将有一个定制的PC应用程序,使用专有协议(即USB有效载荷)控制数据传输 .

我在以下链接中看到Microsoft描述了如何为USB设备编写驱动程序 . 但我需要一个吗?

Developing Windows client drivers for USB devices

PC应用程序是我们打算知道如何与设备通信的唯一应用程序,因此从应用程序共享的角度来看,不需要驱动程序 .

我可以直接将自定义协议烘焙到应用程序中,让应用程序对设备说“原始USB”,并且没有单独的驱动程序吗?

2 回答

  • 2

    “原始USB”,不,你不能从应用程序那样做 .

    但是因为您也控制了设备,所以您可以将其显示为Windows提供的设备驱动程序之一,该设备驱动程序的通用性足以执行您想要的任何操作 .

    那些设备类是HID(人机接口设备)和“WinUSB” . 其中,HID是跨平台的,但功能更受限制,WinUSB允许高性能数据传输以及中断 endpoints .

    设置设备的字符串描述符以便Windows自动将其绑定到WinUSB驱动程序的说明是on MSDN

    WinUSB设备是通用串行总线(USB)设备,其固件定义某些Microsoft操作系统(OS)功能描述符,将兼容ID报告为“WINUSB” . WinUSB设备的目的是使Windows能够在没有自定义INF文件的情况下将Winusb.sys加载为设备的功能驱动程序 . 对于WinUSB设备,您无需为设备分发INF文件,从而使最终用户的驱动程序安装过程变得简单 .

  • 1

    no need to write driver 还有另一种方法可以使用WriteFile函数编写你想要的设备:WinUSB,如何做到这一点:

    • 包括WinUsb.h

    • 将WinUsb.lib添加到链接库列表中 .

    • 在Usb100.h中的一些宏 .

    • 使用设备接口GUID获取设备路径 . 正确的GUID是您在INF中用于安装WinUsb.sys的GUID .

    • 通过将在INF中定义的设备接口GUID传递给SetupDiGetClassDevs来获取设备信息集的句柄 . 该函数返回一个HDEVINFO句柄 .

    • 调用SetupDiEnumDeviceInterfaces以枚举系统的设备接口并获取有关设备接口的信息 .

    • 调用SetupDiGetDeviceInterfaceDetail以获取设备接口的详细数据 .

    • 调用GetDevicePath函数以获取设备路径 .

    • 将设备路径传递给CreateFile以获取设备的文件句柄 . Use ReadFile and Write File to communicate with device!

    • 将文件句柄传递给WinUsb_Initialize以初始化WinUSB并获取WinUSB句柄 . 您在调用WinUSB API函数时使用设备的WinUSB句柄来识别设备,而不是设备的文件句柄 .

    对于更高级的解决方案 - 使用功能:

    • WinUsb_QueryDeviceInformation获取设备的速度 .

    • WinUsb_QueryInterfaceSettings获取相应的接口描述符 . WinUSB句柄对应于第一个接口 .

    • WinUsb_QueryPipe获取有关每个 endpoints 的信息 .

    • WinUsb_WritePipe将缓冲区写入设备 - 默认行为:零长度写入在堆栈中向下转发 . 如果传输长度大于最大传输长度,WinUSB会将请求分成较小的最大传输长度请求并按顺序提交 .

    • 更多功能和信息:http://download.microsoft.com/download/9/c/5/9c5b2167-8017-4bae-9fde-d599bac8184a/winusb_howto.docx

    出于调试目的,您可能需要:winusbtrace_tool https://blogs.msdn.microsoft.com/usbcoreblog/2010/02/05/how-to-generate-and-view-a-winusb-debug-trace-log/; Wireshark https://www.wireshark.org带有USBPcap插件 .

    其他例子:http://searchingforbit.blogspot.com/2012/04/winusb-communication-with-stm32-part-1.html . 示例模板随Visual Studio一起提供 .

    您还需要具备编写.inf文件的知识 .

    另一种与USB通信的简便方法 - libusb-win32 https://sourceforge.net/projects/libusb-win32/

    我的简单控制台应用程序将块发送到设备(原始数据立即写入设备绕过堆栈):

    #include "stdafx.h"
    #include <SetupAPI.h>
    #include <Hidsdi.h> 
    #include <devguid.h> 
    #include <winusb.h>
    #include <usb.h>
    #pragma comment(lib, "hid.lib")
    #pragma comment(lib, "setupapi.lib")
    #pragma comment(lib, "winusb.lib")
    #include <iUString.h> 
    
    
    iString<char> DevicePath;
    bool                    WinusbHandle_Open=false;
    bool                    DeviceHandle_Open = false;
    WINUSB_INTERFACE_HANDLE WinusbHandle;
    HANDLE                  DeviceHandle;
    UCHAR usb_out_buffer[64];
    DEFINE_GUID(GUID_DEVCLASS_WINUSB, 0x88bae032L, 0x5a81, 0x49f0, 0xbc, 0x3d, 0xa4, 0xff, 0x13, 0x82, 0x16, 0xd6);
    DEFINE_GUID(GUID_DEVCLASS_STL, 0xf177724dL, 0x74d3, 0x430e, 0x86, 0xb5, 0xf0, 0x36, 0x89, 0x10, 0xeb, 0x23);
    GUID winusb_guid;
    GUID stl_guid;
    
    bool connectusb();
    void  disconnectusb();
    
    
    
    
    int main()
    {
        DWORD n;
        DWORD   numEvents;
        HANDLE rHnd;    
    
    WinusbHandle_Open = false;
    DeviceHandle_Open = false;
    winusb_guid = GUID_DEVCLASS_WINUSB;
    stl_guid = GUID_DEVCLASS_STL;
    usb_out_buffer[0] = 0;
    usb_out_buffer[1] = 1;
    usb_out_buffer[2] = 2;
    usb_out_buffer[3] = 3;
    
    ULONG bytesWritten;
    ULONG timeout;
    timeout = 100;
    rHnd = GetStdHandle(STD_INPUT_HANDLE);
    
    WinUsb_SetPipePolicy(WinusbHandle, 0x01, PIPE_TRANSFER_TIMEOUT, sizeof(ULONG), &timeout);
    
    timeout = TRUE;
    WinUsb_SetPipePolicy(WinusbHandle, 0x01, AUTO_CLEAR_STALL, sizeof(ULONG), &timeout);
    
    
    timeout = TRUE;
    WinUsb_SetPipePolicy(WinusbHandle, 0x01, RAW_IO, sizeof(ULONG), &timeout);//Bypasses queuing and error handling to boost performance for multiple read requests.
    
    
    while (true)
    {
    if ((!WinusbHandle_Open) || (!WinusbHandle_Open)) { if (!connectusb())Sleep(2000); }
    if ((!WinusbHandle_Open) || (!WinusbHandle_Open))continue;
    
    bytesWritten = 0;
    if (!WinUsb_WritePipe(WinusbHandle, 0x01, &usb_out_buffer[0], 2, &bytesWritten, NULL))
    {
        n = GetLastError();
    disconnectusb();
    }
    Sleep(2000);
    }
    disconnectusb();
    return 0;
    }
    
    
    
    
    bool connectusb()
    {
        BOOL                             bResult = FALSE;
        HDEVINFO                         deviceInfo;
        SP_DEVICE_INTERFACE_DATA         interfaceData;
        PSP_DEVICE_INTERFACE_DETAIL_DATA detailData = NULL;
        DWORD n;
        SP_DEVINFO_DATA devinfo;
        BYTE devdetailbuffer[4096];
        bool found;
    
        deviceInfo = SetupDiGetClassDevs(&stl_guid, NULL, NULL, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
        if (deviceInfo == INVALID_HANDLE_VALUE) { return false; }
    
        found = false;
        for (n = 0;; n++)
        {
    
            interfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
    
            if (!SetupDiEnumDeviceInterfaces(deviceInfo, NULL, &stl_guid, n, &interfaceData))
            {
                n = GetLastError();
                break;
            }
    
    
    
    
            detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)devdetailbuffer;
            detailData->cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
            devinfo.cbSize = sizeof(devinfo);
            if (!SetupDiGetDeviceInterfaceDetail(deviceInfo, &interfaceData, detailData, sizeof(devdetailbuffer), NULL, &devinfo)) { printf("SetupDiGetDeviceInterfaceDetail: %u\n", GetLastError()); break; }
            if (IsEqualGUID(devinfo.ClassGuid, winusb_guid))
            {
                if ((-1 != iStrPos(detailData->DevicePath, "VID_0483")) || (-1 != iStrPos(detailData->DevicePath, "vid_0483")))
                {
                    if ((-1 != iStrPos(detailData->DevicePath, "PID_576B")) || (-1 != iStrPos(detailData->DevicePath, "pid_576b")))
                    {
    
                        DevicePath = detailData->DevicePath;
                        found = true;
                        break;
                    }
                }
            }
        }
    
    
    
    SetupDiDestroyDeviceInfoList(deviceInfo);
    if (!found)return false;
    
    
    DeviceHandle = CreateFile(DevicePath.Buffer() ,
        GENERIC_WRITE | GENERIC_READ,
        FILE_SHARE_WRITE | FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
        NULL);
    
    if (INVALID_HANDLE_VALUE == DeviceHandle) {
        n = GetLastError();
    }
    
    if (INVALID_HANDLE_VALUE == DeviceHandle) return false;
    DeviceHandle_Open = true;
    
    
    
    if (!WinUsb_Initialize(DeviceHandle, &WinusbHandle))
     {
         n = GetLastError();
         CloseHandle(DeviceHandle); DeviceHandle_Open = false;
         return false;
     }
    
    
    
    WinusbHandle_Open = true;
    return true;
    }
    
    void  disconnectusb()
    {
        if (WinusbHandle_Open) { WinUsb_Free(WinusbHandle); WinusbHandle_Open = false; }
        if (DeviceHandle_Open) { CloseHandle(DeviceHandle); DeviceHandle_Open = false; }
    }
    

相关问题