2015-02-10 120 views
5

我們有基於TI CC2531,其具有(除了控制EP0和多個IN-僅端點)的端點既IN和OUT的嵌入式設備。我們已經注意到了Windows發送OUT報告的方式以及Linux如何執行此操作。這實際上讓我們頗費了一段時間,但我們從來沒有找到過解釋。USB HID OUT報告 - 哪個端點是正確的?

這在我看來,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是很好的通過這個文件描述符接受,但是寫在同一文件描述符的報告,關於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就會找出放置報告的位置。

+0

端點0被保留用於控制傳輸,因此在有效負載之前必須有一個8字節的SETUP數據包,其參數如bRequestType,bRequest,wValue和類似。你可以發佈該SETUP數據包的值嗎?有了這些信息,我們就可以查看HID規範並查看Windows發送的請求以及它是否有效。另外,你用什麼驅動程序/庫棧來發送Linux和Windows上的數據? Windows使用的端點可能取決於驅動程序(例如hidusb.sys)以及用於與驅動程序(例如libusb)交談的庫和代碼。 – 2015-02-10 21:31:24

+0

「嵌入式設備不檢查收到OUT報告的EP」:對我來說這聽起來很不尋常。這是如何運作的?在端點0上發送的控制傳輸的結構比在普通中斷或批量端點上的數據複雜得多,因此您首先需要特殊代碼來處理端點0數據。 – 2015-02-10 21:51:58

回答

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報告使用正確的端點。