I'm working on a Python program to read inputs from a Logitech Extreme 3D Pro joystick. I am able to receive raw data from the joystick, but I'm struggling to correctly interpret the X and Y values from this data.
Problem:
I have raw data as shown in the attached image. From the array, each value represents a different key or axis, but I'm having trouble identifying which values correspond to X and Y axis movements. Specifically, I suspect that array[1] and array[2] are the X and Y values, but the readings are inconsistent and don't seem to correlate with the joystick movements.
Code:
import pywinusb.hid as hid
from time import sleep
from msvcrt import kbhit
def sample_handler(data):
print("Raw data: {}".format(data))
# Known Logitech vendor_id
vendor_id = 0x046D # Logitech
# Find Logitech HID devices
devices = hid.HidDeviceFilter(vendor_id=vendor_id).get_devices()
if not devices:
print("No Logitech device found.")
exit()
# Select the device
device = devices[0] if len(devices) == 1 else None
if not device:
print("Multiple Logitech devices found. Please select one:")
for i, dev in enumerate(devices):
print(f"{i}: {dev.product_name} (Product ID: {dev.product_id:04X})")
selection = int(input("\nEnter the number of the device to select (0-{}): ".format(len(devices) - 1)))
device = devices[selection]
else:
print(f"Automatically selected device: {device.product_name}")
# Open the device and set the data handler
try:
device.open()
device.set_raw_data_handler(sample_handler)
print("Waiting for data... Press any key to stop.")
while not kbhit() and device.is_plugged():
sleep(0.5)
finally:
device.close()
Questions:
HID Descriptors:
USB Input Device
Connection Status Device connected
Current Configuration 1
Speed Full
Device Address 3
Number Of Open Pipes 1
Device Descriptor Extreme 3D pro
Offset Field Size Value Description
0 bLength 1 12h
1 bDescriptorType 1 01h Device
2 bcdUSB 2 0200h USB Spec 2.0
4 bDeviceClass 1 00h Class info in Ifc Descriptors
5 bDeviceSubClass 1 00h
6 bDeviceProtocol 1 00h
7 bMaxPacketSize0 1 08h 8 bytes
8 idVendor 2 046Dh Logitech, Inc.
10 idProduct 2 C215h
12 bcdDevice 2 5711h 57.11
14 iManufacturer 1 01h "Logitech"
15 iProduct 1 02h "Extreme 3D pro"
16 iSerialNumber 1 03h "00000000002A"
17 bNumConfigurations 1 01h
Configuration Descriptor 1 Bus Powered, 100 mA
Offset Field Size Value Description
0 bLength 1 09h
1 bDescriptorType 1 02h Configuration
2 wTotalLength 2 0022h
4 bNumInterfaces 1 01h
5 bConfigurationValue 1 01h
6 iConfiguration 1 04h "HID Config"
7 bmAttributes 1 80h Bus Powered
4..0: Reserved ...00000
5: Remote Wakeup ..0..... No
6: Self Powered .0...... No, Bus Powered
7: Reserved (set to one)
(bus-powered for 1.0) 1.......
8 bMaxPower 1 32h 100 mA
Interface Descriptor 0/0 HID, 1 Endpoint
Offset Field Size Value Description
0 bLength 1 09h
1 bDescriptorType 1 04h Interface
2 bInterfaceNumber 1 00h
3 bAlternateSetting 1 00h
4 bNumEndpoints 1 01h
5 bInterfaceClass 1 03h HID
6 bInterfaceSubClass 1 01h Boot Interface
7 bInterfaceProtocol 1 00h
8 iInterface 1 00h
HID Descriptor
Offset Field Size Value Description
0 bLength 1 09h
1 bDescriptorType 1 21h HID
2 bcdHID 2 0111h 1.11
4 bCountryCode 1 00h
5 bNumDescriptors 1 01h
6 bDescriptorType 1 22h Report
7 wDescriptorLength 2 007Ah 122 bytes
Endpoint Descriptor 81 1 In, Interrupt, 1 ms
Offset Field Size Value Description
0 bLength 1 07h
1 bDescriptorType 1 05h Endpoint
2 bEndpointAddress 1 81h 1 In
3 bmAttributes 1 03h Interrupt
1..0: Transfer Type ......11 Interrupt
7..2: Reserved 000000..
4 wMaxPacketSize 2 0007h 7 bytes
6 bInterval 1 01h 1 ms
Interface 0 HID Report Descriptor Joystick
Item Tag (Value) Raw Data
Usage Page (Generic Desktop) 05 01
Usage (Joystick) 09 04
Collection (Application) A1 01
Collection (Logical) A1 02
Report Count (2) 95 02
Report Size (10) 75 0A
Logical Minimum (0) 15 00
Logical Maximum (1023) 26 FF 03
Physical Minimum (0) 35 00
Physical Maximum (1023) 46 FF 03
Usage (X) 09 30
Usage (Y) 09 31
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Report Size (4) 75 04
Report Count (1) 95 01
Logical Maximum (7) 25 07
Physical Maximum (315) 46 3B 01
Unit (Eng Rot: Degree) 66 14 00
Usage (Hat Switch) 09 39
Input (Data,Var,Abs,NWrp,Lin,Pref,Null,Bit) 81 42
Unit (None) 65 00
Report Size (8) 75 08
Logical Maximum (255) 26 FF 00
Physical Maximum (255) 46 FF 00
Usage (Rz) 09 35
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Push A4
Report Count (8) 95 08
Report Size (1) 75 01
Logical Maximum (1) 25 01
Physical Maximum (1) 45 01
Usage Page (Button) 05 09
Usage Minimum (Button 1) 19 01
Usage Maximum (Button 8) 29 08
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Pop B4
Usage (Slider) 09 36
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Report Count (4) 95 04
Report Size (1) 75 01
Logical Maximum (1) 25 01
Physical Maximum (1) 45 01
Usage Page (Button) 05 09
Usage Minimum (Button 9) 19 09
Usage Maximum (Button 12) 29 0C
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
Report Count (4) 95 04
Input (Cnst,Ary,Abs) 81 01
End Collection C0
Collection (Logical) A1 02
Report Count (4) 95 04
Report Size (8) 75 08
Logical Maximum (255) 26 FF 00
Physical Maximum (255) 46 FF 00
Usage Page (Vendor-Defined 1) 06 00 FF
Usage (Vendor-Defined 1) 09 01
Feature (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) B1 02
End Collection C0
End Collection
Additional Information:
I know libraries like pywinusb.hid, but I want to explore other options if possible.
Any guidance on creating a program to parse and interpret joystick values using HID descriptors automatically would also be appreciated.
I have found a package called Pygame which is used to easily read remote data. It automatically reads the HID descriptor to determine the number of buttons and analogue controls.
Using the Pygame package is a good solution for this issue.