1
\$\begingroup\$

I'm currently making a Playstaion 2 controller to USB converter using an Arduino Uno, and it's going along very well, but I'm stuck on a specific problem.

I'm trying to support the pressure sensitive buttons, but I don't know what HID descriptor to use for the USB. I currently have the following, but my computer doesn't seem to be registering the button states properly, with jstest showing that the buttons seem to "stick" in an on state. Also, I'm not very sure if using Rx and Ry for the second analogue stick is correct.

What areas of the descriptor should I change to make everything work properly?

Here is my current descriptor:

const PROGMEM USB_Descriptor_HIDReport_Datatype_t hidDescriptor[] =
{
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x05,                    // USAGE (Game Pad)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Pointer)
    0xa1, 0x00,                    //   COLLECTION (Physical)
                                   //     ; Right stick
    0x09, 0x33,                    //     USAGE (Rx)
    0x09, 0x34,                    //     USAGE (Ry)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //     LOGICAL_MAXIMUM (255)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x02,                    //     REPORT_COUNT (2)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)

                                   //     ; Left stick
    0x09, 0x30,                    //     USAGE (X)
    0x09, 0x31,                    //     USAGE (Y)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //     LOGICAL_MAXIMUM (255)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x02,                    //     REPORT_COUNT (2)
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)
    0xc0,                          //   END_COLLECTION

    0x05, 0x09,                    //   USAGE_PAGE (Button)
                                   //   ; Pressure sensitive buttons
    0x19, 0x01,                    //   USAGE_MINIMUM (Button 1)
    0x29, 0x0c,                    //   USAGE_MAXIMUM (Button 12)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x0c,                    //   REPORT_COUNT (12)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)

                                   //   ; Other buttons (L3, R3, Select, Start)
    0x19, 0x0d,                    //   USAGE_MINIMUM (Button 13)
    0x29, 0x10,                    //   USAGE_MAXIMUM (Button 16)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x04,                    //   REPORT_COUNT (4)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0xc0                           // END_COLLECTION
};

PS. I'm using LUFA and flashing the firmware of the Uno's USB controller

\$\endgroup\$
2
\$\begingroup\$

You can't have pressure sensitive buttons. You need to specify them as additional axes.

Additionally, the controller really has 12 pressure sensitive buttons? In that case, you're out of luck, as I have yet to find any software that works with more then 8 axes (including windows!).

Furthermore, you can consolidate some of your axes controlls:

const PROGMEM USB_Descriptor_HIDReport_Datatype_t hidDescriptor[] =
{
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x05,                    // USAGE (Game Pad)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x09, 0x01,                    //   USAGE (Pointer)
    0xa1, 0x00,                    //   COLLECTION (Physical)

 // ----- Consolidated
                                   //     ; Right stick
    0x09, 0x33,                    //     USAGE (Rx)
    0x09, 0x34,                    //     USAGE (Ry)
                                   //     ; Left stick
    0x09, 0x30,                    //     USAGE (X)
    0x09, 0x31,                    //     USAGE (Y)
    0x15, 0x00,                    //     LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //     LOGICAL_MAXIMUM (255)
    0x75, 0x08,                    //     REPORT_SIZE (8)
    0x95, 0x02,                    //     REPORT_COUNT (4)    //changed
    0x81, 0x02,                    //     INPUT (Data,Var,Abs)

    0xc0,                          //   END_COLLECTION


    0x05, 0x09,                    //   USAGE_PAGE (Button)
// this section isn't going to work...
                                   //   ; Pressure sensitive buttons
    0x19, 0x01,                    //   USAGE_MINIMUM (Button 1)
    0x29, 0x0c,                    //   USAGE_MAXIMUM (Button 12)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x0c,                    //   REPORT_COUNT (12)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
// this section will, though the previous section will likely break something, and the whole descriptor will likely be rejected.
                                   //   ; Other buttons (L3, R3, Select, Start)
    0x19, 0x0d,                    //   USAGE_MINIMUM (Button 13)
    0x29, 0x10,                    //   USAGE_MAXIMUM (Button 16)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x04,                    //   REPORT_COUNT (4)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0xc0                           // END_COLLECTION
};

What I suspect is happening is the computer is interpreting a 0 for the value on the buttons as "not pressed", and anything else as "pressed". As such, unless the button completely returns to the unpressed state, the button will seem to "stick".

Anyways, the generic desktop usage page of the HID usage table actually only defines a total of 9 analog axes in it's entirety, so you're kind of out of luck. Even the windows controller diagnostic only supports a maximum of 8 axes, and most libraries that access gamepads support even fewer.

DirectX, for example, only allows you to access 6 analog axes.

Anyways, take a look at the USB HID usage tables here.

I also spent a while playing with HID tables in the process of converting an arduino leonardo into a joystick. Look at that here.

Incidentally, if you can, I recommend a Arduino Leonardo for this sort of tinkering. It's a lot easier to deal with then trying to re-flash the ATmega8U2 in a Arduino Uno.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ The Playstation controller certainly does have 12 pressure sensitive buttons! (en.wikipedia.org/wiki/DualShock#DualShock_2) Also, fortunately, the OS I'm using is Linux, and using jstest, it seems to report all of the axis fine. The target software I was going to use the controller for is PCSX2, and it seems to support all the axis too \$\endgroup\$ – 小太郎 Dec 26 '12 at 9:33
  • \$\begingroup\$ No kidding. That's kind of ridiculous. Anyways, if the OS you're on can handle lots of axes, just report all the buttons as separate analog axes, and you should be good. \$\endgroup\$ – Connor Wolf Dec 26 '12 at 17:59
1
\$\begingroup\$

After Fake Name told be that I had to use axis for the buttons, I decided to use this descriptor instead, and it works! (I've only tested in Linux though)
I had to repeat the Usage (Z) 12 times, but that didn't seem to cause any problems.

const PROGMEM USB_Descriptor_HIDReport_Datatype_t hidDescriptor[] =
{
    0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
    0x09, 0x05,                    // USAGE (Game Pad)
    0xa1, 0x01,                    // COLLECTION (Application)

                                   //   ; Right stick
    0x09, 0x33,                    //   USAGE (Rx)
    0x09, 0x34,                    //   USAGE (Ry)
                                   //   ; Left stick
    0x09, 0x30,                    //   USAGE (X)
    0x09, 0x31,                    //   USAGE (Y)
                                   //   ; Pressure sensitive buttons
    0x09, 0x32,                    //   USAGE (Z)
    0x09, 0x32,                    //   USAGE (Z)
    0x09, 0x32,                    //   USAGE (Z)
    0x09, 0x32,                    //   USAGE (Z)
    0x09, 0x32,                    //   USAGE (Z)
    0x09, 0x32,                    //   USAGE (Z)
    0x09, 0x32,                    //   USAGE (Z)
    0x09, 0x32,                    //   USAGE (Z)
    0x09, 0x32,                    //   USAGE (Z)
    0x09, 0x32,                    //   USAGE (Z)
    0x09, 0x32,                    //   USAGE (Z)
    0x09, 0x32,                    //   USAGE (Z)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x10,                    //   REPORT_COUNT (16)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)

    0x05, 0x09,                    //   USAGE_PAGE (Button)
                                   //   ; Other buttons (L3, R3, Select, Start)
    0x19, 0x01,                    //   USAGE_MINIMUM (Button 1)
    0x29, 0x04,                    //   USAGE_MAXIMUM (Button 4)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x25, 0x01,                    //   LOGICAL_MAXIMUM (1)
    0x75, 0x01,                    //   REPORT_SIZE (1)
    0x95, 0x04,                    //   REPORT_COUNT (4)
    0x81, 0x02,                    //   INPUT (Data,Var,Abs)
    0xc0                           // END_COLLECTION
};
|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.