Hi,

I am still not smart enough to do interrupt_read() properly.

The device I am trying to talking to takes commands and answers with replies.

I have used "Snoopy Pro" to spy on the conversation with my device while a Windows-Program that uses the device is running. It sends two commands and receives two replies. The full log in Snoopy-Format is attached, excerpts
from it are made in plain text.

Please bear with me as I first show what the Windows-program registers in Snoopy and then what my Linux-Code using libhid tries to do and where it fails.

The short summary is that I can only get one response using interrupt_read() every follow up comes up empty.

I send the first command. Called "Initial reset":

In Snoopy this registers as two entries:

>19  ??? down        n/a     17.225  BULK_OR_INTERRUPT_TRANSFER      -       
>URB Header (length: 72)
>SequenceNumber: 19
>Function: 0009 (BULK_OR_INTERRUPT_TRANSFER)
>TransferFlags: 0x00000003
>
>No TransferBuffer
>
>20  out down        n/a     17.238  CLASS_INTERFACE 02 00 03 43 30 30 00 >00   
  
>URB Header (length: 80)
>SequenceNumber: 20
>Function: 001b (CLASS_INTERFACE)
>PipeHandle: 00000000
>
>SetupPacket:
>0000: 22 09 02 02 00 00 00 00
>bmRequestType: 22
>  DIR: Host-To-Device
>  TYPE: Class
>  RECIPIENT: Endpoint
>bRequest: 09
>
>
>TransferBuffer: 0x0000000c (12) length
>0000: 02 00 03 43 30 30 00 00 00 00 00 00

I recognize the data here. It's the device-specific protocol:

  02 is the report ID.
  00 03 is the command length. 3 bytes.
  43 is 'C' for Command
  30 30 is '00' and is the code für "Initial reset".
  The rest is padding. Reports are of fixed size, Report ID 02 is
  11 bytes.

The device acts on this command, it cycles a solenoid which is very audible and proves that the command went through OK.

Now it answers:

>20  out up  n/a     17.241  CONTROL_TRANSFER        -       0x00000000
>URB Header (length: 80)
>SequenceNumber: 20
>Function: 0008 (CONTROL_TRANSFER)
>PipeHandle: 887ea618
>
>SetupPacket:
>0000: 21 09 02 02 00 00 0c 00
>bmRequestType: 21
>  DIR: Host-To-Device
>  TYPE: Class
>  RECIPIENT: Interface
>bRequest: 09
>
>
No TransferBuffer
>
>8 ??? up n/a 17.689 BULK_OR_INTERRUPT_TRANSFER 42 00 05 50 30 >30 30 30 0x00000000
>URB Header (length: 72)
>SequenceNumber: 8
>Function: 0009 (BULK_OR_INTERRUPT_TRANSFER)
>TransferFlags: 0x00000003
>
>TransferBuffer: 0x0000000c (12) length
>0000: 42 00 05 50 30 30 30 30 48 42 55 2d

Again, the data decoded using docs from the Vendor:

  42 The report ID.
  00 05 Length of the response.
  50 'P' Positive response.
  30 30 '00' repeats the command the response is for.
  30 30 Two bytes of status, '00' represents the status of internal sensors.

So this was OK.

The next command goes like this:

>21  ??? down        n/a     17.689  BULK_OR_INTERRUPT_TRANSFER      -       
>URB Header (length: 72)
>SequenceNumber: 21
>Function: 0009 (BULK_OR_INTERRUPT_TRANSFER)
>TransferFlags: 0x00000003
>
>No TransferBuffer
>
>22  out down        n/a     24.666  CLASS_INTERFACE 02 00 03 43 56 30 00 >00   
  
>URB Header (length: 80)
>SequenceNumber: 22
>Function: 001b (CLASS_INTERFACE)
>PipeHandle: 00000000
>
>SetupPacket:
>0000: 22 09 02 02 00 00 00 00
>bmRequestType: 22
>  DIR: Host-To-Device
>  TYPE: Class
>  RECIPIENT: Endpoint
>bRequest: 09
>
>
>TransferBuffer: 0x0000000c (12) length
>0000: 02 00 03 43 56 30 00 00 00 00 00 00

Very much like the 'Initial reset':

  02 is the report ID.
  00 03 is the command length. 3 bytes.
  43 is 'C' for Command
  56 30 is 'V0' and is the code für "read version data".
  The rest is padding. Reports are of fixed size, Report ID 02 is
  11 bytes.

The response is larger this time:

>22  out up  n/a     24.671  CONTROL_TRANSFER        -       0x00000000
>URB Header (length: 80)
>SequenceNumber: 22
>Function: 0008 (CONTROL_TRANSFER)
>PipeHandle: 887ea618
>
>SetupPacket:
>0000: 21 09 02 02 00 00 0c 00
>bmRequestType: 21
>  DIR: Host-To-Device
>  TYPE: Class
>  RECIPIENT: Interface
>bRequest: 09
>
>
>No TransferBuffer
>
>19 ??? up n/a 24.697 BULK_OR_INTERRUPT_TRANSFER 45 00 43 50 56 >30 30 30 0x00000000
>URB Header (length: 72)
>SequenceNumber: 19
>Function: 0009 (BULK_OR_INTERRUPT_TRANSFER)
>TransferFlags: 0x00000003
>
>TransferBuffer: 0x0000004c (76) length
>0000: 45 00 43 50 56 30 30 30 48 42 55 2d 4e 41 31 34
>0010: 35 20 20 20 42 20 37 44 34 42 45 46 20 20 20 20
>0020: 20 20 20 20 20 20 20 20 20 20 30 30 30 30 30 30
>0030: 48 42 55 2d 4e 41 31 34 36 20 20 20 45 20 30 30
>0040: 45 42 31 39 39 34 00 00 00 00 00 00

  45 Report ID.
  00 43 Length of the response.
  50 'P' positive response.
  56 30 Repeats the command.
  Then response data.
  Then padding.

So this works fine. Using the windows sample software that ships with the 
device.

Now my program using libhid:

> NOTICE: hid_prepare_parser(): successfully set up the HID parser for USB device 001/007[0].
>  TRACE: hid_force_open(): add open device to list...
> NOTICE: hid_force_open(): successfully opened USB device 001/007[0].
>[DEBUG]: (V4KU) Command (00) Initial reset
>[DEBUG]: (V4KU) Sending report ID 0x02, report size is 12 bytes
>[DEBUG]: (libHID) hid_set_output_report() writing 12 bytes
>[DATA ]: (libHID) S: 0x02 0x00 0x03 0x43 0x30 0x30 0x00 0x00 0x00 0x00
>[DATA ]: (libHID) S: 0x00 0x00
>  TRACE: hid_set_output_report(): looking up report ID...
> TRACE: hid_prepare_parse_path(): preparing search path of depth 3 for parse tree of USB device 001/007[0]... > TRACE: hid_prepare_parse_path(): search path prepared for parse tree of USB device 001/007[0].
> NOTICE: hid_find_object(): found requested item.
> TRACE: hid_set_output_report(): sending report ID 0x02 (length: 12) to USB device 001/007[0]... > NOTICE: hid_set_output_report(): successfully sent report to USB device 001/007[0].

This sends the same 12 bytes as the windows-software does. The device cycles it's solenoid and thus I have feedback that the command went through. Now my program is waiting for the response.

I learned that I am supposed to fetch all the data for the reply in one go. So I first calculate the size of data (from the docs, specific to a command), and from that I derive the report-ID and from that the amount of bytes to request.

This is logged by my code and then libhid as such:

> [DEBUG]: (V4KU) Expecting 5 bytes of data, handled by report ID 0x42, report should be 12 bytes
> hid_interrupt_read(): retrieving interrupt report from device 001/007[0]...
> NOTICE: hid_interrupt_read(): successfully got interrupt report from device 001/007[0]
>[DEBUG]: (libHID) hid_interrupt_read() read 12 bytes
>[DATA ]: (libHID) R: 0x42 0x00 0x05 0x50 0x30 0x30 0x30 0x30 0x48 0x42
>[DATA ]: (libHID) R: 0x55 0x2d

I do get my 12 bytes and they are the same as when using windows. Even the ones that are supposed to be padding and thus unuseable are identical. Fine.

Trying the second command:

> [DEBUG]: (V4KU) command received positive result
> [DEBUG]: (V4KU) Command (V0) Version read
> [DEBUG]: (V4KU) Sending report ID 0x02, report size is 12 bytes
> [DEBUG]: (libHID) hid_set_output_report() writing 12 bytes
> [DATA ]: (libHID) S: 0x02 0x00 0x03 0x43 0x56 0x30 0x00 0x00 0x00 0x00
> [DATA ]: (libHID) S: 0x00 0x00
>  TRACE: hid_set_output_report(): looking up report ID...
> TRACE: hid_prepare_parse_path(): preparing search path of depth 3 for parse tree of USB device 001/007[0]... > TRACE: hid_prepare_parse_path(): search path prepared for parse tree of USB device 001/007[0].
> NOTICE: hid_find_object(): found requested item.
> TRACE: hid_set_output_report(): sending report ID 0x02 (length: 12) to USB device 001/007[0]... > NOTICE: hid_set_output_report(): successfully sent report to USB device 001/007[0].

Same data as in Windows.

But now the trouble starts. I cannot get the response. Note that my code first calculates that it will expect Report ID 0x45 for a total of 76 bytes which again matches the windows snoop log:

> [DEBUG]: (V4KU) Expecting 67 bytes of data, handled by report ID 0x45, report should be 76 bytes > TRACE: hid_interrupt_read(): retrieving interrupt report from device 001/007[0] ... >WARNING: hid_interrupt_read(): failed to get all of interrupt report from device 001/007[0]; requested: 76 bytes, sent: 0 bytes. >2008-09-03 16:22:32 [FATAL]: (libHID) hid_interrupt_read() failed (21: HID_RET_FAIL_INT_READ)

Got no data.

More observations:

I have experimented with a number of timeout options. Short, long, very long. So I do not think this is because of the time the device needs to process the second command.

I have also tried sending "initial reset" twice. I can hear the solenoid cycle twice but still I only receive one positive result, the second read returns 0 bytes. From this I follow that it's the reading not the writing that is at fault: The second command does go through but the response is never received.

I then tried sending the same command three times. There are three clicks from the solenoid, but only one reply on interrupt_read() both others fail. So all three command were received by the device. This time the second one to fail returns HID_RETURN_TIMEOUT instead of FAIL_INT_READ.

The docs for the device say that if I send a new command before I fetched the result of a previous command the new command will be ignored. As I can send many commands down the line and see them being processed I think the device has actually answered or thinks it has answered but the reply has been lost. Again that points to the reading of the data and thus to my usage of libhid.

Any hints on what I could change?

Ciao, MM
_______________________________________________
libhid-discuss mailing list
[email protected]
http://lists.alioth.debian.org/mailman/listinfo/libhid-discuss

Reply via email to