2015-02-10 14 views
5

Abbiamo un dispositivo incorporato basato su CC2531 di TI che ha (a parte il controllo EP0 e un numero di endpoint IN-only) un endpoint che è sia IN che OUT. Abbiamo notato una differenza nel modo in cui Windows invia i report OUT e come fa Linux. Questo ci ha veramente messo in difficoltà da un po 'di tempo, ma non siamo mai stati in grado di trovare una spiegazione.Report HID OUT USB: quale endpoint è giusto?

Mi sembra che Linux lo fa il modo in cui si suppone che sia: il rapporto OUT viene trasmessa attraverso il punto finale che è associato con la relazione HID, l'otteniamo da libusb:

Item    | Dev | EP | Status | Speed |Payload 
-----------------+-----+----+--------+-------+------------------------------- 
OUT transaction | 13 | 4 | ACK | FS | 64 bytes (90 13 00 00 00 00 .. 

D'altra parte, Windows lo invia attraverso l'endpoint del controllo (EP0). Utilizziamo l'API di configurazione per trovare il dispositivo con gli usi di cui abbiamo bisogno, aprirlo per IN e OUT e utilizzare lo stesso descrittore di file per la lettura e la scrittura. L'EP4 Nei rapporti sono ben ricevuti attraverso questo descrittore di file, ma scrivere un rapporto attraverso lo stesso descrittore di file, finisce sul EP0:.

Item    | Dev | EP | Status | Speed |Payload 
-------------------+-----+----+--------+-------+------------------------------- 
Class request OUT | 25 | 0 | OK | FS | 64 bytes (90 13 00 00 00 00 .. 

(spiacente, non postare una foto (ancora) Ho copiato l'Ellisys rapporti a mano)

Il dispositivo incorporato non verifica su quale EP viene inviato il rapporto OUT (cioè i rapporti SET su EP0 eseguiranno la stessa funzione dei rapporti OUT rilevati sugli altri endpoint durante l'elaborazione di eventi HID), quindi risponderà in entrambi i modi.

La mia domanda è: sono entrambi i modi corretti, e se no, che è corretto e quale no? Potrebbe essere che un errore nei nostri descrittori innesca questo comportamento su Windows?

essere completo: ecco il nostro descrittore: http://tny.cz/ac745a8f (spogliato dall'identificazione fornitore per mantenere il mio capo felice :))

Zoom nella relazione, quando su Windows:! (Joy mi è permesso di fare immagini ora:))

enter image description here

L'intera transazione:

enter image description here

Librerie utilizzate su Windows: hid.lib, hidclass.lib e setupapi.lib. Durante la scrittura di un report utilizziamo le funzioni HidP_SetUsageValueArray e HidD_SetOutputReport. PHIDP_PREPARSED_DATA e HIDP_CAPS vengono trovati con le funzioni HidD_GetAttributes, HidD_GetPreparsedData e HidP_GetCaps. Il percorso del file per il dispositivo viene rilevato utilizzando SetupDiEnumDeviceInterfaces. Se troviamo un dispositivo con VID corretto, PID, caps.UsagePage e caps.Usage, questo è il dispositivo che utilizziamo.

Su Linux è un po 'più complicato, in quanto non sono io a implementare il codice linux. Quello che posso dire è che viene utilizzato libusb-1.0.9, il dispositivo viene aperto usando libusb_open_device_with_vid_pid, i report vengono inviati con libusb_fill_interrupt_transfer e libusb_submit_transfer. Vedo che libuwand_fill_interrupt_transfer accetta un endpoint come parametro, quindi penso con il solo handle da libusb_open_device_with_vid_pid e passando il parametro giusto come endpoint, libusb capirà dove mettere il rapporto.

+0

L'endpoint 0 è riservato ai trasferimenti di controllo, quindi è necessario un pacchetto SETUP di 8 byte inviato prima del payload, con parametri come bRequestType, bRequest, wValue e simili. Potresti postare i valori di quel pacchetto SETUP? Avere queste informazioni ci consentirà di esaminare le specifiche HID e vedere quale richiesta invia Windows e se è valida. Inoltre, quali stack di driver/libreria stai usando per inviare i dati su Linux e Windows? L'endpoint utilizzato da Windows potrebbe dipendere dal driver (ad es. Hidusb.sys) e dalla libreria che si utilizza per comunicare con il driver (ad es. Libusb) e il proprio codice. –

+0

"Il dispositivo incorporato non verifica su quale EP viene ricevuto il rapporto OUT": Mi sembra strano. Come funziona? La struttura dei trasferimenti di controllo inviati sull'endpoint 0 è molto più complicata dei dati su un normale interrupt o bulk endpoint, quindi è necessario un codice speciale per elaborare i dati dell'endpoint 0 in primo luogo. –

risposta

1

Penso di aver trovato la risposta.

per pura coincidenza, mi sono imbattuto nel forum Keil in cui ho trovato l'istruzione "HidD_SetOutputReport utilizzerà l'endpoint del controllo, se lo si desidera tramite un altro endpoint, utilizzare WriteFile". So che più di 5 anni fa avevo provato quella strada, ma mi sono arenato in un IO asincrono con strutture sovrapposte.Da quando è apparso ho avuto una via d'uscita (usando HidD_SetOutputReport) ho abbandonato il percorso WriteFile. Quindi ora è il momento di cercare di nuovo quella strada, e l'ho fatto. Il codice:

res = HidD_SetOutputReport(m_DeviceControl[dev], report, m_CapsControl[dev].OutputReportByteLength); 

è stato sostituito da

   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); 
        } 
       } 
      } 

e questo rende la richiesta di andare oltre il corretto endpoint.

pertanto giunto alla seguente conclusione:

  • Credo sia sbagliato che il dispositivo HID interpreta le relazioni OUT inviati attraverso il punto finale di controllo.
  • Se si utilizza WriteFile correttamente (con IO sovrapposto), i report OUT utilizzano l'endpoint corretto.
Problemi correlati