##3.3. 下行数据接收(host to device)
hidControlHandler用来与PC端通过HID接口交换数据。其源码如下:
static void hidControlHandler(Task task, MessageId id, Message message)
{
MessageMoreData *msg = (MessageMoreData*)message;
uint16 packet_size;
hid_status_t status_report;
const uint8 *in;
if (id == MESSAGE_MORE_DATA)
{
PRINT(("USB: MESSAGE_MORE_DATA hid consumer\n"));
if (msg->source == StreamUsbClassSource(device->usb_interface[usb_interface_hid_control]))
{
handleHidClassRequest(StreamUsbClassSource(device->usb_interface[usb_interface_hid_control]), USB_DEVICE_CLASS_TYPE_HID_CONTROL);
}
else if (msg->source == USB_SOURCE)
{
while ((packet_size = SourceBoundary(msg->source)) != 0)
{
in = SourceMap(msg->source);
PRINT(("USB MORE INT DATA: %d\n",packet_size));
PRINT(("command: %d\n",((hid_command_t*)in)->command));
status_report.report_id = REPORT_STATUS_ID;
status_report.last_command = ((hid_command_t*)in)->command;
status_report.last_command_status= STATUS_CMD_FAILED;
SourceDrop(msg->source, packet_size);
HidSendStatus(&status_report);
}
}
}
}
##3.4. 上行数据发送(device to host)
USB源收到新的数据后,hidControlHandler会收到MESSAGE_MORE_DATA消息。此时判断USB数据源是默认端口0还是端口end_point_bulk_in。如果是端口end_point_bulk_in,读取端口数据并调用HidSendStatus(&status_report)返回消息状态。HidSendStatus源码如下:
/* returns handle when device found or NULL when not found */
HANDLE OpenDevice(void) {
wchar_t device_path[MAX_PATH];
HANDLE DeviceHandle;
if (EnumerateDevices(device_path)) {
/* create handle to the device */
DeviceHandle=CreateFile(device_path,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (DeviceHandle!=INVALID_HANDLE_VALUE) {
return(DeviceHandle);
}
}
return(NULL);
}
int EnumerateDevices(wchar_t *device_path) {
SP_DEVICE_INTERFACE_DATA devInfoData;
int MemberIndex;
ULONG Length;
GUID HidGuid;
HANDLE hDevInfo;
HANDLE LocDevHandle;
HIDD_ATTRIBUTES Attributes;
PSP_DEVICE_INTERFACE_DETAIL_DATA detailData;
PHIDP_PREPARSED_DATA PreparsedData;
HIDP_CAPS Capabilities;
int result=0;
/* get HID GUID */
HidD_GetHidGuid(&HidGuid);
/* get pointer to the device information */
hDevInfo = SetupDiGetClassDevs(&HidGuid,
NULL,
NULL,
DIGCF_PRESENT|DIGCF_DEVICEINTERFACE);
/* go through all the device infos and find devices we are interested in */
devInfoData.cbSize = sizeof(devInfoData);
MemberIndex = 0;
while((SetupDiEnumDeviceInterfaces(hDevInfo,
0,
&HidGuid,
MemberIndex,
&devInfoData))&&(result==0)) {
/* first get the size of memory needed to hold the device interface info */
SetupDiGetDeviceInterfaceDetail(hDevInfo,
&devInfoData,
NULL,
0,
&Length,
NULL);
/* allocate memory */
detailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(Length);
/* and set the size in the structure */
detailData -> cbSize = sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
/* now get the actual device interface info */
SetupDiGetDeviceInterfaceDetail(hDevInfo,
&devInfoData,
detailData,
Length,
NULL,
NULL);
#ifdef DEBUG
wprintf(L"%s\n",detailData->DevicePath);
#endif
/* create handle to the device */
LocDevHandle=CreateFile(detailData->DevicePath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
(LPSECURITY_ATTRIBUTES)NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
/* set the size in the structure */
Attributes.Size = sizeof(Attributes);
/* get and test the VID and PID */
HidD_GetAttributes(LocDevHandle,&Attributes);
if ((Attributes.ProductID == 0x1243) &&
(Attributes.VendorID == 0xa12)) {
/* found the right device */
/* is it the right HID collection? */
HidD_GetPreparsedData(LocDevHandle, &PreparsedData);
HidP_GetCaps(PreparsedData, &Capabilities);
#if 1
wprintf(L"%04x %04x\n",Capabilities.UsagePage,Capabilities.Usage);
#endif
if ((Capabilities.UsagePage == 0xFF00) &&
(Capabilities.Usage == 0x0001)) {
/* this is the correct HID collection */
if (device_path!=NULL) {
wcscpy(device_path,detailData->DevicePath);
}
#ifdef DEBUG
wprintf(L"Device Found\n");
#endif
result=1;
}
}
/* close the device handle again */
CloseHandle(LocDevHandle);
/* and free the memory used to hold device info */
free(detailData);
/* try the next device */
MemberIndex++;
}
/* free memory used for the device information set */
SetupDiDestroyDeviceInfoList(hDevInfo);
return result;
}
##4.3. 下行数据发送(host to device)
PC端调用API函数向device发送数据:
/* reboot to bootmode 0 */ command_report.report_id=REPORT_COMMAND_ID;
command_report.command=COMMAND_NOP;
command_report.data[0]=0x00;
status_response.last_command_status=-1;
if (!WriteFile(DeviceHandle,&command_report,sizeof(hid_command_t),&count,NULL)) {
/* cannot write */
return(FALSE);
}
这里的REPORT_COMMAND_ID与CSR8675程序中定义的值相同。
##4.4. 上行数据接收(device to host)
PC端调用API函数查询接收device的上行数据:
/* wait for response */ if (!ReadFile(DeviceHandle,&status_response,sizeof(hid_status_t),&count,NULL)) {
/* cannot read */
return(FALSE);
}
wprintf(L"Response is %d.\n", status_response.last_command_status);