Marian Aldenhoevel
2008-09-03 14:44:51 UTC
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.
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.
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.
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.
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.
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.
ones that are supposed to be padding and thus unuseable are identical. Fine.
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
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
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.
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
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: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
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
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.
20 out up n/a 17.241 CONTROL_TRANSFER - 0x00000000
URB Header (length: 80)
SequenceNumber: 20
Function: 0008 (CONTROL_TRANSFER)
PipeHandle: 887ea618
0000: 21 09 02 02 00 00 0c 00
bmRequestType: 21
DIR: Host-To-Device
TYPE: Class
RECIPIENT: Interface
bRequest: 09
No TransferBufferURB Header (length: 80)
SequenceNumber: 20
Function: 0008 (CONTROL_TRANSFER)
PipeHandle: 887ea618
0000: 21 09 02 02 00 00 0c 00
bmRequestType: 21
DIR: Host-To-Device
TYPE: Class
RECIPIENT: Interface
bRequest: 09
8 ??? up n/a 17.689 BULK_OR_INTERRUPT_TRANSFER 42 00 05 50 30 >30 30 30
0x00000000URB 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: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
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.
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
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':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
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
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.
22 out up n/a 24.671 CONTROL_TRANSFER - 0x00000000
URB Header (length: 80)
SequenceNumber: 22
Function: 0008 (CONTROL_TRANSFER)
PipeHandle: 887ea618
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
0x00000000URB Header (length: 80)
SequenceNumber: 22
Function: 0008 (CONTROL_TRANSFER)
PipeHandle: 887ea618
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
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.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
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.
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]...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
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]...TRACE: hid_set_output_report(): sending report ID 0x02 (length: 12) to USB
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.
[DEBUG]: (V4KU) Expecting 5 bytes of data, handled by report ID 0x42,
report should be 12 byteshid_interrupt_read(): retrieving interrupt report from device 001/007[0]...
NOTICE: hid_interrupt_read(): successfully got interrupt report from device
001/007[0]NOTICE: hid_interrupt_read(): successfully got interrupt report from device
[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[DATA ]: (libHID) R: 0x42 0x00 0x05 0x50 0x30 0x30 0x30 0x30 0x48 0x42
[DATA ]: (libHID) R: 0x55 0x2d
ones that are supposed to be padding and thus unuseable are identical. Fine.
[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]...[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
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]...TRACE: hid_set_output_report(): sending report ID 0x02 (length: 12) to USB
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
[DEBUG]: (V4KU) Expecting 67 bytes of data, handled by report ID 0x45,
report should be 76 bytesTRACE: 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.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