USB Host Mouse Driver

Status
Not open for further replies.
These can't work without ... a full HID report descriptor parser.

A full HID report descriptor parser is *exactly* what we're doing.


Edit: well, except so far "full" doesn't include seldom-used or not-really-necessary features: secondary level collections, physical units, physical min/max, global state push/pop, long format items, designators, strings and delimiters. And so far it's only for input. Output and maybe feature reports may be added later, but we're going to need to find more than just keyboard LEDs for testing...
 
Last edited:
Paul,

You might also simply look at plugging in a teensy configured as both Keyboard, Mouse and Joystick,

I think I am seeing the same hang:

Code:
USB Host Testing
sizeof Device = 32
sizeof Pipe = 96
sizeof Transfer = 64
power up USBHS PHY

ISR: 408C
 Port Change
port change: 10001803
    connect

ISR: 1004088
 Timer0
  begin reset

ISR: 408C
 Port Change
port change: 10001805
  port enabled

ISR: 1004080
 Timer0
  end recovery
new_Device: 12 Mbit/sec
new_Pipe
new_Control_Transfer

ISR: 4E081
 USB Async
Async Followup
  Followup 1FFF5420    token=80000200
  Followup 1FFF5360    token=100
  Followup 1FFF53A0    token=8000
enumeration:
new_Control_Transfer
  Followup 1FFF53E0    token=80280
  Followup 1FFF5420    token=80008180

ISR: 4E081
 USB Async
Async Followup
  Followup 1FFF53E0    token=80000200
  Followup 1FFF5420    token=8100
enumeration:
new_Control_Transfer
  Followup 1FFF5360    token=80280
  Followup 1FFF2EC0    token=80120180
  Followup 1FFF53A0    token=80008080

ISR: 4E081
 USB Async
Async Followup
  Followup 1FFF5360    token=80000200
  Followup 1FFF2EC0    token=100
  Followup 1FFF53A0    token=8000
enumeration:
new_Control_Transfer
  Followup 1FFF53E0    token=80280
  Followup 1FFF5420    token=80FC0180
  Followup 1FFF5360    token=80008080

ISR: 4E081
 USB Async
Async Followup
  Followup 1FFF53E0    token=80000200
  Followup 1FFF5420    token=F80100
  Followup 1FFF5360    token=8000
enumeration:
new_Control_Transfer
  Followup 1FFF2EC0    token=80280
  Followup 1FFF53A0    token=80FC0180
  Followup 1FFF53E0    token=80008080

ISR: 4E081
 USB Async
Async Followup
  Followup 1FFF2EC0    token=80000200
  Followup 1FFF53A0    token=E40100
  Followup 1FFF53E0    token=8000
enumeration:
new_Control_Transfer
  Followup 1FFF5420    token=80280
  Followup 1FFF5360    token=80FC0180
  Followup 1FFF2EC0    token=80008080

ISR: 4E081
 USB Async
Async Followup
  Followup 1FFF5420    token=80000200
  Followup 1FFF5360    token=CC0100
  Followup 1FFF2EC0    token=8000
enumeration:
new_Control_Transfer
  Followup 1FFF53A0    token=80280
  Followup 1FFF53E0    token=80FC0180
  Followup 1FFF5420    token=80008080

ISR: 4E081
 USB Async
Async Followup
  Followup 1FFF53A0    token=80000200
  Followup 1FFF53E0    token=EC0100
  Followup 1FFF5420    token=8000
enumeration:
new_Control_Transfer
  Followup 1FFF5360    token=80280
  Followup 1FFF2EC0    token=80090180
  Followup 1FFF53A0    token=80008080

ISR: 4E081
 USB Async
Async Followup
  Followup 1FFF5360    token=80000200
  Followup 1FFF2EC0    token=100
  Followup 1FFF53A0    token=8000
enumeration:
Config data length = 141
new_Control_Transfer
  Followup 1FFF53E0    token=80280
  Followup 1FFF5420    token=808D0180
  Followup 1FFF5360    token=80008080

ISR: 4E081
 USB Async
Async Followup
  Followup 1FFF53E0    token=80000200
  Followup 1FFF5420    token=100
  Followup 1FFF5360    token=8000
enumeration:
bNumInterfaces = 5
bConfigurationValue = 1
new_Control_Transfer
  Followup 1FFF2EC0    token=80280
  Followup 1FFF53E0    token=80008180

ISR: 4E081
 USB Async
Async Followup
  Followup 1FFF2EC0    token=80000200
  Followup 1FFF53E0    token=8100
enumeration:
USBHub memory usage = 1312
USBHub claim_device this=1FFF2F00
USBHub memory usage = 1312
USBHub claim_device this=1FFF3420
USBHub memory usage = 1312
USBHub claim_device this=1FFF3940
KeyboardController claim this=1FFF2020
KeyboardController claim this=1FFF2220
HIDParser claim this=1FFF3E80
HIDParser claim this=1FFF4220
HIDParser claim this=1FFF2420
HIDParser claim this=1FFF27C0
HIDParser claim this=1FFF2B60
Descriptor 4 = INTERFACE
KeyboardController claim this=1FFF2020
ep = 83
packet size = 8
polling interval = 1
new_Pipe
allocate_interrupt_pipe_bandwidth
 best_bandwidth = 3
, at offset = 0, shift= 0
add_qh_to_periodic_schedule:
  interval = 1
  offset =   0
  add to slot 0
  add to slot 1
  add to slot 2
  add to slot 3
  add to slot 4
  add to slot 5
  add to slot 6
  add to slot 7
  add to slot 8
  add to slot 9
  add to slot 10
  add to slot 11
  add to slot 12
  add to slot 13
  add to slot 14
  add to slot 15
  add to slot 16
  add to slot 17
  add to slot 18
  add to slot 19
  add to slot 20
  add to slot 21
  add to slot 22
  add to slot 23
  add to slot 24
  add to slot 25
  add to slot 26
  add to slot 27
  add to slot 28
  add to slot 29
  add to slot 30
  add to slot 31
Periodic Schedule:
 0: 1FFF2DA0
 1: 1FFF2DA0
 2: 1FFF2DA0
 3: 1FFF2DA0
 4: 1FFF2DA0
 5: 1FFF2DA0
 6: 1FFF2DA0
 7: 1FFF2DA0
 8: 1FFF2DA0
 9: 1FFF2DA0
10: 1FFF2DA0
11: 1FFF2DA0
12: 1FFF2DA0
13: 1FFF2DA0
14: 1FFF2DA0
15: 1FFF2DA0
16: 1FFF2DA0
17: 1FFF2DA0
18: 1FFF2DA0
19: 1FFF2DA0
20: 1FFF2DA0
21: 1FFF2DA0
22: 1FFF2DA0
23: 1FFF2DA0
24: 1FFF2DA0
25: 1FFF2DA0
26: 1FFF2DA0
27: 1FFF2DA0
28: 1FFF2DA0
29: 1FFF2DA0
30: 1FFF2DA0
31: 1FFF2DA0
new_Data_Transfer
new_Control_Transfer
Descriptor 33 = HID
Descriptor 5 = ENDPOINT
Descriptor 4 = INTERFACE
KeyboardController claim this=1FFF2220
HIDParser claim this=1FFF3E80
 bInterfaceClass =    3
 bInterfaceSubClass = 0
 bInterfaceProtocol = 0
report descriptor size = 84
Single endpoint HID:
  endpoint = 85
   size = 8
   interval = 1
 *** before new pipe ***
new_Pipe
allocate_interrupt_pipe_bandwidth
 best_bandwidth = 5
, at offset = 0, shift= 3
add_qh_to_periodic_schedule:
  interval = 1
  offset =   0
  traverse list 0
  traverse list 1
 
Yup, I've reproduced the problem with a Teensy LC.

I guess we now have a pretty definitive answer to the question in the comment on line 1107.

Code:
        // TODO: does this really make an inverted tree like EHCI figure 4-18, page 93

Working on a fix...

FWIW, here's the code I put on the Teensy LC plugged into the Teensy 3.6 ref board.

Code:
#include <Bounce.h>

Bounce button2 = Bounce(15, 10);
Bounce button3 = Bounce(16, 10);
Bounce button4 = Bounce(17, 10);
Bounce button5 = Bounce(18, 10);

void setup() {
  // put your setup code here, to run once:
  pinMode(15, INPUT_PULLUP);
  pinMode(16, INPUT_PULLUP);
  pinMode(17, INPUT_PULLUP);
  pinMode(18, INPUT_PULLUP);
  delay(1);
}

void loop() {
  button2.update();
  button3.update();
  button4.update();
  button5.update();
  if (button3.fallingEdge()) {
    Mouse.move(-1, 0); // move Left
  }
  if (button2.fallingEdge()) {
    Mouse.move(1, 0);  // move Right
  }
  if (button5.fallingEdge()) {
    Keyboard.press(KEY_B);
  }
  if (button5.risingEdge()) {
    Keyboard.release(KEY_B);
  }
  if (button4.fallingEdge()) {
    Keyboard.press(KEY_MEDIA_PLAY_PAUSE);
  }
  if (button4.risingEdge()) {
    Keyboard.release(KEY_MEDIA_PLAY_PAUSE);
  }
}

DSC_0718_web.jpg
 
Yup, definitely a bug. It's sometimes creating looped lists instead of the inverted tree structure.

I'm working on a fix, but it's not simple. This is one of the harder parts of USB host. Obviously my first attempt wasn't quite good enough...
 
I'm working with the PS3 controller again. Fixed another bug, so at least Teensy isn't crashing or getting stuck. But the controller decides to play dead after 900 ms.

Is there any more info about this mystery command?

With PS3 - I believe I read that you also need to tell the PS3 to start sending Report 1 to get it to work...
I think the command bytes is:
Code:
static const uint8_t ps3_feature_F4_report[]  = {0x42, 0x0c, 0x00, 0x00};

I tried a few different things like:
Code:
	if ((dev->idVendor == 0x54c) && (dev->idProduct == 0x268)) {
		println("*** Sony PS3");
		mk_setup(setup, 0x21, 9, 0x3f4, 0, 4); // ps3 tell it to send report 1?
		print_hexbytes((uint8_t*)&setup, 8);
		queue_Control_Transfer(dev, &setup, (void*)ps3_feature_F4_report, this);		
	}
But that appears to crash the USB, so probably wrong...
 
I will try looking again...

Also wonder about looking also at the Usb_host_shield_2.0 code base: https://github.com/felis/USB_Host_Shield_2.0

I do see they have PS3 modules

Just updated to your checked in stuff. So you have a Joystick subclass I can start working with or should I pick it up from my other branch and adapt it to your HID parser?

Thanks
 
I added the special PS3 command, and sure enough it does cause the controller to start sending HID input reports!

https://github.com/PaulStoffregen/USBHost_t36/commit/356700d9d5c2b59b41b4356400b95263cc6e3df9

So you have a Joystick subclass I can start working with or should I pick it up from my other branch and adapt it to your HID parser?

No, not yet. I'm working mostly with the verbose debug printing and watching USB packets with the Beagle protocol analyzer.

I'll start one today, similar to the mouse. That ought to give a good starting point for hacking...
 
If I have time, if you don't beat me to it, will hack up my earlier one and test out the PS4, which worked fine earlier.

If I am reading the code correctly, you are interpreting the HID descriptor with each packet that is received?

So it will interesting to figure out with the Joystick, you probably want a couple of methods, like:
Count of buttons and Count of Axes.

Question will be on Query functions for the Axes, There appears to be some semi-standard ones and then some that are device specific...
Again like ID of: 0x10030 is I believe X and...

But then there was areas where they would have a use page: 0xff00 or something like that and a repeat count of 20 and then input variable... So you know there are something like 20 buttons defined... So question will be:

Should the host code simply ask for the 15th axes and it get's it in whatever order they were defined in the report. If so probably want another query to say what is the ID for for #15. And/Or - should there be a query for X, Y,


Side note: Wonder with Mouse if the method should be: getMouseX(), or maybe getX() or maybe just x()
likewise getButtons, should simply be buttons()
 
If I am reading the code correctly, you are interpreting the HID descriptor with each packet that is received?

Yes. That was part of my concern about speed. Others seem to parse the descriptor into something they can walk through more efficiently when the data arrives.

Side note: Wonder with Mouse if the method should be: getMouseX(), or maybe getX() or maybe just x()
likewise getButtons, should simply be buttons()

Yeah, we should probably put some thought into a friendly & stable API before this gets into 1.40.
 
Hi Paul,

I hacked up a Joystick class and saw that you had the PS3 reporting :D

So I am getting output from it... Can Upload a version if you like, but my guess is you already have one.

The PS4 controller was not working at all. Figured out report descriptor was not working fully.

Mesg you print: report descriptor size = 483
However you reserved 256 bytes for it. When i changed it to 512, started working
 
Thanks,

I synced up and the PS4 does not work as per the previous posting. Changed descriptor to 512 instead of 256 made it work.

I tried a couple of hacks to see if you could make it work when the descriptor size > sizeof(descriptor). But did not work (yet).
I modified line 75: if (descsize > sizeof(descriptor)) return false; // can't fit the report descriptor
To instead set descsize = sizeof(descriptor)

Also modified line 156 in ::control
if (mesg == 0x22000681 && transfer->length == descsize) { // HID report descriptor
To allow it to work if length was == descsize or sizeof(descriptor)...

The code than called the parse code but did not show any data coming out... Probably parse did not like having it's data truncated in the middle of some levels of collection or the like.

I also edited your version of Mouse.ino to output RX and RY as well:
Code:
  if (joystick1.available()) {
    Serial.print("Joystick: buttons = ");
    Serial.print(joystick1.getButtons(), HEX);
    Serial.print(", X = ");
    Serial.print(joystick1.getAxis(0));
    Serial.print(", Y = ");
    Serial.print(joystick1.getAxis(1));
    Serial.print(", RX = ");
    Serial.print(joystick1.getAxis(2));
    Serial.print(", RY = ");
    Serial.print(joystick1.getAxis(5));

    Serial.println();
    joystick1.joystickDataClear();
  }
Will play some more... Yes maybe having the code do mapping from physical min/max to logical min/max or the like makes sense.
From posting #42, the DS4 HID descriptor beginning looks like:
Code:
kurt@kurt-UP-CHT01:~$ sudo usbhid-dump  -i0 | grep -v : | xxd -r -p | hidrd-convert -o spec
Usage Page (Desktop),               ; Generic desktop controls (01h)
Usage (Gamepad),                    ; Gamepad (05h, application collection)
Collection (Application),
    Report ID (1),
[COLOR="#FF0000"]    Usage (X),                      ; X (30h, dynamic value)
    Usage (Y),                      ; Y (31h, dynamic value)
    Usage (Z),                      ; Z (32h, dynamic value)
    Usage (Rz),                     ; Rz (35h, dynamic value)[/COLOR]
    Logical Minimum (0),
    Logical Maximum (255),
    Report Size (8),
    Report Count (4),
 [COLOR="#FF0000"]   Input (Variable),
    Usage (Hat Switch),             ; Hat switch (39h, dynamic value)
    Logical Minimum (0),
    Logical Maximum (7),
    Physical Minimum (0),
    Physical Maximum (315),
    Unit (Degrees),
    Report Size (4),
    Report Count (1),
    Input (Variable, Null State),[/COLOR]
    Unit,
    Usage Page (Button),            ; Button (09h)
    Usage Minimum (01h),
    Usage Maximum (0Eh),
    Logical Minimum (0),
    Logical Maximum (1),
    Report Size (1),
    Report Count (14),
    Input (Variable),
    Usage Page (FF00h),             ; FF00h, vendor-defined
    Usage (20h),
    Report Size (6),
    Report Count (1),
    Logical Minimum (0),
    Logical Maximum (127),
    Input (Variable),
[COLOR="#FF0000"]    Usage Page (Desktop),           ; Generic desktop controls (01h)
    Usage (Rx),                     ; Rx (33h, dynamic value)
    Usage (Ry),                     ; Ry (34h, dynamic value)[/COLOR]
    Logical Minimum (0),
    Logical Maximum (255),
    Report Size (8),
    Report Count (2),
    Input (Variable),
    Usage Page (FF00h),             ; FF00h, vendor-defined
    Usage (21h),
    Report Count (54),
    Input (Variable),
    Report ID (5),
...
First thing I see is I labeled RX, RY wrong... Should be Z, Rz - Marked that section Red

But the next interesting field is the HAT switch - On PS3 the 4 buttons above the left joystick I believe map as buttons, but on DS4 these are the HAT switch, which is 4 bit value and have a logical/physical settings...

Then there is section for RX/RY... Not sure yet what on joystick controls these... Maybe the top touch pad? ... Will experiment.

But looks like another nice looking day outside ;)
 
Quick update:
I pushed up a version of the code: https://github.com/KurtE/USBHost_t36/tree/joystick-testing
That increased HID report size to 512,
Plus increased the Joystick Axes count to 10 for HAT 0x10039
Updated Mouse test program to print out Z, Rz, Rx, Ry, Hat

Wondering a few things:
a) Should the class give some information, like the Report contains the different Desktop Axes or not... That is does my Joystick have the Rx axis?

b) Probably should have some way to save maybe Vendor specific joystick axes values?

c) Wondering about having something like IOCTL support? Again still learning about these controllers, but for example with the OLD PS2 controllers (on SPIish interface), There used to be command streams you could output to the device to say, for example I want pressure values for some of the controls. Example on both PS3/PS4 it feels like the L2/R2 buttons, should have the ability to say not just that the button is pressed, but how far... But how do you turn that on or off.

d) As I see there are for example several reports that the DS4 can somehow generate at some point, again probably through the IOCTL like from c), may need/want when I receive a report from the device, which report it was... (Report ID).
 
Please send a pull request. I'm going to slow down on this for a few days to focus on another project.

For now, a bigger buffer is fine. Long term, I'd like to do something similar to the (planned) addMemory for Serial & Wire. This is an object where people are likely to need several instances, so wasting space will add up.
 
Sounds good, I created a pull request. Will look into some of the other issues I mentioned...
 
Merged your pull request! :)

How are you feeling about the performance of HID parsing this way, walking the report descriptor every time?
 
@Paul - Speed - I am not sure, I have only used them to run test app... I may try some other tests soon...

I probably won't get much done today, but will continue.

With my Rabbit hole version - I only made one pass through and kept a set of details, like: bit start, bit count, type, ... for each field, that i used on each report, which probably was a bit quicker, but yours is more accurate. Like I special cased (hacked) for buttons, and for the most part combined count and size into one, so the button was one item of the number of buttons. Yours is more correct!

I am thinking of trying a few more hacks (recovery), on your code, that maybe gets us back to 256 bytes should work in majority of cases. And maybe help do some speed ups...
That is if we look at the linux hid dump.. for the DS4
Code:
kurt@kurt-UP-CHT01:~$ sudo usbhid-dump  -i0 | grep -v : | xxd -r -p | hidrd-convert -o spec
Usage Page (Desktop),               ; Generic desktop controls (01h)
Usage (Gamepad),                    ; Gamepad (05h, application collection)
Collection (Application),
[COLOR="#FF0000"]    Report ID (1),
    Usage (X),                      ; X (30h, dynamic value)
    Usage (Y),                      ; Y (31h, dynamic value)
    Usage (Z),                      ; Z (32h, dynamic value)
    Usage (Rz),                     ; Rz (35h, dynamic value)
    Logical Minimum (0),
    Logical Maximum (255),
    Report Size (8),
    Report Count (4),
    Input (Variable),
    Usage (Hat Switch),             ; Hat switch (39h, dynamic value)
    Logical Minimum (0),
    Logical Maximum (7),
    Physical Minimum (0),
    Physical Maximum (315),
    Unit (Degrees),
    Report Size (4),
    Report Count (1),
    Input (Variable, Null State),
    Unit,
    Usage Page (Button),            ; Button (09h)
    Usage Minimum (01h),
    Usage Maximum (0Eh),
    Logical Minimum (0),
    Logical Maximum (1),
    Report Size (1),
    Report Count (14),
    Input (Variable),
    Usage Page (FF00h),             ; FF00h, vendor-defined
    Usage (20h),
    Report Size (6),
    Report Count (1),
    Logical Minimum (0),
    Logical Maximum (127),
    Input (Variable),
    Usage Page (Desktop),           ; Generic desktop controls (01h)
    Usage (Rx),                     ; Rx (33h, dynamic value)
    Usage (Ry),                     ; Ry (34h, dynamic value)
    Logical Minimum (0),
    Logical Maximum (255),
    Report Size (8),
    Report Count (2),
    Input (Variable),
    Usage Page (FF00h),             ; FF00h, vendor-defined
    Usage (21h),
    Report Count (54),
    Input (Variable),[/COLOR]
    Report ID (5),
    Usage (22h),
    Report Count (31),
    Output (Variable),
    Report ID (4),
    Usage (23h),
    Report Count (36),
    Feature (Variable),
    Report ID (2),
    Usage (24h),
    Report Count (36),
    Feature (Variable),
    Report ID (8),
    Usage (25h),
    Report Count (3),
    Feature (Variable),
    Report ID (16),
    Usage (26h),
    Report Count (4),
    Feature (Variable),
    Report ID (17),
    Usage (27h),
    Report Count (2),
    Feature (Variable),
    Report ID (18),
    Usage Page (FF02h),             ; FF02h, vendor-defined
    Usage (21h),
    Report Count (15),
    Feature (Variable),
    Report ID (19),
    Usage (22h),
    Report Count (22),
    Feature (Variable),
    Report ID (20),
    Usage Page (FF05h),             ; FF05h, vendor-defined
    Usage (20h),
    Report Count (16),
    Feature (Variable),
    Report ID (21),
    Usage (21h),
    Report Count (44),
    Feature (Variable),
    Usage Page (FF80h),             ; FF80h, vendor-defined
    Report ID (128),
    Usage (20h),
    Report Count (6),
    Feature (Variable),
    Report ID (129),
    Usage (21h),
    Report Count (6),
    Feature (Variable),
    Report ID (130),
    Usage (22h),
    Report Count (5),
    Feature (Variable),
    Report ID (131),
    Usage (23h),
    Report Count (1),
    Feature (Variable),
    Report ID (132),
    Usage (24h),
    Report Count (4),
    Feature (Variable),
    Report ID (133),
    Usage (25h),
    Report Count (6),
    Feature (Variable),
    Report ID (134),
    Usage (26h),
    Report Count (6),
    Feature (Variable),
    Report ID (135),
    Usage (27h),
    Report Count (35),
    Feature (Variable),
    Report ID (136),
    Usage (28h),
    Report Count (34),
    Feature (Variable),
    Report ID (137),
    Usage (29h),
    Report Count (2),
    Feature (Variable),
    Report ID (144),
    Usage (30h),
    Report Count (5),
    Feature (Variable),
    Report ID (145),
    Usage (31h),
    Report Count (3),
    Feature (Variable),
    Report ID (146),
    Usage (32h),
    Report Count (3),
    Feature (Variable),
    Report ID (147),
    Usage (33h),
    Report Count (12),
    Feature (Variable),
    Report ID (160),
    Usage (40h),
    Report Count (6),
    Feature (Variable),
    Report ID (161),
    Usage (41h),
    Report Count (1),
    Feature (Variable),
    Report ID (162),
    Usage (42h),
    Report Count (1),
    Feature (Variable),
    Report ID (163),
    Usage (43h),
    Report Count (48),
    Feature (Variable),
    Report ID (164),
    Usage (44h),
    Report Count (13),
    Feature (Variable),
    Report ID (165),
    Usage (45h),
    Report Count (21),
    Feature (Variable),
    Report ID (166),
    Usage (46h),
    Report Count (21),
    Feature (Variable),
    Report ID (240),
    Usage (47h),
    Report Count (63),
    Feature (Variable),
    Report ID (241),
    Usage (48h),
    Report Count (63),
    Feature (Variable),
    Report ID (242),
    Usage (49h),
    Report Count (15),
    Feature (Variable),
    Report ID (167),
    Usage (4Ah),
    Report Count (1),
    Feature (Variable),
    Report ID (168),
    Usage (4Bh),
    Report Count (1),
    Feature (Variable),
    Report ID (169),
    Usage (4Ch),
    Report Count (8),
    Feature (Variable),
    Report ID (170),
    Usage (4Eh),
    Report Count (1),
    Feature (Variable),
    Report ID (171),
    Usage (4Fh),
    Report Count (57),
    Feature (Variable),
    Report ID (172),
    Usage (50h),
    Report Count (57),
    Feature (Variable),
    Report ID (173),
    Usage (51h),
    Report Count (11),
    Feature (Variable),
    Report ID (174),
    Usage (52h),
    Report Count (1),
    Feature (Variable),
    Report ID (175),
    Usage (53h),
    Report Count (2),
    Feature (Variable),
    Report ID (176),
    Usage (54h),
    Report Count (63),
    Feature (Variable),
    Report ID (177),
    Usage (55h),
    Report Count (2),
    Feature (Variable),
    Report ID (178),
    Usage (56h),
    Report Count (2),
    Feature (Variable),
End Collection
kurt@kurt-UP-CHT01:~$
That once we work through the bytes that I marked in RED, the rest does not actually do anything for our Report (id #1). So maybe cache the last Report ID that we processed and the last byte needed for the information, and as soon as we get there, bail out and issue the hid_input_end() call. This would also be
used in the I only read 256 bytes out of the 450+ hid descriptor... WIll assume if I got to the end of the data for the descriptor, to say we are done and do the call back...

Current code output on DS4
Code:
Joystick: buttons = 0, X = 125, Y = 129, Z = 129, Rz = 129, Rx = 0, Ry = 0, Hat = 8
Joystick: buttons = 0, X = 125, Y = 129, Z = 130, Rz = 129, Rx = 0, Ry = 0, Hat = 8
Joystick: buttons = 0, X = 125, Y = 129, Z = 129, Rz = 129, Rx = 0, Ry = 0, Hat = 8
Joystick: buttons = 0, X = 125, Y = 129, Z = 130, Rz = 129, Rx = 0, Ry = 0, Hat = 8
Joystick: buttons = 0, X = 125, Y = 129, Z = 129, Rz = 129, Rx = 0, Ry = 0, Hat = 8
Joystick: buttons = 0, X = 125, Y = 129, Z = 130, Rz = 129, Rx = 0, Ry = 0, Hat = 8
Joystick: buttons = 0, X = 125, Y = 129, Z = 129, Rz = 129, Rx = 0, Ry = 0, Hat = 8
Joystick: buttons = 0, X = 125, Y = 129, Z = 129, Rz = 128, Rx = 0, Ry = 0, Hat = 8
Appears to be working fine The buttons show all of the buttons, except the 4 associated with "Hat" which the value 8 is no buttons pressed... Not sure if we should map these from logical to physical... X,Y - Left joystick. Z, Rz - right joystick, Rx, Ry - Left and right trigger (L2, R2)

DS3 controller: Currently looks like only left joystick and buttons is working. Need to investigate.

Note: to self/Paul - Probably Hid controller needs to inform Joystick/Mouse code that previous device was disconnected... Actually I think the User code should be able to see the state of being connected or not. I had this in my Rabbit Hole - May merge in.


@defragster:
Are you considering making a static table of 'known' devices stored in flash table versus parsing on the fly on device arrival?
I was thinking of something like this before I went down the Rabbit hole. That is have a table by Vendor ID/Product ID - Maps to table of offset, size, type values for each of the fields, but that probably would be pretty limited and then at best maybe guessing for those other PIDs that are not in table. That is there may be 50? logitech mice over the years? ...

Note: - I do think we probably need to have method to query more device info like PID/VID - The user code may want to detect that the are running on DS3 or DS4 and change their mapping of what button does what...

Now back to playing with DS3
Edit:
Linux info for PS3 controller
Code:
kurt@kurt-UP-CHT01:~$ sudo usbhid-dump  -i0 | grep -v : | xxd -r -p | hidrd-convert -o spec
Usage Page (Desktop),               ; Generic desktop controls (01h)
Usage (Joystik),                    ; Joystik (04h, application collection)
[COLOR="#FF0000"]Collection (Application),
    Collection (Logical),
        Report ID (1),
        Report Size (8),
        Report Count (1),
        Logical Minimum (0),
        Logical Maximum (255),
        Input (Constant, Variable),
        Report Size (1),
        Report Count (19),
        Logical Minimum (0),
        Logical Maximum (1),
        Physical Minimum (0),
        Physical Maximum (1),
        Usage Page (Button),        ; Button (09h)
        Usage Minimum (01h),
        Usage Maximum (13h),
        Input (Variable),
        Report Size (1),
        Report Count (13),
        Usage Page (FF00h),         ; FF00h, vendor-defined
        Input (Constant, Variable),
        Logical Minimum (0),
        Logical Maximum (255),
        Usage Page (Desktop),       ; Generic desktop controls (01h)
        Usage (Pointer),            ; Pointer (01h, physical collection)
        Collection (Physical),
            Report Size (8),
            Report Count (4),
            Physical Minimum (0),
            Physical Maximum (255),
            Usage (X),              ; X (30h, dynamic value)
            Usage (Y),              ; Y (31h, dynamic value)
            Usage (Z),              ; Z (32h, dynamic value)
            Usage (Rz),             ; Rz (35h, dynamic value)
            Input (Variable),
        End Collection,
        Usage Page (Desktop),       ; Generic desktop controls (01h)
        Report Size (8),
        Report Count (39),
        Usage (Pointer),            ; Pointer (01h, physical collection)
        Input (Variable),
        Report Size (8),
        Report Count (48),
        Usage (Pointer),            ; Pointer (01h, physical collection)
        Output (Variable),
        Report Size (8),
        Report Count (48),
        Usage (Pointer),            ; Pointer (01h, physical collection)
        Feature (Variable),
    End Collection,
    Collection (Logical),
[/COLOR]        Report ID (2),
        Report Size (8),
        Report Count (48),
        Usage (Pointer),            ; Pointer (01h, physical collection)
        Feature (Variable),
    End Collection,
    Collection (Logical),
        Report ID (238),
        Report Size (8),
        Report Count (48),
        Usage (Pointer),            ; Pointer (01h, physical collection)
        Feature (Variable),
    End Collection,
    Collection (Logical),
        Report ID (239),
        Report Size (8),
        Report Count (48),
        Usage (Pointer),            ; Pointer (01h, physical collection)
        Feature (Variable),
    End Collection,
End Collection
kurt@kurt-UP-CHT01:~$
Looks like data is correct... also looked like data is changing in reports. So will see what we are called with... Actually sort of interesting. I printed out bytes received, plus the callback with data...
Code:
HID:  1  0  0  0  0  0 80 7c a7 ff  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  2 ee 12 ff c8  0  0 12 ae 77  0 40  2  e  2 19  1 96  0  5  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 
Joystick: usage=90001, value=0
Joystick: usage=90002, value=0
Joystick: usage=90003, value=0
Joystick: usage=90004, value=0
Joystick: usage=90005, value=0
Joystick: usage=90006, value=0
Joystick: usage=90007, value=0
Joystick: usage=90008, value=0
Joystick: usage=90009, value=0
Joystick: usage=9000A, value=0
Joystick: usage=9000B, value=0
Joystick: usage=9000C, value=0
Joystick: usage=9000D, value=0
Joystick: usage=9000E, value=0
Joystick: usage=9000F, value=0
Joystick: usage=90010, value=0
Joystick: usage=90011, value=0
Joystick: usage=90012, value=0
Joystick: usage=90013, value=0
J[COLOR="#FF0000"]oystick: usage=10030, value=128
Joystick: usage=10031, value=124
Joystick: usage=10032, value=167
Joystick: usage=10035, value=255[/COLOR]
Joystick: usage=10001, value=0
Joystick: usage=10000, value=0
Joystick: usage=10032, value=0
Joystick: usage=10035, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=2
Joystick: usage=10000, value=238
Joystick: usage=10000, value=18
Joystick: usage=10000, value=255
Joystick: usage=10000, value=200
Joystick: usage=10000, value=0
Joystick: usage=10000, value=0
Joystick: usage=10000, value=18
Joystick: usage=10000, value=174
Joystick: usage=10000, value=119
Joystick: usage=10000, value=0
Joystick: usage=10000, value=64
Joystick: usage=10000, value=2
Joystick: usage=10000, value=14
Joystick: usage=10000, value=2
Joystick: usage=10000, value=25
Joystick: usage=10000, value=1
Joystick: usage=10000, value=150
Joystick: usage=10000, value=0
Joystick: usage=10000, value=5
Joystick: buttons = 0, X = 128, Y = 124, Z = 0, Rz = 0, Rx = 0, Ry = 0, Hat = 0
HID:  1  0  0  0  0  0 80 7c a7 ff  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  2 ee 12 ff c8  0  0 12 ae 77  0 40  2  d  2 19  1 95  0  5  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
Looks like it gets the data But the data gets overwritten...
 
Last edited:
Status
Not open for further replies.
Back
Top