Add stock-USB native Joy-Con R/L hub bridge

This commit is contained in:
Joey Yakimowich-Payne 2026-09-12 15:28:58 -06:00
commit 1748910316
41 changed files with 7101 additions and 909 deletions

View file

@ -1,33 +1,66 @@
#pragma once
#include <stdint.h>
#include "model.h"
// Published Joy-Con 2 (R) USB descriptors, reproduced for enumeration capture.
// Published Joy-Con 2 USB descriptors, reproduced for the selected model.
// https://github.com/ndeadly/switch2_controller_research/blob/master/descriptors.md
static const uint8_t probe_device_descriptor[] = {
0x12, 0x01, 0x00, 0x02, 0xef, 0x02, 0x01, 0x40, 0x7e, 0x05, 0x66, 0x20,
0x00, 0x01, 0x01, 0x02, 0x03, 0x01,
};
// Composite retains the primary right PID (0x2066): USB has one device identity,
// not a separate device PID for each left/right function.
#define PROBE_DEVICE_DESCRIPTOR(pid) { \
0x12, 0x01, 0x00, 0x02, 0xef, 0x02, 0x01, 0x40, 0x7e, 0x05, \
(pid) & 0xff, (pid) >> 8, \
0x00, 0x01, 0x01, 0x02, 0x03, 0x01, \
}
static const uint8_t probe_device_descriptor[] = PROBE_DEVICE_DESCRIPTOR(PROBE_JOYCON_PID);
#if SWITCH2_PROBE_HUB
static const uint8_t probe_left_device_descriptor[] = PROBE_DEVICE_DESCRIPTOR(0x2067u);
#endif
#undef PROBE_DEVICE_DESCRIPTOR
static const uint8_t probe_configuration_descriptor[] = {
0x09, 0x02, 0x50, 0x00, 0x02, 0x01, 0x04, 0xc0, 0xfa, 0x08, 0x0b, 0x00,
#if SWITCH2_PROBE_COMPOSITE
0x09, 0x02, 0x97, 0x00, 0x04, 0x01, 0x04, 0xc0, 0xfa,
#else
0x09, 0x02, 0x50, 0x00, 0x02, 0x01, 0x04, 0xc0, 0xfa,
#endif
0x08, 0x0b, 0x00,
0x01, 0x03, 0x00, 0x00, 0x00, 0x09, 0x04, 0x00, 0x00, 0x02, 0x03, 0x00,
0x00, 0x05, 0x09, 0x21, 0x11, 0x01, 0x00, 0x01, 0x22, 0x64, 0x00, 0x07,
0x05, 0x81, 0x03, 0x40, 0x00, 0x04, 0x07, 0x05, 0x01, 0x03, 0x40, 0x00,
0x04, 0x08, 0x0b, 0x01, 0x01, 0xff, 0x00, 0x00, 0x00, 0x09, 0x04, 0x01,
0x00, 0x02, 0xff, 0x00, 0x00, 0x06, 0x07, 0x05, 0x02, 0x02, 0x40, 0x00,
0x00, 0x07, 0x05, 0x82, 0x02, 0x40, 0x00, 0x00,
#if SWITCH2_PROBE_COMPOSITE
0x08, 0x0b, 0x02, 0x01, 0x03, 0x00, 0x00, 0x00,
0x09, 0x04, 0x02, 0x00, 0x02, 0x03, 0x00, 0x00, 0x07,
0x09, 0x21, 0x11, 0x01, 0x00, 0x01, 0x22, 0x64, 0x00,
0x07, 0x05, 0x83, 0x03, 0x40, 0x00, 0x04,
0x07, 0x05, 0x03, 0x03, 0x40, 0x00, 0x04,
0x08, 0x0b, 0x03, 0x01, 0xff, 0x00, 0x00, 0x00,
0x09, 0x04, 0x03, 0x00, 0x02, 0xff, 0x00, 0x00, 0x08,
0x07, 0x05, 0x04, 0x02, 0x40, 0x00, 0x00,
0x07, 0x05, 0x84, 0x02, 0x40, 0x00, 0x00,
#endif
};
static const uint8_t probe_hid_report_descriptor[] = {
0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x05, 0x05, 0xff, 0x09, 0x01,
0x15, 0x00, 0x26, 0xff, 0x00, 0x95, 0x3f, 0x75, 0x08, 0x81, 0x02, 0x85,
0x08, 0x09, 0x01, 0x95, 0x02, 0x81, 0x02, 0x05, 0x09, 0x19, 0x01, 0x29,
0x10, 0x25, 0x01, 0x95, 0x10, 0x75, 0x01, 0x81, 0x02, 0x05, 0xff, 0x09,
0x01, 0x26, 0xff, 0x00, 0x95, 0x01, 0x75, 0x08, 0x81, 0x02, 0x05, 0x01,
0x09, 0x01, 0xa1, 0x00, 0x09, 0x30, 0x09, 0x31, 0x26, 0xff, 0x0f, 0x95,
0x02, 0x75, 0x0c, 0x81, 0x02, 0xc0, 0x05, 0xff, 0x09, 0x02, 0x26, 0xff,
0x00, 0x95, 0x37, 0x75, 0x08, 0x81, 0x02, 0x85, 0x01, 0x09, 0x01, 0x95,
0x3f, 0x91, 0x02, 0xc0,
#define PROBE_HID_DESCRIPTOR(report_id) { \
0x05, 0x01, 0x09, 0x05, 0xa1, 0x01, 0x85, 0x05, 0x05, 0xff, 0x09, 0x01, \
0x15, 0x00, 0x26, 0xff, 0x00, 0x95, 0x3f, 0x75, 0x08, 0x81, 0x02, 0x85, \
report_id, 0x09, 0x01, 0x95, 0x02, 0x81, 0x02, 0x05, 0x09, 0x19, 0x01, 0x29, \
0x10, 0x25, 0x01, 0x95, 0x10, 0x75, 0x01, 0x81, 0x02, 0x05, 0xff, 0x09, \
0x01, 0x26, 0xff, 0x00, 0x95, 0x01, 0x75, 0x08, 0x81, 0x02, 0x05, 0x01, \
0x09, 0x01, 0xa1, 0x00, 0x09, 0x30, 0x09, 0x31, 0x26, 0xff, 0x0f, 0x95, \
0x02, 0x75, 0x0c, 0x81, 0x02, 0xc0, 0x05, 0xff, 0x09, 0x02, 0x26, 0xff, \
0x00, 0x95, 0x37, 0x75, 0x08, 0x81, 0x02, 0x85, 0x01, 0x09, 0x01, 0x95, \
0x3f, 0x91, 0x02, 0xc0, \
}
static const uint8_t probe_hid_report_descriptors[PROBE_CONTROLLER_COUNT][100] = {
PROBE_HID_DESCRIPTOR(PROBE_NATIVE_REPORT_ID),
#if SWITCH2_PROBE_COMPOSITE || SWITCH2_PROBE_HUB
PROBE_HID_DESCRIPTOR(0x07u),
#endif
};
#undef PROBE_HID_DESCRIPTOR