2016-07-22 134 views
1

我正在设计一个USB外围设备,它偶尔会连接到Windows PC,并在每个方向上传输几KB的数据。将会有一个定制的PC应用程序使用专有协议(即USB有效载荷)来控制数据传输。需要为USB外围设备编写驱动程序?

我在以下链接中看到微软描述的如何为USB设备编写驱动程序。但是我需要一个吗?

Developing Windows client drivers for USB devices

的PC应用程序,我们打算知道如何与设备进行通信的唯一的应用程序,所以没有需要从应用程序共享的角度来看一个驱动程序。

我可以只直接烤自定义协议到应用程序,让应用程序说“生USB”的设备,没有一个单独的驱动程序吗?

回答

2

“原始USB”,不,你不能这样做,从一个应用程序。

但是因为你控制装置也可以使它看起来针对Windows提供了这是通用的,足以做几乎任何你想要的设备驱动程序的设备类之一。

这些设备类的HID(人机接口设备)和 “了WinUSB”。其中,HID是跨平台的,但功能有限,WinUSB允许高性能数据传输以及中断端点。

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

一个了WinUSB设备是通用串行总线(USB)设备,其固件定义某些Microsoft操作系统( OS)功能描述符,将兼容ID报告为"WINUSB"

一个了WinUSB设备的目的是为了使Windows能够加载Winusb.sys作为设备的功能驱动程序没有自定义INF文件。对于WinUSB设备,您不需要为设备分发INF文件,从而使最终用户的驱动程序安装过程变得简单。

+0

,我发现这个信息也是。 https://en.wikipedia.org/wiki/WinUSB –

+0

为什么人们如此害怕编写设备驱动程序?什么是如此复杂呢?当然,一个驱动程序不会是100,000行代码的权利? – quantum231

1

没有与无需另一种方式编写驱动程序写什么你使用WriteFile函数需要设备:了WinUSB,如何做到这一点:

  • 包括WinUsb.h
  • 添加将WinUsb.lib添加到链接库的列表中。
  • in Usb100.h一些宏。
  • 使用设备接口GUID获取设备路径。正确的GUID是您在用于安装WinUsb.sys的INF中指定的GUID。
  • 得到一个处理通过传递您在INF到SetupDiGetClassDevs定义的设备接口GUID设置的设备信息。该函数返回一个HDEVINFO句柄。
  • 调用SetupDiEnumDeviceInterfaces来枚举系统的设备接口并获取设备接口上的信息。
  • 调用SetupDiGetDeviceInterfaceDetail来获取设备接口的详细数据。
  • 调用GetDevicePath函数获取设备路径。
  • 将设备路径传递给CreateFile以获取设备的文件句柄。 使用ReadFile和Write File与设备进行通信!
  • 将文件句柄传递给WinUsb_Initialize以初始化WinUSB并获取WinUSB句柄。当您调用WinUSB API函数时,您使用设备的WinUSB句柄来识别设备,而不是设备的文件句柄。

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

  • WinUsb_QueryDeviceInformation获得设备的速度。
  • WinUsb_QueryInterfaceSettings获取相应的接口描述符。 WinUSB句柄对应于第一个界面。
  • WinUsb_QueryPipe获取有关每个端点的信息。
  • 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; } 
} 
相关问题