Page 1 of 1

HID Composite device with reports bigger than 8 bytes

Posted: Sat Nov 01, 2008 11:25 am
by wilin
Hi

Does anybody know, how to successfully send reports for two devices (2 gamepads in my case), that are more than 8 bytes long? (1 byte reportID + 8 bytes data). Because I can send >8 bytes for one joystick (not a composite device) or 2x8bytes (composite device, two joysticks, but then I'm missing 8 buttons on each). This is the last thing that I want to implement in my converter (it's a Playstation/Playstation2 gamepad converter with support for DDR pads and possibly Guitar Hero controllers) and it's been driving me crazy for the past two days (for some reason whatever I tried presented itself as a mouse under linux, and didn't work fully under windows).

Posted: Tue Nov 04, 2008 12:36 pm
by christian
When you send reports of more than 8 bytes, concatenate several calls to usbSetInterrupt() and make sure the buffer is empty with usbInterruptIsReady() before you call usbSetInterrupt(). The last chunk should be less than 8 bytes to indicate the end of transfer.

Posted: Tue Nov 04, 2008 9:32 pm
by wilin
I've tried sending two reports (first 8 bytes, then one, then 8 again, and one again), and it doesn't really work. Linux detects it as a mouse, while Windows detects it as a gamepad and everything, but eats (doesn't change) 3 bits from the eight and ninth byte (maybe even more). I think I made Windows not eat those bits by sending 18 bytes together (8+8+2), but it still didn't work properly under linux.

I think my problem is somewhere else, probably in the if(rq->bRequest == USBRQ_HID_GET_REPORT) statement. I've uploaded the current main.c (minimalistic version, most of the features cut out) to http://pastebin.com/m5474b7ff

Posted: Wed Nov 05, 2008 1:01 pm
by christian
Sorry, I don't have the time to go through your code. But I can confirm that sending a 18 byte report as 8 + 8 + 2 should work as long as you make sure that the buffer is available when you call usbSetInterrupt().

Posted: Wed Nov 05, 2008 1:05 pm
by christian
Sorry, I don't have the time to go through your code. But I can confirm that sending a 18 byte report as 8 + 8 + 2 should work as long as you make sure that the buffer is available when you call usbSetInterrupt().

Re: HID Composite device with reports bigger than 8 bytes

Posted: Mon Sep 21, 2009 8:37 pm
by mojo
Christian, can you elaborate a little? When you say you need to make sure the buffer is available with usbInterruptIsReady(), do you mean before every call to usbSetInterrupt() or just once before all the calls?

For example, this does not seem to work properly:

Code: Select all

        if(usbInterruptIsReady())
      {
            /* called after every poll of the interrupt endpoint */
         ReadJoystick();
         usbSetInterrupt((void *)&reportBuffer + 0, 8);
         usbSetInterrupt((void *)&reportBuffer + 8, 8);   // 16
         usbSetInterrupt((void *)&reportBuffer + 16, 8);   // 24
         usbSetInterrupt((void *)&reportBuffer + 24, 8);   // 32
         usbSetInterrupt((void *)&reportBuffer + 32, 8);   // 40
         usbSetInterrupt((void *)&reportBuffer + 40, 7);   // 47
        }


And neither does this:

Code: Select all

        if(usbInterruptIsReady())
      {
            /* called after every poll of the interrupt endpoint */
         ReadJoystick();
         usbSetInterrupt((void *)&reportBuffer + 0, 8);
                        while(!usbInterruptIsReady());
         usbSetInterrupt((void *)&reportBuffer + 8, 8);   // 16
                        while(!usbInterruptIsReady());
         usbSetInterrupt((void *)&reportBuffer + 16, 8);   // 24
                        while(!usbInterruptIsReady());
         usbSetInterrupt((void *)&reportBuffer + 24, 8);   // 32
                        while(!usbInterruptIsReady());
         usbSetInterrupt((void *)&reportBuffer + 32, 8);   // 40
                        while(!usbInterruptIsReady());
         usbSetInterrupt((void *)&reportBuffer + 40, 7);   // 47
        }

Re: HID Composite device with reports bigger than 8 bytes

Posted: Mon Sep 21, 2009 8:53 pm
by mojo
Oh, I tried with this too:

Code: Select all

while (!usbInterruptIsReady()) usbPoll();


Didn't help.

Re: HID Composite device with reports bigger than 8 bytes

Posted: Mon Sep 21, 2009 9:45 pm
by christian
This latest version should work, unless parts of your software suffer under the large delay of this construct.

I noticed you compute (void *)&buffer + intvalue. Gcc probably handles it correctly, but strictly speaking, a void pointer has no size and adding a value to it is nonsense. You probably want (char *)&buffer + intvalue.

Re: HID Composite device with reports bigger than 8 bytes

Posted: Tue Sep 22, 2009 1:07 am
by mojo
Thanks for the reply. I am not the OP, but I have a similar problem. I am getting some strange results.

The above code works, sort of. I get 50 bytes returned with the correct data when I use SimpleHIDWrite to check it. For some reason though, the HID gamepad interface just seems to ignore it. I get absolutely nothing, even when I write random rolling values.

The report descriptor seems to be valid (I tried a few, they are all based on the PS3 SIXAXIS one). It must be some kind of issue like that though.

Thanks for the assistance.