On Mon, 23 Mar 2009, Richard wrote: > Hi, > > I have some questions about the HID USB driver in Linux. Just thought I'd mention that nothing in your message below talks about the HID driver... > I have > a Linux From Scratch LFS 6.2 system, with many additions > according to BLFS 6.2. I am using the 2.6.16.27 kernel. That's a pretty old kernel. You should upgrade, if at all possible. > I am communicating with a Cypress PSoc device, part number > CY8C24894, over usb. The device is configured as an HID with > bInterval of 1ms. I am communicating over interrupt in and > out endpoints. Here is the relevant portion from a lsusb > listing which shows how the interrupt endpoints are set up: > > --------------------------------------------------------------- > Endpoint Descriptor: > bLength 7 > bDescriptorType 5 > bEndpointAddress 0x81 EP 1 IN > bmAttributes 3 > Transfer Type Interrupt > Synch Type None > Usage Type Data > wMaxPacketSize 0x0040 1x 64 bytes > bInterval 1 > Endpoint Descriptor: > bLength 7 > bDescriptorType 5 > bEndpointAddress 0x02 EP 2 OUT > bmAttributes 3 > Transfer Type Interrupt > Synch Type None > Usage Type Data > wMaxPacketSize 0x0040 1x 64 bytes > bInterval 1 > Device Status: 0x0000 > (Bus Powered) > ------------------------------------------------------- > > As you can see the PSoc device is configured with one > interrupt in endpoint and one interrupt out endpoint, > with maximum packet size of 64 bytes and 1ms polling > interval. > > My program, which is written in C and uses libusb > calls, is continually sending out usb interrupt > messages with 64 bytes each, and after each message > is sent the program requests a reply from the > PSoc device, which consists of a packet of 62 > bytes. I am seeing about an 8ms round trip for > this process, i.e. from the time one 64-byte packet > is sent, the 62-byte reply is received, and the > next 64-byte packet is sent out. > > I have enabled debugfs and I've used usbmon to > capture a typical cycle of the usb transactions. > Here is a representative set, where I have added > numbers at the beginning of each line for > reference: > > 1. dfb324c0 1787068080 S Io:002:02 -115 64 = 043e0100 0c000e0e 00000000 > 00000000 00000000 00000000 00000000 00000000 > 2. dfb324c0 1787069920 C Io:002:02 0 64 > > 3. dfb324c0 1787069957 S Ii:002:01 -115 62 < > 4. dfb324c0 1787072920 C Ii:002:01 0 62 = 01000c00 0e0e0000 00000000 > 00000000 00000000 00000000 00000000 00000000 > 5. dfb324c0 1787076043 S Io:002:02 -115 64 = 043e0100 0c001c0e 00000000 > 00000000 00000000 00000000 00000000 00000000 > > I don't completely understand this report, so any help with > interpretation will be appreciated. Line 1 shows your first interrupt-OUT (Io) URB being submitted (S). Line 2 shows the interrupt-OUT URB completing (C) successfully. Line 3 shows your interrupt-IN URB (Ii) being submitted. Line 4 shows the interrupt-IN URB completing successfully. Line 5 shows a second interrupt-OUT URB being submitted. > I think it is clear that > line 1 is where the PC sends an interrupt out message to > the PSoc device consisting of 64 bytes. Not exactly. Line 1 is where the message is _submitted_. It doesn't get sent immediately; there is always a delay between submission and transmission. > This is accomplished > in the program by a libusb usb_interrupt_write() call. > Immediately after that call, the program starts looking > for a 62-byte reply from the PSoc, via a usb_interrupt_read() > call. I am assuming that in line 2 the PC is sending out > a message that it is looking for this reply. No. See above. The interrupt-IN _submission_ occurs in line 3, and the actual data transmission occurs a little later. > This occurs > 1.84ms after the 64-byte out transaction. More accurately, your interrupt-OUT URB completes 1.84 ms after it is submitted and your interrupt-IN URB is submitted 0.037 ms afterward. > I'm not sure > what is happening in line 3, I am guessing that the PSoc > device is notifying the PC that it has 62 bytes ready to > send via an in transaction, or maybe it is telling the > PC that the reply is not yet ready. Then on line 4, 3ms after it > was requested in line 2, the 62-byte in transaction is > received from the PSoc device. Pretty much. The interrupt-IN URB completes almost 3 ms after it was submitted (exactly 3 ms after the preceding interrupt-OUT completed). > Finally in line 5, 3.12ms > after the in transaction is received, the next 64-byte > out transaction in the series is sent. Right. > My basic question regards some of the delays in this > process. In my program, there should be very little > delay between the time a 62-byte in transaction is > received, and the time when the next 64-byte out > transaction is sent. But it appears that it takes over > 3ms before the next out transaction is sent. I wouldn't > expect this delay to be more than 1ms. Does anyone > have an idea why it takes so long to send the next > message? I don't know. It seems unlikely that the kernel or a user library is adding any significant delay. Maybe your program takes longer than you expect or maybe some other process is using the CPU. > My understanding is that with a 1ms polling interval, > all usb requested actions should be initiated in at > most 1ms. Does the HID driver strictly enforce this > timing? If you're using libusb then the HID driver isn't involved at all. It's worth pointing out that although a 1-ms polling interval guarantees that ongoing transfers will occur once per millisecond, it says nothing about how long a new transfer takes to get set up. > Also, my program immediately starts looking for > a 62-byte reply after it sends a 64-byte out > message, however it appears that the usb is > waiting 1.84ms before requesting this reply. > Again, any insight as to why this takes so long? You have misunderstood the delays. See above. > The 3ms delay between when the 62-byte in transaction > is requested in line 2, and when it is actually > received in line 4, is understandable because this > is essentially the time it takes the PSoc device > to process the data it has received and to formulate > its reply message, plus some extra delay to coincide > with the next usb frame sync, I would imagine. That sounds reasonable. > Are the libusb calls good to use for this > application, or should I be using another interface > to the usb system? libusb is fine. If you really want to get fancy you can use asynchronous transfers, which are supported in libusb-1.0. But in this case it's not clear they would help much, since a lot of the delay appears to be caused by the device itself. In theory you could get some improvement by making the IN transfer asynchronous and submitting the second OUT transfer before the first IN transfer finishes. But your device might not be able to handle this. Probably the best improvement you could make would be to raise your program's priority. That should help eliminate the nagging 3 ms delay between the IN transfer and the next OUT transfer. > Any help with these timing > issues or suggestions about how I could speed up > the usb communications will be very much appreciated. Alan Stern -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html