我们有一个基于TI CC2531的embedded式设备,除了控制EP0和一些IN-only端点外,还有一个IN和OUT端点。 我们已经注意到了windows发送OUT报告的方式和linux如何做这个的区别。 这实际上让我们相当难受,但是我们从来没有find过解释。
在我看来,linux是这样做的:OUT报告是通过与HID报告相关的端点传输的,因为我们从libusb获得它:
Item | Dev | EP | Status | Speed |Payload -----------------+-----+----+--------+-------+------------------------------- OUT transaction | 13 | 4 | ACK | FS | 64 bytes (90 13 00 00 00 00 ..
另一方面,Windows通过控制端点(EP0)发送它。 我们使用设置API来查找具有我们需要的用法的设备,打开IN和OUT并使用相同的文件描述符进行读写。 通过这个文件描述符很好地接收到EP4 IN报告,但是通过相同的文件描述符写入一个报告,结束于EP0:
Item | Dev | EP | Status | Speed |Payload -------------------+-----+----+--------+-------+------------------------------- Class request OUT | 25 | 0 | OK | FS | 64 bytes (90 13 00 00 00 00 ..
(抱歉,不能张贴图片(我还没有),我抄了Ellisys报告)
embedded式设备不会检查接收到OUT报告的EP(即,EP0上的SET报告将处理与处理HID事件时在其他端点上发现的OUT报告相同的function),因此它将以任一方式进行响应。
我的问题是:两种方式都是正确的,如果不正确,哪一种是正确的? 难道是我们的描述符中的错误触发这种行为在Windows上?
要完成:这是我们的描述: http : //tny.cz/ac745a8f (从供应商身份剥离,让我的老板高兴:))
在窗户上放大报告:(Joy!我现在可以拍照了:))
整个交易:
在Windows上使用库:hid.lib,hidclass.lib和setupapi.lib。 在编写报告时,我们使用函数HidP_SetUsageValueArray和HidD_SetOutputReport。 通过函数HidD_GetAttributes,HidD_GetPreparsedData和HidP_GetCapsfindPHIDP_PREPARSED_DATA和HIDP_CAPS。 设备的文件path是使用SetupDiEnumDeviceInterfacesfind的。 如果我们find具有正确的VID,PID,caps.UsagePage和caps.Usage的设备,那就是我们使用的设备。
在Linux上,这有点棘手,因为我不是那个实施linux代码的人。 我可以告诉的是使用libusb-1.0.9,使用libusb_open_device_with_vid_pid打开设备,使用libusb_fill_interrupt_transfer和libusb_submit_transfer发送报告。 我看到libuwand_fill_interrupt_transfer接受一个端点作为参数,所以我认为只要使用libusb_open_device_with_vid_pid的句柄并将正确的参数作为端点传递,libusb就会知道报告的放置位置。
我想我已经找到了答案。
纯粹巧合我偶然发现Keil论坛,我发现声明'HidD_SetOutputReport将使用控制端点,如果你想通过另一个端点,使用WriteFile'。 我知道,5年多以前,我尝试了这条路,但是我陷入了异步的IO结构。 由于它出现了我有一个出路(使用HidD_SetOutputReport)我放弃了WriteFile路径。 所以现在是时候再次寻找这条道路,而我做到了。 代码:
res = HidD_SetOutputReport(m_DeviceControl[dev], report, m_CapsControl[dev].OutputReportByteLength);
已被替换
DWORD bytesWritten; OVERLAPPED eventWrite = {0}; eventWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); int rv3 = WriteFile(m_DeviceControl[dev], report, m_CapsControl[dev].OutputReportByteLength, &bytesWritten, &eventWrite); if (rv3 == 0) { int err = GetLastError(); if (err == ERROR_IO_PENDING) { bool done = false; do { // yes. Wait till pending state has gone rv3 = WaitForSingleObject(eventWrite.hEvent, 25); if (rv3 == WAIT_OBJECT_0) { GetOverlappedResult(m_DeviceControl[dev], &eventWrite, &bytesWritten, FALSE); done = true; res = TRUE; } else if (rv3 == WAIT_TIMEOUT) { // Need to try again. } else { m_StoppingControlOut = true; done = true; } } while (!done && !m_StoppingControlOut); } } }
这使请求超过正确的端点。
因此,我得出以下结论: