Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ src/display/GPGFX_UI.cpp
src/drivermanager.cpp
src/eventmanager.cpp
src/layoutmanager.cpp
src/hostlighting.cpp
src/peripheralmanager.cpp
src/storagemanager.cpp
src/system.cpp
Expand Down
542 changes: 542 additions & 0 deletions docs/host-lighting.md

Large diffs are not rendered by default.

81 changes: 81 additions & 0 deletions headers/drivers/hid/HIDDescriptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include <stdint.h>

#include "hostlighting.h"

#define HID_ENDPOINT_SIZE 64

// Mac OS-X and Linux automatically load the correct drivers. On
Expand All @@ -26,6 +28,9 @@
#define GAMEPAD_ENDPOINT 1
#define GAMEPAD_SIZE 64

#define HOST_LIGHTING_INTERFACE 1
#define HOST_LIGHTING_ENDPOINT 2

#define LSB(n) (n & 255)
#define MSB(n) ((n >> 8) & 255)

Expand Down Expand Up @@ -175,3 +180,79 @@ static const uint8_t hid_configuration_descriptor[] =
GAMEPAD_SIZE, 0, // wMaxPacketSize
1 // bInterval (1 ms)
};

// Variant with the host lighting interface appended; selected at runtime by
// HostLighting::enabledForMode()
#define CONFIG1_HOST_LIGHTING_DESC_SIZE (9+9+9+7 + 9+9+7+7)
static const uint8_t hid_hostlighting_configuration_descriptor[] __attribute__((unused)) =
{
// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
9, // bLength;
2, // bDescriptorType;
LSB(CONFIG1_HOST_LIGHTING_DESC_SIZE), // wTotalLength
MSB(CONFIG1_HOST_LIGHTING_DESC_SIZE),
2, // bNumInterfaces
1, // bConfigurationValue
0, // iConfiguration
0x80, // bmAttributes
50, // bMaxPower
// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
9, // bLength
4, // bDescriptorType
GAMEPAD_INTERFACE, // bInterfaceNumber
0, // bAlternateSetting
1, // bNumEndpoints
0x03, // bInterfaceClass (0x03 = HID)
0x00, // bInterfaceSubClass (0x00 = No Boot)
0x00, // bInterfaceProtocol (0x00 = No Protocol)
0, // iInterface
// HID interface descriptor, HID 1.11 spec, section 6.2.1
9, // bLength
0x21, // bDescriptorType
0x11, 0x01, // bcdHID
0, // bCountryCode
1, // bNumDescriptors
0x22, // bDescriptorType
sizeof(hid_report_descriptor), // wDescriptorLength
0,
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
GAMEPAD_ENDPOINT | 0x80, // bEndpointAddress
0x03, // bmAttributes (0x03=intr)
GAMEPAD_SIZE, 0, // wMaxPacketSize
1, // bInterval (1 ms)
// host lighting interface descriptor
9, // bLength
4, // bDescriptorType
HOST_LIGHTING_INTERFACE, // bInterfaceNumber
0, // bAlternateSetting
2, // bNumEndpoints
0x03, // bInterfaceClass (0x03 = HID)
0x00, // bInterfaceSubClass (0x00 = No Boot)
0x00, // bInterfaceProtocol (0x00 = No Protocol)
0, // iInterface
// HID interface descriptor, HID 1.11 spec, section 6.2.1
9, // bLength
0x21, // bDescriptorType
0x11, 0x01, // bcdHID
0, // bCountryCode
1, // bNumDescriptors
0x22, // bDescriptorType
sizeof(hostlighting_report_descriptor), // wDescriptorLength
0,
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
HOST_LIGHTING_ENDPOINT | 0x80, // bEndpointAddress
0x03, // bmAttributes (0x03=intr)
HID_ENDPOINT_SIZE, 0, // wMaxPacketSize
1, // bInterval (1 ms)
// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
7, // bLength
5, // bDescriptorType
HOST_LIGHTING_ENDPOINT, // bEndpointAddress
0x03, // bmAttributes (0x03=intr)
HID_ENDPOINT_SIZE, 0, // wMaxPacketSize
1 // bInterval (1 ms)
};
19 changes: 19 additions & 0 deletions headers/drivers/keyboard/KeyboardDescriptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <stdint.h>
#include "tusb.h"
#include "hostlighting.h"

#define KEYBOARD_KEY_REPORT_ID 0x01
#define KEYBOARD_MULTIMEDIA_REPORT_ID 0x02
Expand Down Expand Up @@ -60,8 +61,12 @@ enum
};

#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN)
#define CONFIG_TOTAL_LEN_LIGHTING (TUD_CONFIG_DESC_LEN + TUD_HID_DESC_LEN + TUD_HID_INOUT_DESC_LEN)

#define EPNUM_HID 0x81
#define ITF_NUM_HID_LIGHTING 1
#define EPNUM_LIGHTING_OUT 0x02
#define EPNUM_LIGHTING_IN 0x82

static const uint8_t keyboard_report_descriptor[] =
{
Expand Down Expand Up @@ -124,4 +129,18 @@ static const uint8_t keyboard_configuration_descriptor[] =

// Interface number, string index, protocol, report descriptor len, EP Out & In address, size & polling interval
TUD_HID_DESCRIPTOR(ITF_NUM_HID_KEYBOARD, 0, HID_ITF_PROTOCOL_KEYBOARD, sizeof(keyboard_report_descriptor), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 1)
};

// Variant with the host lighting interface appended; selected at runtime by
// HostLighting::enabledForMode()
static const uint8_t keyboard_hostlighting_configuration_descriptor[] __attribute__((unused)) =
{
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, 2, 0, CONFIG_TOTAL_LEN_LIGHTING, 32, 100),

// Interface number, string index, protocol, report descriptor len, EP Out & In address, size & polling interval
TUD_HID_DESCRIPTOR(ITF_NUM_HID_KEYBOARD, 0, HID_ITF_PROTOCOL_KEYBOARD, sizeof(keyboard_report_descriptor), EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 1),

// Interface number, string index, protocol, report descriptor len, EP Out & In address, size & polling interval
TUD_HID_INOUT_DESCRIPTOR(ITF_NUM_HID_LIGHTING, 0, HID_ITF_PROTOCOL_NONE, sizeof(hostlighting_report_descriptor), EPNUM_LIGHTING_OUT, EPNUM_LIGHTING_IN, CFG_TUD_HID_EP_BUFSIZE, 1)
};
147 changes: 147 additions & 0 deletions headers/drivers/xinput/XInputDescriptors.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <stdint.h>
#include <pico/unique_id.h>

#include "hostlighting.h"

#define XINPUT_ENDPOINT_SIZE 20

// Buttons 1 (8 bits)
Expand Down Expand Up @@ -94,6 +96,62 @@ static const uint8_t * xinput_get_string_descriptor(int index) {
return xinput_string_descriptors[index];
}

// Composite variant: per-interface driver binding (XUSB via the MS OS compatible
// ID below), so the device class is 0 and the ID differs from the stock 045E:028E,
// which Windows would otherwise bind whole-device to its XUSB driver. Selected at
// runtime by HostLighting::xinputCompositeActive().
static const uint8_t xinput_composite_device_descriptor[] __attribute__((unused)) =
{
0x12, // bLength
0x01, // bDescriptorType (Device)
0x00, 0x02, // bcdUSB 2.00
0x00, // bDeviceClass (per-interface)
0x00, // bDeviceSubClass
0x00, // bDeviceProtocol
0x40, // bMaxPacketSize0 64
// Vendor chosen from the Linux xpad driver's 360-vendor wildcard list so the
// composite still binds xpad there; PID deliberately not a known product so
// Windows has no device-level match and splits the composite (WCID binds XUSB)
0xC6, 0x24, // idVendor 0x24C6
0xAD, 0x5B, // idProduct 0x5BAD
0x14, 0x01, // bcdDevice 2.14
0x01, // iManufacturer (String Index)
0x02, // iProduct (String Index)
0x03, // iSerialNumber (String Index)
0x01, // bNumConfigurations 1
};

// MS OS 1.0 string descriptor (string index 0xEE): "MSFT100" + vendor request code
static const uint16_t xinput_ms_os_string_descriptor[] __attribute__((unused)) =
{
0x0312, // bLength 18, bDescriptorType string
'M', 'S', 'F', 'T', '1', '0', '0',
0x0020, // bMS_VendorCode 0x20, padding
};

// MS OS 1.0 Extended Compat ID descriptor: interface 0 binds the XUSB driver via
// compatible ID, interface 1 (lighting) stays plain HID
static const uint8_t xinput_wcid_compat_id_descriptor[] __attribute__((unused)) =
{
0x40, 0x00, 0x00, 0x00, // dwLength 64
0x00, 0x01, // bcdVersion 1.00
0x04, 0x00, // wIndex: extended compat ID
0x02, // bCount: 2 functions
0, 0, 0, 0, 0, 0, 0, // reserved
// function: interface 0 -> XUSB10
0x00, // bFirstInterfaceNumber
0x01, // reserved
'X', 'U', 'S', 'B', '1', '0', 0x00, 0x00, // compatibleID
0, 0, 0, 0, 0, 0, 0, 0, // subCompatibleID
0, 0, 0, 0, 0, 0, // reserved
// function: interface 1 -> none (HID class binding)
0x01, // bFirstInterfaceNumber
0x01, // reserved
0, 0, 0, 0, 0, 0, 0, 0, // compatibleID
0, 0, 0, 0, 0, 0, 0, 0, // subCompatibleID
0, 0, 0, 0, 0, 0, // reserved
};

static const uint8_t xinput_device_descriptor[] =
{
0x12, // bLength
Expand All @@ -112,6 +170,95 @@ static const uint8_t xinput_device_descriptor[] =
0x01, // bNumConfigurations 1
};

// Composite variant: the XUSB control interface plus the host lighting HID
// interface. The console-only interfaces (audio, plug-in module, security) are
// omitted -- they serve no purpose on PC and would enumerate driverless.
// Selected at runtime by HostLighting::xinputCompositeActive().
static const uint8_t xinput_composite_configuration_descriptor[] __attribute__((unused)) =
{
0x09, // bLength
0x02, // bDescriptorType (Configuration)
0x51, 0x00, // wTotalLength 81
0x02, // bNumInterfaces 2
0x01, // bConfigurationValue
0x00, // iConfiguration (String Index)
0xA0, // bmAttributes (remote wakeup)
0xFA, // bMaxPower 500mA

// Control Interface (0x5D 0xFF)
0x09, // bLength
0x04, // bDescriptorType (Interface)
0x00, // bInterfaceNumber 0
0x00, // bAlternateSetting
0x02, // bNumEndpoints 2
0xFF, // bInterfaceClass
0x5D, // bInterfaceSubClass
0x01, // bInterfaceProtocol
0x00, // iInterface (String Index)

// Gamepad Descriptor
0x11, // bLength
0x21, // bDescriptorType (HID)
0x00, 0x01, // bcdHID 1.10
0x01, // SUB_TYPE
0x25, // reserved2
0x81, // DEVICE_EPADDR_IN
0x14, // bMaxDataSizeIn
0x00, 0x00, 0x00, 0x00, 0x13, // reserved3
0x02, // DEVICE_EPADDR_OUT is this right?
0x08, // bMaxDataSizeOut
0x00, 0x00, // reserved4

// Report IN Endpoint 1.1
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x81, // bEndpointAddress (IN/D2H)
0x03, // bmAttributes (Interrupt)
0x20, 0x00, // wMaxPacketSize 32
0x01, // bInterval 1 (unit depends on device speed)

// Report OUT Endpoint 1.2
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x02, // bEndpointAddress (OUT/H2D)
0x03, // bmAttributes (Interrupt)
0x20, 0x00, // wMaxPacketSize 32
0x08, // bInterval 8 (unit depends on device speed)

// Host Lighting Interface
0x09, // bLength
0x04, // bDescriptorType (Interface)
0x01, // bInterfaceNumber 1
0x00, // bAlternateSetting
0x02, // bNumEndpoints
0x03, // bInterfaceClass (HID)
0x00, // bInterfaceSubClass (No Boot)
0x00, // bInterfaceProtocol (No Protocol)
0x00, // iInterface (String Index)
// HID interface descriptor, HID 1.11 spec, section 6.2.1
0x09, // bLength
0x21, // bDescriptorType (HID)
0x11, 0x01, // bcdHID 1.11
0x00, // bCountryCode
0x01, // bNumDescriptors
0x22, // bDescriptorType (Report)
sizeof(hostlighting_report_descriptor), 0x00, // wDescriptorLength
// Lighting IN Endpoint
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x83, // bEndpointAddress (IN/D2H)
0x03, // bmAttributes (Interrupt)
0x40, 0x00, // wMaxPacketSize 64
0x01, // bInterval 1
// Lighting OUT Endpoint
0x07, // bLength
0x05, // bDescriptorType (Endpoint)
0x03, // bEndpointAddress (OUT/H2D)
0x03, // bmAttributes (Interrupt)
0x40, 0x00, // wMaxPacketSize 64
0x01, // bInterval 1
};

// This needs to be:
// 4 interfaces
// remote wakeup enabled
Expand Down
Loading