USB HID Device on STM32
USB-HID的初步認識
Descriptor即描述符,是一個完整的數據結構,可以通過C語言等編程實現,並存儲在USB設備中,用於描述一個USB設備的所有屬性,USB主機是通過一系列命令來要求設備發送這些信息的。USB有5種標準描述符:設備描述符 、配置描述符、字符描述符、接口描述符、端點描述符 。
HID描述符是關聯於接口(而不是端點)的,所以設備不需要爲每個端點都提供一個HID描述符。
設備描述符
struct _DEVICE_DEscriptOR_STRUCT
{
BYTE bLength; //設備描述符的字節數大小
BYTE bDescriptorType; //描述符類型編號,爲0x01
WORD bcdUSB; //USB版本號
BYTE bDeviceClass; //USB分配的設備類代碼,0x01~0xfe爲標準設備類,0xff爲廠商自定義類型,0x00不是在設備描述符中定義的,如HID
BYTE bDeviceSubClass; //usb分配的子類代碼,同上,值由USB規定和分配的,HID設備此值爲0
BYTE bDeviceProtocl; //USB分配的設備協議代碼,同上HID設備此值爲0
BYTE bMaxPacketSize0; //端點0的最大包的大小
WORD idVendor; //廠商編號
WORD idProduct; //產品編號
WORD bcdDevice; //設備出廠編號
BYTE iManufacturer; //描述廠商字符串的索引
BYTE iProduct; //描述產品字符串的索引
BYTE iSerialNumber; //描述設備序列號字符串的索引
BYTE bNumConfiguration; //可能的配置數量
}
配置描述符
struct _CONFIGURATION_DEscriptOR_STRUCT
{
BYTE bLength; //配置描述符的字節數大小
BYTE bDescriptorType; //描述符類型編號,爲0x02
WORD wTotalLength; //配置所返回的所有數量的大小
BYTE bNumInterface; //此配置所支持的接口數量
BYTE bConfigurationVale; //Set_Configuration命令需要的參數值
BYTE iConfiguration; //描述該配置的字符串的索引值
BYTE bmAttribute; //供電模式的選擇
BYTE MaxPower; //設備從總線提取的最大電流
}
字符描述符
struct _STRING_DEscriptOR_STRUCT
{
BYTE bLength; //字符串描述符的字節數大小
BYTE bDescriptorType; //描述符類型編號,爲0x03
BYTE SomeDescriptor[36]; //UNICODE編碼的字符串
}
接口描述符
struct _INTERFACE_DEscriptOR_STRUCT
{
BYTE bLength; //接口描述符的字節數大小
BYTE bDescriptorType; //描述符類型編號,爲0x04
BYTE bInterfaceNunber; //接口的編號
BYTE bAlternateSetting;//備用的接口描述符編號
BYTE bNumEndpoints; //該接口使用端點數,不包括端點0
BYTE bInterfaceClass; //接口類型 HID設備此值爲0x03
BYTE bInterfaceSubClass;//接口子類型 HID設備此值爲0或者1
BYTE bInterfaceProtocol;//接口所遵循的協議
BYTE iInterface; //描述該接口的字符串索引值
}
端點描述符
struct _ENDPOIN_DEscriptOR_STRUCT
{
BYTE bLength; //端點描述符的字節數大小
BYTE bDescriptorType; //描述符類型編號,爲0x05
BYTE bEndpointAddress; //端點地址及輸入輸出屬性
BYTE bmAttribute; //端點的傳輸類型屬性
WORD wMaxPacketSize; //端點收、發的最大包的大小
BYTE bInterval; //主機查詢端點的時間間隔
}
HID讀寫設備
INT CHidUsb::WriteDevice(HANDLE hUsbDevice, const CHAR *lpszBuf, INT nSize, BOOL bNeedRead)
{
DWORD dwSizeWritten;
OVERLAPPED OverLapped;
DWORD dwErrCode;
INT nWriteSize;
INT nNeedWriteSize;
CHAR szHidBuf[HID_PACKAGE_SIZE + 1];
nNeedWriteSize = nSize;
nWriteSize = 0;
// 只能已HID包的格式發送
memset(&OverLapped, 0, sizeof(OverLapped));
OverLapped.hEvent = m_hWriteEvent;
while (1)
{
if (nSize < 0)
{
break;
}
nNeedWriteSize = HID_PACKAGE_SIZE;
if (nNeedWriteSize > nSize)
{
nNeedWriteSize = nSize;
}
nSize -= nNeedWriteSize;
memset(szHidBuf, 0xff, HID_PACKAGE_SIZE + 1);
<span style="color:#ff0000;">szHidBuf[0] = 0</span>;// 這裏一定不要忘記,這個是ID,定義爲0,所以加上64個字節,所以一次操作爲65個字節
memcpy(szHidBuf + 1, lpszBuf, nNeedWriteSize);
lpszBuf += nNeedWriteSize;
<span style="color:#ff0000;">if (!::WriteFile(m_hUsbDevice, szHidBuf, HID_PACKAGE_SIZE + 1, &dwSizeWritten, &OverLapped))</span>
{
dwErrCode = GetLastError();
break;
}
assert(dwSizeWritten == HID_PACKAGE_SIZE + 1);
nWriteSize += dwSizeWritten;
}
if (bNeedRead)
{
SetEvent(m_hWaitEvent);
}
return nWriteSize;
}