zoukankan      html  css  js  c++  java
  • USB driver develop on wince (转)

    USB协议 http://www.usb.org   http://www.driverdevolep.com

    Windows CE.NET 的USB系统软件分为两层: USB Client设备驱动程序和底层的Windows CE实现的函数层。USB设备驱动程序主要负责利用系统提供的底层接口配置设备,和设备进行通讯。底层的函数提本身又由两部分组成,通用串行总线驱动程序(USBD)模块和较低的主控制器驱动程序(HCD)模块。HCD负责最最底层的处理,USBD模块实现较高的USBD函数接口。USB设备驱动主要利用USBD接口函数和他们的外围设备打交道。

    USB设备驱动程序主要和USBD打交道,所以我们必须详细的了解USBD提供的函数。

    主要的传输函数有:
    AbourtTransfer IssueControlTransfer
    CloseTransfer IssueInterrupTransfer
    GetIsochResult IssueIsochTransfer
    GetTransferStatus IstransferComplete
    IssueBulkTransfer IssueVendorTransfer

    主要的用于打开和关闭USBD和USB设备之间的通信通道的函数有:
    AbortPipeTransfers ClosePipe
    IsDefaultPipeHalted IsPipeHalted
    OpenPipe ResetDefaultPipe
    ResetPipe

    相应的打包函数接口有:
    GetFrameLength GetFrameNumber ReleaseFrameLengthControl
    SetFrameLength TakeFrameLengthControl

    取得设置设备配置函数:
    ClearFeature SetDescriptor
    GetDescriptor SetFeature
    GetInterface SetInterface
    GetStatus SyncFrame

    与USB进行交互的实现方法相关的多任务函数:
    FindInterface RegisterClientDeviceId
    GetDeviceInfo RegisterClientSettings
    GetUSBDVersion RegisterNotificationRoutine
    LoadGenericInterfaceDriver TranslateStringDescr
    OpenClientRegisterKey UnRegisterNotificationRoutine
    常见的Windows CE.NET下USB的设备驱动程序的编写有以下几种方法:

    ● 流式接口函数
    这种驱动程序主要呈现流式函数接口,主要输出XXX_Init,XXX_Deinit,XXX_Open,XXX_Close,XXX_Open,XXX_Close,XXX_Read,XXX_Write,
    XXX_Seek,XXX_IOControl,XXX_PowerUp,XXX_PowerDown等流式接口,注意上述的几个接口一定都要输出,另外XXX必须为三个字符,否则会出错。但是此类的驱动程序不是通过设备管理接口来加载的,所以必须手工的调用RegisterDevice()和DeregisterDevice()函数来加载和卸载驱动程序。用户可以将此类的设备作为标准的文件来操作,只要调用相应的文件操作就可以和驱动程序打交道。

    ● 使用现有的Window CE.NET的应用程序接口
    此类设备主要是利用Windows CE.NET中已经有了现成的函数接口,例如USB Mass Storage Disk,它主要利用现有的Windows CE.Net中已经有的可安装文件系统接口,呈现给系统可用的文件系统,对于用户来讲,它是透明的,用户仅仅感觉在操作一个文件夹。

    ● 创建指定到特定的USBD的用户指定的API
    这种方法在USBD呈现设备时不需要任何限制,主要是特制的提供API给用户,一般不太常见。


    USB设备驱动程序必须输出的函数有:
    ● USBDeviecAttach
    当USB设备连接到计算机上时,USBD模块就会调用此函数,这个函数主要用于初始化USB设备,取得USB设备信息,配置USB设备,并且申请必需的资源。
    ● USBInstallDriver
    主要用于创建一个驱动程序加载所需的注册表信息,例如读写超时,设备名称等。
    ● USBUninstallDriver
    主要用于释放驱动程序所占用的资源,以及删除USBInstallDriver函数创建的注册表等。
    上述的三个函数接口是所有的USB驱动程序必须提供的,缺一不可。
    另外比较重要的是USB设备驱动程序的注册表配置,一般的USB设备驱动程序的注册表配置在HKEY_LOCAL_MACHINE\Drivers\USB\LoadClients下,每个驱动程序的子键都有Group1_ID\Group2_ID\Group3_ID\DriverName格式,如果注册表信息与USB设备信息符合,USBD就会加载此驱动程序。否则设备的子键应该由供应商,设备类和协议信息通过下划线组成。
    具体的配置举个例子:
    例如你有个PDA设备,它具有一个USB接口,它的供应厂商ID假设为0x0888,设备ID为0x0999,没有使用特殊的协议,那么它的加载注册表应该写为:
    [HKEY_LOCAL_MACHINE\Drivers\USB\LoadClients\2184_2457\Default\Default\PDA] "DLL"="pdausb.dll"
    需要注意的是注册表构成都是十进制数值来标识的,注意一下十进制和十六进制的转换。
    再举个USB鼠标的例子,USB鼠标是标准的HID设备,它的协议为:InterfaceClassCode为3(HID类),InterfaceSubclassCode为1(引导接口类),InterfaceProtocolCode为2(鼠标协议类),所以它的注册如下:
    [HKEY_LOCAL_MACHINE\Drivers\USB\LoadClients\Default\Default\3_1_2\USBMouse] "DLL"="usbmouse.dll"

    到此为止,我们可以看出,其实驱动开发无非做两件事情,一件是和硬件打交道,另外一件是和操作系统打交道。举个简单的例子,例如:我们需要开发一个USB鼠标驱动程序,我们就需要了解USB鼠标硬件上是怎么发送数据的?操作系统怎么才能得到鼠标的控制事件?其实USB鼠标是有一个中断PIPE的,用于传送鼠标产生的数据,Windwos CE.NET中有个接口函数叫做mouse_event(),专门用于产生鼠标事件,但是它是不关心具体什么硬件的,甚至我们自己在应用程序中调用这个函数都可以实现模拟鼠标,对应的有个keybd_event(),用于产生键盘事件,知道了这个就好办多了,只要将相应的数据转换一下,调用一下mouse_event()即可,

    上述讲了堆理论,可能读者脑袋都已经大了,为此,我们举个简单的例子来详细说明一下驱动程序的开发过程。

    例如我们有个USB Mouse设备,设备信息描述如下:
    Device Descriptor:
    bcdUSB: 0x0100
    bDeviceClass: 0x00
    bDeviceSubClass: 0x00
    bDeviceProtocol: 0x00
    bMaxPacketSize0: 0x08 (8)
    idVendor: 0x05E3 (Genesys Logic Inc.)
    idProduct: 0x0001
    bcdDevice: 0x0101
    iManufacturer: 0x00
    iProduct: 0x01
    iSerialNumber: 0x00
    bNumConfigurations: 0x01

    ConnectionStatus: DeviceConnected
    Current Config Value: 0x01
    Device Bus Speed: Low
    Device Address: 0x02
    Open Pipes: 1

    Endpoint Descriptor:
    bEndpointAddress: 0x81
    Transfer Type: Interrupt
    wMaxPacketSize: 0x0003 (3)
    bInterval: 0x0A

    可以看出上述设备有一个中断PIPE,包的最大值为3。可能有人问上述的值怎么得到的,win2k 的DDK中有个usbview的例程,编译一下,将你的USB设备插到PC机的USB口中,运行usbview.exe即可看得相应的设备信息。

    有了这些基本信息,就可以编写USB设备了,首先声明一下,下面的代码取自微软的USB鼠标样本程序,版权归微软所有,此处仅仅借用来描述一下USB鼠标驱动的开发过程,读者如需要引用此代码,需要得到微软的同意。

    首先,必须输出USBD要求调用的三个函数,首先到设备插入到USB端口时,USBD会调用USBDeviceAttach()函数,相应的代码如下:
    extern "C" BOOL
    USBDeviceAttach(
    USB_HANDLE hDevice, // USB设备句柄
    LPCUSB_FUNCS lpUsbFuncs, // USBDI的函数集合
    LPCUSB_INTERFACE lpInterface, // 设备接口描述信息
    LPCWSTR szUniqueDriverId, // 设备ID描述字符串。
    LPBOOL fAcceptControl, // 返回TRUE,标识我们可以控制此设备, 反之表示不能控制
    DWORD dwUnused)
    {
    *fAcceptControl = FALSE;
    // 我们的鼠标设备有特定的描述信息,要检测是否是我们的设备。
    if (lpInterface == NULL)
    return FALSE;
    // 打印相关的USB设备接口描述信息。
    DEBUGMSG(ZONE_INIT,(TEXT("USBMouse: DeviceAttach, IF %u, #EP:%u, Class:%u, Sub:%u,Prot:%u\r\n"), lpInterface->Descriptor.bInterfaceNumber,lpInterface->Descriptor.bNumEndpoints, lpInterface->Descriptor.bInterfaceClass,lpInterface->Descriptor.bInterfaceSubClass,lpInterface->Descriptor.bInterfaceProtocol));
    // 初试数据USB鼠标类,产生一个接受USB鼠标数据的线程
    CMouse * pMouse = new CMouse(hDevice, lpUsbFuncs, lpInterface);
    if (pMouse == NULL)
    return FALSE;

    if (!pMouse->Initialize())
    {
    delete pMouse;
    return FALSE;
    }

    // 注册一个监控USB设备事件的回调函数,用于监控USB设备是否已经拔掉。
    (*lpUsbFuncs->lpRegisterNotificationRoutine)(hDevice,
    USBDeviceNotifications, pMouse);

    *fAcceptControl = TRUE;
    return TRUE;
    }

    第二个函数是 USBInstallDriver()函数,
    一些基本定义如下:
    const WCHAR gcszRegisterClientDriverId[] = L"RegisterClientDriverID";
    const WCHAR gcszRegisterClientSettings[] = L"RegisterClientSettings";
    const WCHAR gcszUnRegisterClientDriverId[] = L"UnRegisterClientDriverID";
    const WCHAR gcszUnRegisterClientSettings[] = L"UnRegisterClientSettings";
    const WCHAR gcszMouseDriverId[] = L"Generic_Sample_Mouse_Driver";

    函数接口如下:
    extern "C" BOOL
    USBInstallDriver(
    LPCWSTR szDriverLibFile) // @parm [IN] - Contains client driver DLL name
    {
    BOOL fRet = FALSE;
    HINSTANCE hInst = LoadLibrary(L"USBD.DLL");

    // 注册USB设备信息
    if(hInst)
    {
    LPREGISTER_CLIENT_DRIVER_ID pRegisterId = (LPREGISTER_CLIENT_DRIVER_ID)
    GetProcAddress(hInst, gcszRegisterClientDriverId);

    LPREGISTER_CLIENT_SETTINGS pRegisterSettings =
    (LPREGISTER_CLIENT_SETTINGS) GetProcAddress(hInst,
    gcszRegisterClientSettings);

    if(pRegisterId && pRegisterSettings)
    {
    USB_DRIVER_SETTINGS DriverSettings;

    DriverSettings.dwCount = sizeof(DriverSettings);

    // 设置我们的特定的信息。
    DriverSettings.dwVendorId = USB_NO_INFO;
    DriverSettings.dwProductId = USB_NO_INFO;
    DriverSettings.dwReleaseNumber = USB_NO_INFO;

    DriverSettings.dwDeviceClass = USB_NO_INFO;
    DriverSettings.dwDeviceSubClass = USB_NO_INFO;
    DriverSettings.dwDeviceProtocol = USB_NO_INFO;

    DriverSettings.dwInterfaceClass = 0x03; // HID
    DriverSettings.dwInterfaceSubClass = 0x01; // boot device
    DriverSettings.dwInterfaceProtocol = 0x02; // mouse

    fRet = (*pRegisterId)(gcszMouseDriverId);

    if(fRet)
    {
    fRet = (*pRegisterSettings)(szDriverLibFile,
    gcszMouseDriverId, NULL, &DriverSettings);

    if(!fRet)
    {
    //BUGBUG unregister the Client Drivers ID
    }
    }
    }
    else
    {
    RETAILMSG(1,(TEXT("!USBMouse: Error getting USBD function pointers\r\n")));
    }
    FreeLibrary(hInst);
    }
    return fRet;
    }
    上述代码主要用于产生USB设备驱动程序需要的注册表信息,需要注意的是:USB设备驱动程序不使用标准的注册表函数,而是使用RegisterClientDriverID()和RegisterClientSettings来注册相应的设备信息。

    另外一个函数是USBUninstallDriver()函数,具体代码如下:
    extern "C" BOOL
    USBUnInstallDriver()
    {
    BOOL fRet = FALSE;
    HINSTANCE hInst = LoadLibrary(L"USBD.DLL");

    if(hInst)
    {
    LPUN_REGISTER_CLIENT_DRIVER_ID pUnRegisterId =
    (LPUN_REGISTER_CLIENT_DRIVER_ID)
    GetProcAddress(hInst, gcszUnRegisterClientDriverId);

    LPUN_REGISTER_CLIENT_SETTINGS pUnRegisterSettings =
    (LPUN_REGISTER_CLIENT_SETTINGS) GetProcAddress(hInst,
    gcszUnRegisterClientSettings);

    if(pUnRegisterSettings)
    {
    USB_DRIVER_SETTINGS DriverSettings;

    DriverSettings.dwCount = sizeof(DriverSettings);
    // 必须填入与注册时相同的信息。
    DriverSettings.dwVendorId = USB_NO_INFO;
    DriverSettings.dwProductId = USB_NO_INFO;
    DriverSettings.dwReleaseNumber = USB_NO_INFO;

    DriverSettings.dwDeviceClass = USB_NO_INFO;
    DriverSettings.dwDeviceSubClass = USB_NO_INFO;
    DriverSettings.dwDeviceProtocol = USB_NO_INFO;

    DriverSettings.dwInterfaceClass = 0x03; // HID
    DriverSettings.dwInterfaceSubClass = 0x01; // boot device
    DriverSettings.dwInterfaceProtocol = 0x02; // mouse

    fRet = (*pUnRegisterSettings)(gcszMouseDriverId, NULL,
    &DriverSettings);
    }

    if(pUnRegisterId)
    {
    BOOL fRetTemp = (*pUnRegisterId)(gcszMouseDriverId);
    fRet = fRet ? fRetTemp : fRet;
    }
    FreeLibrary(hInst);
    }
    return fRet;
    }
    此函数主要用于删除USBInstallDriver()时创建的注册表信息,同样的它使用自己的函数接口UnRegisterClientDriverID()和UnRegisterClientSettings()来做相应的处理。

    另外一个需要处理的注册的监控通知函数USBDeviceNotifications():
    extern "C" BOOL USBDeviceNotifications(LPVOID lpvNotifyParameter, DWORD dwCode,
    LPDWORD * dwInfo1, LPDWORD * dwInfo2, LPDWORD * dwInfo3,
    LPDWORD * dwInfo4)
    {
    CMouse * pMouse = (CMouse *)lpvNotifyParameter;

    switch(dwCode)
    {
    case USB_CLOSE_DEVICE:
    //删除相关的资源。
    delete pMouse;
    return TRUE;
    }
    return FALSE;
    }


    USB鼠标的类的定义如下:
    class CMouse
    {
    public:
    CMouse::CMouse(USB_HANDLE hDevice, LPCUSB_FUNCS lpUsbFuncs,
    LPCUSB_INTERFACE lpInterface);
    ~CMouse();

    BOOL Initialize();
    private:
    // 传输完毕调用的回调函数
    static DWORD CALLBACK MouseTransferCompleteStub(LPVOID lpvNotifyParameter);
    // 中断处理函数
    static ULONG CALLBACK CMouse::MouseThreadStub(PVOID context);
    DWORD MouseTransferComplete();
    DWORD MouseThread();

    BOOL SubmitInterrupt();
    BOOL HandleInterrupt();

    BOOL m_fClosing;
    BOOL m_fReadyForMouseEvents;

    HANDLE m_hEvent;
    HANDLE m_hThread;

    USB_HANDLE m_hDevice;
    USB_PIPE m_hInterruptPipe;
    USB_TRANSFER m_hInterruptTransfer;

    LPCUSB_FUNCS m_lpUsbFuncs;
    LPCUSB_INTERFACE m_pInterface;

    BOOL m_fPrevButton1;
    BOOL m_fPrevButton2;
    BOOL m_fPrevButton3;

    // 数据接受缓冲区。
    BYTE m_pbDataBuffer[8];
    };

    具体实现如下:

    // 构造函数,初始化时调用
    CMouse::CMouse(USB_HANDLE hDevice, LPCUSB_FUNCS lpUsbFuncs,
    LPCUSB_INTERFACE lpInterface)
    {
    m_fClosing = FALSE;
    m_fReadyForMouseEvents = FALSE;
    m_hEvent = NULL;
    m_hThread = NULL;

    m_hDevice = hDevice;
    m_hInterruptPipe = NULL;
    m_hInterruptTransfer = NULL;

    m_lpUsbFuncs = lpUsbFuncs;
    m_pInterface = lpInterface;

    m_fPrevButton1 = FALSE;
    m_fPrevButton2 = FALSE;
    m_fPrevButton3 = FALSE;

    memset(m_pbDataBuffer, 0, sizeof(m_pbDataBuffer));
    }

    // 析构函数,用于清除申请的资源。
    CMouse::~CMouse()
    {
    // 通知系统去关闭相关的函数接口。
    m_fClosing = TRUE;

    // Wake up the connection thread again and give it time to die.
    if (m_hEvent != NULL)
    {
    // 通知关闭数据接受线程。
    SetEvent(m_hEvent);

    if (m_hThread != NULL)
    {
    DWORD dwWaitReturn;

    dwWaitReturn = WaitForSingleObject(m_hThread, 1000);
    if (dwWaitReturn != WAIT_OBJECT_0)
    {
    TerminateThread(m_hThread, DWORD(-1));
    }
    CloseHandle(m_hThread);
    m_hThread = NULL;
    }
    CloseHandle(m_hEvent);
    m_hEvent = NULL;
    }

    if(m_hInterruptTransfer)
    (*m_lpUsbFuncs->lpCloseTransfer)(m_hInterruptTransfer);

    if(m_hInterruptPipe)
    (*m_lpUsbFuncs->lpClosePipe)(m_hInterruptPipe);
    }


    // 初始化USB鼠标驱动程序
    BOOL CMouse::Initialize()
    {
    LPCUSB_DEVICE lpDeviceInfo = (*m_lpUsbFuncs->lpGetDeviceInfo)(m_hDevice);

    // 检测配置:USB鼠标应该只有一个中断管道
    if ((m_pInterface->lpEndpoints[0].Descriptor.bmAttributes & USB_ENDPOINT_TYPE_MASK) != USB_ENDPOINT_TYPE_INTERRUPT)
    {
    RETAILMSG(1,(TEXT("!USBMouse: EP 0 wrong type (%u)!\r\n"),
    m_pInterface->lpEndpoints[0].Descriptor.bmAttributes));
    return FALSE;
    }
    DEBUGMSG(ZONE_INIT,(TEXT("USBMouse: EP 0:MaxPacket: %u, Interval: %u\r\n"),
    m_pInterface->lpEndpoints[0].Descriptor.wMaxPacketSize,
    m_pInterface->lpEndpoints[0].Descriptor.bInterval));

    m_hInterruptPipe = (*m_lpUsbFuncs->lpOpenPipe)(m_hDevice,
    &m_pInterface->lpEndpoints[0].Descriptor);

    if (m_hInterruptPipe == NULL) {
    RETAILMSG(1,(TEXT("Mouse: Error opening interrupt pipe\r\n")));
    return (FALSE);
    }
    m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
    if (m_hEvent == NULL)
    {
    RETAILMSG(1,(TEXT("USBMouse: Error on CreateEvent for connect event\r\n")));
    return(FALSE);
    }
    // 创建数据接受线程
    m_hThread = CreateThread(0, 0, MouseThreadStub, this, 0, NULL);
    if (m_hThread == NULL)
    {
    RETAILMSG(1,(TEXT("USBMouse: Error on CreateThread\r\n")));
    return(FALSE);
    }

    return(TRUE);
    }

    // 从USB鼠标设备中读出数据,产生相应的鼠标事件。
    BOOL CMouse::SubmitInterrupt()
    {
    if(m_hInterruptTransfer)
    (*m_lpUsbFuncs->lpCloseTransfer)(m_hInterruptTransfer);

    // 从USB鼠标PIPE中读数据
    m_hInterruptTransfer = (*m_lpUsbFuncs->lpIssueInterruptTransfer)
    (m_hInterruptPipe, MouseTransferCompleteStub, this,
    USB_IN_TRANSFER | USB_SHORT_TRANSFER_OK, // 表示读数据
    min(m_pInterface->lpEndpoints[0].Descriptor.wMaxPacketSize,
    sizeof(m_pbDataBuffer)),
    m_pbDataBuffer,
    NULL);

    if (m_hInterruptTransfer == NULL)
    {
    DEBUGMSG(ZONE_ERROR,(L "!USBMouse: Error in IssueInterruptTransfer\r\n"));
    return FALSE;
    }
    else
    {
    DEBUGMSG(ZONE_TRANSFER,(L"USBMouse::SubmitInterrupt,Transfer:0x%X\r\n",
    m_hInterruptTransfer));
    }
    return TRUE;
    }

    // 处理鼠标中断传输的数据
    BOOL CMouse::HandleInterrupt()
    {
    DWORD dwError;
    DWORD dwBytes;

    DWORD dwFlags = 0;
    INT dx = (signed char)m_pbDataBuffer[1];
    INT dy = (signed char)m_pbDataBuffer[2];

    BOOL fButton1 = m_pbDataBuffer[0] & 0x01 ? TRUE : FALSE;
    BOOL fButton2 = m_pbDataBuffer[0] & 0x02 ? TRUE : FALSE;
    BOOL fButton3 = m_pbDataBuffer[0] & 0x04 ? TRUE : FALSE;

    if (!(*m_lpUsbFuncs->lpGetTransferStatus)(m_hInterruptTransfer, &dwBytes,&dwError))
    {
    DEBUGMSG(ZONE_ERROR,(TEXT("!USBMouse: Error in GetTransferStatus(0x%X)\r\n"),
    m_hInterruptTransfer));
    return FALSE;
    }
    else
    {
    DEBUGMSG(ZONE_TRANSFER,(TEXT("USBMouse::HandleInterrupt, hTransfer 0x%X complete (%u bytes, Error:%X)\r\n"),
    m_hInterruptTransfer,dwBytes,dwError));
    }

    if (!SubmitInterrupt())
    return FALSE;

    if(dwError != USB_NO_ERROR)
    {
    DEBUGMSG(ZONE_ERROR,(TEXT("!USBMouse: Error 0x%X in interrupt transfer\r\n"),dwError));
    return TRUE;
    }

    if(dwBytes < 3)
    {
    DEBUGMSG(ZONE_ERROR,(TEXT("!USBMouse: Invalid byte cnt %u from interrupt transfer\r\n"),dwBytes));
    return TRUE;
    }

    if(dx || dy)
    dwFlags |= MOUSEEVENTF_MOVE;

    if(fButton1 != m_fPrevButton1)
    {
    if(fButton1)
    dwFlags |= MOUSEEVENTF_LEFTDOWN;
    else
    dwFlags |= MOUSEEVENTF_LEFTUP;
    }

    if(fButton2 != m_fPrevButton2)
    {
    if(fButton2)
    dwFlags |= MOUSEEVENTF_RIGHTDOWN;
    else
    dwFlags |= MOUSEEVENTF_RIGHTUP;
    }

    if(fButton3 != m_fPrevButton3)
    {
    if(fButton3)
    dwFlags |= MOUSEEVENTF_MIDDLEDOWN;
    else
    dwFlags |= MOUSEEVENTF_MIDDLEUP;
    }

    m_fPrevButton1 = fButton1;
    m_fPrevButton2 = fButton2;
    m_fPrevButton3 = fButton3;

    DEBUGMSG(ZONE_EVENTS,
    (TEXT("USBMouse event: dx:%d, dy:%d, dwFlags:0x%X (B1:%u, B2:%u, B3:%u)\r\n"),
    dx,dy,dwFlags,fButton1,fButton2,fButton3));

    // 通知系统产生鼠标事件
    if (m_fReadyForMouseEvents)
    mouse_event(dwFlags, dx, dy, 0, 0);
    else
    m_fReadyForMouseEvents = IsAPIReady(SH_WMGR);

    return TRUE;
    }


    DWORD CALLBACK CMouse::MouseTransferCompleteStub(LPVOID lpvNotifyParameter)
    {
    CMouse * pMouse = (CMouse *)lpvNotifyParameter;
    return(pMouse->MouseTransferComplete());
    }

    // 数据传输完毕回调函数
    DWORD CMouse::MouseTransferComplete()
    {
    if (m_hEvent)
    SetEvent(m_hEvent);
    return 0;
    }


    ULONG CALLBACK CMouse::MouseThreadStub(PVOID context)
    {
    CMouse * pMouse = (CMouse *)context;
    return(pMouse->MouseThread());
    }

    // USB鼠标线程
    DWORD CMouse::MouseThread()
    {
    DEBUGMSG(ZONE_INIT,(TEXT("USBMouse: Worker thread started\r\n")));
    SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);

    if (SubmitInterrupt())
    {
    while (!m_fClosing)
    {
    WaitForSingleObject(m_hEvent, INFINITE);

    if (m_fClosing)
    break;

    if ((*m_lpUsbFuncs->lpIsTransferComplete)(m_hInterruptTransfer))
    {
    if (!HandleInterrupt())
    break;
    }
    else
    {
    RETAILMSG(1,(TEXT("!USBMouse: Event signalled, but transfer not complete\r\n")));
    // The only time this should happen is if we get an error on the transfer
    ASSERT(m_fClosing || (m_hInterruptTransfer == NULL));
    break;
    }
    }
    }
    RETAILMSG(1,(TEXT("USBMouse: Worker thread exiting\r\n")));
    return(0);
    }

    看到了没有,其实USB的驱动程序编写就这么简单,类似的其他设备,例如打印机设备,就有Bulk OUT PIPE,需要Bulk传输,那就需要了解一下IssueBulkTransfer()的应用。当然如果是开发USB Mass Storage Disk的驱动,那就需要了解更多的协议,例如Bulk-Only Transport协议等。

    微软的Windows CE.NET的Platform Build中已经带有USB Printer和USB Mass Storage Disk的驱动的源代码了,好好研究一下,你一定回受益非浅的。

    参考资料:
    1. 微软出版社 <<Windows Ce Device Driver Kit>>
    2. <<Universal Serial Bus Specification 1.1>> 来自http:://www.usb.org

  • 相关阅读:
    AGC037F Counting of Subarrays
    AGC025F Addition and Andition
    CF506C Mr. Kitayuta vs. Bamboos
    AGC032D Rotation Sort
    ARC101F Robots and Exits
    AGC032E Modulo Pairing
    CF559E Gerald and Path
    CF685C Optimal Point
    聊聊Mysql索引和redis跳表
    什么是线程安全
  • 原文地址:https://www.cnblogs.com/maintell/p/2112191.html
Copyright © 2011-2022 走看看