CMouse::~CMouse()
{
//通知系统去关闭相关的函数接口。
m_fClosing=TRUE;
//Wakeuptheconnectionthreadagainandgiveittimetodie.
if(m_hEvent!=NULL)
{
//通知关闭数据接受线程。
SetEvent(m_hEvent);
if(m_hThread!=NULL)
{
DWORDdwWaitReturn;
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鼠标驱动程序
BOOLCMouse::Initialize()
{
LPCUSB_DEVICElpDeviceInfo=(*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:EP0wrongtype(%u)!rn"),
m_pInterface->lpEndpoints[0].Descriptor.bmAttributes));
returnFALSE;
}
DEBUGMSG(ZONE_INIT,(TEXT("USBMouse:EP0:MaxPACket:%u,Interval:%urn"),
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:Erroropeninginterruptpipern")));
return(FALSE);
}
m_hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
if(m_hEvent==NULL)
{
RETAILMSG(1,(TEXT("USBMouse:ErroronCreateEventforconnecteventrn")));
return(FALSE);
}
//创建数据接受线程
m_hThread=CreateThread(0,0,MouseThreadStub,this,0,NULL);
if(m_hThread==NULL)
{
RETAILMSG(1,(TEXT("USBMouse:ErroronCreateThreadrn")));
return(FALSE);
}
return(TRUE);
}
//从USB鼠标设备中读出数据,产生相应的鼠标事件。
BOOLCMouse::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:ErrorinIssueInterruptTransferrn"));
returnFALSE;
}
else
{
DEBUGMSG(ZONE_TRANSFER,(L"USBMouse::SubmitInterrupt,Transfer:0x%Xrn",
m_hInterruptTransfer));
}
returnTRUE;
}
//处理鼠标中断传输的数据
BOOLCMouse::HandleInterrupt()
{
DWORDdwError;
DWORDdwBytes;
DWORDdwFlags=0;
INTdx=(signedchar)m_pbDataBuffer[1];
INTdy=(signedchar)m_pbDataBuffer[2];
BOOLfButton1=m_pbDataBuffer[0]&0x01?TRUE:FALSE;
BOOLfButton2=m_pbDataBuffer[0]&0x02?TRUE:FALSE;
BOOLfButton3=m_pbDataBuffer[0]&0x04?TRUE:FALSE;
if(!(*m_lpUsbFuncs->lpGetTransferStatus)(m_hInterruptTransfer,&dwBytes,&dwError))
{
DEBUGMSG(ZONE_ERROR,(TEXT("!USBMouse:ErrorinGetTransferStatus(0x%X)rn"),
m_hInterruptTransfer));
returnFALSE;
}
else
{
DEBUGMSG(ZONE_TRANSFER,(TEXT("USBMouse::HandleInterrupt,hTransfer0x%Xcomplete(%ubytes,Error:%X)rn"),
m_hInterruptTransfer,dwBytes,dwError));
}
if(!SubmitInterrupt())
returnFALSE;
if(dwError!=USB_NO_ERROR)
{
DEBUGMSG(ZONE_ERROR,(TEXT("!USBMouse:Error0x%Xininterrupttransferrn"),dwError));
returnTRUE;
}
if(dwBytes<3)
{
DEBUGMSG(ZONE_ERROR,(TEXT("!USBMouse:Invalidbytecnt%ufrominterrupttransferrn"),dwBytes));
returnTRUE;
}
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("USBMouseevent:dx:%d,dy:%d,dwFlags:0x%X(B1:%u,B2:%u,B3:%u)rn"),
dx,dy,dwFlags,fButton1,fButton2,fButton3));
//通知系统产生鼠标事件
if(m_fReadyForMouseEvents)
mouse_event(dwFlags,dx,dy,0,0);
else
m_fReadyForMouseEvents=ISAPIReady(SH_WMGR);
returnTRUE;
}
DWORDCALLBACKCMouse::MouseTransferCompleteStub(LPVOIDlpvNotifyParameter)
{
CMouse*pMouse=(CMouse*)lpvNotifyParameter;
return(pMouse->MouseTransferComplete());
}
//数据传输完毕回调函数
DWORDCMouse::MouseTransferComplete()
{
if(m_hEvent)
SetEvent(m_hEvent);
return0;
}
ULONGCALLBACKCMouse::MouseThreadStub(PVOIDcontext)
{
CMouse*pMouse=(CMouse*)context;
return(pMouse->MouseThread());
}
//USB鼠标线程
DWORDCMouse::MouseThread()
{
DEBUGMSG(ZONE_INIT,(TEXT("USBMouse:Workerthreadstartedrn")));
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:Eventsignalled,buttransfernotcompletern")));
//Theonlytimethisshouldhappenisifwegetanerroronthetransfer
ASSERT(m_fClosing||(m_hInterruptTransfer==NULL));
break;
}
}
}
RETAILMSG(1,(TEXT("USBMouse:Workerthreadexitingrn")));
return(0);
}
看到了没有,其实USB的驱动程序编写就这么简单,类似的其他设备,例如打印机设备,就有BulkOUTPIPE,需要Bulk传输,那就需要了解一下IssueBulkTransfer()的应用。当然如果是开发USBMassStorageDisk的驱动,那就需要了解更多的协议,例如Bulk-OnlyTransport协议等。
微软的WindowsCE.NET的PlatformBuild中已经带有USBPrinter和USBMassStorageDisk的驱动的源代码了,好好研究一下,你一定回受益非浅的。