USB HID OUT报告 - 哪个端点是对的?

时间:2015-02-10 09:59:47

标签: linux windows usb endpoint hid

我们有一个基于TI的CC2531的嵌入式设备,它具有(除了控制EP0和许多仅IN端点)一个IN和OUT端点。我们注意到Windows发送OUT报告的方式以及linux如何做到这一点有所不同。这实际上让我们感到困惑,但我们从来没有找到解释。

在我看来,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报告)

嵌入式设备不会检查收到OUT报告的EP(即EP0上的SET报告将汇集到与处理HID事件时在其他端点上找到的OUT报告相同的功能),因此它将以任一方式响应。

我的问题是:两种方式都是正确的,如果没有,哪种方法是正确的,哪种方法不正确?难道我们的描述符中的错误会在Windows上触发此行为吗?

要完成:这是我们的描述符:http://tny.cz/ac745a8f(从供应商身份中剥离,让我的老板高兴:))

在Windows上缩放到报告中:(欢乐!我现在可以拍照:))

enter image description here

整个交易:

enter image description here

Windows上使用的库:hid.lib,hidclass.lib和setupapi.lib。在编写报告时,我们使用函数HidP_SetUsageValueArray和HidD_SetOutputReport。找到PHIDP_PREPARSED_DATA和HIDP_CAPS,其函数为HidD_GetAttributes,HidD_GetPreparsedData和HidP_GetCaps。使用SetupDiEnumDeviceInterfaces找到设备的文件路径。如果我们发现设备具有正确的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将找出报告的放置位置。

1 个答案:

答案 0 :(得分:1)

我想我找到了答案。

纯粹是巧合,我偶然发现了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);
                    }
                }
            }

这会使请求超过正确的端点。

因此,我得出以下结论:

  • 我认为HID设备解释通过控制端点发送的OUT报告是错误的。
  • 正确使用WriteFile(重叠IO)会使OUT报告使用正确的端点。