1、void CMainFrame::OnDeviceConnect() 连接设备
//定时器作用:每隔一段读缓存(从设备端点读取数据)
//每隔一段时间(10ms)执行mycallback()回调函数,以实现连续采集。
::timeSetEvent (10,0,mycallback,(DWORD)this,TIME_PERIODIC);
2、执行mycallback回调函数
3、执行Execute_ReadFile()函数
4、待hEvent_Read置为有信号状态后,ThreadExecute_Read(PVOID pContext)在waitForSingleObject(```)后执行,开始将设备端点数据读取至计算机中。
WaitForSingleObject()函数介绍详见 hj的多线程程序设计P93页
引用:事实上,win32中大部分以HANDLE表示的对象都能够作为WaitForSingleObject()的等待目标。视你所拥有的对象不同,操作系统等待的事情也不太一样。形式上来说,系统等待着这一对象“被激发”。
Ps: ThreadExecute_Read是线程函数,在CBioUSBAPI类的构造函数中被CreateThread启动。
Api函数 |
IRP主要功能代码 |
说明 |
CreateFile |
IRP_MJ_CREATE |
打开设备 |
ReadFile |
IRP_MJ_READ |
从设备获取数据 |
WriteFile |
IRP_MJ_WRITE |
向设备发送数据 |
CloseHandle |
IRP_MJ_CLOSE |
关闭设备 |
DeviceIoControl |
IRP_MJ_DEVICE_CONTROL |
控制操作 |
|
|
|
|
|
|
在usb设备进行通信之前,首先需要得到usb设备的句柄。通过获取设备GUID、获取设备信息集、获取设备路径名可查找到设备并得到所要打开设备的路径名。然后通过API函数CreateFile来打开设备,当成功打开后,CreateFile函数会返回一个其他API函数可用来与设备交换数据的句柄。打开设备之后,应用程序就可以使用ReadFile和WriteFile函数和设备进行数据交换了。当读写usb设备结束可以断开设备时候,就可以调用CloseHandle函数关闭设备。
在以下函数OpenDeviceInterface中被调用
HANDLE CBioUSBAPI::OpenDeviceInterface(PCHAR pDeviceInterfaceSymbolicName) { HANDLE hReturnHandle = CreateFile( pDeviceInterfaceSymbolicName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); return hReturnHandle; } OpenDeviceInterface()在void CMainFrame::OnDeviceConnect()中被调用 void CMainFrame::OnDeviceConnect() { // TODO: Add your command handler code here // TODO: Add your command handler code here if(hdev != INVALID_HANDLE_VALUE) return; int IdIndex = m_wndTransBar.m_DeviceName.GetCurSel(); if(IdIndex >= 0) { m_wndTransBar.m_DeviceName.GetLBText(IdIndex,m_CurrentInterfaceSymbolicName); hdev = pBioScan->OpenDeviceInterface(m_CurrentInterfaceSymbolicName); if(hdev != INVALID_HANDLE_VALUE) { dwCurStep = CURSTEP_NOTHING; m_Link = TRUE; timeKillEvent(mr); mr = ::timeSetEvent (10,0,mycallback,(DWORD)this,TIME_PERIODIC); } else { MessageBox("Get device handle failed!"); } } }
The ReadFile function reads data from a file, starting at the position indicated by the file pointer. After the read operation has been completed, the file pointer is adjusted by the number of bytes actually read, unless the file handle is created with the overlapped attribute. If the file handle is created for overlapped input and output (I/O), the application must adjust the position of the file pointer after the read operation.
BOOL ReadFile(
HANDLE hFile, // handle of file to read
LPVOID lpBuffer, // pointer to buffer that receives data
DWORD nNumberOfBytesToRead, // number of bytes to read
LPDWORD lpNumberOfBytesRead, // pointer to number of bytes read
LPOVERLAPPED lpOverlapped // pointer to structure for data
);
hFile
Handle to the file to be read. The file handle must have been created with GENERIC_READ access to the file.
lpBuffer
Pointer to the buffer that receives the data read from the file.
程序中:
ReadFile(pUSBAPI->stRead.hDevice,
pUSBAPI->stRead.pInBuffer,
pUSBAPI->stRead.dwInSize,
pUSBAPI->stRead.lpBytesReturned,
&olRead))
pUSBAPI定义:
CBioUSBAPI* pUSBAPI = (CBioUSBAPI *)pContext;
是一个指向CBioUSBAPI类的指针。
stRead是类CBioUSBAPI的成员变量,
class CBioUSBAPI
{···
STRUCT_IO stRead; //类型为结构体类型(即STRUCT_IO)
····
}
STRUCT_IO定义:
typedef struct _STRUCT_IO
{
HWND hTargetWnd;
HANDLE hDevice;
DWORD dwIoControlCode;
PBYTE pInBuffer;
DWORD dwInSize;
PBYTE pOutBuffer;
DWORD dwOutSize;
LPDWORD lpBytesReturned;
DWORD dwTimeOut;
}STRUCT_IO,*PSTRUCT_IO;
SendMessage(pUSBAPI->stRead.hTargetWnd,
MSG_READ_COMPLETION,
0,
(LPARAM)&pUSBAPI->stRead);
作用:读取端点数据后,发消息MSG_READ_COMPLETION通知窗口过程函数。
stRead作为SendMessage()函数的第四个参数被传送给消息处理函数。
虚函数WindowProc()定义在类CMainFrame中:
class CMainFrame : public CFrameWnd { // Overrides // ClassWizard generated virtual function overrides //{{AFX_VIRTUAL(CMainFrame) public: virtual BOOL PreCreateWindow(CREATESTRUCT& cs); virtual BOOL OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo); protected: virtual LRESULT WindowProc(UINT message, WPARAM wParam, LPARAM lParam); //}}AFX_VIRTUAL // Implementation public: virtual ~CMainFrame(); #ifdef _DEBUG virtual void AssertValid() const; virtual void Dump(CDumpContext& dc) const; #endif public: HANDLE hdev; CBioUSBAPI * pBioScan; void EnumDeviceInterfaces(); void CloseDevice(); DWORD dwCurStep; long lSysTick; protected: // control bar embedded members CStatusBar m_wndStatusBar; CTrueColorToolBar m_wndToolBar; CTransDlgBar m_wndTransBar; CReBar m_wndReBar; private: MMRESULT mr; public: DWORD dwBytesReturned; TCHAR m_CurrentInterfaceSymbolicName[MAX_PATH]; DWORD dwReadLength; BYTE ReadBuff[REQ_NUM]; HANDLE hEvent_ReadNext; protected: // control bar embedded members BOOLEAN m_Online; public: BOOLEAN m_Link; BOOLEAN m_FileOpen; DWORD dwLength; }; pDoc->AddFrames(&(pIO->pInBuffer[0]),dwCurNum)将调用如下函数: void CScanViewerDoc::AddFrames(PBYTE pData,int wNums) { SetModifiedFlag(TRUE); SetPathName("Bioscan.scv*"); for( int i = 0;i<wNums;i++) { CDataFrame * pDataFrame = new CDataFrame(); pDataFrame->AddData(pData + i * EP_PACKET_SIZE); m_ObArray.Add(pDataFrame); } } pDataFrame->AddData(pData + i * EP_PACKET_SIZE);调用 void CDataFrame::AddData(PBYTE pData)函数 void CDataFrame::AddData(PBYTE pData) { // char bDotOrder[16] = {16,32,30,46,28,44,26,42,24,40,22,38,20,36,18,34}; if(!pData) return; int i; for (i=0;i<EP_PACKET_SIZE;i++) { m_bData[i] = pData[i]; } }