Using libusb in linux

Post questions and issues with Concept2 PM3 SDK
Post Reply
johroo
Paddler
Posts: 8
Joined: May 23rd, 2007, 2:29 pm

Using libusb in linux

Post by johroo » May 23rd, 2007, 2:50 pm

Hi all,

I am trying to use libusb under linux to communicate with my PM3.
I thought someone here might be interested what I have found so far.

Linux will get hold of the usb device when it is plugged in so the first thing you must do in yur program is to call usb_detach_kernel_driver_np to be able to do anything yourself with the device. And to be able to make this call work you need to run the code under root privileges. This is not so good but this is what you get by doing it in user space I suppose.

When this is done you should be able to make queries about the device. As concept2 sdk documentation mentions that the endpoints used by the pm3 are so called interrupt endpoints I used the commands

usb_interrupt_write and usb_interrupt_read

to communicate with the PM3. Remember to get hold of the interface before you do this using the usb_claim_interface command.

This is about as far as I have come. I can get the command
usb_interrupt_write to work i.e. not fail by returning an error code BUT it seems the command does not reach the PM3 or something is wrong with the frames I send. For example sending the command

{0xF1 ,0x80 ,0x80 ,0xF2} = GET STATUS FRAME

I would expect that the PM3 would respond with the status but calling

usb_interrupt_read

just times out and no data is received.
My PM3 has firmware 97 and everything seems to work OK. Maybe someone can give me a hint what more is needed to get the PM3 to respond?
Last edited by johroo on May 23rd, 2007, 4:54 pm, edited 1 time in total.

haboustak
500m Poster
Posts: 77
Joined: March 17th, 2006, 3:02 pm
Location: Cincinnati

Post by haboustak » May 23rd, 2007, 3:10 pm

The PM3 is an HID device and as such its Interrupt IN/OUT endpoints expect data to follow the HID spec. That is:

1: The size of the transfer buffer (in both directions) should equal the size of one of the HID reports defined on the endpoint via the HID Report Descriptor.
2: On a device with multiple HID reports, the first byte must be the ID of the report you're sending.
3: (optionally) On Windows, when issuing a READ on an Interrupt IN endpoint, the first byte of the receive buffer must also contain the Report ID you're expecting. This is a signal to the kernel, not the device, and is probably irrelevant on Linux.

If you're willing to write a few hundred lines of code you could use the hiddev IOCTLs to communicate with the PM. You wouldn't be able to use libusb, but you wouldn't have to detach the kernel driver either. The benefit of using hiddev is that it gives you a real HID parser that tells you information about what reports are defined. If you want to stick with libusb you can try to also use its friend libhid. Not sure if their parser can handle the PM or not -- should be fine. The support for libhid seems dicey at best.

Mike

johroo
Paddler
Posts: 8
Joined: May 23rd, 2007, 2:29 pm

Post by johroo » May 23rd, 2007, 4:02 pm

Thank you for the very good information.

I fixed the code to comply with the report sizes and it worked on the first try :D . I used the report ID#1 which has size 20+1 for ID.

Command to PM3: 1 F1 80 80 F2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

Answer from PM3: 2 F1 99 99 F2 33 30 30 31 31 36 37 34 30 2A F2 CC 1 0 98 F C5 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 D3 4F F2

Thanks again haboustak.

I have noticed another thing. When I issue commands to the PM3 and do not repect the usb interrupt frame time of 1ms I don't get an error message from the read function. Instead old data is returned. I wonder how do the concept2 SDK handle the usb hid interface restriction of reading only once every usb frame?

Is there a built in delay of 1ms after every command?
I cannot test this myself as I don't have any windows box.

Peewee1963
Paddler
Posts: 5
Joined: May 8th, 2007, 5:03 am

Post by Peewee1963 » May 25th, 2007, 8:53 am

I exactly have tried this with libusb on my mac, using the PM4. Endpoint number 0, report size 20+1, -> no effect, no bytes read. Have I to change some parameters?

johroo
Paddler
Posts: 8
Joined: May 23rd, 2007, 2:29 pm

Post by johroo » May 25th, 2007, 9:13 am

Hi Peewee1963.

You should not use endpoint 0 as this is the control endpoint. You should use endpoint 4 for writing and endpoint 0x83 for reading.

haboustak
500m Poster
Posts: 77
Joined: March 17th, 2006, 3:02 pm
Location: Cincinnati

Post by haboustak » May 26th, 2007, 12:25 pm

Peewee1963,
The key difference between libusb on Mac and Linux is that you can't detach the kernel driver on the Mac. The function usb_detach_kernel_driver_np depends on kernel support and there isn't any on Mac. In fact, it was only added to Linux in a recent 2.6.x version.

johroo,
There's a historical post by Mark Lyons where he describes the typical update rate of the hardware at ~30-50msec. Maybe even 20 ms. I think a good portion of this is bus latency. Keep in mind that the Win32 SDK uses 120-byte reports exclusively, which requires two HID transactions in each direction.
http://www.c2forum.com/viewtopic.php?p=492#492

On an OS where you have an HID driver you don't need to worry about outpacing the HID spec because the driver respects that for you. The PM3 is a synchronous device, only one request at a time or it will error out, so you queue up a request and wait for it to finish. On Windows, you issue a write and then a following read will block until new data appears. On Mac, you issue an output transaction and wait for an event from the input queue. On Linux, you issue the HIDIOCSREPORT IOCTL and then select() the file descriptor for usage events that indicate HIDIOCGREPORT can be called.

Mike

Peewee1963
Paddler
Posts: 5
Joined: May 8th, 2007, 5:03 am

Post by Peewee1963 » May 26th, 2007, 3:34 pm

Hello Mike,
which type of element do you use on the mac to issue the output?

johroo
Paddler
Posts: 8
Joined: May 23rd, 2007, 2:29 pm

Post by johroo » May 26th, 2007, 3:40 pm

When I read out distance and time(in one ID#1 command) as fast as I can from the PM3 I get about 50 frames per second. Doing this I have to empty the usb buffer by doing 1ms interrupt reads until I get a timeout, otherwise I get old data. This usually takes about two reads. ~50 frames per second equals an updating time of about 20ms just as you suggest. This is a snapshot of a one second dump.

109.9 m @ 0:0:44:0
109.9 m @ 0:0:44:0
110.0 m @ 0:0:44:3
110.0 m @ 0:0:44:3
110.0 m @ 0:0:44:6
110.1 m @ 0:0:44:9
110.1 m @ 0:0:44:9
110.2 m @ 0:0:44:12
110.2 m @ 0:0:44:15
110.3 m @ 0:0:44:18
110.4 m @ 0:0:44:21
110.4 m @ 0:0:44:21
110.5 m @ 0:0:44:24
110.5 m @ 0:0:44:24
110.5 m @ 0:0:44:28
110.6 m @ 0:0:44:31
110.7 m @ 0:0:44:34
110.7 m @ 0:0:44:34
110.7 m @ 0:0:44:37
110.7 m @ 0:0:44:37
110.8 m @ 0:0:44:40
110.9 m @ 0:0:44:43
110.9 m @ 0:0:44:43
110.9 m @ 0:0:44:46
111.0 m @ 0:0:44:49
111.0 m @ 0:0:44:49
111.1 m @ 0:0:44:52
111.1 m @ 0:0:44:52
111.2 m @ 0:0:44:56
111.2 m @ 0:0:44:59
111.2 m @ 0:0:44:59
111.3 m @ 0:0:44:62
111.4 m @ 0:0:44:65
111.4 m @ 0:0:44:65
111.4 m @ 0:0:44:68
111.4 m @ 0:0:44:68
111.5 m @ 0:0:44:71
111.5 m @ 0:0:44:71
111.6 m @ 0:0:44:74
111.6 m @ 0:0:44:78
111.7 m @ 0:0:44:81
111.7 m @ 0:0:44:81
111.8 m @ 0:0:44:84
111.8 m @ 0:0:44:84
111.9 m @ 0:0:44:87
111.9 m @ 0:0:44:87
111.9 m @ 0:0:44:90
112.0 m @ 0:0:44:94
112.0 m @ 0:0:44:94
112.1 m @ 0:0:44:97

Stephen Nicklin
Paddler
Posts: 8
Joined: September 26th, 2007, 7:16 am
Location: Oxford, UK
Contact:

Post by Stephen Nicklin » September 26th, 2007, 7:22 am

Hi johroo,

Can you post or send me the code you used to get this dump? I'm looking into using libusb or libhid to hook up a PM3 rower to a Linux box (debian etch).

Thanks,

Steve

Post Reply