国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

WinUSB驅(qū)動實現(xiàn)及其通信傳輸應(yīng)用

2018-09-14 07:51石保敬王長荀怯肇乾
軟件 2018年8期
關(guān)鍵詞:句柄描述符線程

石保敬,王長荀,怯肇乾

?

WinUSB驅(qū)動實現(xiàn)及其通信傳輸應(yīng)用

石保敬,王長荀,怯肇乾

(河南馳誠電氣,河南 鄭州 450001)

微軟近年來推出的規(guī)范簡便的WinUSB設(shè)備通信模型,編程對接的關(guān)鍵是“底層USB設(shè)備如何添加描述使Windows OS識別其為WinUSB設(shè)備”和“可視化測試/應(yīng)用程序怎樣通過WinUSB.dll調(diào)用與之進行管道數(shù)據(jù)傳輸?shù)膶崿F(xiàn)”,恰到好處的運用定時器或線程是異步快速實時數(shù)據(jù)接收軟件設(shè)計的核心,USB測試/應(yīng)用程序發(fā)布針對低級操作系統(tǒng)版本需要編寫引導(dǎo)安裝程序,USB設(shè)備插拔處置和多USB設(shè)備通信的操控也需要特定處置,如此編程設(shè)計,Windows下USB設(shè)備傳輸通信就如同傳統(tǒng)的RS-232C通信一樣方便自如而且還直截了當(dāng)和迅速高效了。

USB描述符;WinUSB設(shè)備;異步數(shù)據(jù)傳輸;定時數(shù)據(jù)接收;線程數(shù)據(jù)接收

0 引言[9]

Windows操作系統(tǒng)OS(Operation System)下,通過USB(Universal Serial Bus)接口,讀寫訪問USB設(shè)備,是嵌入式應(yīng)用系統(tǒng)和可視化測試/應(yīng)用軟件開發(fā)必不可少的常用環(huán)節(jié)。微軟從Winxp-SP2版本開始,在Windows中集成了通用的WinUSB Device驅(qū)動及其連接OS底層和應(yīng)用層的WinUSB.dll,極大簡化了USB數(shù)據(jù)的通信傳輸。恰到好處的運用WinUSB進行開發(fā),同樣可以到達類似使用傻瓜托管式的WinDriver軟件的效果。編程設(shè)計的關(guān)鍵是如何讓W(xué)indows快速的把USB設(shè)備識別為通用WinUSB設(shè)備和應(yīng)用軟件怎樣合理調(diào)用WinUSB.dll對應(yīng)的WinUSB.lib庫。本文就此展開詳細闡述。

開發(fā)WinUSB驅(qū)動實現(xiàn)及其通信傳輸應(yīng)用,可以采用C++、C#或JavaScript等語言,最好的集成開發(fā)環(huán)境IDE(Integrated Development Environment)是Visial Studio,也可以是Rad Studio XE等,無論哪個IDE都需要首先安裝Windows驅(qū)動程序開發(fā)工具包WDK(Windows Driver Kit)。這里以Rad Studio XE和STM32F103系列微控制器的可視化USB設(shè)備通信開發(fā)為例加以說明。

1 底層USB設(shè)備通信支持[1-4]

嵌入式應(yīng)用系統(tǒng)實現(xiàn)USB設(shè)備通信,主要是在高優(yōu)先級的中斷服務(wù)程序中實現(xiàn)的,包括常規(guī)的USB標(biāo)準(zhǔn)請求應(yīng)答和管道讀寫收發(fā)實現(xiàn),管道操作主要是中斷和批量傳輸,USB標(biāo)準(zhǔn)請求包括設(shè)備、配置、接口及其端點描述與速度限定變換。必須設(shè)法讓W(xué)indows識別為通用WinUSB設(shè)備,可視化測試/應(yīng)用程序才可以使用通用的WinUSB設(shè)備驅(qū)動進行溝通交互,如圖1所示。

圖1 通用WinUSB設(shè)備的操作系統(tǒng)識別

為此,需要特別構(gòu)造1個標(biāo)準(zhǔn)USB類描述符--OS描述符和2個供應(yīng)商類描述符--OS特征ID(Identifier)描述符和注冊設(shè)備接口GUID描述符。全球唯一標(biāo)識符GUID(Globally Unique Identifier)。

1.1 標(biāo)準(zhǔn)USB類OS描述符

OS描述符,定義存儲在字符串索引0xEE 處,對應(yīng)的USB標(biāo)準(zhǔn)請求為:

80 06 ee 03 00 00 12 00

典型的OS描述符定義如下:

#define bMS_VendorCode 0x01

//Vendor 請求的請求代碼

const unsigned char OsDscrptStr[] =

// "MSFT100" : index : 0xEE : langId : 0

{ 0x12, 0x03, 'M', 0, 'S', 0, 'F', 0, 'T', 0, '1', 0, '0', 0, '0', 0, bMS_VendorCode, 0 };

1.2 供應(yīng)商類OS特征ID描述符

供應(yīng)商類OS特征ID描述符,用作設(shè)置擴展兼容,對應(yīng)的供應(yīng)商類請求為:

初步請求--c0 01 00 00 04 00 10 00,再次請求--c0 01 00 00 04 00 28 00

典型的OS特征ID描述符包定義如下:

const unsigned char cptbIdDscrpt [] =

{ 0x28, 0x00, 0x00, 0x00, //包長

0x00, 0x01, //BCD版本

0x04, 0x00, //索引

0x01, //數(shù)量

0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, //保留[7]

0x00, //第一接口編號

0x01, //保留(0x01)

'W', 'I', 'N', 'U', 'S', 'B',

0x00, 0x00, //兼容ID[8]

0x00, 0x00, 0x00, 0x00,

0x00, 0x00, 0x00, 0x00, //子兼容ID[8]

0x00, 0x00, 0x00,

0x00, 0x00, 0x00 //保留[6]

};

1.3 供應(yīng)商類注冊設(shè)備接口GUID

供應(yīng)商類注冊設(shè)備接口GUID,將體現(xiàn)在注冊表中,如圖2所示,GUID可用相應(yīng)工具軟件產(chǎn)生。

圖2 Windows注冊表中的特定通用USB設(shè)備接口GUID示意圖

該描述符,供應(yīng)用程序調(diào)用該GUID做讀寫訪問的USB設(shè)備識別,對應(yīng)的供應(yīng)商類請求為:

初次請求--c1 01 00 00 05 00 0a 00,再次請求--c1 01 00 00 05 00 8e 00

典型的注冊設(shè)備接口 GUID描述符定義如下:

const unsigned char itfcGuidDscrpt[] =

{ 0x8E, 0x00, 0x00, 0x00, //包長(頭+各部分)

0x00, 0x01, //頭: BCD版本

0x05, 0x00, //索引

0x01, 0x00, //數(shù)量

0x84, 0x00, 0x00, 0x00 //部分: 大小

0x01, 0x00, 0x00, 0x00, //屬性數(shù)據(jù)類型

0x28, 0x00, //屬性名字長度

{ 'D', 0, 'e', 0, 'v', 0, 'i', //屬性名稱[40]:

0, 'c', 0, 'e', 0, 'I', 0, "DeviceInterfaceGUID"

'n',0, 't', 0, 'e', 0, 'r',

0, 'f',0, 'a', 0, 'c', 0,

'e', 0, 'G',0, 'U', 0,

'I', 0, 'D', 0, 0, 0

},

0x4E, 0x00, //屬性數(shù)據(jù)長度:

0x00, 0x00, 78[0x4E]

{ '{', 0, '1', 0, '2', 0, '3', 0, //屬性數(shù)據(jù): {12345678-

'4', 0, '5', 0, '6', 0, '7', 1234-1234-1234-

0, 8', 0, '-', 0, '1', 0, '2', 123456789ABC}

0, '3', 0, '4', 0, '-', 0, '1',

0, '2', 0, '3', 0, 4', 0, ' '-',

0, '1', 0, '2', 0, '3', 0, '4',

0, '-', 0, '1', 0,'2', 0, '3', 0,

'4', 0, '5', 0, '6', 0, '7', 0,

8', 0, '9', 0, 'A', 0, 'B', 0,

'C', 0, '}', 0, 0, 0

}

};

可用作者的“ARM系列微處理控制器的軟件體系架構(gòu)工具”得到完整的STM32103系列USB驅(qū)動程序,包括上述3個特殊描述符在內(nèi)的標(biāo)準(zhǔn)USB請求類和供應(yīng)商請求及其應(yīng)答配置與控制、中斷、批量或同步管道傳輸代碼,限于篇幅,不再贅述。

2 WinUSB設(shè)備驅(qū)動運用[3-4,10]

可視化測試/應(yīng)用程序中使用Windows OS通用的WinUSB設(shè)備驅(qū)動,必須引入對WDK頭文件的引用,需要在可視化窗口.cpp文件頭部加入的典型.h文件引用如下:

#include "Windows Kits10Include10.0.15063. 0sharedusb.h"

#include "Windows Kits10Include10.0.15063. 0sharedstrsafe.h"

#include "Windows Kits10Include10.0.15063. 0umSetupAPI.h"

#include "Windows Kits10Include10.0.15063. 0umwinusb.h"

可視化測試/應(yīng)用程序,通過連接OS底層和應(yīng)用層的WinUSB.dll操作特定的通用WinUSB Device,必須在項目工程中引用WinUSB.dll對應(yīng)的WinUSB.lib庫文件。WDK提供有相應(yīng)的WinUSB. lib,在Visival Studio中引用沒有問題,但不能直接在Rad Studio XE中引用,編譯連接時會報錯:

BCB contains invalid OMF record, type 0x21 (possibly COFF)

這是IDE要求的原始設(shè)備制造商OEM(Original Equipment Manufacturer)的通用對象文件格式COFF(Common Object File Format)不同引起的lib文件兼容不足導(dǎo)致的??梢允褂肦ad Studio XE的coff2omf. exe工具進行轉(zhuǎn)換再加以引用,命令行操作如下,其中前者是微軟DDK提供的,后者就是得到的Rad Studio XE開發(fā)所需的庫:

coff2omf -lib:ms WinUSB.lib bcb WinUSB.lib

3 WinUSB通信傳輸實現(xiàn)[3-8]

3.1 WinUSB設(shè)備文件操作

與其它OS一樣,Winsows把設(shè)備當(dāng)做文件操作,但USB設(shè)備又有特定的集成端點在內(nèi)的管道傳輸?shù)慕涌冢源蜷_USB設(shè)備文件后還要打開相應(yīng)的USB接口,得到特定的USB接口操作句柄,之后就可以運用該句柄,調(diào)用管道讀寫進行數(shù)據(jù)傳輸了??梢暬瘻y試/應(yīng)用程序退出時必須依次關(guān)閉USB接口操作句柄和設(shè)備文件操作句柄。

獲取USB設(shè)備及其接口操作句柄的典型函數(shù)代碼如下:

HANDLE hDeviceHandle = INVALID_HANDLE_VALUE; // 設(shè)備文件句柄

WINUSB_INTERFACE_HANDLE hWinUSBHandle // WinUSB操作句柄

= INVALID_HANDLE_VALUE;

// USB設(shè)備文件句柄創(chuàng)建[接口GUID,設(shè)備句柄]-------------------------------------------------------------------

BOOL GetDeviceHandle(GUID guidDeviceInterface, PHANDLE hDeviceHandle )

{ if ( guidDeviceInterface == GUID_NULL ) return FALSE;

BOOL bResult = TRUE; HDEVINFO hDeviceInfo;

SP_DEVINFO_DATA DeviceInfoData; DWORD index = 0;

SP_DEVICE_INTERFACE_DATA deviceInterfaceData;

PSP_DEVICE_INTERFACE_DETAIL_DATA pInterfaceDetailData = NULL;

ULONG requiredLength = 0; LPTSTR lpDevicePath = NULL;

// 為特定設(shè)備的接口類而獲取安裝設(shè)備的所有信息

hDeviceInfo = SetupDiGetClassDevs(&guidDeviceInterface, NULL, NULL,

DIGCF_PRESENT | DIGCF_DEVICEINTERFACE );

if ( hDeviceInfo == INVALID_HANDLE_VALUE ) goto done; // 無效退出

// 在設(shè)備信息集中枚舉所有設(shè)備接口

DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

for(index=0; SetupDiEnumDeviceInfo(hDeviceInfo, index, & DeviceInfoData); index++)

{ if(lpDevicePath) LocalFree(lpDevicePath); // 復(fù)位相應(yīng)項

if(pInterfaceDetailData) LocalFree(pInterfaceDetailData);

deviceInterfaceData.cbSize = sizeof(SP_INTERFACE_DEVICE_DATA);

bResult = SetupDiEnumDeviceInterfaces( hDeviceInfo, // 獲取設(shè)備接口信息

&DeviceInfoData, &guidDeviceInterface, 0, &deviceInterfaceData );

if(GetLastError()== ERROR_NO_MORE_ITEMS) break; // 最后項?

if(!bResult) goto done; // 錯誤退出

// 動態(tài)調(diào)用2次,首次分配空間,再次得到接口數(shù)據(jù)

bResult = SetupDiGetDeviceInterfaceDetail( hDeviceInfo,

&deviceInterfaceData, NULL, 0, &requiredLength, NULL );

if(!bResult) // 錯誤檢查

{ if((ERROR_INSUFFICIENT_BUFFER == GetLastError())

&& ( requiredLength > 0 ) )

{ pInterfaceDetailData = // 動態(tài)分配緩沖區(qū)大小

(PSP_DEVICE_INTERFACE_DETAIL_DATA)

LocalAlloc(LPTR, requiredLength );

if (!pInterfaceDetailData ) goto done; // 錯誤退出

}

else goto done; // 錯誤退出

}

pInterfaceDetailData->cbSize // 獲取接口詳細數(shù)據(jù)

= sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);

bResult = SetupDiGetDeviceInterfaceDetail( hDeviceInfo,

&deviceInterfaceData, pInterfaceDetailData,

requiredLength, NULL, &DeviceInfoData );

if (!bResult) goto done; // 錯誤退出

size_t nLength = wcslen(pInterfaceDetailData->DevicePath ) + 1; // 設(shè)備文件路徑

lpDevicePath = (TCHAR *) LocalAlloc( LPTR, nLength * sizeof(TCHAR));

StringCchCopy(lpDevicePath, nLength, pInterfaceDetailData->DevicePath);

lpDevicePath[(nLength - 1)] = 0;

}

if (!lpDevicePath) goto done; // 錯誤退出

}

*hDeviceHandle = CreateFile( lpDevicePath, // 打開設(shè)備文件, 得到設(shè)備文件句柄

GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ

| FILE_SHARE_WRITE, NULL, OPEN_EXISTING,

FILE_FLAG_OVERLAPPED, NULL);

if (*hDeviceHandle != INVALID_HANDLE_VALUE ) return true;

done: LocalFree( lpDevicePath );

LocalFree( pInterfaceDetailData );

bResult = SetupDiDestroyDeviceInfoList( hDeviceInfo );

return bResult;

}

// 獲取設(shè)備的 WinUSB 接口句柄------------------------------------------------------------------------------------

BOOL GetWinUSBHandle(HANDLE hDeviceHandle,

PWINUSB_INTERFACE_HANDLE phWinUSBHandle)

{ if(hDeviceHandle == INVALID_HANDLE_VALUE) return FALSE;

BOOL bResult = WinUsb_Initialize(hDeviceHandle, phWinUSBHandle);

if (!bResult) return FALSE;

return bResult;

}

可視化窗口,創(chuàng)建時運用特定USB接口GUID,調(diào)用這兩個函數(shù)創(chuàng)建設(shè)備文件句柄和USB接口操作句柄;窗口關(guān)閉時依次關(guān)閉這兩個句柄;若USB設(shè)備沒有掛接,應(yīng)用禁止窗口上所有USB數(shù)據(jù)收發(fā)按鈕操作,相關(guān)核心代碼如下:

void__fastcall TfrmShow::FormCreate(TObject *Sender)

{static const GUID stm32F1xxDvcItfc = { 0x-12345678, 0x1234, 0x1344,

{0x12, 0x34, 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC } };

GUID guidDeviceInterface = stm32F1xxDvcItfc;

BOOL bResult = TRUE; ULONG cbSize = 0;

bResult = GetDeviceHandle(guidDeviceInterface, &hDeviceHandle);

if (!bResult) return;

bResult = GetWinUSBHandle(hDeviceHandle, & hWinUSBHandle);

if(!bResult) return;

flgWinUSB = true;

}

//---------------------------------------------------------

void __fastcall TfrmShow::FormClose(TObject *Sender, TCloseAction &Action)

{ if(!flgWinUSB) return;

CloseHandle(hDeviceHandle);

WinUsb_Free(hWinUSBHandle);

}

3.2 收發(fā)傳輸?shù)牟呗钥紤]

運用WinUSB應(yīng)用程序編程接口API (Appli-cation Programming Interface)函數(shù)WinUsb_ReadPipe和WinUsb_WritePipe進行數(shù)據(jù)管道收發(fā)傳輸時,若沒有收到或發(fā)出數(shù)據(jù),程序會一直等待,造成可視化窗口失控,可以通過調(diào)用WinUsb_SetPipePolicy函數(shù),使用WinUSB的超時管道傳輸策略來避免這種阻塞式的尷尬局面,取消請求之前等待超時時間,超過超時時間退出等待。通常在USB設(shè)備文件句柄和WinUSB接口句柄創(chuàng)建成功后進行超時傳輸設(shè)置,時間據(jù)實際傳輸量而定,典型代碼如下,這里超時時間取100ms,0x81對應(yīng)輸入IN管道1,0x02對應(yīng)輸出OUT管道2:

UINT timeout = 100;

bResult = WinUsb_SetPipePolicy(hWinUSBHandle, 0x81, // 輸入IN管道1

PIPE_TRANSFER_TIMEOUT, sizeof (timeout), & timeout);

if(!bResult) return;

bResult = WinUsb_SetPipePolicy(hWinUSBHandle, 0x02, // 輸出OUT管道2

PIPE_TRANSFER_TIMEOUT, sizeof(timeout), &timeout);

if(!bResult) return;

3.3 數(shù)據(jù)發(fā)送操作實現(xiàn)

數(shù)據(jù)發(fā)送,同異步操作差別不大,只要準(zhǔn)備好數(shù)據(jù),很容易知道其數(shù)據(jù)大小,主動同步發(fā)出,以最簡方式實現(xiàn),典型代碼如下:

if(hWinUSBHandle==INVALID_HANDLE_VALUE) return;

UCHAR szBffr[50]; ULONG cbSent = 0;

AnsiString str = edtSdDt->Text; // 窗口文本輸入控件

strcpy(szBffr, str.c_str());

ULONG cbSize = str.Length();

WinUsb_WritePipe(hWinUSBHandle, 0x02, szBffr, cbSize, &cbSent, 0 );

3.4 異步數(shù)據(jù)傳輸?shù)膶崿F(xiàn)

異步數(shù)據(jù)收發(fā)傳輸,對于不知數(shù)據(jù)量大小的操作非常有效,特別是USB管道的讀操作。

首先需要定義全局的OVERLAPPED結(jié)構(gòu)變量,并在USB設(shè)備文件及其WinUSB接口句柄創(chuàng)建成功后初始化這個結(jié)構(gòu)變量,主要是其相關(guān)“事件Event”的初始化,典型代碼如下:

OVERLAPPED overlapped;

ZeroMemory(&overlapped, sizeof(overlapped));

overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

典型的異步USB管道讀事件代碼如下,首先以小固定數(shù)量15進行盲讀,在限定的超時時間內(nèi),只要收到數(shù)據(jù),都可以接收,并成行顯示在窗口的文本指示框內(nèi):

void WinUSB_Read(void)

{ if(hWinUSBHandle==INVALID_HANDLE_VALUE) return;

ULONG cbRead = 0; UCHAR szBffr[20] = {'0'}; AnsiString str;

BOOL bResult = WinUsb_ReadPipe(hWinUSB-Handle, 0x81,

szBffr, 15, &cbRead, &overlapped);

if(bResult)

{ const char* t = szBffr; str = t;

mRcvDt->Lines->Add(str); // 可視窗口文本顯示控件

}

else if(ERROR_IO_PENDING == GetLastError ())

{bResult = WinUsb_GetOverlappedResult(hW-inUSBHandle, & overlapped, &cbRead, true);

if(NULL != cbRead)

{ int m = cbRead; cbRead = 0;

if(bResult)

{ const char* d = szBffr; str = d;

mmRcvDt->Lines->Add(str);

}

}

}

}

3.5 定時數(shù)據(jù)接收的實現(xiàn)

隨時監(jiān)聽USB輸入管道并接收可能傳入的數(shù)據(jù),在可視化測試/應(yīng)用程序設(shè)計中,簡潔高效的方法就是采用定時器控制,以一定的時間間隔,在定時器的OnTimer事件處理中,去異步的讀取USB輸入管道,典型代碼如下,其中設(shè)置的時間間隔是100 ms:

void __fastcall TfrmShow::rcvTmrTimer(TObject *Sender)

{ rcvTmr->Enabled = false; // 關(guān)閉定時器

WinUSB_Read(); // 異步數(shù)據(jù)謀取并進行可視化窗口顯示

rcvTmr->Enabled = true; // 重開定時器

}

3.6 后臺線程數(shù)據(jù)接收實現(xiàn)

以線程方式在后臺進行USB輸入管道的監(jiān)聽并接收可能傳入的數(shù)據(jù),是另外一種及時高效的USB數(shù)據(jù)接收形式。在項目工程中新建線程對象rcvThrd,進而在生成的rcvThrd.h文件中聲明引用的窗口顯示控件和數(shù)據(jù)接收函數(shù)RcvDt(),典型代碼如下:

class thrdRcvDt : public TThread

{ private: TMemo *memo;

protected: void __fastcall Execute();

public: void __fastcall thrdRcvDt::RcvDt();

__fastcall thrdRcvDt(bool CreateSuspended, TMemo *Amemo);

};

在rcvThrd.cpp文件中,聲明所需的包含文件、外部變量,并定義操作函數(shù),典型代碼如下:

#include "frmStm32Tst.h" // 可視化窗口文件

#include "Windows Kits10Include10.0.15063. 0sharedusb.h" // DDK文件

#include "Windows Kits10Include10.0.15063. 0sharedstrsafe.h"

#include "Windows Kits10Include10.0.15063. 0umSetupAPI.h"

#include "Windows Kits10Include10.0.15063. 0umwinusb.h"

extern WINUSB_INTERFACE_HANDLE hWin-USBHandle;

extern OVERLAPPED overlapped;

extern void WinUSB_Read(void);

__fastcall thrdRcvDt::thrdRcvDt(bool Create-Suspended, TMemo *Amemo) : TThread(CreateSu-spended)

{ memo = Amemo; }

void __fastcall thrdRcvDt::Execute() // 線程執(zhí)行[休眠100ms]

{ while(!Terminated)

{ Synchronize(RcvDt); Sleep(100); }

}

void __fastcall thrdRcvDt::RcvDt() // 數(shù)據(jù)異步接收窗口指示

{ WinUSB_Read(); }

在可視化窗口的frmStm32Tst.h中加入線程對象包含和線程實例化聲明,典型代碼如下:

#include "rcvThrd.h"

class TfrmShow : public TForm

{ …

private: thrdRcvDt *rcvThrd;

}

在可視化窗口的frmStm32Tst.cpp中,打開設(shè)備文件和WinUSB接口句柄后,啟動線程,定義線程終止時自動銷毀,然后運行線程,典型代碼如下:

rcvThrd = new thrdRcvDt(true, mmRcvDt);

rcvThrd->FreeOnTerminate = true;

rcvThrd->Resume();

對比定時數(shù)據(jù)接收,異曲同工。定時器控件,本質(zhì)就是休眠時間可調(diào)整的線程操作封裝。

3.7 設(shè)備插撥及相應(yīng)處置

以上闡述基于先插上USB設(shè)備,再打開可視化測試/應(yīng)用程序,進行通信傳輸,用后關(guān)閉應(yīng)用程序,撥下設(shè)備。而USB設(shè)備即插即用,在USB設(shè)備突然被拔下后,還進行讀寫傳輸,程序就阻塞了。為避免這種現(xiàn)象發(fā)生,可創(chuàng)建一個線程,定時(如每2s)枚舉檢查相關(guān)的USB設(shè)備,若被拔下,停止定時數(shù)據(jù)接收或休眠接收線程;若重新插入,則重新創(chuàng)建操作句柄,恢復(fù)定時數(shù)據(jù)接收或線程數(shù)據(jù)接收。

4 WinUSB應(yīng)用/測試程序的發(fā)布[3-4,8]

4.1 Win8.1以上系統(tǒng)

應(yīng)用軟件發(fā)布,除Rad Studio產(chǎn)生的.exe文件外,還需要包含WinUSB.lib。若編譯時不能包含動態(tài)庫,還需要包含IDE相關(guān)的cc32240mt.dll和borlndmm.dll。上述各種方法綜合在一起,得到的針對STM32F103系列微控制USB設(shè)備的WinUSB數(shù)據(jù)收發(fā)測試的可視化應(yīng)用程序窗口界面如圖3所示:

圖3 WinUSB數(shù)據(jù)收發(fā)測試的可視化應(yīng)用程序窗口界面

4.2 WinXP-Win8系統(tǒng)

編寫驅(qū)動安裝文件.inf,引導(dǎo)OS調(diào)用內(nèi)置的winusb.sys驅(qū)動文件的安裝應(yīng)用,主要指明USB設(shè)備的廠商號、產(chǎn)品號、USB接口GUID等,通知安裝程序類已設(shè)置為 "USBDevice"。需要使用WinUSB協(xié)助安裝庫文件WinUsbCoInstaller,區(qū)分32位和64位版本,常用版本是V1.9,Win7之后也可以是V1.11。Win7之后系統(tǒng),還需要準(zhǔn)備cat文件,可運用WDK的Inf2Cat.exe工具得到,命令行操作如下:

Inf2Cat.exe /driver:[inf文件目錄] /os: XP_X86, XP_X64,7_X86,7_X64,8_X32,8_X64

典型inf驅(qū)動安裝文件如下:

[Version]

Signature="$Windows NT$"

Class=USBDevice

ClassGUID={88BAE032-5A81-49f0-BC3D-A4-FF138216D6}

Provider=%ManufacturerName%

CatalogFile=instlWinUSB.cat

DriverVer=01/13/2018,12.4.23.896

[Manufacturer]

%ManufacturerName%=Standard,NTx86,NTx64

[Standard.NTx86]

%DeviceName%=USB_Install,USBVID_0483& PID_5720

[Standard.NTx64]

%DeviceName%=USB_Install,USBVID_0483& PID_5720

[ClassInstall32]

AddReg=ClassInstall_AddReg

[ClassInstall_AddReg]

HKR,,,,%ClassName%

HKR,,NoInstallClass,,1

HKR,,IconPath,%REG_MULTI_SZ%,"C:WindowsSystem32setupapi.dll,-20"

HKR,,LowerLogoVersion,,5.2

[USB_Install]

Include=winusb.inf

Needs=WINUSB.NT

[USB_Install.Services]

Include=winusb.inf

AddService=WinUsb,0x00000002,WinUsb_Ser-viceInstall

[WinUsb_ServiceInstall]

DisplayName=%WinUsb_SvcDesc%

ServiceType=1

StartType=3

ErrorControl=1

ServiceBinary=C:WindowsSystem32driversWin--USB.sys

[USB_Install.HW]

AddReg=Dev_AddReg

[Dev_AddReg]

HKR,,DeviceInterfaceGUIDs,0x10000,"{12345678-1234-1344-1234-123456789ABC}"

[USB_Install.Wdf]

KmdfService=WINUSB, WinUsb_Install

[WinUSB_Install]

KmdfLibraryVersion=1.9

[USB_Install.CoInstallers]

AddReg=CoInstallers_AddReg

CopyFiles=CoInstallers_CopyFiles

[CoInstallers_AddReg]

HKR,,CoInstallers32,0x00010000,"WdfCoInstaller01009.dll,WdfCoInstaller"

[CoInstallers_CopyFiles]

WdfCoInstaller01009.dll

[DestinationDirs]

CoInstallers_CopyFiles=11

[SourceDisksNames]

1=%DiskName%

[SourceDisksFiles]

WdfCoInstaller01009.dll=1

[Strings]

ManufacturerName="STMicroelectronics"

ClassName="USB通用串行總線設(shè)備"

DiskName="kzq"

WinUsb_SvcDesc="WinUSB Driver"

DeviceName="STM3210"

REG_MULTI_SZ = 0x00010000

5 多WinUSB設(shè)備應(yīng)用測試的實現(xiàn)

多個同類WinUSB設(shè)備插入同一臺電腦,系統(tǒng)都可以識別,通信時連接傳輸快的USB設(shè)備占主動權(quán)后,其它USB設(shè)備就不通信了??梢孕薷腢SB設(shè)備的接口GUID,使連入USB設(shè)備差異化,以實現(xiàn)各個對應(yīng)的傳輸通信,找到一個設(shè)備通信一個,從而實現(xiàn)類似設(shè)備參數(shù)配置的批量操作實現(xiàn)。

6 驅(qū)動開發(fā)對比

表1 幾種驅(qū)動及其開發(fā)對比表

Tab.1 Some kind of device drivers and it’s design comparison

7 結(jié)語

底層嵌入式應(yīng)用軟件中添加特定描述支持,Windows OS就可以自動識其為WinUSB設(shè)備,上層可視化測試/應(yīng)用程序就可以通過WinUSB.dll與其進行USB數(shù)據(jù)傳輸通信了。這樣,Windows下USB設(shè)備的數(shù)據(jù)采集、監(jiān)視控制、配置參數(shù)、軟件刷新等軟件編程操控,就同傳統(tǒng)的“RS-232C通信”一樣了,無需USB轉(zhuǎn)串口硬軟件轉(zhuǎn)接,而且速度快、實時性強,直截了當(dāng)。同樣,定時接收、線程接收、多設(shè)備通信等軟件手段也可以搬來使用,進一步提升效率和實用性。

[1] CSDN博客. USB設(shè)備描述符舉例說明[EB/OL]. http://blog. csdn.net/u013256018/article/details/60805770?locationNum=10&fps=1, 2017.3.

[2] CSDN博客﹒WinUSB--微軟為所有USB設(shè)備提供的常規(guī)驅(qū)動程序[EB/OL]. http://blog.csdn.net/whw8007/article/details/ 9569989, 2013.8.

[3] 微軟開發(fā)網(wǎng). 如何通過WinUSB功能訪問USB設(shè)備[EB/OL]. https://msdn.microsoft.com/zh-cn/library/windows/hardware/ff540174(v=vs.85).aspx, 2017.12.

[4] 馬開東博客. 如何使用WinUSB與USB設(shè)備USBDevice通信[EB/OL]. http://www.makaidong.com/%E5%8D%9A%E5% AE%A2%E5%9B%AD7/20151013/306670_4.html, 2015.10.

[5] 微軟開發(fā)網(wǎng). 適用于USB設(shè)備的Windows桌面應(yīng)用[EB/OL]. https://msdn.microsoft.com/zh-cn/library/windows/ hardware/dn376885(v=vs.85).aspx, 2017.12.

[6] 微軟開發(fā)網(wǎng). 編寫基于WinUSB模板的Windows桌面應(yīng)用[EB/OL]. https://msdn.microsoft.com/zh-cn/library/windows/ hardware/dn376872(v=vs.85).aspx, 2017.12.

[7] 微軟開發(fā)網(wǎng). 用于管道策略修改的WinUSB功能[EB/OL]. https://msdn.microsoft.com/zh-cn/library/windows/hardware/ff728833(v=vs.85).aspx, 2017.12.

[8] 怯肇乾等. Windows異步串行通信編程縱橫[J]. 電腦與開發(fā)應(yīng)用, 2009, 6(445): 21-25.

[9] CSDN博客. winusb--不再為你的usb設(shè)備編寫驅(qū)動[EB/OL]. https://blog.csdn.net/phenixyf/article/details/46744419, 2015.7.

[10] 彭偉. 基于WinUSB與SHT75的溫濕度數(shù)據(jù)采集與控制系統(tǒng)設(shè)計仿真[J]. 制造業(yè)自動化, 2013, 7(15): 129-133.

Implementation of WinUSB Driver and Its Application in Communication Transmission

SHI Bao-jing, WANG Chang-xun, KAI Zhao-qian

(HNCC Electronic Co., LTD, Zhengzhou 450001, China)

Software design key about WinUSB-Device-Model-Application is how to add descriptor to WinUSB-Device in Windows OS and how to communicate in Windows Application. It’s kernel is how to use timer and thread with asynchronous-data-transmission. Note WinUSB-Application-Publishing in low operating system version, account USB-Plug-in-Plug-out handling and multi-USB-devices-communication. So, Windows USB device data transmission are easy to use such as RS-232C.

USB descriptor; WinUSB device; Asynchronous data transmission; Data reception with timer; Data reception with thread.

TP36

B

10.3969/j.issn.1003-6970.2018.08.013

怯肇乾(1969-),男,電子與信息技術(shù)高級工程師,嵌入式系統(tǒng)設(shè)計師/培訓(xùn)師,web網(wǎng)絡(luò)測控軟件系統(tǒng)架構(gòu)師,研究方向為軟硬件體系及其網(wǎng)絡(luò)系統(tǒng)軟件設(shè)計;石保敬(1977-),男,經(jīng)濟師,風(fēng)險評估師,環(huán)保健康探測警報專家,研究方向為危害和易燃易爆氣體探測產(chǎn)品系統(tǒng)及其開發(fā)設(shè)計;王長荀(1988-),男,嵌入式硬軟件開發(fā)工程師,研究方向為軟硬件體系及其網(wǎng)絡(luò)系統(tǒng)軟件設(shè)計。

本文著錄格式:石保敬,王長荀,怯肇乾. WinUSB驅(qū)動實現(xiàn)及其通信傳輸應(yīng)用[J]. 軟件,2018,39(8):57-64

猜你喜歡
句柄描述符線程
基于結(jié)構(gòu)信息的異源遙感圖像局部特征描述符研究
基于AKAZE的BOLD掩碼描述符的匹配算法的研究
Linux單線程并發(fā)服務(wù)器探索
利用CNN的無人機遙感影像特征描述符學(xué)習(xí)
淺談linux多線程協(xié)作
基于上下文定界的Fork/Join并行性的并發(fā)程序可達性分析*
Linux線程實現(xiàn)技術(shù)研究
么移動中間件線程池并發(fā)機制優(yōu)化改進