From 491b0b38e19d38fb481c7d6899d44e6f8bc9d393 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 6 Apr 2025 14:19:11 +1200 Subject: [PATCH 001/239] fix pro keys --- include/reports/pc_reports.h | 50 ++++++++++++++++++++-- include/reports/ps3_reports.h | 63 +++++++++++++++++++++++----- include/reports/xinput_reports.h | 56 +++++++++++++++++++++---- include/state_translation/pro_keys.h | 6 +-- 4 files changed, 149 insertions(+), 26 deletions(-) diff --git a/include/reports/pc_reports.h b/include/reports/pc_reports.h index c4e625545..65602f23a 100644 --- a/include/reports/pc_reports.h +++ b/include/reports/pc_reports.h @@ -431,12 +431,54 @@ typedef struct uint8_t pedalDigital : 1; uint8_t : 7; DPAD; - uint8_t key1; - uint8_t key2; - uint8_t key3; + union { + struct { + uint8_t key8 : 1; + uint8_t key7 : 1; + uint8_t key6 : 1; + uint8_t key5 : 1; + uint8_t key4 : 1; + uint8_t key3 : 1; + uint8_t key2 : 1; + uint8_t key1 : 1; + uint8_t key16 : 1; + uint8_t key15 : 1; + uint8_t key14 : 1; + uint8_t key13 : 1; + uint8_t key12 : 1; + uint8_t key11 : 1; + uint8_t key10 : 1; + uint8_t key9 : 1; + uint8_t key24 : 1; + uint8_t key23 : 1; + uint8_t key22 : 1; + uint8_t key21 : 1; + uint8_t key20 : 1; + uint8_t key19 : 1; + uint8_t key18 : 1; + uint8_t key17 : 1; + }; + uint8_t keys[3]; + }; + uint8_t pedalAnalog; uint8_t touchPad; - uint8_t velocities[5]; + union { + struct { + uint8_t velocity1 : 7; + uint8_t key25 : 1; + uint8_t velocity2 : 7; + uint8_t : 1; + uint8_t velocity3 : 7; + uint8_t : 1; + uint8_t velocity4 : 7; + uint8_t : 1; + uint8_t velocity5 : 7; + uint8_t : 1; + }; + + uint8_t velocities[5]; + }; } __attribute__((__packed__)) PCRockBandProKeyboard_Data_t; typedef struct { uint8_t reportTypeId; // 0x5B diff --git a/include/reports/ps3_reports.h b/include/reports/ps3_reports.h index 2804741e8..a9d35f49d 100644 --- a/include/reports/ps3_reports.h +++ b/include/reports/ps3_reports.h @@ -411,7 +411,7 @@ typedef struct uint8_t unused1[8]; uint8_t yellowVelocity; - uint8_t redVelocity; // If you hit two cymbals at once, it puts the velocity for the cymbal here + uint8_t redVelocity; // If you hit two cymbals at once, it puts the velocity for the cymbal here uint8_t greenVelocity; uint8_t blueVelocity; uint8_t blueCymbalVelocity; @@ -456,18 +456,18 @@ typedef struct uint8_t yellowVelocity; uint8_t redVelocity; - uint8_t greenVelocity; + uint8_t greenVelocity; uint8_t blueVelocity; uint8_t kickVelocity; uint8_t orangeVelocity; uint8_t unused2[2]; - uint8_t midiByte1; // x + uint8_t midiByte1; // x uint8_t unused3; - uint16_t unused4; // z - uint8_t midiByte2; // y + uint16_t unused4; // z + uint8_t midiByte2; // y uint8_t unused7; - uint16_t unused6; // gyro + uint16_t unused6; // gyro } __attribute__((packed)) PS3GuitarHeroDrums_Data_t; typedef struct @@ -656,11 +656,52 @@ typedef struct uint8_t unused1[2]; - uint8_t key1; - uint8_t key2; - uint8_t key3; - - uint8_t velocities[5]; + union { + struct { + uint8_t key8 : 1; + uint8_t key7 : 1; + uint8_t key6 : 1; + uint8_t key5 : 1; + uint8_t key4 : 1; + uint8_t key3 : 1; + uint8_t key2 : 1; + uint8_t key1 : 1; + uint8_t key16 : 1; + uint8_t key15 : 1; + uint8_t key14 : 1; + uint8_t key13 : 1; + uint8_t key12 : 1; + uint8_t key11 : 1; + uint8_t key10 : 1; + uint8_t key9 : 1; + uint8_t key24 : 1; + uint8_t key23 : 1; + uint8_t key22 : 1; + uint8_t key21 : 1; + uint8_t key20 : 1; + uint8_t key19 : 1; + uint8_t key18 : 1; + uint8_t key17 : 1; + }; + uint8_t keys[3]; + }; + + union { + struct { + uint8_t velocity1 : 7; + uint8_t key25 : 1; + uint8_t velocity2 : 7; + uint8_t : 1; + uint8_t velocity3 : 7; + uint8_t : 1; + uint8_t velocity4 : 7; + uint8_t : 1; + uint8_t velocity5 : 7; + uint8_t : 1; + }; + + uint8_t velocities[5]; + }; uint8_t : 7; uint8_t overdrive : 1; diff --git a/include/reports/xinput_reports.h b/include/reports/xinput_reports.h index 4487f4d85..da1c19a4c 100644 --- a/include/reports/xinput_reports.h +++ b/include/reports/xinput_reports.h @@ -216,12 +216,12 @@ typedef struct uint8_t unused1[2]; int16_t unused2; uint8_t greenVelocity; - uint8_t redVelocity; // redVelocity stores the velocity for the cymbal if both cymbal and pad of the same colour get hit simultaneously + uint8_t redVelocity; // redVelocity stores the velocity for the cymbal if both cymbal and pad of the same colour get hit simultaneously uint8_t yellowVelocity; uint8_t blueVelocity; uint8_t orangeVelocity; uint8_t kickVelocity; - uint8_t midiPacket[6]; // 0x99 note, velocity, xxxx + uint8_t midiPacket[6]; // 0x99 note, velocity, xxxx } __attribute__((packed)) XInputGuitarHeroDrums_Data_t; typedef struct @@ -372,12 +372,52 @@ typedef struct uint8_t b : 1; // red uint8_t x : 1; // blue uint8_t y : 1; // yellow - - uint8_t key1; - uint8_t key2; - uint8_t key3; - - uint8_t velocities[5]; + union { + struct { + uint8_t key8 : 1; + uint8_t key7 : 1; + uint8_t key6 : 1; + uint8_t key5 : 1; + uint8_t key4 : 1; + uint8_t key3 : 1; + uint8_t key2 : 1; + uint8_t key1 : 1; + uint8_t key16 : 1; + uint8_t key15 : 1; + uint8_t key14 : 1; + uint8_t key13 : 1; + uint8_t key12 : 1; + uint8_t key11 : 1; + uint8_t key10 : 1; + uint8_t key9 : 1; + uint8_t key24 : 1; + uint8_t key23 : 1; + uint8_t key22 : 1; + uint8_t key21 : 1; + uint8_t key20 : 1; + uint8_t key19 : 1; + uint8_t key18 : 1; + uint8_t key17 : 1; + }; + uint8_t keys[3]; + }; + + union { + struct { + uint8_t velocity1 : 7; + uint8_t key25 : 1; + uint8_t velocity2 : 7; + uint8_t : 1; + uint8_t velocity3 : 7; + uint8_t : 1; + uint8_t velocity4 : 7; + uint8_t : 1; + uint8_t velocity5 : 7; + uint8_t : 1; + }; + + uint8_t velocities[5]; + }; uint8_t : 7; uint8_t overdrive : 1; diff --git a/include/state_translation/pro_keys.h b/include/state_translation/pro_keys.h index faf73c15b..10530a63e 100644 --- a/include/state_translation/pro_keys.h +++ b/include/state_translation/pro_keys.h @@ -23,9 +23,9 @@ /* uint8 -> int14 (but only the positive half!) */ \ onPitchBend(0, report->touchPad << 5); \ uint32_t keyMask = \ - (report->key1 << 17) | \ - (report->key2 << 9) | \ - (report->key3 << 1) | \ + (report->keys[0] << 17) | \ + (report->keys[1] << 9) | \ + (report->keys[0] << 1) | \ ((report->velocities[0] & 0x80) >> 7); \ \ int pressed = 0; /* Number of keys pressed */ \ From 0298d4a3de75413a91f0e7ea9e995c88da0374e9 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 6 Apr 2025 15:16:23 +1200 Subject: [PATCH 002/239] dont use drum trigger logic for keys --- src/shared/main/shared_main.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index aeca871a4..b8349aecd 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -70,8 +70,10 @@ void onNote(uint8_t channel, uint8_t note, uint8_t velocity) { void offNote(uint8_t channel, uint8_t note, uint8_t velocity) { printf("Note OFF ch=%d, note=%d, vel=%d\r\n", channel, note, velocity); - // midiData.midiVelocities[note] = 0; - // midiData.midiVelocitiesTemp[note] = 0; + #if DEVICE_TYPE == ROCK_BAND_PRO_KEYS + midiData.midiVelocities[note] = 0; + midiData.midiVelocitiesTemp[note] = 0; + #endif } void onControlChange(uint8_t channel, uint8_t b1, uint8_t b2) { @@ -3003,10 +3005,12 @@ void tick(void) { if ((millis() - input_start) < 2000) { tick_inputs(NULL, NULL, consoleType); } + #if DEVICE_TYPE != ROCK_BAND_PRO_KEYS if ((millis() - lastMidi) > 1000) { memset(midiData.midiVelocities, 0, sizeof(midiData.midiVelocities)); lastMidi = millis(); } + #endif #ifdef TICK_LED_PERIPHERAL // If we are controlling peripheral leds, then we need to send the latest state when From a62fb8055cdd99283ef7eb235fc547645248558c Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 6 Apr 2025 21:07:08 +1200 Subject: [PATCH 003/239] more pro keys fixes --- include/state_translation/pro_keys.h | 88 ++++++++++++++-------------- src/shared/main/shared_main.cpp | 2 +- 2 files changed, 44 insertions(+), 46 deletions(-) diff --git a/include/state_translation/pro_keys.h b/include/state_translation/pro_keys.h index 10530a63e..db1da804d 100644 --- a/include/state_translation/pro_keys.h +++ b/include/state_translation/pro_keys.h @@ -1,49 +1,47 @@ #define PRO_KEY_COUNT 25 #define PRO_KEY_FIRST_NOTE 24 #define DEFAULT_VELOCITY 64 -// Translate a Pro keys style report to a usb host report -// Note that we temporarily clear the buttons and then merge after -// As that makes it easier to process the velocities -#define TRANSLATE_PRO_KEYS \ - usb_host_data->a |= report->a; \ - usb_host_data->b |= report->b; \ - usb_host_data->x |= report->x; \ - usb_host_data->y |= report->y; \ - usb_host_data->back |= report->back; \ - usb_host_data->start |= report->start; \ - usb_host_data->guide |= report->guide; \ - if (report->pedalDigital) { \ - onControlChange(0, MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL, 0x7F); \ - } else if (~(report->pedalAnalog)) { \ - onControlChange(0, MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL, ~(report->pedalAnalog)); \ - } else { \ - onControlChange(0, MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL, 0); \ - } \ - onControlChange(0, MIDI_CONTROL_COMMAND_MOD_WHEEL, report->overdrive ? 0xFF : 0x00); \ - /* uint8 -> int14 (but only the positive half!) */ \ - onPitchBend(0, report->touchPad << 5); \ - uint32_t keyMask = \ - (report->keys[0] << 17) | \ - (report->keys[1] << 9) | \ - (report->keys[0] << 1) | \ - ((report->velocities[0] & 0x80) >> 7); \ - \ - int pressed = 0; /* Number of keys pressed */ \ - int keyBit = 1 << (PRO_KEY_COUNT - 1); /* Bitmask used to test for a specific key */ \ - for (int i = 0; i < PRO_KEY_COUNT; i++) { \ - /* Check if the key is pressed */ \ - if (keyMask & keyBit) { \ - /* There are only 5 key velocities stored*/ \ - if (pressed < 5) { \ - /* Retrieve velocity (ranges from 0-127)*/ \ - onNote(1, PRO_KEY_FIRST_NOTE + i, (report->velocities[pressed++] & 0x7F)); \ - } else { \ - onNote(1, PRO_KEY_FIRST_NOTE + i, DEFAULT_VELOCITY); \ - } \ - } else { \ - offNote(1, PRO_KEY_FIRST_NOTE + i, 0); \ - } \ - \ - /* Shift the key mask to the next key*/ \ - keyMask >>= 1; \ +// Translate a Pro keys style report to midi + usb host +#define TRANSLATE_PRO_KEYS \ + usb_host_data->a |= report->a; \ + usb_host_data->b |= report->b; \ + usb_host_data->x |= report->x; \ + usb_host_data->y |= report->y; \ + usb_host_data->back |= report->back; \ + usb_host_data->start |= report->start; \ + usb_host_data->guide |= report->guide; \ + if (report->pedalDigital) { \ + onControlChange(0, MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL, 0x7F); \ + } else if (~(report->pedalAnalog)) { \ + onControlChange(0, MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL, ~(report->pedalAnalog)); \ + } else { \ + onControlChange(0, MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL, 0); \ + } \ + onControlChange(0, MIDI_CONTROL_COMMAND_MOD_WHEEL, report->overdrive ? 0xFF : 0x00); \ + /* uint8 -> int14 (but only the positive half!) */ \ + onPitchBend(0, report->touchPad << 5); \ + uint32_t keyMask = \ + (((uint32_t)report->keys[0]) << 17) | \ + (((uint32_t)report->keys[1]) << 9) | \ + (((uint32_t)report->keys[2]) << 1) | \ + (((uint32_t)report->velocities[0] & 0x80) >> 7); \ + \ + int pressed = 0; /* Number of keys pressed */ \ + uint32_t keyBit = 1 << (PRO_KEY_COUNT - 1); /* Bitmask used to test for a specific key */ \ + for (int i = 0; i < PRO_KEY_COUNT; i++) { \ + /* Check if the key is pressed */ \ + if (keyMask & keyBit) { \ + /* There are only 5 key velocities stored*/ \ + if (pressed < 5) { \ + /* Retrieve velocity (ranges from 0-127)*/ \ + onNote(1, PRO_KEY_FIRST_NOTE + i, (report->velocities[pressed++] & 0x7F)); \ + } else { \ + onNote(1, PRO_KEY_FIRST_NOTE + i, DEFAULT_VELOCITY); \ + } \ + } else { \ + offNote(1, PRO_KEY_FIRST_NOTE + i, 0); \ + } \ + \ + /* Shift the key mask to the next key*/ \ + keyMask >>= 1; \ } diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index b8349aecd..aa1027748 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3010,7 +3010,7 @@ void tick(void) { memset(midiData.midiVelocities, 0, sizeof(midiData.midiVelocities)); lastMidi = millis(); } - #endif +#endif #ifdef TICK_LED_PERIPHERAL // If we are controlling peripheral leds, then we need to send the latest state when From 6ab5116d6b96ccf4e4641a50761b1f9d28808817 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 7 Apr 2025 11:20:29 +1200 Subject: [PATCH 004/239] fix pro keys --- include/state_translation/pro_keys.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/state_translation/pro_keys.h b/include/state_translation/pro_keys.h index db1da804d..3caf5047f 100644 --- a/include/state_translation/pro_keys.h +++ b/include/state_translation/pro_keys.h @@ -43,5 +43,5 @@ } \ \ /* Shift the key mask to the next key*/ \ - keyMask >>= 1; \ + keyMask <<= 1; \ } From 70f37ae13b3762a982c4c97407a5eb00810cd620 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 9 Apr 2025 14:14:43 +1200 Subject: [PATCH 005/239] pro guitar tilt fixes --- include/state_translation/pro_guitar.h | 3 +- include/state_translation/pro_keys.h | 80 ++++++++++++-------------- 2 files changed, 40 insertions(+), 43 deletions(-) diff --git a/include/state_translation/pro_guitar.h b/include/state_translation/pro_guitar.h index d81d6d5f4..abaac57dc 100644 --- a/include/state_translation/pro_guitar.h +++ b/include/state_translation/pro_guitar.h @@ -27,7 +27,7 @@ usb_host_data->bFret = report->bFret; \ usb_host_data->highEFret = report->highEFret; \ \ - usb_host_data->tilt |= report->tilt; \ + usb_host_data->tilt = report->tilt; \ /* TODO: pedalDigital should map to pedalDigital*/ \ usb_host_data->back |= report->pedal; @@ -38,6 +38,7 @@ report->gFretVelocity = item.gFretVelocity; \ report->bFretVelocity = item.bFretVelocity; \ report->highEFretVelocity = item.highEFretVelocity; \ + report->tilt = item.tilt; \ report->green = item.green; \ report->red = item.red; \ report->yellow = item.yellow; \ diff --git a/include/state_translation/pro_keys.h b/include/state_translation/pro_keys.h index 3caf5047f..f1d852322 100644 --- a/include/state_translation/pro_keys.h +++ b/include/state_translation/pro_keys.h @@ -2,46 +2,42 @@ #define PRO_KEY_FIRST_NOTE 24 #define DEFAULT_VELOCITY 64 // Translate a Pro keys style report to midi + usb host -#define TRANSLATE_PRO_KEYS \ - usb_host_data->a |= report->a; \ - usb_host_data->b |= report->b; \ - usb_host_data->x |= report->x; \ - usb_host_data->y |= report->y; \ - usb_host_data->back |= report->back; \ - usb_host_data->start |= report->start; \ - usb_host_data->guide |= report->guide; \ - if (report->pedalDigital) { \ - onControlChange(0, MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL, 0x7F); \ - } else if (~(report->pedalAnalog)) { \ - onControlChange(0, MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL, ~(report->pedalAnalog)); \ - } else { \ - onControlChange(0, MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL, 0); \ - } \ - onControlChange(0, MIDI_CONTROL_COMMAND_MOD_WHEEL, report->overdrive ? 0xFF : 0x00); \ - /* uint8 -> int14 (but only the positive half!) */ \ - onPitchBend(0, report->touchPad << 5); \ - uint32_t keyMask = \ - (((uint32_t)report->keys[0]) << 17) | \ - (((uint32_t)report->keys[1]) << 9) | \ - (((uint32_t)report->keys[2]) << 1) | \ - (((uint32_t)report->velocities[0] & 0x80) >> 7); \ - \ - int pressed = 0; /* Number of keys pressed */ \ - uint32_t keyBit = 1 << (PRO_KEY_COUNT - 1); /* Bitmask used to test for a specific key */ \ - for (int i = 0; i < PRO_KEY_COUNT; i++) { \ - /* Check if the key is pressed */ \ - if (keyMask & keyBit) { \ - /* There are only 5 key velocities stored*/ \ - if (pressed < 5) { \ - /* Retrieve velocity (ranges from 0-127)*/ \ - onNote(1, PRO_KEY_FIRST_NOTE + i, (report->velocities[pressed++] & 0x7F)); \ - } else { \ - onNote(1, PRO_KEY_FIRST_NOTE + i, DEFAULT_VELOCITY); \ - } \ - } else { \ - offNote(1, PRO_KEY_FIRST_NOTE + i, 0); \ - } \ - \ - /* Shift the key mask to the next key*/ \ - keyMask <<= 1; \ +#define TRANSLATE_PRO_KEYS \ + usb_host_data->a |= report->a; \ + usb_host_data->b |= report->b; \ + usb_host_data->x |= report->x; \ + usb_host_data->y |= report->y; \ + usb_host_data->back |= report->back; \ + usb_host_data->start |= report->start; \ + usb_host_data->guide |= report->guide; \ + if (report->pedalDigital) { \ + onControlChange(0, MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL, 0x7F); \ + } else if (~(report->pedalAnalog)) { \ + onControlChange(0, MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL, ~(report->pedalAnalog)); \ + } else { \ + onControlChange(0, MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL, 0); \ + } \ + onControlChange(0, MIDI_CONTROL_COMMAND_MOD_WHEEL, report->overdrive ? 0xFF : 0x00); \ + /* uint8 -> int14 (but only the positive half!) */ \ + onPitchBend(0, report->touchPad << 5); \ + uint32_t keyMask = \ + (((uint32_t)report->keys[0]) << 17) | \ + (((uint32_t)report->keys[1]) << 9) | \ + (((uint32_t)report->keys[2]) << 1) | \ + (((uint32_t)report->velocities[0] & 0x80) >> 7); \ + \ + int pressed = 0; /* Number of keys pressed */ \ + for (uint32_t i = 0; i < PRO_KEY_COUNT; i++) { \ + /* Check if the key is pressed */ \ + if (keyMask & (1 << (PRO_KEY_COUNT - 1 - i))) { \ + /* There are only 5 key velocities stored*/ \ + if (pressed < 5) { \ + /* Retrieve velocity (ranges from 0-127)*/ \ + onNote(1, PRO_KEY_FIRST_NOTE + i, (report->velocities[pressed++] & 0x7F)); \ + } else { \ + onNote(1, PRO_KEY_FIRST_NOTE + i, DEFAULT_VELOCITY); \ + } \ + } else { \ + offNote(1, PRO_KEY_FIRST_NOTE + i, 0); \ + } \ } From 050b008434f567f91f606000d8373322d84bde7b Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 14 Apr 2025 10:29:07 +1200 Subject: [PATCH 006/239] make sure we build the right fw --- include/defines.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/defines.h b/include/defines.h index ac9683ad9..b31ab2ab5 100644 --- a/include/defines.h +++ b/include/defines.h @@ -161,6 +161,7 @@ typedef enum { WII_NO_EXTENSION = 0x180b, WII_NOT_INITIALISED = 0xFFFF } WiiExtType_t; + typedef enum { Announce, WaitingDesc1, From 5d2f0384b340ec8cc5ce711ecf757704adf97095 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 17 Apr 2025 15:49:02 +1200 Subject: [PATCH 007/239] rewrite rb3 cymbal fix --- src/shared/main/shared_main.cpp | 47 +++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index aa1027748..9097ae066 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2,6 +2,7 @@ #include "Arduino.h" #include "accel.h" +#include "bh_drum.h" #include "bt.h" #include "config.h" #include "controllers.h" @@ -16,14 +17,13 @@ #include "pico_slave.h" #include "pin_funcs.h" #include "ps2.h" +#include "state_translation/drums.h" #include "state_translation/pro_guitar.h" #include "state_translation/pro_keys.h" -#include "state_translation/drums.h" #include "usbhid.h" #include "util.h" #include "wii.h" #include "wt_drum.h" -#include "bh_drum.h" #define DJLEFT_ADDR 0x0E #define DJRIGHT_ADDR 0x0D #define DJ_BUTTONS_PTR 0x12 @@ -65,15 +65,14 @@ void onNote(uint8_t channel, uint8_t note, uint8_t velocity) { midiData.midiVelocitiesTemp[note] = velocity; } lastMidi = millis(); - } void offNote(uint8_t channel, uint8_t note, uint8_t velocity) { printf("Note OFF ch=%d, note=%d, vel=%d\r\n", channel, note, velocity); - #if DEVICE_TYPE == ROCK_BAND_PRO_KEYS - midiData.midiVelocities[note] = 0; - midiData.midiVelocitiesTemp[note] = 0; - #endif +#if DEVICE_TYPE == ROCK_BAND_PRO_KEYS + midiData.midiVelocities[note] = 0; + midiData.midiVelocitiesTemp[note] = 0; +#endif } void onControlChange(uint8_t channel, uint8_t b1, uint8_t b2) { @@ -2306,6 +2305,12 @@ void bluetooth_connected() { } uint8_t rbcount = 0; uint8_t lastrbcount = 0; +uint8_t hadCymbal = 0; +bool greenCymbal; +bool greenPad; +bool yellowCymbal; +bool blueCymbal; +long lastCymbalOff; uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t output_console_type) { uint8_t packet_size = 0; Buffer_Report_t current_queue_report = {val : 0}; @@ -2315,17 +2320,17 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #endif // Tick Inputs #include "inputs/accel.h" +#include "inputs/bh_drum.h" #include "inputs/clone_neck.h" #include "inputs/gh5_neck.h" -#include "inputs/bh_drum.h" #include "inputs/mpr121.h" #include "inputs/ps2.h" #include "inputs/slave_tick.h" #include "inputs/turntable.h" #include "inputs/usb_host.h" #include "inputs/wii.h" -#include "inputs/wt_neck.h" #include "inputs/wt_drum.h" +#include "inputs/wt_neck.h" TICK_SHARED; if (!startedInactivityPulse) { @@ -2531,7 +2536,6 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #if DEVICE_TYPE_IS_GUITAR || DEVICE_TYPE_IS_LIVE_GUITAR report->whammy = INT16_MIN; #endif - TICK_XINPUT; #if DEVICE_TYPE == GUITAR_HERO_GUITAR @@ -2564,6 +2568,16 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->leftThumbClick = true; #endif report_size = packet_size = sizeof(XINPUT_REPORT); +#if DEVICE_TYPE == ROCK_BAND_DRUMS + if (!report->cymbalFlag && ready_for_next_packet()) { + greenCymbal = false; + yellowCymbal = false; + blueCymbal = false; + } + if (!report->padFlag && ready_for_next_packet()) { + greenPad = false; + } +#endif } // Guitars and Drums can fall back to their PS3 versions, so don't even include the PS4 version there. // DJ Hero was never on ps4, so we can't really implement that either, so just fall back to PS3 there too. @@ -2800,6 +2814,17 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } #endif +#if DEVICE_TYPE == ROCK_BAND_DRUMS + if (!report->cymbalFlag && ready_for_next_packet()) { + greenCymbal = false; + yellowCymbal = false; + blueCymbal = false; + } + if (!report->padFlag && ready_for_next_packet()) { + greenPad = false; + } +#endif + #if DEVICE_TYPE == ROCK_BAND_PRO_KEYS bool key25 = report->key25; uint8_t currentVel = 0; @@ -3005,7 +3030,7 @@ void tick(void) { if ((millis() - input_start) < 2000) { tick_inputs(NULL, NULL, consoleType); } - #if DEVICE_TYPE != ROCK_BAND_PRO_KEYS +#if DEVICE_TYPE != ROCK_BAND_PRO_KEYS if ((millis() - lastMidi) > 1000) { memset(midiData.midiVelocities, 0, sizeof(midiData.midiVelocities)); lastMidi = millis(); From 71503c414d32622ba91d825f8b90aa867a0428ab Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 22 Apr 2025 19:57:25 +1200 Subject: [PATCH 008/239] fix pro guitar tilt --- include/state_translation/pro_guitar.h | 38 +++++++++++++------------- src/shared/main/shared_main.cpp | 12 ++++++++ src/shared/usb/descriptors.cpp | 2 +- 3 files changed, 32 insertions(+), 20 deletions(-) diff --git a/include/state_translation/pro_guitar.h b/include/state_translation/pro_guitar.h index abaac57dc..1a121c95f 100644 --- a/include/state_translation/pro_guitar.h +++ b/include/state_translation/pro_guitar.h @@ -27,26 +27,26 @@ usb_host_data->bFret = report->bFret; \ usb_host_data->highEFret = report->highEFret; \ \ - usb_host_data->tilt = report->tilt; \ + usb_host_data->tilt = report->tilt == 0x7F ? INT16_MAX : 0; \ /* TODO: pedalDigital should map to pedalDigital*/ \ usb_host_data->back |= report->pedal; -#define TRANSLATE_TO_PRO_GUITAR(item) \ - report->lowEFretVelocity = item.lowEFretVelocity; \ - report->aFretVelocity = item.aFretVelocity; \ - report->dFretVelocity = item.dFretVelocity; \ - report->gFretVelocity = item.gFretVelocity; \ - report->bFretVelocity = item.bFretVelocity; \ - report->highEFretVelocity = item.highEFretVelocity; \ - report->tilt = item.tilt; \ - report->green = item.green; \ - report->red = item.red; \ - report->yellow = item.yellow; \ - report->blue = item.blue; \ - report->orange = item.orange; \ - report->lowEFret = item.lowEFret; \ - report->aFret = item.aFret; \ - report->dFret = item.dFret; \ - report->gFret = item.gFret; \ - report->bFret = item.bFret; \ +#define TRANSLATE_TO_PRO_GUITAR(item) \ + report->lowEFretVelocity = item.lowEFretVelocity; \ + report->aFretVelocity = item.aFretVelocity; \ + report->dFretVelocity = item.dFretVelocity; \ + report->gFretVelocity = item.gFretVelocity; \ + report->bFretVelocity = item.bFretVelocity; \ + report->highEFretVelocity = item.highEFretVelocity; \ + report->tilt = item.tilt == INT16_MAX ? 0x7F : 0x60; \ + report->green = item.green; \ + report->red = item.red; \ + report->yellow = item.yellow; \ + report->blue = item.blue; \ + report->orange = item.orange; \ + report->lowEFret = item.lowEFret; \ + report->aFret = item.aFret; \ + report->dFret = item.dFret; \ + report->gFret = item.gFret; \ + report->bFret = item.bFret; \ report->highEFret = item.highEFret; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 9097ae066..6dbf0a92e 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2545,9 +2545,13 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #endif #if PRO_GUITAR && USB_HOST_STACK TRANSLATE_TO_PRO_GUITAR(usb_host_data) + report->autoCal_Light = report->tilt; + report->autoCal_Microphone = report->tilt; #endif #if PRO_GUITAR && BLUETOOTH_RX TRANSLATE_TO_PRO_GUITAR(bt_data) + report->autoCal_Light = report->tilt; + report->autoCal_Microphone = report->tilt; #endif asm volatile("" :: : "memory"); @@ -2602,9 +2606,13 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #if PRO_GUITAR && USB_HOST_STACK TRANSLATE_TO_PRO_GUITAR(usb_host_data) + report->autoCal_Light = report->tilt; + report->autoCal_Microphone = report->tilt; #endif #if PRO_GUITAR && BLUETOOTH_RX TRANSLATE_TO_PRO_GUITAR(bt_data) + report->autoCal_Light = report->tilt; + report->autoCal_Microphone = report->tilt; #endif asm volatile("" :: : "memory"); @@ -2795,9 +2803,13 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #if PRO_GUITAR && USB_HOST_STACK TRANSLATE_TO_PRO_GUITAR(usb_host_data) + report->autoCal_Light = report->tilt; + report->autoCal_Microphone = report->tilt; #endif #if PRO_GUITAR && BLUETOOTH_RX TRANSLATE_TO_PRO_GUITAR(bt_data) + report->autoCal_Light = report->tilt; + report->autoCal_Microphone = report->tilt; #endif asm volatile("" :: : "memory"); diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index cd7c73f77..6d54f7f67 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -953,7 +953,7 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const #endif } // Fakemote sends this, so we know to jump to PS3 mode - if (consoleType == UNIVERSAL && wValue == 0x03f2 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT && wLength == 0x11) { + if ((consoleType == UNIVERSAL || consoleType == WINDOWS) && wValue == 0x03f2 && (wIndex == INTERFACE_ID_Device || wIndex == INTERFACE_ID_Config) && request == HID_REQUEST_GET_REPORT && wLength == 0x11) { consoleType = PS3; reset_usb(); } From 363b7817a262a4f8d096ec41e71cf3d8db11e2e6 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 23 Apr 2025 08:53:16 +1200 Subject: [PATCH 009/239] fix serial midi without usb --- src/pico/main.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 8ba408d8e..d5137f251 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -87,8 +87,10 @@ typedef struct { uint8_t prev_bt_report[32]; static const uint8_t capabilitiesRequest[] = {0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static const uint8_t xbox360w_prescence[] = {0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -#ifdef INPUT_USB_HOST +#if defined(INPUT_USB_HOST) || defined(INPUT_SERIAL_MIDI) using namespace usbMidi; +#endif +#ifdef INPUT_USB_HOST UsbMidiTransport usbMIDITransport(0); MidiInterface MIDI(usbMIDITransport); #endif From cc0fb6ba2a28e732711dcf9bba05515b350d66fd Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 24 Apr 2025 12:16:12 +1200 Subject: [PATCH 010/239] make it so that dolphin hotplug is toggleable --- src/shared/usb/descriptors.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 6d54f7f67..240e371bc 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -954,8 +954,10 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const } // Fakemote sends this, so we know to jump to PS3 mode if ((consoleType == UNIVERSAL || consoleType == WINDOWS) && wValue == 0x03f2 && (wIndex == INTERFACE_ID_Device || wIndex == INTERFACE_ID_Config) && request == HID_REQUEST_GET_REPORT && wLength == 0x11) { - consoleType = PS3; - reset_usb(); + if (RPCS3_COMPAT) { + consoleType = PS3; + reset_usb(); + } } // RPCS3 sends this. Jump any devices with RPCS3 compat enabled if ((consoleType == UNIVERSAL || consoleType == WINDOWS) && wValue == 0x03f2 && wIndex == INTERFACE_ID_Config && request == HID_REQUEST_GET_REPORT) { From 028f189624c579e4bfbbdd827a8d431a0edde4ef Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 26 Apr 2025 13:24:30 +1200 Subject: [PATCH 011/239] ps3 kits dont invert velocity --- src/shared/main/shared_main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 6dbf0a92e..9096ec6c6 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1174,10 +1174,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t } case ROCK_BAND_DRUMS: { PS3RockBandDrums_Data_t *report = (PS3RockBandDrums_Data_t *)data; - uint8_t redVelocity = ~report->redVelocity; - uint8_t greenVelocity = ~report->greenVelocity; - uint8_t yellowVelocity = ~report->yellowVelocity; - uint8_t blueVelocity = ~report->blueVelocity; + uint8_t redVelocity = report->redVelocity; + uint8_t greenVelocity = report->greenVelocity; + uint8_t yellowVelocity = report->yellowVelocity; + uint8_t blueVelocity = report->blueVelocity; bool kick1 = report->leftShoulder; bool kick2 = report->rightShoulder; usb_host_data->a |= report->a; From 25807cb23eeb0f795fbae94c6951af67d468168d Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 26 Apr 2025 14:55:08 +1200 Subject: [PATCH 012/239] fix wii kits --- include/state_translation/drums.h | 100 ++++++++++++++++++++---------- src/shared/main/shared_main.cpp | 8 +-- src/shared/main/wii.cpp | 28 ++++++++- 3 files changed, 97 insertions(+), 39 deletions(-) diff --git a/include/state_translation/drums.h b/include/state_translation/drums.h index c40c88c82..dbd341808 100644 --- a/include/state_translation/drums.h +++ b/include/state_translation/drums.h @@ -27,46 +27,47 @@ offNote(10, RB_MIDI_NOTE_BLUE, 0); \ offNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, 0); \ } \ - /* If you hit both the pad and cymbal of the same colour simultaneously, the velocity for the cymbal \ - is placed in the redVelocity, but the red button won't be pressed. */ \ - if (!red && redVelocity) { \ - if (up) { \ - onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, redVelocity >> 1); \ - onNote(10, RB_MIDI_NOTE_YELLOW, yellowVelocity >> 1); \ - } else if (down) { \ - onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, redVelocity >> 1); \ - onNote(10, RB_MIDI_NOTE_BLUE, blueVelocity >> 1); \ - } else { \ - onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, redVelocity >> 1); \ - onNote(10, RB_MIDI_NOTE_GREEN, greenVelocity >> 1); \ - } \ - pad = false; \ - cymbal = false; \ - } \ if (pad && cymbal) { \ /* The d-pad inputs let us resolve the ambiguity of a pad+cymbal hit \ Only d-pad is checked here since it is the only unique identifier due to hardware bugs \ (sometimes the color flag is released before the d-pad input is, particularly at high polling rates)*/ \ \ - /* Yellow */ \ - if (up) { \ - onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, yellowVelocity >> 1); \ - yellow = false; \ + /* If you hit both the pad and cymbal of the same colour simultaneously, the velocity for the cymbal \ + is placed in the redVelocity, but the red button won't be pressed. */ \ + if (!red && redVelocity) { \ + if (up) { \ + onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, redVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_YELLOW, yellowVelocity >> 1); \ + } else if (down) { \ + onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, redVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_BLUE, blueVelocity >> 1); \ + } else { \ + onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, redVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_GREEN, greenVelocity >> 1); \ + } \ + pad = false; \ cymbal = false; \ - } \ + } else { \ + /* Yellow */ \ + if (up) { \ + onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, yellowVelocity >> 1); \ + yellow = false; \ + cymbal = false; \ + } \ \ - /* Blue */ \ - if (down) { \ - onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, blueVelocity >> 1); \ - blue = false; \ - cymbal = false; \ - } \ + /* Blue */ \ + if (down) { \ + onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, blueVelocity >> 1); \ + blue = false; \ + cymbal = false; \ + } \ \ - /* Green */ \ - if (!(up || down)) { \ - onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, blueVelocity >> 1); \ - green = false; \ - cymbal = false; \ + /* Green */ \ + if (!(up || down)) { \ + onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, blueVelocity >> 1); \ + green = false; \ + cymbal = false; \ + } \ } \ } \ if (pad) { \ @@ -105,7 +106,39 @@ } else { \ offNote(10, RB_MIDI_NOTE_KICK2, 0); \ } - +#if DEVICE_TYPE == ROCK_BAND_DRUMS +#define SET_GH_PADS() \ + if (report->greenVelocity) { \ + onNote(10, RB_MIDI_NOTE_GREEN, report->greenVelocity); \ + } else { \ + offNote(10, RB_MIDI_NOTE_GREEN, report->greenVelocity); \ + } \ + if (report->redVelocity) { \ + onNote(10, RB_MIDI_NOTE_RED, report->redVelocity); \ + } else { \ + offNote(10, RB_MIDI_NOTE_RED, report->redVelocity); \ + } \ + if (report->yellowVelocity) { \ + onNote(10, RB_MIDI_NOTE_YELLOW, report->yellowVelocity); \ + } else { \ + offNote(10, RB_MIDI_NOTE_YELLOW, report->yellowVelocity); \ + } \ + if (report->blueVelocity) { \ + onNote(10, RB_MIDI_NOTE_BLUE, report->blueVelocity); \ + } else { \ + offNote(10, RB_MIDI_NOTE_BLUE, report->blueVelocity); \ + } \ + if (report->orangeVelocity) { \ + onNote(10, RB_MIDI_NOTE_GREEN, report->orangeVelocity); \ + } else { \ + offNote(10, RB_MIDI_NOTE_GREEN, report->orangeVelocity); \ + } \ + if (report->kickVelocity) { \ + onNote(10, RB_MIDI_NOTE_KICK, report->kickVelocity); \ + } else { \ + offNote(10, RB_MIDI_NOTE_KICK, report->kickVelocity); \ + } +#else #define SET_GH_PADS() \ if (report->greenVelocity) { \ onNote(10, GH_MIDI_NOTE_GREEN, report->greenVelocity); \ @@ -137,3 +170,4 @@ } else { \ offNote(10, GH_MIDI_NOTE_KICK, report->kickVelocity); \ } +#endif \ No newline at end of file diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 9096ec6c6..6dbf0a92e 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1174,10 +1174,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t } case ROCK_BAND_DRUMS: { PS3RockBandDrums_Data_t *report = (PS3RockBandDrums_Data_t *)data; - uint8_t redVelocity = report->redVelocity; - uint8_t greenVelocity = report->greenVelocity; - uint8_t yellowVelocity = report->yellowVelocity; - uint8_t blueVelocity = report->blueVelocity; + uint8_t redVelocity = ~report->redVelocity; + uint8_t greenVelocity = ~report->greenVelocity; + uint8_t yellowVelocity = ~report->yellowVelocity; + uint8_t blueVelocity = ~report->blueVelocity; bool kick1 = report->leftShoulder; bool kick2 = report->rightShoulder; usb_host_data->a |= report->a; diff --git a/src/shared/main/wii.cpp b/src/shared/main/wii.cpp index d62262edf..5d7942405 100644 --- a/src/shared/main/wii.cpp +++ b/src/shared/main/wii.cpp @@ -4,11 +4,11 @@ #include #include "Arduino.h" +#include "commands.h" #include "config.h" #include "controllers.h" #include "io.h" #include "shared_main.h" -#include "commands.h" uint8_t wiiBytes; #ifdef INPUT_WII uint8_t wiiPointer = 0; @@ -120,7 +120,7 @@ void initWiiExt(void) { bool initialised = false; bool lastWiiEuphoriaLed = false; bool hadDrum = false; -static uint8_t packetIssueCount = 0; +static uint8_t packetIssueCount = 0; bool wiiDataValid() { return initialised; } @@ -175,7 +175,31 @@ uint8_t* tickWii() { velocity = 0x7F - velocity; note = 0x7F - note; if (velocity || note) { + // map gh notes to their rb counterparts in rb mode +#if DEVICE_TYPE == ROCK_BAND_DRUMS + switch (note) { + case GH_MIDI_NOTE_GREEN: + onNote(channel, RB_MIDI_NOTE_GREEN, velocity); + break; + case GH_MIDI_NOTE_RED: + onNote(channel, RB_MIDI_NOTE_RED, velocity); + break; + case GH_MIDI_NOTE_YELLOW: + onNote(channel, RB_MIDI_NOTE_YELLOW, velocity); + break; + case GH_MIDI_NOTE_BLUE: + onNote(channel, RB_MIDI_NOTE_BLUE, velocity); + break; + case GH_MIDI_NOTE_ORANGE: + onNote(channel, RB_MIDI_NOTE_GREEN, velocity); + break; + default: + onNote(channel, note, velocity); + break; + } +#else onNote(channel, note, velocity); +#endif } } initialised = true; From 3b633a3a19ef8ada86930e76c8e7797190e67ba1 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 3 May 2025 13:41:30 +1200 Subject: [PATCH 013/239] Support matrixes --- include/pin_funcs.h | 1 + src/pico/pins.cpp | 7 +++++++ src/shared/main/shared_main.cpp | 4 ++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/pin_funcs.h b/include/pin_funcs.h index 8272e4134..59dd38c36 100644 --- a/include/pin_funcs.h +++ b/include/pin_funcs.h @@ -11,6 +11,7 @@ uint16_t adc(uint8_t pin); uint8_t digital_read(uint8_t port, uint8_t mask); uint16_t adc_read(uint8_t pin, uint8_t mask); uint16_t multiplexer_read(uint8_t pin, uint32_t mask, uint32_t bits); +uint8_t matrix_read(uint8_t pin, uint8_t outPin); void digital_write(uint8_t port, uint8_t mask, uint8_t activeMask); void putWs2812(uint8_t r, uint8_t g, uint8_t b); void putWs2812(uint8_t r, uint8_t g, uint8_t b, uint8_t w); \ No newline at end of file diff --git a/src/pico/pins.cpp b/src/pico/pins.cpp index c2a0b747c..fc353a98d 100644 --- a/src/pico/pins.cpp +++ b/src/pico/pins.cpp @@ -102,4 +102,11 @@ uint16_t multiplexer_read(uint8_t pin, uint32_t mask, uint32_t bits) { return adc_read() << 4; } return 0; +} + +uint8_t matrix_read(uint8_t pin, uint8_t outPin) { + gpio_put(outPin, 0); + uint8_t ret = gpio_get(pin); + gpio_put(outPin, 1); + return ret; } \ No newline at end of file diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 6dbf0a92e..9c02ab20e 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -58,7 +58,7 @@ unsigned long lastMidi = 0; Midi_Data_t midiData = {0}; void onNote(uint8_t channel, uint8_t note, uint8_t velocity) { // velocities are 7 bit - printf("Note ON ch=%d, note=%d, vel=%d\r\n", channel, note, velocity); + // printf("Note ON ch=%d, note=%d, vel=%d\r\n", channel, note, velocity); velocity = velocity << 1; if (velocity > midiData.midiVelocitiesTemp[note]) { midiData.midiVelocities[note] = velocity; @@ -68,7 +68,7 @@ void onNote(uint8_t channel, uint8_t note, uint8_t velocity) { } void offNote(uint8_t channel, uint8_t note, uint8_t velocity) { - printf("Note OFF ch=%d, note=%d, vel=%d\r\n", channel, note, velocity); + // printf("Note OFF ch=%d, note=%d, vel=%d\r\n", channel, note, velocity); #if DEVICE_TYPE == ROCK_BAND_PRO_KEYS midiData.midiVelocities[note] = 0; midiData.midiVelocitiesTemp[note] = 0; From bf7e81a261f6a509e5784bd028acb3c1cf82db00 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 3 May 2025 16:45:47 +1200 Subject: [PATCH 014/239] Support matrixes --- src/pico/pins.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/pico/pins.cpp b/src/pico/pins.cpp index fc353a98d..8f86ec09a 100644 --- a/src/pico/pins.cpp +++ b/src/pico/pins.cpp @@ -105,8 +105,11 @@ uint16_t multiplexer_read(uint8_t pin, uint32_t mask, uint32_t bits) { } uint8_t matrix_read(uint8_t pin, uint8_t outPin) { - gpio_put(outPin, 0); - uint8_t ret = gpio_get(pin); - gpio_put(outPin, 1); - return ret; + if (!disable_multiplexer) { + gpio_put(outPin, 0); + uint8_t ret = gpio_get(pin); + gpio_put(outPin, 1); + return ret; + } + return 0; } \ No newline at end of file From e1cc886649a7d0a18464142db7e61f56561bf49d Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 3 May 2025 20:41:16 +1200 Subject: [PATCH 015/239] Support matrixes --- src/pico/pins.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pico/pins.cpp b/src/pico/pins.cpp index 8f86ec09a..e59483d88 100644 --- a/src/pico/pins.cpp +++ b/src/pico/pins.cpp @@ -107,9 +107,10 @@ uint16_t multiplexer_read(uint8_t pin, uint32_t mask, uint32_t bits) { uint8_t matrix_read(uint8_t pin, uint8_t outPin) { if (!disable_multiplexer) { gpio_put(outPin, 0); + sleep_us(1); uint8_t ret = gpio_get(pin); gpio_put(outPin, 1); return ret; } - return 0; + return 1; } \ No newline at end of file From 1f7657d56203851f575e88f6efe83d4177ca529d Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 3 May 2025 20:59:19 +1200 Subject: [PATCH 016/239] support bh drums --- include/commands.h | 2 ++ src/shared/hid/hid.cpp | 5 +++++ src/shared/main/bh_drum.cpp | 7 +++---- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/include/commands.h b/include/commands.h index 7d1651474..87b15294d 100644 --- a/include/commands.h +++ b/include/commands.h @@ -51,6 +51,7 @@ enum SerialCommands { COMMAND_ACCEL_VALID, COMMAND_READ_BLUETOOTH_INPUTS, COMMAND_WT_DRUM_VALID, + COMMAND_BH_DRUM_VALID, MAX=100 }; @@ -71,6 +72,7 @@ extern bool lastTurntableWasSuccessfulRight; extern bool lastWiiWasSuccessful; extern bool lastPS2WasSuccessful; extern bool wt_drum_found; +extern bool bh_drum_found; extern uint16_t wiiControllerType; extern uint8_t ps2ControllerType; extern bool overrideR2; diff --git a/src/shared/hid/hid.cpp b/src/shared/hid/hid.cpp index 01d55f0d6..cfbf0d76b 100644 --- a/src/shared/hid/hid.cpp +++ b/src/shared/hid/hid.cpp @@ -911,6 +911,11 @@ uint8_t handle_serial_command(uint8_t request, uint16_t wValue, uint8_t *respons response_buffer[0] = wt_drum_found; return 1; #endif +#ifdef BH_DRUM_TWI_PORT + case COMMAND_BH_DRUM_VALID: + response_buffer[0] = bh_drum_found; + return 1; +#endif #ifdef MAX1704X_TWI_PORT case COMMAND_READ_MAX170X_VALID: response_buffer[0] = max170x_init; diff --git a/src/shared/main/bh_drum.cpp b/src/shared/main/bh_drum.cpp index 793d3e805..29364725c 100644 --- a/src/shared/main/bh_drum.cpp +++ b/src/shared/main/bh_drum.cpp @@ -6,13 +6,12 @@ #define DRUM_ADDR 0x0D #define BH_DRUM_PTR 0x10 #ifdef BH_DRUM_TWI_PORT -static long lastTick = 0; -static int missing = 0; -bool wt_drum_found = false; +bool bh_drum_found = false; void tickBhDrum() { // BH Drum format: 0x10 uint8_t data[8]; - if (twi_readFromPointer(BH_DRUM_TWI_PORT, DRUM_ADDR, BH_DRUM_PTR, sizeof(data), data) && data[0] == BH_DRUM_PTR) { + bh_drum_found = twi_readFromPointer(BH_DRUM_TWI_PORT, DRUM_ADDR, BH_DRUM_PTR, sizeof(data), data) && data[0] == BH_DRUM_PTR; + if (bh_drum_found) { uint8_t status = data[1]; uint8_t type = (status & 0xf0); uint8_t channel = status & 0x0f; From 57535401ee8674ca60b88f3c91d295f861b50b32 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 4 May 2025 21:49:31 +1200 Subject: [PATCH 017/239] fix bh drums --- src/shared/main/bh_drum.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/shared/main/bh_drum.cpp b/src/shared/main/bh_drum.cpp index 29364725c..735c77546 100644 --- a/src/shared/main/bh_drum.cpp +++ b/src/shared/main/bh_drum.cpp @@ -7,22 +7,24 @@ #define BH_DRUM_PTR 0x10 #ifdef BH_DRUM_TWI_PORT bool bh_drum_found = false; +static long lastTick = 0; +static int missing = 0; void tickBhDrum() { - // BH Drum format: 0x10 - uint8_t data[8]; - bh_drum_found = twi_readFromPointer(BH_DRUM_TWI_PORT, DRUM_ADDR, BH_DRUM_PTR, sizeof(data), data) && data[0] == BH_DRUM_PTR; + // BH Drum format: 0x10 0x0 + uint8_t data[5]; + bh_drum_found = twi_readFromPointer(BH_DRUM_TWI_PORT, DRUM_ADDR, BH_DRUM_PTR, sizeof(data), data); if (bh_drum_found) { - uint8_t status = data[1]; + uint8_t status = data[2]; uint8_t type = (status & 0xf0); uint8_t channel = status & 0x0f; // TODO: CC and stuff, can the midi lib parse this all for us? if (type == 0x90) { - uint8_t note = data[2]; - uint8_t velocity = data[3]; + uint8_t note = data[3]; + uint8_t velocity = data[4]; onNote(channel, note, velocity); } else if (type == 0x80) { - uint8_t note = data[2]; - uint8_t velocity = data[3]; + uint8_t note = data[3]; + uint8_t velocity = data[4]; offNote(channel, note, velocity); } } From 2af7c5c677ed7ee4c5a42df9da4ca35de7b561e7 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 5 May 2025 21:49:53 +1200 Subject: [PATCH 018/239] use proper ids for guitars and other instruments --- include/config.h | 6 ++++++ include/endpoints.h | 4 ++-- src/shared/usb/descriptors.cpp | 5 ----- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/include/config.h b/include/config.h index ca995eb23..190a6dfe8 100644 --- a/include/config.h +++ b/include/config.h @@ -528,10 +528,14 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define XBOX_ONE_VID XBOX_ONE_RB_VID #define XBOX_ONE_PID XBOX_ONE_RB_GUITAR_PID #define XBOX_ONE_DESCRIPTOR_SIZE 256 +#define PS4_VID PDP_VID +#define PS4_PID PS4_JAG_PID #elif DEVICE_TYPE_IS_DRUMS #define XBOX_ONE_VID XBOX_ONE_RB_VID #define XBOX_ONE_PID XBOX_ONE_RB_DRUM_PID #define XBOX_ONE_DESCRIPTOR_SIZE 224 +#define PS4_VID MADCATZ_VID +#define PS4_PID PS4_MADCATZ_DRUM_PID #elif DEVICE_TYPE == LIVE_GUITAR #define XBOX_ONE_VID XBOX_ONE_GHLIVE_DONGLE_VID #define XBOX_ONE_PID XBOX_ONE_GHLIVE_DONGLE_PID @@ -552,6 +556,8 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define XBOX_ONE_VID XBOX_ONE_CONTROLLER_VID #define XBOX_ONE_PID XBOX_ONE_CONTROLLER_PID #define XBOX_ONE_DESCRIPTOR_SIZE 244 +#define PS4_VID 0x03EB +#define PS4_PID 0x2043 #endif typedef union { #if DEVICE_TYPE_IS_GAMEPAD diff --git a/include/endpoints.h b/include/endpoints.h index d3fdcea94..e86ae89a8 100644 --- a/include/endpoints.h +++ b/include/endpoints.h @@ -32,8 +32,6 @@ enum endpoints_t { #define NINTENDO_VID 0x057E #define SWITCH_PRO_PID 0x2009 #define REDOCTANE_VID 0x12ba -#define PS4_VID 0x03EB -#define PS4_PID 0x2043 #define SONY_VID 0x054c #define SONY_DS3_PID 0x0268 #define PS4_DS_PID_1 0x05c4 @@ -41,9 +39,11 @@ enum endpoints_t { #define PS4_DS_PID_3 0x0ba0 #define PS4_STRAT_VID 0x0738 #define PS4_STRAT_PID 0x8261 +#define MADCATZ_VID 0x0738 #define PDP_VID 0x0E6F #define PS4_JAG_PID 0x0173 #define PS4_RIFFMASTER_PID 0x024A +#define PS4_MADCATZ_DRUM_PID 0x8262 #define XBOX_ONE_RIFFMASTER_PID 0x0248 #define PS5_DS_PID 0x0ce6 #define PS5_RIFFMASTER_PID 0x0249 diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 240e371bc..672511999 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1223,13 +1223,8 @@ uint16_t descriptorRequest(const uint16_t wValue, } #endif else if (consoleType == PS4) { -#if DEVICE_TYPE_IS_INSTRUMENT - dev->idVendor = XBOX_REDOCTANE_VID; - dev->idProduct = PS4_GHLIVE_DONGLE_PID; -#else dev->idVendor = PS4_VID; dev->idProduct = PS4_PID; -#endif } else if (consoleType == IOS_FESTIVAL) { dev->idVendor = SONY_VID; dev->idProduct = SONY_DS3_PID; From 5b6d4aed090618d9e3645e1dddee366ec0d38803 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 6 May 2025 17:07:40 +1200 Subject: [PATCH 019/239] Implement 360 auth --- src/shared/usb/descriptors.cpp | 13 +--------- src/shared/usb/xsm3/xsm3.c | 45 ++++++++++++++-------------------- src/shared/usb/xsm3/xsm3.h | 3 --- 3 files changed, 19 insertions(+), 42 deletions(-) diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 672511999..ee96eafeb 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -883,7 +883,7 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const reset_usb(); return 0; } -#ifdef KV_KEY_ARRAY +#if SUPPORTS_PICO switch (request) { case 0x81: uint8_t serial[0x0C]; @@ -909,17 +909,6 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const memcpy(requestBuffer, &state, sizeof(state)); return sizeof(state); } -#elif USB_HOST_STACK - switch (request) { - case 0x81: - case 0x82: - case 0x87: - case 0x84: - case 0x83: - case 0x86: - USB_Device_Type_t type = get_device_address_for(XBOX360); - return transfer_with_usb_controller(type.dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); - } #else switch (request) { case 0x81: diff --git a/src/shared/usb/xsm3/xsm3.c b/src/shared/usb/xsm3/xsm3.c index a2934496e..71140ec46 100644 --- a/src/shared/usb/xsm3/xsm3.c +++ b/src/shared/usb/xsm3/xsm3.c @@ -38,16 +38,6 @@ #define XSM3_printf #endif // XSM3_NO_DEBUGGING -#ifdef KV_KEY_ARRAY -#ifdef CONFIGURABLE_BLOBS -static const uint8_t* kv_keys = (const uint8_t*)&KV_KEY_ARRAY; -uint8_t key_count = KV_KEY_SIZE; -#else -static const PROGMEM uint8_t kv_keys[] = KV_KEY_ARRAY; -uint8_t key_count = KV_KEY_SIZE; -#endif -#endif - // constant variables uint8_t xsm3_id_data_ms_controller[0x1D] = { 0x49, 0x4B, 0x00, 0x00, 0x17, 0x41, 0x41, 0x41, @@ -55,7 +45,7 @@ uint8_t xsm3_id_data_ms_controller[0x1D] = { 0x00, 0x00, 0x80, 0x02, 0x09, 0x12, 0x82, 0x28, 0x03, 0x00, 0x01, 0x01, 0x71}; -// constant variables (not exposed outside of this module) +// static global keys from the keyvault (shared across every retail system) static const uint8_t xsm3_key_0x1D[0x10] = { 0xE3, 0x5B, 0xFB, 0x1C, 0xCD, 0xAD, 0x32, 0x5B, 0xF7, 0x0E, 0x07, 0xFD, 0x62, 0x3D, 0xA7, 0xC4}; @@ -63,6 +53,15 @@ static const uint8_t xsm3_key_0x1E[0x10] = { 0x8F, 0x29, 0x08, 0x38, 0x0B, 0x5B, 0xFE, 0x68, 0x7C, 0x26, 0x46, 0x2A, 0x51, 0xF2, 0xBC, 0x19}; +// retail keys for generating 0x23/0x24 keys from console ID +static const uint8_t xsm3_root_key_0x23[0x10] = { + 0x82, 0x80, 0x78, 0x68, 0x3A, 0x52, 0x3A, 0x98, + 0x10, 0xF4, 0x0C, 0x12, 0x70, 0x66, 0xDC, 0xBA}; + +static const uint8_t xsm3_root_key_0x24[0x10] = { + 0x66, 0x62, 0x1A, 0x78, 0xF8, 0x60, 0x9C, 0x8A, + 0x26, 0x9A, 0x04, 0xAE, 0xD8, 0x5C, 0x1E, 0xC8}; + // response to give to the given challenge command uint8_t xsm3_challenge_response[0x30]; // console id fetched from challenge init packet @@ -116,7 +115,6 @@ static uint8_t xsm3_calculate_checksum(const uint8_t* packet) { } void xsm3_set_vid_pid(const uint8_t serial[0x0C], uint16_t vid, uint16_t pid) { - memcpy(xsm3_id_data_ms_controller + 6, serial, 0x0C); uint8_t* id_data = xsm3_id_data_ms_controller; // skip over the packet header @@ -160,10 +158,13 @@ void xsm3_set_identification_data(const uint8_t id_data[0x1D]) { memcpy(xsm3_identification_data + 0x16, id_data + 0x14, sizeof(unsigned short)); } -void xsm3_import_kv_keys(const uint8_t key1[0x10], const uint8_t key2[0x10]) { - // copy the provided keys into our buffers - memcpy(xsm3_kv_2des_key_1, key1, sizeof(xsm3_kv_2des_key_1)); - memcpy(xsm3_kv_2des_key_2, key2, sizeof(xsm3_kv_2des_key_2)); +void xsm3_generate_kv_keys(const uint8_t console_id[0x8]) { + // make a sha-1 hash of the console id + uint8_t console_id_hash[0x14]; + ExCryptSha(console_id, 0x8, NULL, 0, NULL, 0, console_id_hash, 0x14); + // encrypt it with the root keys for 1st party controllers + UsbdSecXSM3AuthenticationCrypt(xsm3_root_key_0x23, console_id_hash, 0x10, xsm3_kv_2des_key_1, 1); + UsbdSecXSM3AuthenticationCrypt(xsm3_root_key_0x24, console_id_hash + 0x4, 0x10, xsm3_kv_2des_key_2, 1); } void xsm3_do_challenge_init(uint8_t challenge_packet[0x22]) { @@ -188,17 +189,7 @@ void xsm3_do_challenge_init(uint8_t challenge_packet[0x22]) { if (memcmp(incoming_packet_mac + 4, challenge_packet + 0x5 + 0x18, 0x4) != 0) { XSM3_printf("[ MAC failed when validating challenge init! ]\n"); } -#ifdef KV_KEY_ARRAY - for (int i = 0; i < key_count; i++) { - uint8_t* keys = kv_keys + (i * (sizeof(xsm3_kv_2des_key_1) + sizeof(xsm3_kv_2des_key_2) + 5)); - if (memcmp(keys, xsm3_console_id, 5) == 0) { - memcpy(xsm3_kv_2des_key_1, keys + 5, sizeof(xsm3_kv_2des_key_1)); - memcpy(xsm3_kv_2des_key_2, keys + 5 + sizeof(xsm3_kv_2des_key_1), sizeof(xsm3_kv_2des_key_2)); - break; - } - } -#endif - // TODO: somehow..derive the kv keys from the console certificate + xsm3_generate_kv_keys(xsm3_console_id); // the random value is swapped at an 8 byte boundary memcpy(xsm3_random_console_data_swap, xsm3_random_console_data + 0x8, 0x8); diff --git a/src/shared/usb/xsm3/xsm3.h b/src/shared/usb/xsm3/xsm3.h index 9a78a3484..b4b0f6e90 100644 --- a/src/shared/usb/xsm3/xsm3.h +++ b/src/shared/usb/xsm3/xsm3.h @@ -41,9 +41,6 @@ void xsm3_initialise_state(); // Sets the identification data to use. void xsm3_set_identification_data(const uint8_t id_data[0x1D]); -// Imports the console-specific keys (GetKey index 0x23 and 0x24 for wired controllers) into the current state. -void xsm3_import_kv_keys(const uint8_t key1[0x10], const uint8_t key2[0x10]); - // Initialises the XSM3 state using information from the challenge init packet (0x82) and places a response in xsm3_challenge_response. void xsm3_do_challenge_init(uint8_t challenge_packet[0x22]); From b9511e3c3a688fb3ba85d734ae4a559d264aecb7 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 6 May 2025 17:27:54 +1200 Subject: [PATCH 020/239] Remove more passthrough auth code --- include/controllers.h | 2 -- src/pico/main.cpp | 21 --------------------- src/shared/controllers/controllers.c | 2 -- src/shared/main/shared_main.cpp | 27 --------------------------- src/shared/usb/descriptors.cpp | 6 +++--- 5 files changed, 3 insertions(+), 55 deletions(-) diff --git a/include/controllers.h b/include/controllers.h index fffed4061..f989fc037 100644 --- a/include/controllers.h +++ b/include/controllers.h @@ -6,8 +6,6 @@ extern Xbox_One_State_t xbox_one_state; // State of the Xbox 360 controller init extern Xbox_360_State_t xbox_360_state; -extern uint16_t xbox_360_vid; -extern uint16_t xbox_360_pid; // Used for passing authentication data between the console and authentication controller extern uint8_t data_from_console_size; diff --git a/src/pico/main.cpp b/src/pico/main.cpp index d5137f251..744014903 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -119,10 +119,6 @@ bool authDone = false; long test3 = 0; static void tick_usb() { #if USB_HOST_STACK - if (consoleType == XBOX360 && !foundXB && xboxAuthValid) { - tuh_task(); - return; - } if (consoleType == XBOXONE && !foundXB) { tuh_task(); return; @@ -142,14 +138,6 @@ static void tick_usb() { #ifdef INPUT_SERIAL_MIDI MIDI2.read(); #endif - if (!authDone) { - if (consoleType != XBOXONE && (consoleType != XBOX360 || !xboxAuthValid)) { - authReady = millis() > 1000; - } - if (authReady) { - authDone = true; - } - } } #if BLUETOOTH_RX void tick_bluetooth(const void *buf, uint8_t len, USB_Device_Type_t type) { @@ -340,15 +328,6 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ usb_host_devices[total_usb_host_devices].type = type; total_usb_host_devices++; xinput_controller_connected(host_vid, host_pid); - if (consoleType == XBOX360) { - foundXB = true; - // Reboot the controller and wait for auth - if (!xboxAuthValid) { - xboxAuthValid = true; - reset_usb(); - } - printf("found xb\r\n"); - } break; case XBOX360_W: x360_dev_addr = type; diff --git a/src/shared/controllers/controllers.c b/src/shared/controllers/controllers.c index 8a759e248..b11bc13ed 100644 --- a/src/shared/controllers/controllers.c +++ b/src/shared/controllers/controllers.c @@ -8,8 +8,6 @@ bool seen_ps4 = false; bool seen_rpcs3 = false; bool descriptor_requested = false; Xbox_One_State_t xbox_one_state = Announce; -uint16_t xbox_360_vid = ARDWIINO_VID; -uint16_t xbox_360_pid = ARDWIINO_PID; Xbox_360_State_t xbox_360_state = Auth1; uint8_t data_from_console_size = 0; uint8_t data_from_controller_size = 0; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 9c02ab20e..d2d3ba6df 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3243,33 +3243,6 @@ void receive_report_from_controller(uint8_t const *report, uint16_t len) { void xinput_controller_connected(uint16_t vid, uint16_t pid) { handle_player_leds(0); if (xbox_360_state == Authenticated) return; - xbox_360_vid = vid; - xbox_360_pid = pid; - // Using the skylander pid on a 360 results in it not being classed as a controller - // IDs from the xplorer auth just fine with the portals blobs however - if (xbox_360_vid == XBOX_REDOCTANE_VID && xbox_360_pid == 0x1f17) { - xbox_360_pid = 0x4748; - } - // Same thing with disney infinity portals and lego dimensions portals - if (xbox_360_vid == XBOX_POWERA_VID && (xbox_360_pid == 0xFA00 || xbox_360_pid == 0xFA01)) { - xbox_360_pid = 0x4748; - } - // Skylanders games require you use the portal vid and pid -#if DEVICE_TYPE == SKYLANDERS - if (xbox_360_vid == XBOX_REDOCTANE_VID) { - xbox_360_pid = 0x1f17; - } -#endif -#if DEVICE_TYPE == DISNEY_INFINITY - if (xbox_360_vid == XBOX_POWERA_VID) { - xbox_360_pid = 0xFA00; - } -#endif -#if DEVICE_TYPE == LEGO_DIMENSIONS - if (xbox_360_vid == XBOX_POWERA_VID) { - xbox_360_pid = 0xFA01; - } -#endif } void xinput_w_controller_connected() { diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index ee96eafeb..16b031db4 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -888,7 +888,7 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const case 0x81: uint8_t serial[0x0C]; read_serial(serial, sizeof(serial)); - xsm3_set_vid_pid(serial, xbox_360_vid, xbox_360_pid); + xsm3_set_vid_pid(serial, ARDWIINO_VID, ARDWIINO_PID); xsm3_initialise_state(); xsm3_set_identification_data(xsm3_id_data_ms_controller); memcpy(requestBuffer, xsm3_id_data_ms_controller, sizeof(xsm3_id_data_ms_controller)); @@ -1196,8 +1196,8 @@ uint16_t descriptorRequest(const uint16_t wValue, dev->idVendor = HORI_VID; dev->idProduct = HORI_POKKEN_TOURNAMENT_DX_PRO_PAD_PID; } else if (consoleType == XBOX360) { - dev->idVendor = xbox_360_vid; - dev->idProduct = xbox_360_pid; + dev->idVendor = ARDWIINO_VID; + dev->idProduct = ARDWIINO_PID; } else if (consoleType == OG_XBOX) { dev->idVendor = 0x045E; dev->idProduct = 0x0289; From f687012567880b4d949cd2b0c3cb7eb2c5c1ff0a Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 6 May 2025 20:54:23 +1200 Subject: [PATCH 021/239] fix xb1 controllers --- src/shared/main/shared_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index d2d3ba6df..42ab99884 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3546,7 +3546,7 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D } break; case XBOX_ONE_CONTROLLER_VID: - if (pid >= 0x02e0 && pid <= 0x02eF) { + if (pid >= 0x02e0 && pid <= 0x02eF && type->console_type != XBOXONE) { type->console_type = XINPUTCOMPAT; type->sub_type = GAMEPAD; break; From cac9cb90fb2f9df9e50e471701d699150d971152 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 6 May 2025 22:02:11 +1200 Subject: [PATCH 022/239] set lower poll rate for ds1 --- src/shared/main/ps2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/ps2.cpp b/src/shared/main/ps2.cpp index fc67e0f45..6d6043d16 100644 --- a/src/shared/main/ps2.cpp +++ b/src/shared/main/ps2.cpp @@ -177,7 +177,7 @@ extern unsigned long millis_at_boot; uint8_t *tickPS2() { uint8_t *in; // PS2 guitars die if you poll them too fast - if (ps2ControllerType == PSX_GUITAR_HERO_CONTROLLER && micros() - last < 3000) { + if ((ps2ControllerType == PSX_GUITAR_HERO_CONTROLLER || ps2ControllerType == PSX_DUALSHOCK_1_CONTROLLER) && micros() - last < 3000) { return inputBuffer; } // If this is changed to a different port, you can talk to different devices From f8fb4143fc82fb1f6f7d9b848e9ffe39c3621120 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 7 May 2025 10:22:16 +1200 Subject: [PATCH 023/239] delay console detection a touch on 360 --- include/controllers.h | 1 + src/shared/main/shared_main.cpp | 4 ++++ src/shared/usb/descriptors.cpp | 32 ++++++++++++++++++-------------- src/shared/usb/xsm3/xsm3.c | 4 ++-- 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/include/controllers.h b/include/controllers.h index f989fc037..b9747de33 100644 --- a/include/controllers.h +++ b/include/controllers.h @@ -6,6 +6,7 @@ extern Xbox_One_State_t xbox_one_state; // State of the Xbox 360 controller init extern Xbox_360_State_t xbox_360_state; +extern long reset_after_360; // Used for passing authentication data between the console and authentication controller extern uint8_t data_from_console_size; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 42ab99884..6cbd78660 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -512,6 +512,7 @@ int16_t handle_calibration_turntable_360(int16_t previous, int16_t orig_val, uin return previous; } uint16_t descriptor_index = 0; +long reset_after_360 = 0; uint8_t tick_xbox_one() { uint32_t serial = micros(); switch (xbox_one_state) { @@ -3033,6 +3034,9 @@ void tick(void) { #ifdef TICK_LED_BLUETOOTH TICK_LED_BLUETOOTH; #endif + if (reset_after_360 && millis() > reset_after_360) { + reset_usb(); + } // Only sleep if the timeout has passed and we aren't connected over USB if (SLEEP_PIN != -1 && SLEEP_INACTIVITY_TIMEOUT_MS && millis() - lastInputActivity >= SLEEP_INACTIVITY_TIMEOUT_MS && !usb_configured()) { go_to_sleep(); diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 16b031db4..406e72f5a 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -709,13 +709,13 @@ const PROGMEM uint8_t ps3_feature_f8[] = { // Gyro and accel calibration are in here somewhere! const PROGMEM uint8_t ps3_feature_ef[] = { - 0x00, 0xef, 0x04, 0x00, 0x05, 0x03, 0x01, 0xb0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, - 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xef, 0x04, 0x00, 0x05, 0x03, 0x01, 0xb0, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x03, + 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const PROGMEM uint8_t ps4_feature_config[] = { @@ -820,7 +820,7 @@ uint8_t ps3_id_id = 4; bool cleared_input = false; bool cleared_output = false; uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, uint8_t *requestBuffer, bool *status) { - // printf("%02x %04x %04x %04x %04x\r\n", requestType, request, wValue, wIndex, wLength); + printf("%02x %04x %04x %04x %04x\r\n", requestType, request, wValue, wIndex, wLength); #if DEVICE_TYPE_IS_GAMEPAD if (consoleType != OG_XBOX && requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && request == 6 && wValue == 0x4200) { consoleType = OG_XBOX; @@ -843,7 +843,7 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const } #endif - if (consoleType == XBOX360 && requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && request == 0x83) { + if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && request == 0x83) { if (xbox_360_state == Auth1) { xbox_360_state = Auth2; } else if (xbox_360_state == Auth2) { @@ -851,6 +851,10 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const } else if (xbox_360_state == Auth3) { xbox_360_state = Authenticated; handle_auth_led(); + if (consoleType != XBOX360) { + consoleType = XBOX360; + reset_after_360 = millis() + 100; + } } } if (seen_windows_xb1 && !(requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_VENDOR) && request == REQ_GET_OS_FEATURE_DESCRIPTOR && wIndex == DESC_EXTENDED_COMPATIBLE_ID_DESCRIPTOR)) { @@ -878,11 +882,6 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const } #if DEVICE_TYPE_IS_GAMEPAD - if (consoleType == UNIVERSAL && requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && request == 0x81) { - consoleType = XBOX360; - reset_usb(); - return 0; - } #if SUPPORTS_PICO switch (request) { case 0x81: @@ -910,6 +909,11 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const return sizeof(state); } #else + if (consoleType == UNIVERSAL && requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && request == 0x81) { + consoleType = XBOX360; + reset_usb(); + return 0; + } switch (request) { case 0x81: case 0x82: diff --git a/src/shared/usb/xsm3/xsm3.c b/src/shared/usb/xsm3/xsm3.c index 71140ec46..277c1deb5 100644 --- a/src/shared/usb/xsm3/xsm3.c +++ b/src/shared/usb/xsm3/xsm3.c @@ -18,7 +18,7 @@ */ #include "xsm3.h" - +#include "Arduino.h" #include #include #include @@ -116,6 +116,7 @@ static uint8_t xsm3_calculate_checksum(const uint8_t* packet) { void xsm3_set_vid_pid(const uint8_t serial[0x0C], uint16_t vid, uint16_t pid) { memcpy(xsm3_id_data_ms_controller + 6, serial, 0x0C); + xsm3_id_data_ms_controller[6] = micros(); uint8_t* id_data = xsm3_id_data_ms_controller; // skip over the packet header id_data += 0x5; @@ -166,7 +167,6 @@ void xsm3_generate_kv_keys(const uint8_t console_id[0x8]) { UsbdSecXSM3AuthenticationCrypt(xsm3_root_key_0x23, console_id_hash, 0x10, xsm3_kv_2des_key_1, 1); UsbdSecXSM3AuthenticationCrypt(xsm3_root_key_0x24, console_id_hash + 0x4, 0x10, xsm3_kv_2des_key_2, 1); } - void xsm3_do_challenge_init(uint8_t challenge_packet[0x22]) { uint8_t incoming_packet_mac[0x8]; uint8_t response_packet_mac[0x8]; From 1428024cbdb771a365c51ed36fd3d5b1911e6f78 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 7 May 2025 21:39:56 +1200 Subject: [PATCH 024/239] support waking up an xbox 360 --- include/io.h | 1 + src/avr/shared/io.cpp | 3 +++ src/pico/main.cpp | 27 +++++++++++++++++++++++---- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/include/io.h b/include/io.h index 0831cfc5f..faefcf9f5 100644 --- a/include/io.h +++ b/include/io.h @@ -32,6 +32,7 @@ void spi_high(SPI_BLOCK block); void init_ack(); void init_att(); void go_to_sleep(); +void wakeup_360(); void read_serial(uint8_t* id, uint8_t len); extern volatile bool spi_acknowledged; #ifdef INPUT_WT_NECK diff --git a/src/avr/shared/io.cpp b/src/avr/shared/io.cpp index f1a6f1bbf..aaa25d107 100644 --- a/src/avr/shared/io.cpp +++ b/src/avr/shared/io.cpp @@ -577,4 +577,7 @@ void read_serial(uint8_t *id, uint8_t len) { } void go_to_sleep() { // TODO: sleep is current pico only. +} +void wakeup_360() { + // TODO: waking up the 360 is pico only. } \ No newline at end of file diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 744014903..a09551027 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -49,7 +49,6 @@ static uint32_t __uninitialized_ram(windows_in_hid); static uint32_t __uninitialized_ram(persistedConsoleTypeValid); static uint32_t __uninitialized_ram(xboxAuthValid); static uint32_t __uninitialized_ram(pico_is_sleeping); -bool connected = false; #if USB_HOST_STACK USB_Device_Type_t xone_dev_addr = {}; USB_Device_Type_t x360_dev_addr = {}; @@ -107,7 +106,7 @@ bool ready_for_next_packet() { } bool usb_configured() { - return connected; + return tud_mounted(); } void send_report_to_pc(const void *report, uint8_t len) { @@ -160,6 +159,27 @@ void go_to_sleep() { reset_usb(); } +void wakeup_360() { + if (tud_mounted()) { + return; + } + // the 360 will wake up the console if it sees the data lines being driven high and low constantly + // save the previous usb state + uint32_t prev_direct = usb_hw->phy_direct; + uint32_t prev_direct_override = usb_hw->phy_direct_override; + // drive both pins high + hw_set_bits(&usb_hw->phy_direct_override, USB_USBPHY_DIRECT_OVERRIDE_TX_DM_OE_OVERRIDE_EN_BITS | USB_USBPHY_DIRECT_OVERRIDE_TX_DM_OVERRIDE_EN_BITS | + USB_USBPHY_DIRECT_OVERRIDE_TX_DP_OE_OVERRIDE_EN_BITS | USB_USBPHY_DIRECT_OVERRIDE_TX_DP_OVERRIDE_EN_BITS | USB_USBPHY_DIRECT_OVERRIDE_TX_DIFFMODE_OVERRIDE_EN_BITS); + hw_set_bits(&usb_hw->phy_direct, USB_USBPHY_DIRECT_TX_DM_OE_BITS | USB_USBPHY_DIRECT_TX_DP_OE_BITS | USB_USBPHY_DIRECT_TX_DIFFMODE_BITS); + hw_clear_bits(&usb_hw->phy_direct, USB_USBPHY_DIRECT_TX_DIFFMODE_BITS); + hw_set_bits(&usb_hw->phy_direct, USB_USBPHY_DIRECT_TX_DP_BITS | USB_USBPHY_DIRECT_TX_DM_BITS); + // wait a bit + sleep_ms(50); + // revert the pin state + usb_hw->phy_direct = prev_direct; + usb_hw->phy_direct_override = prev_direct_override; +} + void setup() { #if USB_HOST_STACK set_sys_clock_khz(120000, true); @@ -276,9 +296,8 @@ void send_report_to_controller(uint8_t dev_addr, uint8_t instance, const uint8_t tuh_xinput_send_report(dev_addr, instance, report, len); } } -void tud_mount_cb(void) { +extern "C" void tud_mount_cb(void) { device_reset(); - connected = true; } #if USB_HOST_STACK uint8_t get_usb_host_device_count() { From ee4d1be23f8e7354b5f5c5edf87f65b1f26621c3 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 8 May 2025 09:27:09 +1200 Subject: [PATCH 025/239] support waking up an xbox 360 --- src/pico/main.cpp | 27 ++++++++++++++++----------- src/shared/main/shared_main.cpp | 5 +++-- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index a09551027..4fcdb626f 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -167,17 +167,22 @@ void wakeup_360() { // save the previous usb state uint32_t prev_direct = usb_hw->phy_direct; uint32_t prev_direct_override = usb_hw->phy_direct_override; - // drive both pins high - hw_set_bits(&usb_hw->phy_direct_override, USB_USBPHY_DIRECT_OVERRIDE_TX_DM_OE_OVERRIDE_EN_BITS | USB_USBPHY_DIRECT_OVERRIDE_TX_DM_OVERRIDE_EN_BITS | - USB_USBPHY_DIRECT_OVERRIDE_TX_DP_OE_OVERRIDE_EN_BITS | USB_USBPHY_DIRECT_OVERRIDE_TX_DP_OVERRIDE_EN_BITS | USB_USBPHY_DIRECT_OVERRIDE_TX_DIFFMODE_OVERRIDE_EN_BITS); - hw_set_bits(&usb_hw->phy_direct, USB_USBPHY_DIRECT_TX_DM_OE_BITS | USB_USBPHY_DIRECT_TX_DP_OE_BITS | USB_USBPHY_DIRECT_TX_DIFFMODE_BITS); - hw_clear_bits(&usb_hw->phy_direct, USB_USBPHY_DIRECT_TX_DIFFMODE_BITS); - hw_set_bits(&usb_hw->phy_direct, USB_USBPHY_DIRECT_TX_DP_BITS | USB_USBPHY_DIRECT_TX_DM_BITS); - // wait a bit - sleep_ms(50); - // revert the pin state - usb_hw->phy_direct = prev_direct; - usb_hw->phy_direct_override = prev_direct_override; + for (int i = 0; i < 2; i++) { + // drive both pins high + hw_set_bits(&usb_hw->phy_direct_override, USB_USBPHY_DIRECT_OVERRIDE_TX_DM_OE_OVERRIDE_EN_BITS | USB_USBPHY_DIRECT_OVERRIDE_TX_DM_OVERRIDE_EN_BITS | + USB_USBPHY_DIRECT_OVERRIDE_TX_DP_OE_OVERRIDE_EN_BITS | USB_USBPHY_DIRECT_OVERRIDE_TX_DP_OVERRIDE_EN_BITS | USB_USBPHY_DIRECT_OVERRIDE_TX_DIFFMODE_OVERRIDE_EN_BITS); + hw_set_bits(&usb_hw->phy_direct, USB_USBPHY_DIRECT_TX_DM_OE_BITS | USB_USBPHY_DIRECT_TX_DP_OE_BITS | USB_USBPHY_DIRECT_TX_DIFFMODE_BITS); + hw_clear_bits(&usb_hw->phy_direct, USB_USBPHY_DIRECT_TX_DIFFMODE_BITS); + hw_set_bits(&usb_hw->phy_direct, USB_USBPHY_DIRECT_TX_DP_BITS | USB_USBPHY_DIRECT_TX_DM_BITS); + // wait a bit + sleep_ms(1); + // revert the pin state + usb_hw->phy_direct = prev_direct; + usb_hw->phy_direct_override = prev_direct_override; + sleep_ms(1000); + } + // Reset the pico just to make sure any other state is reset in case this was triggered by usb host + reset_usb(); } void setup() { diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 6cbd78660..9220624d9 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3139,8 +3139,9 @@ void tick(void) { } last_poll = micros(); - // Tick the controller every 5ms if this device is connected to a usb port and usb is not ready - if (!INPUT_QUEUE && !ready && usb_configured() && millis() - lastSentPacket >= 5) { + // Tick the controller every 5ms if usb is not ready + // This is also used for waking up the 360, so it needs to happen even if usb isnt ready + if (!INPUT_QUEUE && !ready && millis() - lastSentPacket >= 5) { lastSentPacket = millis(); tick_inputs(NULL, NULL, consoleType); } From 2f2ca7056cb8731b1b11d2b2b267c8dd93ad88f9 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 8 May 2025 09:56:13 +1200 Subject: [PATCH 026/239] support waking up an xbox 360 --- src/pico/main.cpp | 4 ++-- src/shared/main/shared_main.cpp | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 4fcdb626f..3b5f7ba0c 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -106,7 +106,7 @@ bool ready_for_next_packet() { } bool usb_configured() { - return tud_mounted(); + return tud_ready(); } void send_report_to_pc(const void *report, uint8_t len) { @@ -160,7 +160,7 @@ void go_to_sleep() { } void wakeup_360() { - if (tud_mounted()) { + if (usb_configured()) { return; } // the 360 will wake up the console if it sees the data lines being driven high and low constantly diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 9220624d9..fc7c5cd1c 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3042,8 +3042,9 @@ void tick(void) { go_to_sleep(); } - // Tick inputs constantly for detection - if ((millis() - input_start) < 2000) { + // Tick inputs constantly for detection for 2 seconds + // Tick inputs constantly for xbox 360 wakeup if usb isnt configured + if ((millis() - input_start) < 2000 || !usb_configured()) { tick_inputs(NULL, NULL, consoleType); } #if DEVICE_TYPE != ROCK_BAND_PRO_KEYS @@ -3139,9 +3140,8 @@ void tick(void) { } last_poll = micros(); - // Tick the controller every 5ms if usb is not ready - // This is also used for waking up the 360, so it needs to happen even if usb isnt ready - if (!INPUT_QUEUE && !ready && millis() - lastSentPacket >= 5) { + // Tick the controller every 5ms if this device is connected to a usb port and usb is not ready + if (!INPUT_QUEUE && !ready && usb_configured() && millis() - lastSentPacket >= 5) { lastSentPacket = millis(); tick_inputs(NULL, NULL, consoleType); } From 9e634e0f86f344eedf8ab0b4e24360bb038a2947 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 11 May 2025 13:03:42 +1200 Subject: [PATCH 027/239] simplify 6kro code gen --- src/shared/main/shared_main.cpp | 24 +++++++++++------------- src/shared/usb/descriptors.cpp | 2 +- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index fc7c5cd1c..9b9300774 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -236,21 +236,19 @@ uint8_t gh5_mapping[] = { 0xAE, 0xAC, 0xFF, 0xFB, 0xFD, 0xF9, 0xFE, 0xFA, 0xFC, 0xF8, 0xE6, 0xE2, 0xE4, 0xE0, 0xE5, 0xE1, 0xE3, 0xDF}; -void setKey(uint8_t id, uint8_t key, USB_6KRO_Data_t *report, bool state) { - if (state) { - for (size_t i = 0; i < 6; i++) { - if (report->KeyCode[i] == key) { - return; - } - if (!report->KeyCode[i]) { - report->KeyCode[i] = key; - return; - } +void setKey(uint8_t id, uint8_t key, USB_6KRO_Data_t *report) { + for (size_t i = 0; i < 6; i++) { + if (report->KeyCode[i] == key) { + return; + } + if (!report->KeyCode[i]) { + report->KeyCode[i] = key; + return; } - // Too many buttons - flag the overflow condition and clear all key indexes - memset(report->KeyCode, KEY_ERR_OVF, sizeof(report->KeyCode)); - return; } + // Too many buttons - flag the overflow condition and clear all key indexes + memset(report->KeyCode, KEY_ERR_OVF, sizeof(report->KeyCode)); + return; } uint8_t seq = 1; void init_main(void) { diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 406e72f5a..d87a2a40c 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -820,7 +820,7 @@ uint8_t ps3_id_id = 4; bool cleared_input = false; bool cleared_output = false; uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, uint8_t *requestBuffer, bool *status) { - printf("%02x %04x %04x %04x %04x\r\n", requestType, request, wValue, wIndex, wLength); + // printf("%02x %04x %04x %04x %04x\r\n", requestType, request, wValue, wIndex, wLength); #if DEVICE_TYPE_IS_GAMEPAD if (consoleType != OG_XBOX && requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && request == 6 && wValue == 0x4200) { consoleType = OG_XBOX; From 635d3588acc0a6dc9a5ce9919a3255469d7ef903 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 14 May 2025 11:33:52 +1200 Subject: [PATCH 028/239] change ps4 reports to their usb ones --- include/reports/ps4_reports.h | 14 +++++++++----- src/shared/main/shared_main.cpp | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/include/reports/ps4_reports.h b/include/reports/ps4_reports.h index 3911349ee..457c41bec 100644 --- a/include/reports/ps4_reports.h +++ b/include/reports/ps4_reports.h @@ -154,11 +154,12 @@ typedef struct uint8_t soloBlue : 1; uint8_t soloOrange : 1; uint8_t : 3; - - uint8_t unused4[26]; - uint32_t crc32; + uint8_t unused4[16]; + // uint8_t unused4[26]; - bluetooth + // uint32_t crc32; } __attribute__((packed)) PS4RockBandGuitar_Data_t; + typedef struct { uint8_t reportId; @@ -207,8 +208,11 @@ typedef struct uint8_t blueCymbalVelocity; uint8_t greenCymbalVelocity; - uint8_t unused4[24]; - uint32_t crc32; + // uint8_t unused4[24]; + // uint32_t crc32; + uint8_t unused4[14]; + // uint8_t unused4[24]; - bluetooth + // uint32_t crc32; } __attribute__((packed)) PS4RockBandDrums_Data_t; typedef struct { diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 9b9300774..5cfc9f3b8 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2585,7 +2585,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu // Guitars and Drums can fall back to their PS3 versions, so don't even include the PS4 version there. // DJ Hero was never on ps4, so we can't really implement that either, so just fall back to PS3 there too. #if SUPPORTS_PS4 - if (output_console_type == PS4 || output_console_type == IOS_FESTIVAL) { + if (output_console_type == PS4) { if (millis() > 450000 && !auth_ps4_controller_found) { reset_usb(); } From 557be10dcffbdd94299cc697a279e6fb835b0391 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 14 May 2025 15:24:20 +1200 Subject: [PATCH 029/239] disable more drum midi code for non drums --- src/shared/main/shared_main.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 5cfc9f3b8..17772b9c7 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -60,16 +60,24 @@ void onNote(uint8_t channel, uint8_t note, uint8_t velocity) { // velocities are 7 bit // printf("Note ON ch=%d, note=%d, vel=%d\r\n", channel, note, velocity); velocity = velocity << 1; +#if DEVICE_TYPE_IS_DRUM + // drums, base inputs on triggers if (velocity > midiData.midiVelocitiesTemp[note]) { midiData.midiVelocities[note] = velocity; midiData.midiVelocitiesTemp[note] = velocity; } +#else + // Handle midi normally + midiData.midiVelocities[note] = velocity; + midiData.midiVelocitiesTemp[note] = velocity; +#endif lastMidi = millis(); } void offNote(uint8_t channel, uint8_t note, uint8_t velocity) { // printf("Note OFF ch=%d, note=%d, vel=%d\r\n", channel, note, velocity); -#if DEVICE_TYPE == ROCK_BAND_PRO_KEYS + // ignore note off for drums as we handle that ourselves +#if !(DEVICE_TYPE_IS_DRUM) midiData.midiVelocities[note] = 0; midiData.midiVelocitiesTemp[note] = 0; #endif From bb3ad1643ad36424f3ddd3e4491157f0c5e46006 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 14 May 2025 15:24:45 +1200 Subject: [PATCH 030/239] disable more drum midi code for non drums --- src/shared/main/shared_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 17772b9c7..5cf6a9c9e 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -76,7 +76,7 @@ void onNote(uint8_t channel, uint8_t note, uint8_t velocity) { void offNote(uint8_t channel, uint8_t note, uint8_t velocity) { // printf("Note OFF ch=%d, note=%d, vel=%d\r\n", channel, note, velocity); - // ignore note off for drums as we handle that ourselves + // ignore note off for drums as we handle that ourselves, and not all drums send it #if !(DEVICE_TYPE_IS_DRUM) midiData.midiVelocities[note] = 0; midiData.midiVelocitiesTemp[note] = 0; From 33f5a95d7ccbe9a26cece88b6b30a036cd0c1685 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 17 May 2025 11:54:53 +1200 Subject: [PATCH 031/239] add vid and pid for ghl ps4 --- include/config.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/config.h b/include/config.h index 190a6dfe8..dc0180a08 100644 --- a/include/config.h +++ b/include/config.h @@ -540,18 +540,26 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define XBOX_ONE_VID XBOX_ONE_GHLIVE_DONGLE_VID #define XBOX_ONE_PID XBOX_ONE_GHLIVE_DONGLE_PID #define XBOX_ONE_DESCRIPTOR_SIZE 329 +#define PS4_VID XBOX_REDOCTANE_VID +#define PS4_PID PS4_GHLIVE_DONGLE_PID #elif DEVICE_TYPE == SKYLANDERS #define XBOX_ONE_VID XBOX_ONE_GHLIVE_DONGLE_VID #define XBOX_ONE_PID XBOX_ONE_GHLIVE_DONGLE_PID #define XBOX_ONE_DESCRIPTOR_SIZE 168 +#define PS4_VID 0x03EB +#define PS4_PID 0x2043 #elif DEVICE_TYPE == DISNEY_INFINITY #define XBOX_ONE_VID XBOX_ONE_GHLIVE_DONGLE_VID #define XBOX_ONE_PID XBOX_ONE_GHLIVE_DONGLE_PID #define XBOX_ONE_DESCRIPTOR_SIZE 96 +#define PS4_VID 0x03EB +#define PS4_PID 0x2043 #elif DEVICE_TYPE == LEGO_DIMENSIONS #define XBOX_ONE_VID XBOX_ONE_GHLIVE_DONGLE_VID #define XBOX_ONE_PID XBOX_ONE_GHLIVE_DONGLE_PID #define XBOX_ONE_DESCRIPTOR_SIZE 166 +#define PS4_VID 0x03EB +#define PS4_PID 0x2043 #else #define XBOX_ONE_VID XBOX_ONE_CONTROLLER_VID #define XBOX_ONE_PID XBOX_ONE_CONTROLLER_PID From 884281dd93372e6be01d9b9c65fac675aa9a9f87 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 26 May 2025 11:23:58 +1200 Subject: [PATCH 032/239] remove dependancy on platformio lib --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index c7e1dab53..1ce96c8bc 100644 --- a/platformio.ini +++ b/platformio.ini @@ -261,7 +261,7 @@ build_src_filter = + lib_deps = https://github.com/Santroller/USB_Host_Shield_2.0/archive/refs/heads/master.zip@1.6.3 - fortyseveneffects/MIDI Library@5.0.2 + https://github.com/FortySevenEffects/arduino_midi_library/archive/refs/tags/5.0.2.zip@5.0.2 SPI [pico] extends = pico_parent From d26f4cecf57a18c9848e9e5d55b7d4ec2fc17cce Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 30 May 2025 18:43:52 +1200 Subject: [PATCH 033/239] fix ps3 usb host whammy --- src/shared/main/shared_main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 5cf6a9c9e..eea70f3e6 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1117,7 +1117,7 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->soloOrange |= report->leftShoulder; } if (report->whammy) { - usb_host_data->whammy = report->whammy; + usb_host_data->whammy = (report->whammy - PS3_STICK_CENTER) << 1; } if (report->pickup) { usb_host_data->pickup = report->pickup; @@ -1148,7 +1148,7 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->tilt = (report->tilt - PS3_ACCEL_CENTER) << 6; } if (report->whammy) { - usb_host_data->whammy = report->whammy; + usb_host_data->whammy = (report->whammy - PS3_STICK_CENTER) << 1; } // Detect GH5 vs WT. Wait for a neutral input, then use that to detect instrument type if (device_type.sub_type == GUITAR_HERO_GUITAR_WT) { @@ -1244,7 +1244,7 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->tilt = (report->tilt - PS3_ACCEL_CENTER) << 6; } if (report->whammy) { - usb_host_data->whammy = report->whammy << 8; + usb_host_data->whammy = (report->whammy - PS3_STICK_CENTER) << 1; } break; } From 3817ead77131104da4733fb223bffb6b8c72f231 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 6 Jun 2025 16:12:53 +1200 Subject: [PATCH 034/239] work on gharcade, poll wii instruments every 1ms --- include/defines.h | 1 + include/descriptors.h | 13 +++- include/hid.h | 1 + include/reports/pc_reports.h | 19 ++++++ include/string_descriptors.h | 1 + src/pico/main.cpp | 1 + src/pico/xinput_device.cpp | 17 +++-- src/shared/hid/ps3_wii_switch.h | 44 +++++++++++++ src/shared/main/shared_main.cpp | 8 +-- src/shared/main/wii.cpp | 2 +- src/shared/usb/descriptors.cpp | 97 ++++++++++++++++++++++++++++- src/shared/usb/string_descriptors.c | 3 + 12 files changed, 193 insertions(+), 14 deletions(-) diff --git a/include/defines.h b/include/defines.h index b31ab2ab5..3fdf5118d 100644 --- a/include/defines.h +++ b/include/defines.h @@ -65,6 +65,7 @@ #define SKYLANDERS 22 #define LEGO_DIMENSIONS 23 #define TAIKO 24 +#define ARCADE 25 #define UNIVERSAL 0 #define XBOX360 1 diff --git a/include/descriptors.h b/include/descriptors.h index 6e2658941..57a1a0b26 100644 --- a/include/descriptors.h +++ b/include/descriptors.h @@ -27,7 +27,6 @@ #define ENDPOINT_USAGE_FEEDBACK (1 << 4) #define ENDPOINT_USAGE_IMPLICIT_FEEDBACK (2 << 4) - typedef struct { USB_CONFIGURATION_DESCRIPTOR Config; USB_INTERFACE_DESCRIPTOR InterfaceGamepad; @@ -72,6 +71,18 @@ typedef struct { USB_ENDPOINT_DESCRIPTOR ReportOUTEndpoint12; } __attribute__((packed)) OG_XBOX_CONFIGURATION_DESCRIPTOR; +typedef struct { + USB_CONFIGURATION_DESCRIPTOR Config; + uint8_t UnknownDescriptor1[3]; + USB_INTERFACE_DESCRIPTOR InterfaceHID; + USB_HID_DESCRIPTOR HIDDescriptor; + USB_ENDPOINT_DESCRIPTOR EndpointInHID; + USB_INTERFACE_DESCRIPTOR InterfaceVendor; + USB_ENDPOINT_DESCRIPTOR ReportINEndpoint21; + USB_ENDPOINT_DESCRIPTOR ReportOUTEndpoint22; + USB_ENDPOINT_DESCRIPTOR ReportINEndpoint23; +} __attribute__((packed)) GH_ARCADE_CONFIGURATION_DESCRIPTOR; + typedef struct { USB_CONFIGURATION_DESCRIPTOR Config; USB_INTERFACE_DESCRIPTOR InterfaceHID; diff --git a/include/hid.h b/include/hid.h index 988c7302b..ecd2d2663 100644 --- a/include/hid.h +++ b/include/hid.h @@ -77,6 +77,7 @@ extern const uint8_t keyboard_mouse_descriptor[NKRO_SIZE + SIXKRO_SIZE + CONSUMER_SIZE + MOUSE_SIZE]; extern const uint8_t ps3_descriptor[148]; extern const uint8_t ps3_instrument_descriptor[137]; +extern const uint8_t gha_descriptor[83]; extern const uint8_t ps4_descriptor[160]; extern const uint8_t fnf_descriptor[53]; extern long last_strobe; diff --git a/include/reports/pc_reports.h b/include/reports/pc_reports.h index 65602f23a..c5b60e7e1 100644 --- a/include/reports/pc_reports.h +++ b/include/reports/pc_reports.h @@ -182,6 +182,25 @@ typedef struct uint8_t tilt; } __attribute__((packed)) PCGuitarHeroGuitar_Data_t; +typedef struct +{ + uint8_t report_id; // Always 0x1d + uint8_t tilt; + uint8_t accel_y; + uint8_t padding; // Always 0xFF + uint8_t accel_z; + + + uint8_t dpad : 4; + uint8_t a : 1; // cross, green + uint8_t b : 1; // circle, red + uint8_t x : 1; // square, blue + uint8_t y : 1; // triangle, yellow + + uint8_t leftShoulder : 1; // orange, l1 + uint8_t : 7; +} __attribute__((packed)) ArcadeGuitarHeroGuitar_Data_t; + // Festivals default mappings suck, so its easiest to set up custom mappings for that here typedef struct { diff --git a/include/string_descriptors.h b/include/string_descriptors.h index f66d061e3..0de4af33b 100644 --- a/include/string_descriptors.h +++ b/include/string_descriptors.h @@ -44,6 +44,7 @@ extern const PROGMEM STRING_DESCRIPTOR xboxString; extern const PROGMEM STRING_DESCRIPTOR languageString; extern const PROGMEM STRING_DESCRIPTOR manufacturerString; extern const PROGMEM STRING_DESCRIPTOR productString; +extern const PROGMEM STRING_DESCRIPTOR rtString; #ifdef __cplusplus } #endif diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 3b5f7ba0c..5abe67c26 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -214,6 +214,7 @@ void setup() { xboxAuthValid = false; consoleType = UNIVERSAL; } + // consoleType = ARCADE; generateSerialString(&serialstring, consoleType); printf("ConsoleType: %d\r\n", consoleType); init_main(); diff --git a/src/pico/xinput_device.cpp b/src/pico/xinput_device.cpp index 78d8eb7b6..4307a38c6 100644 --- a/src/pico/xinput_device.cpp +++ b/src/pico/xinput_device.cpp @@ -121,10 +121,18 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, } TU_VERIFY(p_xinput, 0); uint8_t const *p_desc = (uint8_t const *)itf_desc; - if (itf_desc->bInterfaceSubClass == 0x5D && - (itf_desc->bInterfaceProtocol == 0x01 || - itf_desc->bInterfaceProtocol == 0x03 || - itf_desc->bInterfaceProtocol == 0x02)) { + + if (itf_desc->bInterfaceSubClass == 0x00 && itf_desc->bInterfaceProtocol == 0xFF) { + p_desc = tu_desc_next(p_desc); + TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, itf_desc->bNumEndpoints, + TUSB_XFER_INTERRUPT, &p_xinput->ep_out, + &p_xinput->ep_in), + 0); + return drv_len; + } else if (itf_desc->bInterfaceSubClass == 0x5D && + (itf_desc->bInterfaceProtocol == 0x01 || + itf_desc->bInterfaceProtocol == 0x03 || + itf_desc->bInterfaceProtocol == 0x02)) { // Xinput reserved endpoint //-------------- Xinput Descriptor --------------// p_desc = tu_desc_next(p_desc); @@ -171,7 +179,6 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, } } } else if (0x58 == itf_desc->bInterfaceClass) { - // len = interface + n*endpoints drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t); TU_ASSERT(max_len >= drv_len, 0); diff --git a/src/shared/hid/ps3_wii_switch.h b/src/shared/hid/ps3_wii_switch.h index 3d144c220..1de50ba61 100644 --- a/src/shared/hid/ps3_wii_switch.h +++ b/src/shared/hid/ps3_wii_switch.h @@ -2,6 +2,50 @@ #include "config.h" #include "progmem.h" +const uint8_t PROGMEM gha_descriptor[] = { + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x04, // Usage (Joystick) + 0xA1, 0x01, // Collection (Application) + 0x09, 0x01, // Usage (Pointer) + 0xA1, 0x00, // Collection (Physical) + 0x09, 0x30, // Usage (X) + 0x25, 0x7F, // Logical Maximum (127) + 0x35, 0x00, // Physical Minimum (0) + 0x45, 0x00, // Physical Maximum (0) + 0x65, 0x00, // Unit (None) + 0x55, 0x00, // Unit Exponent (0) + 0x75, 0x08, // Report Size (8) + 0x95, 0x01, // Report Count (1) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x09, 0x31, // Usage (Y) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x09, 0x32, // Usage (Z) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x09, 0x33, // Usage (Rx) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x09, 0x34, // Usage (Ry) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0xC0, // End Collection + 0x09, 0x39, // Usage (Hat switch) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x03, // Logical Maximum (3) + 0x46, 0x0E, 0x01, // Physical Maximum (270) + 0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter) + 0x75, 0x04, // Report Size (4) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x01, // Usage Minimum (0x01) + 0x29, 0x0A, // Usage Maximum (0x0A) + 0x25, 0x01, // Logical Maximum (1) + 0x45, 0x01, // Physical Maximum (1) + 0x65, 0x00, // Unit (None) + 0x75, 0x01, // Report Size (1) + 0x95, 0x0A, // Report Count (10) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x95, 0x02, // Report Count (2) + 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0xC0, // End Collection +}; const uint8_t PROGMEM ps3_instrument_descriptor[] = { 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x05, // Usage (Game Pad) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index eea70f3e6..8f4d68a0f 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2760,7 +2760,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu if (output_console_type != OG_XBOX && output_console_type != WINDOWS && output_console_type != XBOX360 && output_console_type != PS3 && output_console_type != BLUETOOTH_REPORT && output_console_type != UNIVERSAL && output_console_type != XBOXONE && output_console_type != PS4) { #else // For instruments, we instead use the below block, as all other console types use the below format - if ((output_console_type != OG_XBOX && output_console_type != WINDOWS && output_console_type != KEYBOARD_MOUSE && output_console_type != IOS_FESTIVAL && output_console_type != FNF && output_console_type != XBOX360 && output_console_type != PS4 && output_console_type != BLUETOOTH_REPORT && output_console_type != UNIVERSAL && output_console_type != XBOXONE) || updateHIDSequence) { + if ((output_console_type != OG_XBOX && output_console_type != ARCADE && output_console_type != WINDOWS && output_console_type != KEYBOARD_MOUSE && output_console_type != IOS_FESTIVAL && output_console_type != FNF && output_console_type != XBOX360 && output_console_type != PS4 && output_console_type != BLUETOOTH_REPORT && output_console_type != UNIVERSAL && output_console_type != XBOXONE) || updateHIDSequence) { #endif report_size = sizeof(PS3_REPORT); // Do NOT update the size for XBONE, since the XBONE packets have a totally different size! @@ -2883,7 +2883,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } TICK_RESET // Some hosts want packets sent every frame - if (last_report && output_console_type != OG_XBOX && output_console_type != PS4 && output_console_type != IOS_FESTIVAL && output_console_type != PS3 && output_console_type != BLUETOOTH_REPORT && output_console_type != XBOX360 && !updateHIDSequence) { + if (last_report && output_console_type != ARCADE && output_console_type != OG_XBOX && output_console_type != PS4 && output_console_type != IOS_FESTIVAL && output_console_type != PS3 && output_console_type != BLUETOOTH_REPORT && output_console_type != XBOX360 && !updateHIDSequence) { uint8_t cmp = memcmp(last_report, report_data, report_size); if (cmp == 0) { return 0; @@ -3146,8 +3146,8 @@ void tick(void) { } last_poll = micros(); - // Tick the controller every 5ms if this device is connected to a usb port and usb is not ready - if (!INPUT_QUEUE && !ready && usb_configured() && millis() - lastSentPacket >= 5) { + // Tick the controller every 1ms if this device is connected to a usb port and usb is not ready + if (!INPUT_QUEUE && !ready && usb_configured() && millis() - lastSentPacket >= 1) { lastSentPacket = millis(); tick_inputs(NULL, NULL, consoleType); } diff --git a/src/shared/main/wii.cpp b/src/shared/main/wii.cpp index 5d7942405..bb00c3f89 100644 --- a/src/shared/main/wii.cpp +++ b/src/shared/main/wii.cpp @@ -172,7 +172,7 @@ uint8_t* tickWii() { ((data[3] & (0b11100000)) >> 1)); uint8_t note = (data[2] >> 1) & 0x7f; uint8_t channel = ((~data[3]) >> 1) & 0xF; - velocity = 0x7F - velocity; + velocity = (~velocity) & 0x7f; note = 0x7F - note; if (velocity || note) { // map gh notes to their rb counterparts in rb mode diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index d87a2a40c..2043c58a5 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -325,6 +325,86 @@ const PROGMEM XBOX_360_CONFIGURATION_MULTI_DESCRIPTOR XBOX360MultiConfigurationD }, SecurityDescriptor : {0x06, 0x41, 0x00, 0x01, 0x01, 0x03}, }; + +const PROGMEM GH_ARCADE_CONFIGURATION_DESCRIPTOR GHArcadeConfigurationDescriptor{ + Config : { + bLength : sizeof(USB_CONFIGURATION_DESCRIPTOR), + bDescriptorType : USB_DESCRIPTOR_CONFIGURATION, + wTotalLength : sizeof(GH_ARCADE_CONFIGURATION_DESCRIPTOR), + bNumInterfaces : 2, + bConfigurationValue : 1, + iConfiguration : NO_DESCRIPTOR, + bmAttributes : + (USB_CONFIG_ATTRIBUTE_RESERVED | USB_CONFIG_ATTRIBUTE_REMOTEWAKEUP), + bMaxPower : USB_CONFIG_POWER_MA(500) + }, + UnknownDescriptor1 : {0x03, 0x09, 0x00}, + InterfaceHID : { + bLength : sizeof(USB_INTERFACE_DESCRIPTOR), + bDescriptorType : USB_DESCRIPTOR_INTERFACE, + bInterfaceNumber : INTERFACE_ID_Device, + bAlternateSetting : 0, + bNumEndpoints : 1, + bInterfaceClass : HID_INTF, + bInterfaceSubClass : USB_HID_PROTOCOL_NONE, + bInterfaceProtocol : USB_HID_PROTOCOL_NONE, + iInterface : NO_DESCRIPTOR + }, + HIDDescriptor : { + bLength : sizeof(USB_HID_DESCRIPTOR), + bDescriptorType : HID_DESCRIPTOR_HID, + bcdHID : USB_VERSION_BCD(1, 0, 0), + bCountryCode : 0x00, + bNumDescriptors : 1, + bDescrType : HID_DESCRIPTOR_REPORT, + wDescriptorLength : sizeof(gha_descriptor) + }, + EndpointInHID : { + bLength : sizeof(USB_ENDPOINT_DESCRIPTOR), + bDescriptorType : USB_DESCRIPTOR_ENDPOINT, + bEndpointAddress : DEVICE_EPADDR_IN, + bmAttributes : + (USB_TRANSFER_TYPE_INTERRUPT | ENDPOINT_TATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + wMaxPacketSize : 0x40, + bInterval : 1 + }, + InterfaceVendor : { + bLength : sizeof(USB_INTERFACE_DESCRIPTOR), + bDescriptorType : USB_DESCRIPTOR_INTERFACE, + bInterfaceNumber : INTERFACE_ID_Padding, + bAlternateSetting : 0x00, + bNumEndpoints : 3, + bInterfaceClass : 0xFF, + bInterfaceSubClass : 0x01, + bInterfaceProtocol : 0xFF, + iInterface : NO_DESCRIPTOR + }, + ReportINEndpoint21 : { + bLength : sizeof(USB_ENDPOINT_DESCRIPTOR), + bDescriptorType : USB_DESCRIPTOR_ENDPOINT, + bEndpointAddress : XINPUT_UNK_IN, + bmAttributes : (USB_TRANSFER_TYPE_INTERRUPT | ENDPOINT_TATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + wMaxPacketSize : 0x40, + bInterval : 1, + }, + ReportOUTEndpoint22 : { + bLength : sizeof(USB_ENDPOINT_DESCRIPTOR), + bDescriptorType : USB_DESCRIPTOR_ENDPOINT, + bEndpointAddress : XINPUT_UNK_OUT, + bmAttributes : (USB_TRANSFER_TYPE_INTERRUPT | ENDPOINT_TATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + wMaxPacketSize : 0x40, + bInterval : 1, + }, + ReportINEndpoint23 : { + bLength : sizeof(USB_ENDPOINT_DESCRIPTOR), + bDescriptorType : USB_DESCRIPTOR_ENDPOINT, + bEndpointAddress : XINPUT_PLUGIN_MODULE_IN, + bmAttributes : (USB_TRANSFER_TYPE_INTERRUPT | ENDPOINT_TATTR_NO_SYNC | ENDPOINT_USAGE_DATA), + wMaxPacketSize : 0x40, + bInterval : 1, + }, +}; + const PROGMEM OG_XBOX_CONFIGURATION_DESCRIPTOR OGXBOXConfigurationDescriptor = { Config : { bLength : sizeof(USB_CONFIGURATION_DESCRIPTOR), @@ -1246,6 +1326,10 @@ uint16_t descriptorRequest(const uint16_t wValue, dev->idProduct = XBOX_ONE_JAG_PID; } #endif + if (consoleType == ARCADE) { + dev->idVendor = 0x0c70; + dev->idProduct = 0x0777; + } break; } case USB_DESCRIPTOR_CONFIGURATION: { @@ -1269,6 +1353,9 @@ uint16_t descriptorRequest(const uint16_t wValue, } else if (consoleType == OG_XBOX) { size = sizeof(OG_XBOX_CONFIGURATION_DESCRIPTOR); memcpy_P(descriptorBuffer, &OGXBOXConfigurationDescriptor, size); + } else if (consoleType == ARCADE) { + size = sizeof(GH_ARCADE_CONFIGURATION_DESCRIPTOR); + memcpy_P(descriptorBuffer, &GHArcadeConfigurationDescriptor, size); } else { size = sizeof(UNIVERSAL_CONFIGURATION_DESCRIPTOR); memcpy_P(descriptorBuffer, &UniversalConfigurationDescriptor, size); @@ -1321,8 +1408,10 @@ uint16_t descriptorRequest(const uint16_t wValue, address = keyboard_mouse_descriptor; size = sizeof(keyboard_mouse_descriptor); #elif DEVICE_TYPE_IS_GAMEPAD - - if (consoleType == PS4) { + if (consoleType == ARCADE) { + address = gha_descriptor; + size = sizeof(gha_descriptor); + } else if (consoleType == PS4) { address = ps4_descriptor; size = sizeof(ps4_descriptor); } else if (consoleType == IOS_FESTIVAL) { @@ -1365,7 +1454,9 @@ uint16_t descriptorRequest(const uint16_t wValue, case USB_DESCRIPTOR_STRING: { read_any_string = true; const uint8_t *str; - if (descriptorNumber == 4) { + if (consoleType == ARCADE && descriptorNumber == 2) { + str = (uint8_t *)&rtString; + } else if (descriptorNumber == 4) { str = (uint8_t *)&xboxString; } else if (descriptorNumber < 4) { str = (uint8_t *)pgm_read_pointer(descriptorStrings + descriptorNumber); diff --git a/src/shared/usb/string_descriptors.c b/src/shared/usb/string_descriptors.c index 08d2c5b9e..68e23aa24 100644 --- a/src/shared/usb/string_descriptors.c +++ b/src/shared/usb/string_descriptors.c @@ -32,5 +32,8 @@ const PROGMEM STRING_DESCRIPTOR productString = USB_DESCRIPTOR_STRING_UTF("Santr */ const PROGMEM STRING_DESCRIPTOR xboxString = USB_DESCRIPTOR_STRING_UTF("Xbox Security Method 3, Version 1.00, \xa9 2005 Microsoft Corporation. All rights reserved."); + +const PROGMEM STRING_DESCRIPTOR rtString = USB_DESCRIPTOR_STRING_UTF("RT-GH INPUT "); + const PROGMEM STRING_DESCRIPTOR *const descriptorStrings[3] = { &languageString, &manufacturerString, &productString}; \ No newline at end of file From c56cf43af92a8fbd7b76828ebbf7c3fb5d122756 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 6 Jun 2025 22:51:46 +1200 Subject: [PATCH 035/239] gharcade --- include/descriptors.h | 1 - include/reports/pc_reports.h | 33 ++++++++++++++++++++++----------- src/pico/main.cpp | 1 - src/shared/main/shared_main.cpp | 26 ++++++++++++++++++++++++++ src/shared/usb/descriptors.cpp | 1 - 5 files changed, 48 insertions(+), 14 deletions(-) diff --git a/include/descriptors.h b/include/descriptors.h index 57a1a0b26..a000da379 100644 --- a/include/descriptors.h +++ b/include/descriptors.h @@ -73,7 +73,6 @@ typedef struct { typedef struct { USB_CONFIGURATION_DESCRIPTOR Config; - uint8_t UnknownDescriptor1[3]; USB_INTERFACE_DESCRIPTOR InterfaceHID; USB_HID_DESCRIPTOR HIDDescriptor; USB_ENDPOINT_DESCRIPTOR EndpointInHID; diff --git a/include/reports/pc_reports.h b/include/reports/pc_reports.h index c5b60e7e1..5d881d84f 100644 --- a/include/reports/pc_reports.h +++ b/include/reports/pc_reports.h @@ -184,21 +184,32 @@ typedef struct typedef struct { - uint8_t report_id; // Always 0x1d + uint8_t always_1d; // Always 0x1d + uint8_t unk1; + uint8_t unk2; + uint8_t always_ff; // Always 0xFF uint8_t tilt; - uint8_t accel_y; - uint8_t padding; // Always 0xFF - uint8_t accel_z; - - uint8_t dpad : 4; - uint8_t a : 1; // cross, green - uint8_t b : 1; // circle, red - uint8_t x : 1; // square, blue - uint8_t y : 1; // triangle, yellow + union { + struct { + uint8_t dpadUp : 1; + uint8_t dpadDown : 1; + uint8_t dpadLeft : 1; + uint8_t dpadRight : 1; + uint8_t a : 1; // cross, green + uint8_t b : 1; // circle, red + uint8_t x : 1; // square, blue + uint8_t y : 1; // triangle, yellow + }; + struct { + uint8_t dpad : 4; + uint8_t : 4; + }; + }; uint8_t leftShoulder : 1; // orange, l1 - uint8_t : 7; + uint8_t : 3; + uint8_t side : 4; // 1 for left, 2 for right } __attribute__((packed)) ArcadeGuitarHeroGuitar_Data_t; // Festivals default mappings suck, so its easiest to set up custom mappings for that here diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 5abe67c26..3b5f7ba0c 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -214,7 +214,6 @@ void setup() { xboxAuthValid = false; consoleType = UNIVERSAL; } - // consoleType = ARCADE; generateSerialString(&serialstring, consoleType); printf("ConsoleType: %d\r\n", consoleType); init_main(); diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 8f4d68a0f..9abdc89fc 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -459,6 +459,10 @@ uint16_t handle_calibration_ps3_accel(uint16_t previous, int32_t orig_val, int16 #endif return PS3_ACCEL_CENTER + ret; } +uint8_t handle_calibration_arcade_accel(uint16_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, uint16_t deadzone) { + int8_t ret = handle_calibration_xbox((previous - 65) << 9, orig_val, min, max, center, deadzone) >> 9; + return (uint8_t)(ret + 65); +} long last_zero = 0; uint8_t handle_calibration_ps3_whammy(uint8_t previous, uint16_t orig_val, uint32_t min, int16_t multiplier, uint16_t deadzone) { #if DEVICE_TYPE == ROCK_BAND_GUITAR @@ -2739,6 +2743,28 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } report->back = false; } + if (output_console_type == ARCADE) { + report_size = packet_size = sizeof(ArcadeGuitarHeroGuitar_Data_t); + ArcadeGuitarHeroGuitar_Data_t *report = (ArcadeGuitarHeroGuitar_Data_t *)report_data; + memset(report, 0, sizeof(ArcadeGuitarHeroGuitar_Data_t)); + report->always_1d = 0x1d; + report->always_ff = 0xff; + report->side = 0x1; + TICK_ARCADE; + asm volatile("" :: + : "memory"); + if (report->dpadUp) { + report->dpad = 0; + } else if (report->dpadDown) { + report->dpad = 2; + } else if (report->dpadLeft) { + report->dpad = 3; + } else if (report->dpadRight) { + report->dpad = 1; + } else { + report->dpad = 0xf; + } + } #endif // For gamepads, use the PS3 report format on PS3 #if DEVICE_TYPE == GAMEPAD diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 2043c58a5..50bc61ac0 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -338,7 +338,6 @@ const PROGMEM GH_ARCADE_CONFIGURATION_DESCRIPTOR GHArcadeConfigurationDescriptor (USB_CONFIG_ATTRIBUTE_RESERVED | USB_CONFIG_ATTRIBUTE_REMOTEWAKEUP), bMaxPower : USB_CONFIG_POWER_MA(500) }, - UnknownDescriptor1 : {0x03, 0x09, 0x00}, InterfaceHID : { bLength : sizeof(USB_INTERFACE_DESCRIPTOR), bDescriptorType : USB_DESCRIPTOR_INTERFACE, From a5c7377abf8db55cc7b1033255d5a6e891740a7d Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 7 Jun 2025 09:37:10 +1200 Subject: [PATCH 036/239] gharcade --- include/config.h | 1 + include/descriptors.h | 1 + include/string_descriptors.h | 2 ++ src/avr/micro/main/main.cpp | 9 +++++++++ src/avr/uno/main/main.cpp | 9 +++++++++ src/pico/main.cpp | 12 ++++++++++++ src/shared/config/config.c | 3 ++- src/shared/usb/descriptors.cpp | 17 ++++++++++------- src/shared/usb/string_descriptors.c | 4 +++- 9 files changed, 49 insertions(+), 9 deletions(-) diff --git a/include/config.h b/include/config.h index dc0180a08..56738cec7 100644 --- a/include/config.h +++ b/include/config.h @@ -13,6 +13,7 @@ extern "C" { // ConsoleType can change due to console detection extern uint8_t consoleType; +extern uint8_t arcadeSide; #ifdef CONFIGURABLE_BLOBS extern const uint8_t* config; extern const uint8_t* config_blobs; diff --git a/include/descriptors.h b/include/descriptors.h index a000da379..57a1a0b26 100644 --- a/include/descriptors.h +++ b/include/descriptors.h @@ -73,6 +73,7 @@ typedef struct { typedef struct { USB_CONFIGURATION_DESCRIPTOR Config; + uint8_t UnknownDescriptor1[3]; USB_INTERFACE_DESCRIPTOR InterfaceHID; USB_HID_DESCRIPTOR HIDDescriptor; USB_ENDPOINT_DESCRIPTOR EndpointInHID; diff --git a/include/string_descriptors.h b/include/string_descriptors.h index 0de4af33b..4542fcaa8 100644 --- a/include/string_descriptors.h +++ b/include/string_descriptors.h @@ -45,6 +45,8 @@ extern const PROGMEM STRING_DESCRIPTOR languageString; extern const PROGMEM STRING_DESCRIPTOR manufacturerString; extern const PROGMEM STRING_DESCRIPTOR productString; extern const PROGMEM STRING_DESCRIPTOR rtString; +extern const PROGMEM STRING_DESCRIPTOR rtString2; +extern const PROGMEM STRING_DESCRIPTOR rtString3; #ifdef __cplusplus } #endif diff --git a/src/avr/micro/main/main.cpp b/src/avr/micro/main/main.cpp index 900ab8f55..684529188 100644 --- a/src/avr/micro/main/main.cpp +++ b/src/avr/micro/main/main.cpp @@ -6,6 +6,7 @@ /** * Include LUFA.h after LUFAConfig.h */ +#include #include #include #include @@ -45,6 +46,10 @@ bool usb_configured() { } void setup() { + arcadeSide = EEPROM.read(0); + if (arcadeSide > 2) { + arcadeSide = 1; + } init_main(); if (persistedConsoleTypeValid == 0x3A2F) { consoleType = persistedConsoleType; @@ -54,6 +59,10 @@ void setup() { GlobalInterruptEnable(); // enable global interrupts SetupHardware(); // ask LUFA to setup the hardware } +void setArcadeSide(uint8_t side) { + arcadeSide = side; + EEPROM.write(0, side); +} uint8_t buf[255]; void loop() { diff --git a/src/avr/uno/main/main.cpp b/src/avr/uno/main/main.cpp index 1ffcbd4e3..e40b810e9 100644 --- a/src/avr/uno/main/main.cpp +++ b/src/avr/uno/main/main.cpp @@ -6,6 +6,7 @@ #include "Usb.h" #include "commands.h" +#include #include "config.h" #include "defines.h" #include "descriptors.h" @@ -116,6 +117,10 @@ bool usb_configured(void) { } void setup() { + arcadeSide = EEPROM.read(0); + if (arcadeSide > 2) { + arcadeSide = 1; + } // Configure the UART for controller mode UBRR0 = SERIAL_2X_UBBRVAL(BAUD); UCSR0C = ((1 << UCSZ01) | (1 << UCSZ00)); @@ -133,6 +138,10 @@ void setup() { } USB_Device_GetInternalSerialDescriptor(); } +void setArcadeSide(uint8_t side) { + arcadeSide = side; + EEPROM.write(0, side); +} bool ready_for_next_packet() { return !has_previous_data; } diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 3b5f7ba0c..fd3f71bac 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include "commands.h" #include "common/tusb_types.h" @@ -153,6 +154,11 @@ void setup1() { void loop() { tick_usb(); } +void setArcadeSide(uint8_t side) { + arcadeSide = side; + EEPROM.write(0, side); + EEPROM.commit(); +} void go_to_sleep() { pico_is_sleeping = true; @@ -216,6 +222,12 @@ void setup() { } generateSerialString(&serialstring, consoleType); printf("ConsoleType: %d\r\n", consoleType); + + EEPROM.begin(512); + arcadeSide = EEPROM.read(0); + if (arcadeSide > 2) { + arcadeSide = 1; + } init_main(); tud_init(TUD_OPT_RHPORT); #if USB_HOST_STACK diff --git a/src/shared/config/config.c b/src/shared/config/config.c index ce329c293..c010dd0b4 100644 --- a/src/shared/config/config.c +++ b/src/shared/config/config.c @@ -12,6 +12,7 @@ const uint8_t* config = (uint8_t*)0x100A3000; const uint8_t PROGMEM config[CONFIGURATION_LEN] = CONFIGURATION; #endif uint8_t consoleType = 0xFF; +uint8_t arcadeSide = 1; #if DEVICE_TYPE_IS_GUITAR const uint8_t announce[] = {0x02, 0x20, 0x01, 0x1c, 0x7e, 0xed, 0x81, TEMP, TEMP, TEMP, 0x00, 0x00, 0x38, 0x07, 0x61, 0x41, 0x01, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}; @@ -85,4 +86,4 @@ const uint8_t xb1_descriptor[] = { const uint8_t xb1_descriptor_end[] = { 0x04, 0xa0, 0x03, 0x00, 0xdc, 0x01}; -#endif \ No newline at end of file +#endif diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 50bc61ac0..437c2b9fa 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -338,6 +338,7 @@ const PROGMEM GH_ARCADE_CONFIGURATION_DESCRIPTOR GHArcadeConfigurationDescriptor (USB_CONFIG_ATTRIBUTE_RESERVED | USB_CONFIG_ATTRIBUTE_REMOTEWAKEUP), bMaxPower : USB_CONFIG_POWER_MA(500) }, + UnknownDescriptor1 : {0x03, 0x09, 0x00}, InterfaceHID : { bLength : sizeof(USB_INTERFACE_DESCRIPTOR), bDescriptorType : USB_DESCRIPTOR_INTERFACE, @@ -347,7 +348,7 @@ const PROGMEM GH_ARCADE_CONFIGURATION_DESCRIPTOR GHArcadeConfigurationDescriptor bInterfaceClass : HID_INTF, bInterfaceSubClass : USB_HID_PROTOCOL_NONE, bInterfaceProtocol : USB_HID_PROTOCOL_NONE, - iInterface : NO_DESCRIPTOR + iInterface : 5 }, HIDDescriptor : { bLength : sizeof(USB_HID_DESCRIPTOR), @@ -376,12 +377,12 @@ const PROGMEM GH_ARCADE_CONFIGURATION_DESCRIPTOR GHArcadeConfigurationDescriptor bInterfaceClass : 0xFF, bInterfaceSubClass : 0x01, bInterfaceProtocol : 0xFF, - iInterface : NO_DESCRIPTOR + iInterface : 6 }, ReportINEndpoint21 : { bLength : sizeof(USB_ENDPOINT_DESCRIPTOR), bDescriptorType : USB_DESCRIPTOR_ENDPOINT, - bEndpointAddress : XINPUT_UNK_IN, + bEndpointAddress : 0x82, bmAttributes : (USB_TRANSFER_TYPE_INTERRUPT | ENDPOINT_TATTR_NO_SYNC | ENDPOINT_USAGE_DATA), wMaxPacketSize : 0x40, bInterval : 1, @@ -389,7 +390,7 @@ const PROGMEM GH_ARCADE_CONFIGURATION_DESCRIPTOR GHArcadeConfigurationDescriptor ReportOUTEndpoint22 : { bLength : sizeof(USB_ENDPOINT_DESCRIPTOR), bDescriptorType : USB_DESCRIPTOR_ENDPOINT, - bEndpointAddress : XINPUT_UNK_OUT, + bEndpointAddress : 0x03, bmAttributes : (USB_TRANSFER_TYPE_INTERRUPT | ENDPOINT_TATTR_NO_SYNC | ENDPOINT_USAGE_DATA), wMaxPacketSize : 0x40, bInterval : 1, @@ -397,7 +398,7 @@ const PROGMEM GH_ARCADE_CONFIGURATION_DESCRIPTOR GHArcadeConfigurationDescriptor ReportINEndpoint23 : { bLength : sizeof(USB_ENDPOINT_DESCRIPTOR), bDescriptorType : USB_DESCRIPTOR_ENDPOINT, - bEndpointAddress : XINPUT_PLUGIN_MODULE_IN, + bEndpointAddress : 0x84, bmAttributes : (USB_TRANSFER_TYPE_INTERRUPT | ENDPOINT_TATTR_NO_SYNC | ENDPOINT_USAGE_DATA), wMaxPacketSize : 0x40, bInterval : 1, @@ -1453,8 +1454,10 @@ uint16_t descriptorRequest(const uint16_t wValue, case USB_DESCRIPTOR_STRING: { read_any_string = true; const uint8_t *str; - if (consoleType == ARCADE && descriptorNumber == 2) { - str = (uint8_t *)&rtString; + if (descriptorNumber == 5) { + str = (uint8_t *)&rtString2; + } else if (descriptorNumber == 6) { + str = (uint8_t *)&rtString3; } else if (descriptorNumber == 4) { str = (uint8_t *)&xboxString; } else if (descriptorNumber < 4) { diff --git a/src/shared/usb/string_descriptors.c b/src/shared/usb/string_descriptors.c index 68e23aa24..c2c577c30 100644 --- a/src/shared/usb/string_descriptors.c +++ b/src/shared/usb/string_descriptors.c @@ -33,7 +33,9 @@ const PROGMEM STRING_DESCRIPTOR productString = USB_DESCRIPTOR_STRING_UTF("Santr const PROGMEM STRING_DESCRIPTOR xboxString = USB_DESCRIPTOR_STRING_UTF("Xbox Security Method 3, Version 1.00, \xa9 2005 Microsoft Corporation. All rights reserved."); -const PROGMEM STRING_DESCRIPTOR rtString = USB_DESCRIPTOR_STRING_UTF("RT-GH INPUT "); +const PROGMEM STRING_DESCRIPTOR rtString = USB_DESCRIPTOR_STRING_UTF("RT GH CONTROLLER "); +const PROGMEM STRING_DESCRIPTOR rtString2 = USB_DESCRIPTOR_STRING_UTF("RT-GH LED "); +const PROGMEM STRING_DESCRIPTOR rtString3 = USB_DESCRIPTOR_STRING_UTF("RT-GH INPUT "); const PROGMEM STRING_DESCRIPTOR *const descriptorStrings[3] = { &languageString, &manufacturerString, &productString}; \ No newline at end of file From 5dfc67679c5c853b60030ccf4e020e8c14c42170 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 7 Jun 2025 10:04:34 +1200 Subject: [PATCH 037/239] switch 2 console detection --- src/shared/usb/descriptors.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 437c2b9fa..c98f3c178 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1264,6 +1264,10 @@ uint16_t descriptorRequest(const uint16_t wValue, if (WINDOWS_USES_XINPUT && consoleType == UNIVERSAL && seen_windows_xb1 && descriptorType != HID_DESCRIPTOR_REPORT) { set_console_type(WINDOWS); } + // Switch 2 does this + if (consoleType == UNIVERSAL && descriptorType == 0x22) { + set_console_type(SWITCH); + } #endif #endif From 353fb0ffb9e00dd37aa3d5a039b634aafda5a805 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 7 Jun 2025 10:06:12 +1200 Subject: [PATCH 038/239] comment out gha stuff --- include/descriptors.h | 2 +- src/shared/usb/descriptors.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/descriptors.h b/include/descriptors.h index 57a1a0b26..06f3e0558 100644 --- a/include/descriptors.h +++ b/include/descriptors.h @@ -73,7 +73,7 @@ typedef struct { typedef struct { USB_CONFIGURATION_DESCRIPTOR Config; - uint8_t UnknownDescriptor1[3]; + // uint8_t UnknownDescriptor1[3]; USB_INTERFACE_DESCRIPTOR InterfaceHID; USB_HID_DESCRIPTOR HIDDescriptor; USB_ENDPOINT_DESCRIPTOR EndpointInHID; diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index c98f3c178..68e32b94c 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -338,7 +338,7 @@ const PROGMEM GH_ARCADE_CONFIGURATION_DESCRIPTOR GHArcadeConfigurationDescriptor (USB_CONFIG_ATTRIBUTE_RESERVED | USB_CONFIG_ATTRIBUTE_REMOTEWAKEUP), bMaxPower : USB_CONFIG_POWER_MA(500) }, - UnknownDescriptor1 : {0x03, 0x09, 0x00}, + // UnknownDescriptor1 : {0x03, 0x09, 0x00}, InterfaceHID : { bLength : sizeof(USB_INTERFACE_DESCRIPTOR), bDescriptorType : USB_DESCRIPTOR_INTERFACE, From 58b2e208b8328553e45586253fc186b09fbb9d3a Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 7 Jun 2025 10:31:36 +1200 Subject: [PATCH 039/239] switch 2 console detection --- src/shared/main/shared_main.cpp | 28 +++++++++++++++++----------- src/shared/usb/descriptors.cpp | 4 ---- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 9abdc89fc..7fae56833 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -181,7 +181,7 @@ USB_Host_Data_t bt_data; uint8_t rawWt; uint8_t rawWtPeripheral; bool auth_ps4_controller_found = false; -bool seen_ps4_console = false; +bool report_requested = false; bool hasFlags = false; GipPowerMode_t powerMode; Gip_Led_On_t ledOn; @@ -2610,7 +2610,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu gamepad->rightStickX = PS3_STICK_CENTER; gamepad->rightStickY = PS3_STICK_CENTER; // PS4 does not start using the controller until it sees a PS button press. - if (!seen_ps4_console) { + if (!report_requested) { report->guide = true; } TICK_PS4; @@ -2979,16 +2979,22 @@ bool tick_usb(void) { } #endif #if DEVICE_TYPE_IS_GAMEPAD - // PS2 / Wii / WiiU do not read the hid report descriptor or any of the string descriptors. - if (millis_at_boot && (millis() - millis_at_boot) > 5000 && consoleType == UNIVERSAL && !seen_hid_descriptor_read && !read_any_string && !seen_windows_xb1) { - // The wii however will configure the usb device before it stops communicating + // PS2 / Wii / WiiU / Switch 2 do not read any of the string descriptors. + if (millis_at_boot && (millis() - millis_at_boot) > 5000 && consoleType == UNIVERSAL && !read_any_string && !seen_windows_xb1) { + // Switch 2 does read the hid descriptor + if (seen_hid_descriptor_read) { + set_console_type(SWITCH); + } else { + // PS2 / Wii / WiiU does not read hid descriptor + // The wii however will configure the usb device before it stops communicating #if DEVICE_TYPE == ROCK_BAND_GUITAR || DEVICE_TYPE == ROCK_BAND_DRUMS - if (usb_configured()) { - set_console_type(WII_RB); - } + if (usb_configured()) { + set_console_type(WII_RB); + } #endif - // But the PS2 does not. We also end up here on the wii/wiiu if a device does not have an explicit wii mode. - set_console_type(PS3); + // But the PS2 does not. We also end up here on the wii/wiiu if a device does not have an explicit wii mode. + set_console_type(PS3); + } } // Due to some quirks with how the PS3 detects controllers, we can also end up here for PS3, but in that case, we won't see any requests for controller data if ((millis() - millis_at_boot) > 2000 && consoleType == PS4 && !seen_ps4) { @@ -3042,7 +3048,7 @@ bool tick_usb(void) { lastSentPacket = millis(); // make 5ms idle ticking wait until 5ms after last report send_report_to_pc(&combined_report, size); } - seen_ps4_console = true; + report_requested = true; return size; } #if BLUETOOTH_RX diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 68e32b94c..6a611399e 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1264,10 +1264,6 @@ uint16_t descriptorRequest(const uint16_t wValue, if (WINDOWS_USES_XINPUT && consoleType == UNIVERSAL && seen_windows_xb1 && descriptorType != HID_DESCRIPTOR_REPORT) { set_console_type(WINDOWS); } - // Switch 2 does this - if (consoleType == UNIVERSAL && descriptorType == 0x22) { - set_console_type(SWITCH); - } #endif #endif From adec68807683eb7975a585a25f9f708bdb47b08d Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 7 Jun 2025 11:15:32 +1200 Subject: [PATCH 040/239] GH arcade support, Switch 2 support --- src/shared/main/shared_main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 7fae56833..810fc3547 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2983,7 +2983,8 @@ bool tick_usb(void) { if (millis_at_boot && (millis() - millis_at_boot) > 5000 && consoleType == UNIVERSAL && !read_any_string && !seen_windows_xb1) { // Switch 2 does read the hid descriptor if (seen_hid_descriptor_read) { - set_console_type(SWITCH); + consoleType = SWITCH; + reset_usb(); } else { // PS2 / Wii / WiiU does not read hid descriptor // The wii however will configure the usb device before it stops communicating From de6b24bb2886a870ab7255659da16cea70a448fd Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 8 Jun 2025 20:28:13 +1200 Subject: [PATCH 041/239] GH arcade support fixes --- include/string_descriptors.h | 4 ++-- src/shared/usb/descriptors.cpp | 4 ++-- src/shared/usb/string_descriptors.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/string_descriptors.h b/include/string_descriptors.h index 4542fcaa8..193cc0a17 100644 --- a/include/string_descriptors.h +++ b/include/string_descriptors.h @@ -45,8 +45,8 @@ extern const PROGMEM STRING_DESCRIPTOR languageString; extern const PROGMEM STRING_DESCRIPTOR manufacturerString; extern const PROGMEM STRING_DESCRIPTOR productString; extern const PROGMEM STRING_DESCRIPTOR rtString; -extern const PROGMEM STRING_DESCRIPTOR rtString2; -extern const PROGMEM STRING_DESCRIPTOR rtString3; +extern const PROGMEM STRING_DESCRIPTOR rtStringLED; +extern const PROGMEM STRING_DESCRIPTOR rtStringInput; #ifdef __cplusplus } #endif diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 6a611399e..1e97cbce7 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1455,9 +1455,9 @@ uint16_t descriptorRequest(const uint16_t wValue, read_any_string = true; const uint8_t *str; if (descriptorNumber == 5) { - str = (uint8_t *)&rtString2; + str = (uint8_t *)&rtStringInput; } else if (descriptorNumber == 6) { - str = (uint8_t *)&rtString3; + str = (uint8_t *)&rtStringLED; } else if (descriptorNumber == 4) { str = (uint8_t *)&xboxString; } else if (descriptorNumber < 4) { diff --git a/src/shared/usb/string_descriptors.c b/src/shared/usb/string_descriptors.c index c2c577c30..0a43c725e 100644 --- a/src/shared/usb/string_descriptors.c +++ b/src/shared/usb/string_descriptors.c @@ -34,8 +34,8 @@ const PROGMEM STRING_DESCRIPTOR xboxString = USB_DESCRIPTOR_STRING_UTF("Xbox Sec const PROGMEM STRING_DESCRIPTOR rtString = USB_DESCRIPTOR_STRING_UTF("RT GH CONTROLLER "); -const PROGMEM STRING_DESCRIPTOR rtString2 = USB_DESCRIPTOR_STRING_UTF("RT-GH LED "); -const PROGMEM STRING_DESCRIPTOR rtString3 = USB_DESCRIPTOR_STRING_UTF("RT-GH INPUT "); +const PROGMEM STRING_DESCRIPTOR rtStringLED = USB_DESCRIPTOR_STRING_UTF("RT-GH LED "); +const PROGMEM STRING_DESCRIPTOR rtStringInput = USB_DESCRIPTOR_STRING_UTF("RT-GH INPUT "); const PROGMEM STRING_DESCRIPTOR *const descriptorStrings[3] = { &languageString, &manufacturerString, &productString}; \ No newline at end of file From 3fbdc17d213f359c0544beba4bf1f0d8502ff70a Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 8 Jun 2025 22:32:23 +1200 Subject: [PATCH 042/239] implement side mating --- include/config.h | 1 + src/pico/main.cpp | 3 +++ src/pico/xinput_device.cpp | 15 +++++++++++++-- src/shared/hid/hid.cpp | 7 +++++++ src/shared/main/shared_main.cpp | 2 +- 5 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/config.h b/include/config.h index 56738cec7..f365bd88c 100644 --- a/include/config.h +++ b/include/config.h @@ -14,6 +14,7 @@ extern "C" { // ConsoleType can change due to console detection extern uint8_t consoleType; extern uint8_t arcadeSide; +void setArcadeSide(uint8_t side); #ifdef CONFIGURABLE_BLOBS extern const uint8_t* config; extern const uint8_t* config_blobs; diff --git a/src/pico/main.cpp b/src/pico/main.cpp index fd3f71bac..e475ee844 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -155,6 +155,9 @@ void loop() { tick_usb(); } void setArcadeSide(uint8_t side) { + if (arcadeSide == side) { + return; + } arcadeSide = side; EEPROM.write(0, side); EEPROM.commit(); diff --git a/src/pico/xinput_device.cpp b/src/pico/xinput_device.cpp index 4307a38c6..640bd1ea3 100644 --- a/src/pico/xinput_device.cpp +++ b/src/pico/xinput_device.cpp @@ -121,13 +121,21 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, } TU_VERIFY(p_xinput, 0); uint8_t const *p_desc = (uint8_t const *)itf_desc; - - if (itf_desc->bInterfaceSubClass == 0x00 && itf_desc->bInterfaceProtocol == 0xFF) { + + if (itf_desc->bInterfaceSubClass == 0x01 && itf_desc->bInterfaceProtocol == 0xFF) { p_desc = tu_desc_next(p_desc); + printf("Opened: %d\r\n", itf_desc->bNumEndpoints); TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, itf_desc->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_xinput->ep_out, &p_xinput->ep_in), 0); + printf("Opened: %02x %02x\r\n", p_xinput->ep_out, p_xinput->ep_in); + if (p_xinput->ep_out) { + if (!usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, sizeof(p_xinput->epout_buf))) { + TU_LOG_FAILED(); + TU_BREAKPOINT(); + } + } return drv_len; } else if (itf_desc->bInterfaceSubClass == 0x5D && (itf_desc->bInterfaceProtocol == 0x01 || @@ -277,6 +285,9 @@ bool xinputd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, 0x40)); #endif + } else if (consoleType == ARCADE) { + TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, + 0x40)); } else { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, 0x08)); diff --git a/src/shared/hid/hid.cpp b/src/shared/hid/hid.cpp index cfbf0d76b..bfa42e0d4 100644 --- a/src/shared/hid/hid.cpp +++ b/src/shared/hid/hid.cpp @@ -559,6 +559,13 @@ void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_ // portal_state = 1; // } // } + if (consoleType == ARCADE) { + if (data[0] == 0x03) { + // packet sends 0 for left and 1 for right, hid report uses 1 for left and 2 for right + setArcadeSide(data[1] + 1); + } + return; + } #if DEVICE_TYPE_IS_KEYBOARD handle_keyboard_leds(data[0]); #endif diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 810fc3547..3e9fd2ffd 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2749,7 +2749,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu memset(report, 0, sizeof(ArcadeGuitarHeroGuitar_Data_t)); report->always_1d = 0x1d; report->always_ff = 0xff; - report->side = 0x1; + report->side = arcadeSide; TICK_ARCADE; asm volatile("" :: : "memory"); From 1a8e73809d8e2c4786b13f0d8ffca60a7e136944 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 16 Jun 2025 20:12:19 +1200 Subject: [PATCH 043/239] support switch 2 controllers --- include/defines.h | 1 + include/endpoints.h | 4 + include/reports/switch_reports.h | 134 +++---- src/pico/main.cpp | 615 +++++++++++++++++++------------ src/shared/main/shared_main.cpp | 64 ++++ 5 files changed, 523 insertions(+), 295 deletions(-) diff --git a/include/defines.h b/include/defines.h index 3fdf5118d..ad1c5122c 100644 --- a/include/defines.h +++ b/include/defines.h @@ -100,6 +100,7 @@ #define PS2_ON_PS3 29 #define STADIA 30 #define XINPUTCOMPAT 31 +#define SWITCH2 32 #define NON_CONTROLLER 0xFE #define UNKNOWN 0xFF diff --git a/include/endpoints.h b/include/endpoints.h index e86ae89a8..ca9c698f5 100644 --- a/include/endpoints.h +++ b/include/endpoints.h @@ -31,6 +31,10 @@ enum endpoints_t { #define HORI_POKKEN_TOURNAMENT_DX_PRO_PAD_PID 0x0092 #define NINTENDO_VID 0x057E #define SWITCH_PRO_PID 0x2009 +#define SWITCH_2_PRO_PID 0x2069 +#define SWITCH_2_GC_PID 0x2073 +#define SWITCH_2_JOY_R_PID 0x2066 +#define SWITCH_2_JOY_L_PID 0x2067 #define REDOCTANE_VID 0x12ba #define SONY_VID 0x054c #define SONY_DS3_PID 0x0268 diff --git a/include/reports/switch_reports.h b/include/reports/switch_reports.h index 82006c6b6..f6c2dbaad 100644 --- a/include/reports/switch_reports.h +++ b/include/reports/switch_reports.h @@ -1,72 +1,75 @@ #pragma once #include #define SWITCH_PRO_CON_FULL_REPORT_ID 0x30 -typedef struct { +#define SWITCH_2_GC_FULL_REPORT_ID 0x0A +#define SWITCH_2_PRO_CON_FULL_REPORT_ID 0x09 +#define SWITCH_2_STICK_CENTER 2048 +typedef struct +{ int16_t accX, accY, accZ; int16_t gyroX, gyroY, gyroZ; } __attribute__((packed)) ImuData; -typedef struct { - uint8_t connection_info : 4; - uint8_t battery_level : 4; - - uint8_t y : 1; - uint8_t x : 1; +typedef struct +{ + uint8_t reportId; // 0x0A + uint8_t packetId; // counts up for each packet + uint8_t status; // 0x20 uint8_t b : 1; uint8_t a : 1; - - uint8_t dummy1 : 2; + uint8_t y : 1; + uint8_t x : 1; + uint8_t r2 : 1; uint8_t rightShoulder : 1; - uint8_t rightTrigger : 1; - - uint8_t back : 1; // minus - uint8_t start : 1; // plus - uint8_t leftThumbClick : 1; // l3 - uint8_t rightThumbClick : 1; // r3 - - uint8_t guide : 1; // home - uint8_t capture : 1; - uint8_t dummy2 : 2; - - uint8_t dpad : 4; + uint8_t start : 1; + uint8_t : 1; - uint8_t dummy3 : 2; + uint8_t dpadDown : 1; + uint8_t dpadRight : 1; + uint8_t dpadLeft : 1; + uint8_t dpadUp : 1; + uint8_t l2 : 1; uint8_t leftShoulder : 1; - uint8_t leftTrigger : 1; - - // Bytes 6-11 - uint8_t leftStickX; - uint8_t leftStickY; - uint8_t rightStickX; - uint8_t rightStickY; - - uint8_t vibratorInput; // What is this used for? + uint8_t : 2; - // Bytes 13-48 - // Three samples of the IMU is sent in one message - // See: https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/imu_sensor_notes.md - ImuData imu[3]; -} __attribute__((packed)) SwitchProGamepad_Data_t; + uint8_t guide : 1; + uint8_t capture : 1; + uint8_t gl : 1; + uint8_t gr : 1; + uint8_t c : 1; + uint8_t : 3; + + uint16_t leftStickX : 12; + uint16_t leftStickY : 12; + uint16_t rightStickX : 12; + uint16_t rightStickY : 12; + uint8_t vibrationCode; + uint8_t leftTrigger; + uint8_t rightTrigger; + uint8_t imuLength; + uint8_t motionBuffer[10]; +} __attribute__((packed)) Switch2ProGamepad_Data_t; -typedef struct { +typedef struct +{ // Button bits uint8_t y : 1; uint8_t b : 1; uint8_t a : 1; uint8_t x : 1; - uint8_t leftShoulder : 1; // l1 - uint8_t rightShoulder : 1; // r1 - uint8_t l2 : 1; // l2 - uint8_t r2 : 1; // r2 + uint8_t leftShoulder : 1; // l1 + uint8_t rightShoulder : 1; // r1 + uint8_t l2 : 1; // l2 + uint8_t r2 : 1; // r2 - uint8_t back : 1; // select + uint8_t back : 1; // select uint8_t start : 1; - uint8_t leftThumbClick : 1; // l3 - uint8_t rightThumbClick : 1; // r3 + uint8_t leftThumbClick : 1; // l3 + uint8_t rightThumbClick : 1; // r3 - uint8_t guide : 1; // ps - uint8_t capture : 1; // switch capture button + uint8_t guide : 1; // ps + uint8_t capture : 1; // switch capture button uint8_t : 2; // To make things easier, we use bitfields here, and then we map to a proper hat later @@ -90,33 +93,34 @@ typedef struct { } __attribute__((packed)) SwitchGamepad_Data_t; - // Festivals default mappings suck, so its easiest to set up custom mappings for that here typedef struct { - uint8_t y : 1; // y, triangle, yellow - uint8_t rightShoulder : 1; // b, circle, red + uint8_t y : 1; // y, triangle, yellow + uint8_t rightShoulder : 1; // b, circle, red uint8_t leftShoulder : 1; // a, cross, green - uint8_t x : 1; // x, square, blue + uint8_t x : 1; // x, square, blue - uint8_t dpadUp : 1; // leftShoulder, orange, l1 - uint8_t dpadDown : 1; // rightShoulder, spPedal, r1 - uint8_t back: 1; // back, select - uint8_t start : 1; // start + uint8_t dpadUp : 1; // leftShoulder, orange, l1 + uint8_t dpadDown : 1; // rightShoulder, spPedal, r1 + uint8_t back : 1; // back, select + uint8_t start : 1; // start - uint8_t guide : 1; // ps + uint8_t guide : 1; // ps uint8_t : 2; uint8_t whammy : 1; uint8_t tilt : 1; uint8_t : 2; // To make things easier, we use bitfields here, and then we map to a proper hat later - union { - struct { - uint8_t b : 1; // dpadUp - uint8_t dpadRight : 1; // dpadDown - uint8_t a : 1; // dpadLeft - uint8_t dpadLeft : 1; // dpadRight + union + { + struct + { + uint8_t b : 1; // dpadUp + uint8_t dpadRight : 1; // dpadDown + uint8_t a : 1; // dpadLeft + uint8_t dpadLeft : 1; // dpadRight uint8_t : 4; }; uint8_t dpad; @@ -126,8 +130,8 @@ typedef struct uint8_t slider; } __attribute__((packed)) SwitchFestivalProGuitarLayer_Data_t; - -typedef struct { +typedef struct +{ uint8_t y : 1; uint8_t b : 1; uint8_t a : 1; @@ -139,8 +143,8 @@ typedef struct { uint8_t back : 1; uint8_t start : 1; - uint8_t leftThumbClick : 1; //l3 centerLeft - uint8_t rightThumbClick : 1; //r3 centerRight + uint8_t leftThumbClick : 1; // l3 centerLeft + uint8_t rightThumbClick : 1; // r3 centerRight uint8_t guide : 1; uint8_t capture : 1; uint8_t : 2; diff --git a/src/pico/main.cpp b/src/pico/main.cpp index e475ee844..081359198 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -55,7 +55,8 @@ USB_Device_Type_t xone_dev_addr = {}; USB_Device_Type_t x360_dev_addr = {}; USB_Device_Type_t ps4_dev_addr = {}; uint8_t total_usb_host_devices = 0; -typedef struct { +typedef struct +{ USB_Device_Type_t type; USB_LastReport_Data_t report; uint8_t report_length; @@ -66,11 +67,13 @@ typedef struct { Usb_Host_Device_t usb_host_devices[CFG_TUH_DEVICE_MAX * CFG_TUH_XINPUT]; #endif -typedef enum { - PIO_USB_PINOUT_DPDM = 0, // DM = DP+1 - PIO_USB_PINOUT_DMDP, // DM = DP-1 +typedef enum +{ + PIO_USB_PINOUT_DPDM = 0, // DM = DP+1 + PIO_USB_PINOUT_DMDP, // DM = DP-1 } PIO_USB_PINOUT; -typedef struct { +typedef struct +{ uint8_t pin_dp; uint8_t pio_tx_num; uint8_t sm_tx; @@ -102,24 +105,29 @@ SerialMIDI serialMIDI(Serial1); #endif MidiInterface> MIDI2(serialMIDI); #endif -bool ready_for_next_packet() { +bool ready_for_next_packet() +{ return tud_xinput_n_ready(0) && tud_ready_for_packet(); } -bool usb_configured() { +bool usb_configured() +{ return tud_ready(); } -void send_report_to_pc(const void *report, uint8_t len) { +void send_report_to_pc(const void *report, uint8_t len) +{ tud_xusb_n_report(0, report, len); } bool foundXB = false; bool authReady = false; bool authDone = false; long test3 = 0; -static void tick_usb() { +static void tick_usb() +{ #if USB_HOST_STACK - if (consoleType == XBOXONE && !foundXB) { + if (consoleType == XBOXONE && !foundXB) + { tuh_task(); return; } @@ -128,7 +136,8 @@ static void tick_usb() { #if USB_HOST_STACK tuh_task(); #endif - if (tud_suspended()) { + if (tud_suspended()) + { tud_remote_wakeup(); } tick(); @@ -140,22 +149,28 @@ static void tick_usb() { #endif } #if BLUETOOTH_RX -void tick_bluetooth(const void *buf, uint8_t len, USB_Device_Type_t type) { +void tick_bluetooth(const void *buf, uint8_t len, USB_Device_Type_t type) +{ tick_bluetooth_inputs(buf, len, type); } #endif #if BLUETOOTH -void loop1() { +void loop1() +{ } -void setup1() { +void setup1() +{ btstack_main(); } #endif -void loop() { +void loop() +{ tick_usb(); } -void setArcadeSide(uint8_t side) { - if (arcadeSide == side) { +void setArcadeSide(uint8_t side) +{ + if (arcadeSide == side) + { return; } arcadeSide = side; @@ -163,23 +178,27 @@ void setArcadeSide(uint8_t side) { EEPROM.commit(); } -void go_to_sleep() { +void go_to_sleep() +{ pico_is_sleeping = true; reset_usb(); } -void wakeup_360() { - if (usb_configured()) { +void wakeup_360() +{ + if (usb_configured()) + { return; } // the 360 will wake up the console if it sees the data lines being driven high and low constantly // save the previous usb state uint32_t prev_direct = usb_hw->phy_direct; uint32_t prev_direct_override = usb_hw->phy_direct_override; - for (int i = 0; i < 2; i++) { + for (int i = 0; i < 2; i++) + { // drive both pins high hw_set_bits(&usb_hw->phy_direct_override, USB_USBPHY_DIRECT_OVERRIDE_TX_DM_OE_OVERRIDE_EN_BITS | USB_USBPHY_DIRECT_OVERRIDE_TX_DM_OVERRIDE_EN_BITS | - USB_USBPHY_DIRECT_OVERRIDE_TX_DP_OE_OVERRIDE_EN_BITS | USB_USBPHY_DIRECT_OVERRIDE_TX_DP_OVERRIDE_EN_BITS | USB_USBPHY_DIRECT_OVERRIDE_TX_DIFFMODE_OVERRIDE_EN_BITS); + USB_USBPHY_DIRECT_OVERRIDE_TX_DP_OE_OVERRIDE_EN_BITS | USB_USBPHY_DIRECT_OVERRIDE_TX_DP_OVERRIDE_EN_BITS | USB_USBPHY_DIRECT_OVERRIDE_TX_DIFFMODE_OVERRIDE_EN_BITS); hw_set_bits(&usb_hw->phy_direct, USB_USBPHY_DIRECT_TX_DM_OE_BITS | USB_USBPHY_DIRECT_TX_DP_OE_BITS | USB_USBPHY_DIRECT_TX_DIFFMODE_BITS); hw_clear_bits(&usb_hw->phy_direct, USB_USBPHY_DIRECT_TX_DIFFMODE_BITS); hw_set_bits(&usb_hw->phy_direct, USB_USBPHY_DIRECT_TX_DP_BITS | USB_USBPHY_DIRECT_TX_DM_BITS); @@ -194,7 +213,8 @@ void wakeup_360() { reset_usb(); } -void setup() { +void setup() +{ #if USB_HOST_STACK set_sys_clock_khz(120000, true); #endif @@ -205,11 +225,14 @@ void setup() { Serial1.setRX(SERIAL_MIDI_PIN); #endif #endif - if (persistedConsoleTypeValid == PERSISTED_CONSOLE_TYPE_VALID) { + if (persistedConsoleTypeValid == PERSISTED_CONSOLE_TYPE_VALID) + { consoleType = persistedConsoleType; - if (SLEEP_PIN != -1) { + if (SLEEP_PIN != -1) + { // Sleep works best when nothing else is started, so we reboot the pico before and after sleep - if (pico_is_sleeping) { + if (pico_is_sleeping) + { pinMode(SLEEP_PIN, SLEEP_ACTIVE_HIGH ? INPUT_PULLDOWN : INPUT_PULLUP); sleep_run_from_xosc(); sleep_goto_dormant_until_pin(SLEEP_PIN, true, SLEEP_ACTIVE_HIGH); @@ -218,7 +241,9 @@ void setup() { reset_usb(); } } - } else { + } + else + { windows_in_hid = false; xboxAuthValid = false; consoleType = UNIVERSAL; @@ -228,7 +253,8 @@ void setup() { EEPROM.begin(512); arcadeSide = EEPROM.read(0); - if (arcadeSide > 2) { + if (arcadeSide > 2) + { arcadeSide = 1; } init_main(); @@ -268,11 +294,13 @@ void setup() { } #ifdef INPUT_USB_HOST -void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets) { +void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets) +{ usbMIDITransport.tuh_midi_rx_cb(dev_addr, num_packets); } -void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t in_ep, uint8_t out_ep, uint8_t num_cables_rx, uint16_t num_cables_tx) { +void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t in_ep, uint8_t out_ep, uint8_t num_cables_rx, uint16_t num_cables_tx) +{ printf("MIDI device address = %u, IN endpoint %u has %u cables, OUT endpoint %u has %u cables\r\n", dev_addr, in_ep & 0xf, num_cables_rx, out_ep & 0xf, num_cables_tx); @@ -284,7 +312,8 @@ void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t in_ep, uint8_t out_ep, uint8_t } // Invoked when device with hid interface is un-mounted -void tuh_midi_umount_cb(uint8_t dev_addr, uint8_t instance) { +void tuh_midi_umount_cb(uint8_t dev_addr, uint8_t instance) +{ printf("MIDI device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); usbMIDITransport.midi_dev_addr = 0; @@ -292,43 +321,55 @@ void tuh_midi_umount_cb(uint8_t dev_addr, uint8_t instance) { total_usb_host_devices = 0; } #endif -void authentication_successful() { +void authentication_successful() +{ printf("Auth done\r\n"); authReady = true; } #if USB_HOST_STACK -USB_Device_Type_t get_device_address_for(uint8_t deviceType) { - if (deviceType == XBOXONE) { +USB_Device_Type_t get_device_address_for(uint8_t deviceType) +{ + if (deviceType == XBOXONE) + { return xone_dev_addr; } - if (deviceType == XBOX360) { + if (deviceType == XBOX360) + { return x360_dev_addr; } - if (deviceType == PS4) { + if (deviceType == PS4) + { return ps4_dev_addr; } return {0}; } #endif -void send_report_to_controller(uint8_t dev_addr, uint8_t instance, const uint8_t *report, uint8_t len) { - if (dev_addr && tuh_xinput_mounted(dev_addr, instance)) { +void send_report_to_controller(uint8_t dev_addr, uint8_t instance, const uint8_t *report, uint8_t len) +{ + if (dev_addr && tuh_xinput_mounted(dev_addr, instance)) + { tuh_xinput_send_report(dev_addr, instance, report, len); } } -extern "C" void tud_mount_cb(void) { +extern "C" void tud_mount_cb(void) +{ device_reset(); } #if USB_HOST_STACK -uint8_t get_usb_host_device_count() { +uint8_t get_usb_host_device_count() +{ return total_usb_host_devices; } -USB_Device_Type_t get_usb_host_device_type(uint8_t id) { +USB_Device_Type_t get_usb_host_device_type(uint8_t id) +{ return usb_host_devices[id].type; } -uint8_t get_usb_host_device_data(uint8_t id, uint8_t *buf) { - if (usb_host_devices[id].type.console_type == GENERIC) { +uint8_t get_usb_host_device_data(uint8_t id, uint8_t *buf) +{ + if (usb_host_devices[id].type.console_type == GENERIC) + { USB_Host_Data_t *host = (USB_Host_Data_t *)buf; fill_generic_report_host(usb_host_devices[id].type.dev_addr, usb_host_devices[id].type.instance, (uint8_t *)&usb_host_devices[id].report, host); @@ -342,8 +383,10 @@ uint8_t get_usb_host_device_data(uint8_t id, uint8_t *buf) { return usb_host_devices[id].report_length; } -uint8_t read_usb_host_devices(uint8_t *buf) { - for (int i = 0; i < total_usb_host_devices; i++) { +uint8_t read_usb_host_devices(uint8_t *buf) +{ + for (int i = 0; i < total_usb_host_devices; i++) + { USB_Device_Type_t *type = &usb_host_devices[i].type; buf[(i * 2)] = type->console_type; buf[(i * 2) + 1] = type->sub_type; @@ -351,7 +394,8 @@ uint8_t read_usb_host_devices(uint8_t *buf) { return total_usb_host_devices * 2; } -bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_type, uint8_t sub_type) { +bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_type, uint8_t sub_type) +{ printf("Detected controller: %d (%d) on %d, %d\r\n", console_type, sub_type, dev_addr, instance); uint16_t host_vid = 0; uint16_t host_pid = 0; @@ -361,116 +405,127 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ tuh_descriptor_get_device_sync(dev_addr, buf, sizeof(USB_DEVICE_DESCRIPTOR)); USB_DEVICE_DESCRIPTOR *desc = (USB_DEVICE_DESCRIPTOR *)buf; get_usb_device_type_for(host_vid, host_pid, desc->bcdDevice, &type); - switch (type.console_type) { - case XBOX360: - x360_dev_addr = type; - usb_host_devices[total_usb_host_devices].type = type; - total_usb_host_devices++; - xinput_controller_connected(host_vid, host_pid); - break; - case XBOX360_W: - x360_dev_addr = type; - usb_host_devices[total_usb_host_devices].type = type; - total_usb_host_devices++; - printf("found xb360 wireless\r\n"); - send_report_to_controller(dev_addr, instance, xbox360w_prescence, sizeof(xbox360w_prescence)); - break; - case XBOXONE: - xone_dev_addr = type; - xone_controller_connected(dev_addr, instance); - usb_host_devices[total_usb_host_devices].type = type; - usb_host_devices[total_usb_host_devices].xone_init_id = 0; - total_usb_host_devices++; - if (consoleType == XBOXONE) { - foundXB = true; - } - break; - case SANTROLLER: { - tuh_descriptor_get_product_string_sync(dev_addr, 0, buf, sizeof(buf)); - usb_host_devices[total_usb_host_devices].type = type; - total_usb_host_devices++; - printf("Found Santroller controller\r\n"); - printf("Sub type: %d\r\n", type.sub_type); - break; + switch (type.console_type) + { + case XBOX360: + x360_dev_addr = type; + usb_host_devices[total_usb_host_devices].type = type; + total_usb_host_devices++; + xinput_controller_connected(host_vid, host_pid); + break; + case XBOX360_W: + x360_dev_addr = type; + usb_host_devices[total_usb_host_devices].type = type; + total_usb_host_devices++; + printf("found xb360 wireless\r\n"); + send_report_to_controller(dev_addr, instance, xbox360w_prescence, sizeof(xbox360w_prescence)); + break; + case XBOXONE: + xone_dev_addr = type; + xone_controller_connected(dev_addr, instance); + usb_host_devices[total_usb_host_devices].type = type; + usb_host_devices[total_usb_host_devices].xone_init_id = 0; + total_usb_host_devices++; + if (consoleType == XBOXONE) + { + foundXB = true; } - case RAPHNET: { - uint8_t data[] = {0x00, 0x00, 0x00}; - uint8_t data2[] = {0x06, 0x00, 0x00}; - for (int i = 0; i < 10; i++) { - transfer_with_usb_controller(dev_addr, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE, HID_REQUEST_SET_REPORT, 0x0300, 1, 3, data2, NULL); - transfer_with_usb_controller(dev_addr, USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE, HID_REQUEST_GET_REPORT, 0x0300, 1, 3, data, NULL); - if (data[0]) { - break; - } - sleep_ms(100); - } - switch (data[2]) { - case RNT_TYPE_PSX_DIGITAL: - case RNT_TYPE_PSX_ANALOG: - case RNT_TYPE_PSX_NEGCON: - case RNT_TYPE_PSX_MOUSE: - case RNT_TYPE_CLASSIC: - case RNT_TYPE_UDRAW_TABLET: - case RNT_TYPE_NUNCHUK: - case RNT_TYPE_CLASSIC_PRO: - type.sub_type = GAMEPAD; - break; - case RNT_TYPE_WII_GUITAR: - type.sub_type = GUITAR_HERO_GUITAR; - break; - case RNT_TYPE_WII_DRUM: - type.sub_type = GUITAR_HERO_DRUMS; - break; + break; + case SANTROLLER: + { + tuh_descriptor_get_product_string_sync(dev_addr, 0, buf, sizeof(buf)); + usb_host_devices[total_usb_host_devices].type = type; + total_usb_host_devices++; + printf("Found Santroller controller\r\n"); + printf("Sub type: %d\r\n", type.sub_type); + break; + } + case RAPHNET: + { + uint8_t data[] = {0x00, 0x00, 0x00}; + uint8_t data2[] = {0x06, 0x00, 0x00}; + for (int i = 0; i < 10; i++) + { + transfer_with_usb_controller(dev_addr, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE, HID_REQUEST_SET_REPORT, 0x0300, 1, 3, data2, NULL); + transfer_with_usb_controller(dev_addr, USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE, HID_REQUEST_GET_REPORT, 0x0300, 1, 3, data, NULL); + if (data[0]) + { + break; } - printf("Found Raphnet controller\r\n"); - printf("Sub type: %02x\r\n", type.sub_type); - usb_host_devices[total_usb_host_devices].type = type; - total_usb_host_devices++; - break; + sleep_ms(100); } - case XBOX360_BB: - case OG_XBOX: - case KEYBOARD: - case MOUSE: - case STREAM_DECK: - case PS5: - case SWITCH: - case UNKNOWN: - case GENERIC: - case STEPMANIAX: - case LTEK: - case LTEK_ID: - case XINPUTCOMPAT: - case STADIA: - printf("Found Generic controller\r\n"); - usb_host_devices[total_usb_host_devices].type = type; - total_usb_host_devices++; + switch (data[2]) + { + case RNT_TYPE_PSX_DIGITAL: + case RNT_TYPE_PSX_ANALOG: + case RNT_TYPE_PSX_NEGCON: + case RNT_TYPE_PSX_MOUSE: + case RNT_TYPE_CLASSIC: + case RNT_TYPE_UDRAW_TABLET: + case RNT_TYPE_NUNCHUK: + case RNT_TYPE_CLASSIC_PRO: + type.sub_type = GAMEPAD; break; - case PS3: - // GHWT and GH5 guitars have the same vid and pid, but different tap bar functions. We can read the device name to actually determine what it is - if (type.sub_type == GUITAR_HERO_GUITAR && XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(dev_addr, 0, buf, sizeof(buf))) { - uint16_t wtProduct[] = {'G', 'u', 'i', 't', 'a', 'r', ' ', 'H', 'e', 'r', 'o', '4'}; - if (memcmp(wtProduct, buf, sizeof(wtProduct)) || memcmp(wtProduct, buf + 1, sizeof(wtProduct))) { - type.sub_type = GUITAR_HERO_GUITAR_WT; - } - } - usb_host_devices[total_usb_host_devices].type = type; - usb_host_devices[total_usb_host_devices].xone_init_id = millis(); - total_usb_host_devices++; - printf("Found PS3 controller\r\n"); - printf("Sub type: %d\r\n", type.sub_type); - ps3_controller_connected(dev_addr, host_vid, host_pid); + case RNT_TYPE_WII_GUITAR: + type.sub_type = GUITAR_HERO_GUITAR; break; - case PS4: - usb_host_devices[total_usb_host_devices].type = type; - total_usb_host_devices++; - if (!ps4_dev_addr.dev_addr) { - ps4_dev_addr = type; - - printf("Found PS4 controller\r\n"); - ps4_controller_connected(dev_addr, host_vid, host_pid); - } + case RNT_TYPE_WII_DRUM: + type.sub_type = GUITAR_HERO_DRUMS; break; + } + printf("Found Raphnet controller\r\n"); + printf("Sub type: %02x\r\n", type.sub_type); + usb_host_devices[total_usb_host_devices].type = type; + total_usb_host_devices++; + break; + } + case XBOX360_BB: + case OG_XBOX: + case KEYBOARD: + case MOUSE: + case STREAM_DECK: + case PS5: + case SWITCH: + case SWITCH2: + case UNKNOWN: + case GENERIC: + case STEPMANIAX: + case LTEK: + case LTEK_ID: + case XINPUTCOMPAT: + case STADIA: + printf("Found Generic controller\r\n"); + usb_host_devices[total_usb_host_devices].type = type; + total_usb_host_devices++; + break; + case PS3: + // GHWT and GH5 guitars have the same vid and pid, but different tap bar functions. We can read the device name to actually determine what it is + if (type.sub_type == GUITAR_HERO_GUITAR && XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(dev_addr, 0, buf, sizeof(buf))) + { + uint16_t wtProduct[] = {'G', 'u', 'i', 't', 'a', 'r', ' ', 'H', 'e', 'r', 'o', '4'}; + if (memcmp(wtProduct, buf, sizeof(wtProduct)) || memcmp(wtProduct, buf + 1, sizeof(wtProduct))) + { + type.sub_type = GUITAR_HERO_GUITAR_WT; + } + } + usb_host_devices[total_usb_host_devices].type = type; + usb_host_devices[total_usb_host_devices].xone_init_id = millis(); + total_usb_host_devices++; + printf("Found PS3 controller\r\n"); + printf("Sub type: %d\r\n", type.sub_type); + ps3_controller_connected(dev_addr, host_vid, host_pid); + break; + case PS4: + usb_host_devices[total_usb_host_devices].type = type; + total_usb_host_devices++; + if (!ps4_dev_addr.dev_addr) + { + ps4_dev_addr = type; + + printf("Found PS4 controller\r\n"); + ps4_controller_connected(dev_addr, host_vid, host_pid); + } + break; } printf("Total devices: %d\r\n", total_usb_host_devices); @@ -478,15 +533,19 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ return true; } -void tuh_xinput_umount_cb(uint8_t dev_addr, uint8_t instance) { +void tuh_xinput_umount_cb(uint8_t dev_addr, uint8_t instance) +{ printf("Unplugged %d\r\n", dev_addr); - if (xone_dev_addr.dev_addr == dev_addr && xone_dev_addr.instance == instance) { + if (xone_dev_addr.dev_addr == dev_addr && xone_dev_addr.instance == instance) + { xone_dev_addr.dev_addr = 0; } - if (x360_dev_addr.dev_addr == dev_addr && x360_dev_addr.instance == instance) { + if (x360_dev_addr.dev_addr == dev_addr && x360_dev_addr.instance == instance) + { x360_dev_addr.dev_addr = 0; } - if (ps4_dev_addr.dev_addr == dev_addr && ps4_dev_addr.instance == instance) { + if (ps4_dev_addr.dev_addr == dev_addr && ps4_dev_addr.instance == instance) + { ps4_dev_addr.dev_addr = 0; ps4_controller_disconnected(); } @@ -494,12 +553,17 @@ void tuh_xinput_umount_cb(uint8_t dev_addr, uint8_t instance) { total_usb_host_devices = 0; } bool wasXb1Input = false; -void tuh_xinput_report_sent_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) { +void tuh_xinput_report_sent_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) +{ // If there are xb1 init packets to send, send them - for (int i = 0; i < total_usb_host_devices; i++) { - if (usb_host_devices[i].type.dev_addr == dev_addr && usb_host_devices[i].type.instance == instance) { - if (usb_host_devices[i].type.console_type == XBOXONE) { - if (xone_controller_send_init_packet(dev_addr, instance, usb_host_devices[i].xone_init_id)) { + for (int i = 0; i < total_usb_host_devices; i++) + { + if (usb_host_devices[i].type.dev_addr == dev_addr && usb_host_devices[i].type.instance == instance) + { + if (usb_host_devices[i].type.console_type == XBOXONE) + { + if (xone_controller_send_init_packet(dev_addr, instance, usb_host_devices[i].xone_init_id)) + { usb_host_devices[i].xone_init_id++; } } @@ -508,38 +572,50 @@ void tuh_xinput_report_sent_cb(uint8_t dev_addr, uint8_t instance, uint8_t const } long lastPlayerLed = 0; long lastWakeup = 0; -void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) { - if (!len) { +void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) +{ + if (!len) + { // Skip processing a null report, assume it is corrupted return; } - if (dev_addr == xone_dev_addr.dev_addr && instance == xone_dev_addr.instance) { + if (dev_addr == xone_dev_addr.dev_addr && instance == xone_dev_addr.instance) + { receive_report_from_controller(report, len); } // Send player indicator every 10 seconds or so just as a keep alive - if (millis() - lastPlayerLed > 10000) { + if (millis() - lastPlayerLed > 10000) + { handle_player_leds(0); lastPlayerLed = millis(); } - for (int i = 0; i < total_usb_host_devices; i++) { - if (usb_host_devices[i].type.dev_addr == dev_addr && usb_host_devices[i].type.instance == instance) { - if (usb_host_devices[i].type.console_type == XBOXONE) { + for (int i = 0; i < total_usb_host_devices; i++) + { + if (usb_host_devices[i].type.dev_addr == dev_addr && usb_host_devices[i].type.instance == instance) + { + if (usb_host_devices[i].type.console_type == XBOXONE) + { GipHeader_t *header = (GipHeader_t *)report; - if (header->command == GIP_VIRTUAL_KEYCODE) { + if (header->command == GIP_VIRTUAL_KEYCODE) + { GipKeystroke_t *keystroke = (GipKeystroke_t *)report; - if (wasXb1Input) { + if (wasXb1Input) + { XboxOneInputHeader_Data_t *gamepad = (XboxOneInputHeader_Data_t *)(&(usb_host_devices[i].report)); gamepad->guide = keystroke->pressed; } return; } - if (header->command != GHL_HID_REPORT && header->command != GIP_INPUT_REPORT) { + if (header->command != GHL_HID_REPORT && header->command != GIP_INPUT_REPORT) + { return; } wasXb1Input = header->command == GIP_INPUT_REPORT; } - if ((millis() - usb_host_devices[i].xone_init_id) < 5000) { - if (usb_host_devices[i].type.console_type == PS3 && usb_host_devices[i].type.sub_type == ROCK_BAND_PRO_KEYS) { + if ((millis() - usb_host_devices[i].xone_init_id) < 5000) + { + if (usb_host_devices[i].type.console_type == PS3 && usb_host_devices[i].type.sub_type == ROCK_BAND_PRO_KEYS) + { uint8_t hid_command_enable[40] = { 0xE9, 0x00, 0x89, 0x1B, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -549,36 +625,49 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c transfer_with_usb_controller(dev_addr, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS, HID_REQUEST_SET_REPORT, 0x0300, 0, sizeof(hid_command_enable), hid_command_enable, NULL); } } - if (usb_host_devices[i].type.console_type == XBOX360_W) { + if (usb_host_devices[i].type.console_type == XBOX360_W) + { // Corrupt report, ignore - if (len < sizeof(XBOX_WIRELESS_HEADER)) { + if (len < sizeof(XBOX_WIRELESS_HEADER)) + { return; } XBOX_WIRELESS_HEADER *header = (XBOX_WIRELESS_HEADER *)report; - if (header->id == 0x08) { + if (header->id == 0x08) + { // Disconnected - if (header->type == 0x00) { + if (header->type == 0x00) + { usb_host_devices[i].type.sub_type = UNKNOWN; printf("Disconnected\r\n", dev_addr, instance); } - } else if (header->id == 0x00) { + } + else if (header->id == 0x00) + { // Gamepad inputs - if (header->type == 0x01 || header->type == 0x03) { + if (header->type == 0x01 || header->type == 0x03) + { memcpy(&usb_host_devices[i].report, report + sizeof(header), len - sizeof(header)); usb_host_devices[i].report_length = len - sizeof(header); - if (usb_host_devices[i].type.sub_type == XINPUT_DRUMS) { + if (usb_host_devices[i].type.sub_type == XINPUT_DRUMS) + { XInputGamepad_Data_t *gamepad = (XInputGamepad_Data_t *)&usb_host_devices[i].report; - if (gamepad->leftThumbClick) { + if (gamepad->leftThumbClick) + { usb_host_devices[i].type.sub_type = XINPUT_GH_DRUMS; - } else { + } + else + { usb_host_devices[i].type.sub_type = XINPUT_RB_DRUMS; } } } // Link report - if (header->type == 0x0f) { + if (header->type == 0x0f) + { XBOX_WIRELESS_LINK_REPORT *linkReport = (XBOX_WIRELESS_LINK_REPORT *)report; - if (linkReport->always_0xCC != 0xCC) { + if (linkReport->always_0xCC != 0xCC) + { return; } uint8_t sub_type = linkReport->subtype & ~0x80; @@ -586,18 +675,22 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c printf("Found subtype: %02x %02x %02x\r\n", sub_type, dev_addr, instance); xinput_w_controller_connected(); // Request capabilities so we can figure out WT guitars - if (sub_type == XINPUT_GUITAR_ALTERNATE) { + if (sub_type == XINPUT_GUITAR_ALTERNATE) + { // request capabilities send_report_to_controller(dev_addr, instance, capabilitiesRequest, sizeof(capabilitiesRequest)); } } - if (header->type == 0x05) { + if (header->type == 0x05) + { XBOX_WIRELESS_CAPABILITIES *caps = (XBOX_WIRELESS_CAPABILITIES *)report; - if (caps->always_0x12 != 0x12) { + if (caps->always_0x12 != 0x12) + { return; } printf("Found capabilities: %02x %02x\r\n", dev_addr, instance); - if (caps->leftStickX == 0xFFC0 && caps->rightStickX == 0xFFC0) { + if (caps->leftStickX == 0xFFC0 && caps->rightStickX == 0xFFC0) + { usb_host_devices[i].type.sub_type = XINPUT_GUITAR_WT; printf("Found wt\r\n"); } @@ -605,42 +698,71 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c } return; } - if (usb_host_devices[i].type.console_type == STREAM_DECK && report[0] != STREAM_DECK_INPUT_REPORT_ID) { + if (usb_host_devices[i].type.console_type == STREAM_DECK && report[0] != STREAM_DECK_INPUT_REPORT_ID) + { continue; } - if (usb_host_devices[i].type.console_type == PS5 && report[0] != PS5_INPUT_REPORT_ID) { + if (usb_host_devices[i].type.console_type == PS5 && report[0] != PS5_INPUT_REPORT_ID) + { continue; } - if (usb_host_devices[i].type.console_type == STEPMANIAX && report[0] != STEPMANIA_X_REPORT_ID) { + if (usb_host_devices[i].type.console_type == STEPMANIAX && report[0] != STEPMANIA_X_REPORT_ID) + { continue; } - if (usb_host_devices[i].type.console_type == STADIA && report[0] != STADIA_REPORT_ID) { + if (usb_host_devices[i].type.console_type == STADIA && report[0] != STADIA_REPORT_ID) + { continue; } - if (usb_host_devices[i].type.console_type == SWITCH && usb_host_devices[i].type.sub_type == GAMEPAD) { - if (!usb_host_devices[i].switch_sent_handshake) { + if (usb_host_devices[i].type.console_type == SWITCH && usb_host_devices[i].type.sub_type == GAMEPAD) + { + if (!usb_host_devices[i].switch_sent_handshake) + { usb_host_devices[i].switch_sent_handshake = true; uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x02 /* PROCON_USB_HANDSHAKE */}; send_report_to_controller(dev_addr, instance, buf, 2); - } else if (!usb_host_devices[i].switch_sent_timeout) { + } + else if (!usb_host_devices[i].switch_sent_timeout) + { usb_host_devices[i].switch_sent_timeout = true; uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x04 /* PROCON_USB_ENABLE */}; send_report_to_controller(dev_addr, instance, buf, 2); } - if (report[0] != SWITCH_PRO_CON_FULL_REPORT_ID) { + if (report[0] != SWITCH_PRO_CON_FULL_REPORT_ID) + { + continue; + } + } + if (usb_host_devices[i].type.console_type == SWITCH2 && usb_host_devices[i].type.sub_type == GAMEPAD) + { + if (!usb_host_devices[i].switch_sent_handshake) + { + usb_host_devices[i].switch_sent_handshake = true; + uint8_t buf[] = { 0x03, 0x91, 0x00, 0x0d, 0x00, 0x08, + 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF; + send_report_to_controller(dev_addr, instance, buf, sizeof(buf)); + } + + if (report[0] != SWITCH_2_GC_FULL_REPORT_ID) + { continue; } } memcpy(&usb_host_devices[i].report, report, len); usb_host_devices[i].report_length = len; - if (usb_host_devices[i].type.console_type == XBOX360 && usb_host_devices[i].type.sub_type == XINPUT_DRUMS) { + if (usb_host_devices[i].type.console_type == XBOX360 && usb_host_devices[i].type.sub_type == XINPUT_DRUMS) + { XInputGamepad_Data_t *gamepad = (XInputGamepad_Data_t *)&usb_host_devices[i].report; - if (gamepad->rsize == sizeof(XInputGamepad_Data_t)) { - if (gamepad->leftThumbClick) { + if (gamepad->rsize == sizeof(XInputGamepad_Data_t)) + { + if (gamepad->leftThumbClick) + { usb_host_devices[i].type.sub_type = XINPUT_GH_DRUMS; - } else { + } + else + { usb_host_devices[i].type.sub_type = XINPUT_RB_DRUMS; } } @@ -670,40 +792,50 @@ usbh_class_driver_t driver_host[] = { .xfer_cb = midih_xfer_cb, .close = midih_close}}; -usbh_class_driver_t const *usbh_app_driver_get_cb(uint8_t *driver_count) { +usbh_class_driver_t const *usbh_app_driver_get_cb(uint8_t *driver_count) +{ *driver_count = 2; return driver_host; } #endif -uint8_t const *tud_descriptor_device_cb(void) { +uint8_t const *tud_descriptor_device_cb(void) +{ descriptorRequest(USB_DESCRIPTOR_DEVICE << 8, 0, buf); return buf; } -uint8_t const *tud_hid_custom_descriptor_report_cb(uint8_t instance) { +uint8_t const *tud_hid_custom_descriptor_report_cb(uint8_t instance) +{ descriptorRequest(HID_DESCRIPTOR_REPORT << 8, instance, buf); return buf; } -uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { - (void)index; // for multiple configurations +uint8_t const *tud_descriptor_configuration_cb(uint8_t index) +{ + (void)index; // for multiple configurations descriptorRequest(USB_DESCRIPTOR_CONFIGURATION << 8, index, buf); return buf; } -uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { +uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) +{ // Arduinos handle their own serial descriptor, so theres no point in sharing an implementation there. - if (index == 3) { + if (index == 3) + { return (uint16_t *)&serialstring; } - if (descriptorRequest(USB_DESCRIPTOR_STRING << 8 | index, 0, buf)) { + if (descriptorRequest(USB_DESCRIPTOR_STRING << 8 | index, 0, buf)) + { return (uint16_t *)buf; } return NULL; } -uint32_t transfer_with_usb_controller(const uint8_t dev_addr, const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, uint8_t *buffer, bool *status) { - if (!dev_addr) { +uint32_t transfer_with_usb_controller(const uint8_t dev_addr, const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, uint8_t *buffer, bool *status) +{ + if (!dev_addr) + { // Device is not connected yet! - if (status) { + if (status) + { *status = false; } return 0; @@ -723,8 +855,10 @@ uint32_t transfer_with_usb_controller(const uint8_t dev_addr, const uint8_t requ xfer.complete_cb = NULL; xfer.user_data = 0; tuh_control_xfer(&xfer); - if (xfer.result != XFER_RESULT_SUCCESS) { - if (status) { + if (xfer.result != XFER_RESULT_SUCCESS) + { + if (status) + { *status = false; } return false; @@ -732,42 +866,58 @@ uint32_t transfer_with_usb_controller(const uint8_t dev_addr, const uint8_t requ return xfer.actual_len; } tusb_control_request_t lastreq; -bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) { - if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_GET_DESCRIPTOR) { +bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) +{ + if (request->bmRequestType_bit.type == TUSB_REQ_TYPE_STANDARD && request->bRequest == TUSB_REQ_GET_DESCRIPTOR) + { //------------- STD Request -------------// - if (stage == CONTROL_STAGE_SETUP) { + if (stage == CONTROL_STAGE_SETUP) + { uint8_t const desc_type = tu_u16_high(request->wValue); // uint8_t const desc_index = tu_u16_low (request->wValue); - if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESCRIPTOR_HID) { + if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESCRIPTOR_HID) + { uint16_t len = descriptorRequest(HID_DESCRIPTOR_HID << 8, request->wIndex, buf); TU_VERIFY(tud_control_xfer(rhport, request, buf, len)); return true; - } else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESCRIPTOR_REPORT) { + } + else if (request->bRequest == TUSB_REQ_GET_DESCRIPTOR && desc_type == HID_DESCRIPTOR_REPORT) + { uint16_t len = descriptorRequest(HID_DESCRIPTOR_REPORT << 8, request->wIndex, buf); TU_VERIFY(tud_control_xfer(rhport, request, buf, len)); return true; - } else { - return false; // stall unsupported request + } + else + { + return false; // stall unsupported request } } } - if (controlRequestValid(request->bmRequestType, request->bRequest, request->wValue, request->wIndex, request->wLength)) { + if (controlRequestValid(request->bmRequestType, request->bRequest, request->wValue, request->wIndex, request->wLength)) + { bool status = true; - if (request->bmRequestType_bit.direction == TUSB_DIR_IN) { - if (stage == CONTROL_STAGE_SETUP) { + if (request->bmRequestType_bit.direction == TUSB_DIR_IN) + { + if (stage == CONTROL_STAGE_SETUP) + { uint16_t len = controlRequest(request->bmRequestType, request->bRequest, request->wValue, request->wIndex, request->wLength, buf, &status); tud_control_xfer(rhport, request, buf, len); } - } else { - if (stage == CONTROL_STAGE_SETUP) { + } + else + { + if (stage == CONTROL_STAGE_SETUP) + { tud_control_xfer(rhport, request, buf, request->wLength); } - if (stage == CONTROL_STAGE_DATA || (stage == CONTROL_STAGE_SETUP && !request->wLength)) { + if (stage == CONTROL_STAGE_DATA || (stage == CONTROL_STAGE_SETUP && !request->wLength)) + { uint8_t ret = controlRequest(request->bmRequestType, request->bRequest, request->wValue, request->wIndex, request->wLength, buf, &status); } } - if (!status) { + if (!status) + { return status; } } @@ -787,20 +937,25 @@ usbd_class_driver_t driver[] = { .xfer_cb = xinputd_xfer_cb, .sof = NULL}}; -usbd_class_driver_t const *usbd_app_driver_get_cb(uint8_t *driver_count) { +usbd_class_driver_t const *usbd_app_driver_get_cb(uint8_t *driver_count) +{ *driver_count = 1; return driver; } -void reboot(void) { +void reboot(void) +{ watchdog_enable(1, false); - for (;;) { + for (;;) + { } } -void bootloader(void) { +void bootloader(void) +{ reset_usb_boot(0, 0); } -void reset_usb(void) { +void reset_usb(void) +{ persistedConsoleType = consoleType; persistedConsoleTypeValid = PERSISTED_CONSOLE_TYPE_VALID; reboot(); diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 3e9fd2ffd..398fadcf2 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1587,6 +1587,54 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t } break; } + case SWITCH2: { + switch (device_type.sub_type) { + case GAMEPAD: { + Switch2ProGamepad_Data_t *report = (Switch2ProGamepad_Data_t *)data; + usb_host_data->dpadLeft = report->dpad == 6 || report->dpad == 5 || report->dpad == 7; + usb_host_data->dpadRight = report->dpad == 3 || report->dpad == 2 || report->dpad == 1; + usb_host_data->dpadUp = report->dpad == 0 || report->dpad == 1 || report->dpad == 7; + usb_host_data->dpadDown = report->dpad == 5 || report->dpad == 4 || report->dpad == 3; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->capture |= report->capture; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->rightThumbClick |= report->rightThumbClick; + if (report->leftTrigger) { + usb_host_data->leftTrigger = report->leftTrigger << 8; + } + if (report->rightTrigger) { + usb_host_data->rightTrigger = report->rightTrigger << 8; + } + if (report->leftStickX != SWITCH_2_STICK_CENTER) { + usb_host_data->leftStickX = (report->leftStickX - SWITCH_2_STICK_CENTER) << 5; + } + if (report->leftStickY != SWITCH_2_STICK_CENTER) { + usb_host_data->leftStickY = (((4096 - report->leftStickY) - SWITCH_2_STICK_CENTER)) << 5; + } + if (report->rightStickX != SWITCH_2_STICK_CENTER) { + usb_host_data->rightStickX = (report->rightStickX - SWITCH_2_STICK_CENTER) << 5; + } + if (report->rightStickY != SWITCH_2_STICK_CENTER) { + usb_host_data->rightStickY = (((4096 - report->rightStickY) - SWITCH_2_STICK_CENTER)) << 5; + } + break; + } + } + break; + } case OG_XBOX: { OGXboxGamepad_Data_t *report = (OGXboxGamepad_Data_t *)data; usb_host_data->a |= report->a > 0x20; @@ -3386,6 +3434,22 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D type->console_type = SWITCH; type->sub_type = GAMEPAD; } + if (pid == SWITCH_2_PRO_PID) { + type->console_type = SWITCH2; + type->sub_type = GAMEPAD; + } + if (pid == SWITCH_2_GC_PID) { + type->console_type = SWITCH2; + type->sub_type = GAMEPAD; + } + if (pid == SWITCH_2_JOY_R_PID) { + type->console_type = SWITCH2; + type->sub_type = GAMEPAD; + } + if (pid == SWITCH_2_JOY_L_PID) { + type->console_type = SWITCH2; + type->sub_type = GAMEPAD; + } break; } case ARDWIINO_VID: { From fc128d2cc0262e6827981205efeaa65e74a87c9b Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 16 Jun 2025 20:43:00 +1200 Subject: [PATCH 044/239] switch 2 controller support --- include/reports/switch_reports.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/reports/switch_reports.h b/include/reports/switch_reports.h index f6c2dbaad..2066d2561 100644 --- a/include/reports/switch_reports.h +++ b/include/reports/switch_reports.h @@ -14,7 +14,7 @@ typedef struct { uint8_t reportId; // 0x0A uint8_t packetId; // counts up for each packet - uint8_t status; // 0x20 + uint8_t status; // 0x20 uint8_t b : 1; uint8_t a : 1; uint8_t y : 1; @@ -30,7 +30,8 @@ typedef struct uint8_t dpadUp : 1; uint8_t l2 : 1; uint8_t leftShoulder : 1; - uint8_t : 2; + uint8_t back : 1; + uint8_t : 1; uint8_t guide : 1; uint8_t capture : 1; From 2de072213c8f8b7b5430f58d6956affc251b1857 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 16 Jun 2025 20:45:32 +1200 Subject: [PATCH 045/239] switch 2 controller support --- include/reports/switch_reports.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/reports/switch_reports.h b/include/reports/switch_reports.h index 2066d2561..2821f691f 100644 --- a/include/reports/switch_reports.h +++ b/include/reports/switch_reports.h @@ -22,7 +22,7 @@ typedef struct uint8_t r2 : 1; uint8_t rightShoulder : 1; uint8_t start : 1; - uint8_t : 1; + uint8_t rightThumbClick: 1; uint8_t dpadDown : 1; uint8_t dpadRight : 1; @@ -31,7 +31,7 @@ typedef struct uint8_t l2 : 1; uint8_t leftShoulder : 1; uint8_t back : 1; - uint8_t : 1; + uint8_t leftThumbClick: 1; uint8_t guide : 1; uint8_t capture : 1; From c6a21bce63146fa2e40d05d3818ed471ca67e6f9 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 16 Jun 2025 20:52:36 +1200 Subject: [PATCH 046/239] switch 2 support --- src/shared/main/shared_main.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 398fadcf2..bd4723df2 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1591,10 +1591,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t switch (device_type.sub_type) { case GAMEPAD: { Switch2ProGamepad_Data_t *report = (Switch2ProGamepad_Data_t *)data; - usb_host_data->dpadLeft = report->dpad == 6 || report->dpad == 5 || report->dpad == 7; - usb_host_data->dpadRight = report->dpad == 3 || report->dpad == 2 || report->dpad == 1; - usb_host_data->dpadUp = report->dpad == 0 || report->dpad == 1 || report->dpad == 7; - usb_host_data->dpadDown = report->dpad == 5 || report->dpad == 4 || report->dpad == 3; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; usb_host_data->green |= report->a; usb_host_data->red |= report->b; usb_host_data->yellow |= report->y; From 70425333fce9c11c082a6bd3d7ef303a6f5632f2 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 16 Jun 2025 21:01:30 +1200 Subject: [PATCH 047/239] switch 2 controller support --- include/reports/switch_reports.h | 42 ++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/include/reports/switch_reports.h b/include/reports/switch_reports.h index 2821f691f..b3cb2ff20 100644 --- a/include/reports/switch_reports.h +++ b/include/reports/switch_reports.h @@ -51,6 +51,48 @@ typedef struct uint8_t motionBuffer[10]; } __attribute__((packed)) Switch2ProGamepad_Data_t; +typedef struct { + uint8_t connection_info : 4; + uint8_t battery_level : 4; + + uint8_t y : 1; + uint8_t x : 1; + uint8_t b : 1; + uint8_t a : 1; + + uint8_t dummy1 : 2; + uint8_t rightShoulder : 1; + uint8_t rightTrigger : 1; + + uint8_t back : 1; // minus + uint8_t start : 1; // plus + uint8_t leftThumbClick : 1; // l3 + uint8_t rightThumbClick : 1; // r3 + + uint8_t guide : 1; // home + uint8_t capture : 1; + uint8_t dummy2 : 2; + + uint8_t dpad : 4; + + uint8_t dummy3 : 2; + uint8_t leftShoulder : 1; + uint8_t leftTrigger : 1; + + // Bytes 6-11 + uint8_t leftStickX; + uint8_t leftStickY; + uint8_t rightStickX; + uint8_t rightStickY; + + uint8_t vibratorInput; // What is this used for? + + // Bytes 13-48 + // Three samples of the IMU is sent in one message + // See: https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/imu_sensor_notes.md + ImuData imu[3]; +} __attribute__((packed)) SwitchProGamepad_Data_t; + typedef struct { // Button bits From 35187159411eef95a558c21e19c86b2a517068eb Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 17 Jun 2025 08:57:04 +1200 Subject: [PATCH 048/239] fix compile error --- src/pico/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 081359198..4498b90f8 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -740,7 +740,7 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c { usb_host_devices[i].switch_sent_handshake = true; uint8_t buf[] = { 0x03, 0x91, 0x00, 0x0d, 0x00, 0x08, - 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF; + 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; send_report_to_controller(dev_addr, instance, buf, sizeof(buf)); } From 58d0108bfd49d3c79d7864d4768ea50f4d1c8ae4 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 18 Jun 2025 18:44:42 +1200 Subject: [PATCH 049/239] send switch2 led packet --- src/pico/main.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 4498b90f8..c216e7585 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -739,8 +739,14 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c if (!usb_host_devices[i].switch_sent_handshake) { usb_host_devices[i].switch_sent_handshake = true; - uint8_t buf[] = { 0x03, 0x91, 0x00, 0x0d, 0x00, 0x08, - 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + uint8_t buf[] = {0x03, 0x91, 0x00, 0x0d, 0x00, 0x08, + 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + send_report_to_controller(dev_addr, instance, buf, sizeof(buf)); + } + else if (!usb_host_devices[i].switch_sent_timeout) + { + usb_host_devices[i].switch_sent_timeout = true; + uint8_t buf[] = {0x09, 0x91, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0, 0}; send_report_to_controller(dev_addr, instance, buf, sizeof(buf)); } From d8a6a568d86d11ba4fd92ebcb06f8aa1ed308455 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 24 Jun 2025 20:27:09 +1200 Subject: [PATCH 050/239] remap gh midi notes to be more sane --- include/defines.h | 16 ++++++++++- include/shared_main.h | 1 + include/state_translation/drums.h | 26 ++++++++--------- src/pico/main.cpp | 48 ++++++++++++++++++++++++++----- src/shared/main/wii.cpp | 21 +++++++++++++- 5 files changed, 90 insertions(+), 22 deletions(-) diff --git a/include/defines.h b/include/defines.h index ad1c5122c..87dd4e772 100644 --- a/include/defines.h +++ b/include/defines.h @@ -149,6 +149,11 @@ #define BTN_END 0x0f #define BTN_USAGE(x) 0x09, x +#define DRUM_UNKNOWN 0 +#define DRUM_RB1 1 +#define DRUM_RB2 2 +#define DRUM_GH 3 + typedef enum { WII_NUNCHUK = 0x0000, WII_CLASSIC_CONTROLLER = 0x0001, @@ -225,4 +230,13 @@ typedef enum { #define RB_MIDI_NOTE_GREEN_CYMBAL 49 #define RB_MIDI_NOTE_YELLOW_CYMBAL 22 #define RB_MIDI_NOTE_BLUE_CYMBAL 51 -#define RB_MIDI_NOTE_KICK2 44 \ No newline at end of file +#define RB_MIDI_NOTE_KICK2 44 + +// Remapped GH midi notes as the standard ones are just not useful +#define GH_REM_MIDI_NOTE_KICK 36 +#define GH_REM_MIDI_NOTE_RED 38 +#define GH_REM_MIDI_NOTE_GREEN 41 +#define GH_REM_MIDI_NOTE_YELLOW 46 +#define GH_REM_MIDI_NOTE_BLUE 45 +#define GH_REM_MIDI_NOTE_ORANGE 51 +#define GH_REM_MIDI_NOTE_KICK2 100 \ No newline at end of file diff --git a/include/shared_main.h b/include/shared_main.h index b4d9ff73b..cbe1d5a32 100644 --- a/include/shared_main.h +++ b/include/shared_main.h @@ -38,6 +38,7 @@ typedef struct { uint8_t sub_type; uint8_t dev_addr; uint8_t instance; + uint8_t drum_type; } USB_Device_Type_t; void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_Device_Type_t *type); typedef struct { diff --git a/include/state_translation/drums.h b/include/state_translation/drums.h index dbd341808..4e55b0178 100644 --- a/include/state_translation/drums.h +++ b/include/state_translation/drums.h @@ -70,7 +70,7 @@ } \ } \ } \ - if (pad) { \ + if (pad || device_type.drum_type == DRUM_RB1) { \ if (yellow) { \ onNote(10, RB_MIDI_NOTE_YELLOW, yellowVelocity >> 1); \ } \ @@ -141,33 +141,33 @@ #else #define SET_GH_PADS() \ if (report->greenVelocity) { \ - onNote(10, GH_MIDI_NOTE_GREEN, report->greenVelocity); \ + onNote(10, GH_REM_MIDI_NOTE_GREEN, report->greenVelocity); \ } else { \ - offNote(10, GH_MIDI_NOTE_GREEN, report->greenVelocity); \ + offNote(10, GH_REM_MIDI_NOTE_GREEN, report->greenVelocity); \ } \ if (report->redVelocity) { \ - onNote(10, GH_MIDI_NOTE_RED, report->redVelocity); \ + onNote(10, GH_REM_MIDI_NOTE_RED, report->redVelocity); \ } else { \ - offNote(10, GH_MIDI_NOTE_RED, report->redVelocity); \ + offNote(10, GH_REM_MIDI_NOTE_RED, report->redVelocity); \ } \ if (report->yellowVelocity) { \ - onNote(10, GH_MIDI_NOTE_YELLOW, report->yellowVelocity); \ + onNote(10, GH_REM_MIDI_NOTE_YELLOW, report->yellowVelocity); \ } else { \ - offNote(10, GH_MIDI_NOTE_YELLOW, report->yellowVelocity); \ + offNote(10, GH_REM_MIDI_NOTE_YELLOW, report->yellowVelocity); \ } \ if (report->blueVelocity) { \ - onNote(10, GH_MIDI_NOTE_BLUE, report->blueVelocity); \ + onNote(10, GH_REM_MIDI_NOTE_BLUE, report->blueVelocity); \ } else { \ - offNote(10, GH_MIDI_NOTE_BLUE, report->blueVelocity); \ + offNote(10, GH_REM_MIDI_NOTE_BLUE, report->blueVelocity); \ } \ if (report->orangeVelocity) { \ - onNote(10, GH_MIDI_NOTE_ORANGE, report->orangeVelocity); \ + onNote(10, GH_REM_MIDI_NOTE_ORANGE, report->orangeVelocity); \ } else { \ - offNote(10, GH_MIDI_NOTE_ORANGE, report->orangeVelocity); \ + offNote(10, GH_REM_MIDI_NOTE_ORANGE, report->orangeVelocity); \ } \ if (report->kickVelocity) { \ - onNote(10, GH_MIDI_NOTE_KICK, report->kickVelocity); \ + onNote(10, GH_REM_MIDI_NOTE_KICK, report->kickVelocity); \ } else { \ - offNote(10, GH_MIDI_NOTE_KICK, report->kickVelocity); \ + offNote(10, GH_REM_MIDI_NOTE_KICK, report->kickVelocity); \ } #endif \ No newline at end of file diff --git a/src/pico/main.cpp b/src/pico/main.cpp index c216e7585..dc16a649c 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -401,10 +401,22 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ uint16_t host_pid = 0; tuh_vid_pid_get(dev_addr, &host_vid, &host_pid); printf("VID: %04x, PID: %04x \r\n", host_vid, host_pid); - USB_Device_Type_t type = {console_type, sub_type, dev_addr, instance}; + USB_Device_Type_t type = {console_type, sub_type, dev_addr, instance, DRUM_UNKNOWN}; tuh_descriptor_get_device_sync(dev_addr, buf, sizeof(USB_DEVICE_DESCRIPTOR)); USB_DEVICE_DESCRIPTOR *desc = (USB_DEVICE_DESCRIPTOR *)buf; get_usb_device_type_for(host_vid, host_pid, desc->bcdDevice, &type); + // XBOX 360 has other methods for determining drum type, so it inits as unknown + if (type.console_type != XBOX360) + { + if (type.sub_type == ROCK_BAND_DRUMS) + { + type.drum_type = DRUM_RB1; + } + if (type.sub_type == GUITAR_HERO_DRUMS) + { + type.drum_type = DRUM_GH; + } + } switch (type.console_type) { case XBOX360: @@ -758,21 +770,43 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c memcpy(&usb_host_devices[i].report, report, len); usb_host_devices[i].report_length = len; + // Xinput drum detection if (usb_host_devices[i].type.console_type == XBOX360 && usb_host_devices[i].type.sub_type == XINPUT_DRUMS) { - XInputGamepad_Data_t *gamepad = (XInputGamepad_Data_t *)&usb_host_devices[i].report; - if (gamepad->rsize == sizeof(XInputGamepad_Data_t)) + XInputRockBandDrums_Data_t *drums = (XInputRockBandDrums_Data_t *)&usb_host_devices[i].report; + if (drums->rsize == sizeof(XInputRockBandDrums_Data_t)) { - if (gamepad->leftThumbClick) + if (usb_host_devices[i].type.drum_type == DRUM_UNKNOWN) { - usb_host_devices[i].type.sub_type = XINPUT_GH_DRUMS; + if (drums->leftThumbClick) + { + usb_host_devices[i].type.sub_type = XINPUT_GH_DRUMS; + } + else + { + usb_host_devices[i].type.sub_type = XINPUT_RB_DRUMS; + } } - else + if (usb_host_devices[i].type.drum_type == DRUM_RB1) { - usb_host_devices[i].type.sub_type = XINPUT_RB_DRUMS; + // RB2 and newer kits set pad flags, so we have a newer kit here + if (drums->padFlag || drums->cymbalFlag) + { + usb_host_devices[i].type.drum_type = DRUM_RB2; + } } } } + + if (usb_host_devices[i].type.console_type == PS3 && usb_host_devices[i].type.sub_type == ROCK_BAND_DRUMS && usb_host_devices[i].type.drum_type == DRUM_RB1) + { + PS3RockBandDrums_Data_t *drums = (PS3RockBandDrums_Data_t *)&usb_host_devices[i].report; + // RB2 and newer kits set pad flags, so we have a newer kit here + if (drums->padFlag || drums->cymbalFlag) + { + usb_host_devices[i].type.drum_type = DRUM_RB2; + } + } return; } } diff --git a/src/shared/main/wii.cpp b/src/shared/main/wii.cpp index bb00c3f89..8462d5038 100644 --- a/src/shared/main/wii.cpp +++ b/src/shared/main/wii.cpp @@ -198,7 +198,26 @@ uint8_t* tickWii() { break; } #else - onNote(channel, note, velocity); + switch (note) { + case GH_MIDI_NOTE_GREEN: + onNote(channel, GH_REM_MIDI_NOTE_GREEN, velocity); + break; + case GH_MIDI_NOTE_RED: + onNote(channel, GH_REM_MIDI_NOTE_RED, velocity); + break; + case GH_MIDI_NOTE_YELLOW: + onNote(channel, GH_REM_MIDI_NOTE_YELLOW, velocity); + break; + case GH_MIDI_NOTE_BLUE: + onNote(channel, GH_REM_MIDI_NOTE_BLUE, velocity); + break; + case GH_MIDI_NOTE_ORANGE: + onNote(channel, GH_REM_MIDI_NOTE_ORANGE, velocity); + break; + default: + onNote(channel, note, velocity); + break; + } #endif } } From 7b49235a8d8c85f902ca6e0c2556ee9783045c3a Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 24 Jun 2025 20:48:00 +1200 Subject: [PATCH 051/239] remap gh midi notes to rb --- include/defines.h | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/include/defines.h b/include/defines.h index 87dd4e772..7b7ee0e43 100644 --- a/include/defines.h +++ b/include/defines.h @@ -232,11 +232,11 @@ typedef enum { #define RB_MIDI_NOTE_BLUE_CYMBAL 51 #define RB_MIDI_NOTE_KICK2 44 -// Remapped GH midi notes as the standard ones are just not useful -#define GH_REM_MIDI_NOTE_KICK 36 -#define GH_REM_MIDI_NOTE_RED 38 -#define GH_REM_MIDI_NOTE_GREEN 41 -#define GH_REM_MIDI_NOTE_YELLOW 46 -#define GH_REM_MIDI_NOTE_BLUE 45 -#define GH_REM_MIDI_NOTE_ORANGE 51 +// Remap GH midi notes to RB counterparts +#define GH_REM_MIDI_NOTE_KICK RB_MIDI_NOTE_KICK +#define GH_REM_MIDI_NOTE_RED RB_MIDI_NOTE_RED +#define GH_REM_MIDI_NOTE_GREEN RB_MIDI_NOTE_GREEN +#define GH_REM_MIDI_NOTE_YELLOW RB_MIDI_NOTE_YELLOW_CYMBAL +#define GH_REM_MIDI_NOTE_BLUE RB_MIDI_NOTE_GREEN +#define GH_REM_MIDI_NOTE_ORANGE RB_MIDI_NOTE_BLUE_CYMBAL #define GH_REM_MIDI_NOTE_KICK2 100 \ No newline at end of file From fe8d8fbc0677b74786b2620b1993f5e341a388dc Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 24 Jun 2025 21:26:41 +1200 Subject: [PATCH 052/239] fix xinput rb1 kits --- include/defines.h | 2 - src/pico/main.cpp | 27 +- src/shared/main/shared_main.cpp | 4744 +++++++++++++++++-------------- 3 files changed, 2688 insertions(+), 2085 deletions(-) diff --git a/include/defines.h b/include/defines.h index 7b7ee0e43..b8c288518 100644 --- a/include/defines.h +++ b/include/defines.h @@ -35,8 +35,6 @@ #define XINPUT_GUITAR_WT 26 #define XINPUT_DISNEY_INFINITY_AND_LEGO_DIMENSIONS 33 #define XINPUT_SKYLANDERS 36 -#define XINPUT_RB_DRUMS 37 -#define XINPUT_GH_DRUMS 38 #define PS4_GAMEPAD 0 #define PS4_GUITAR 1 diff --git a/src/pico/main.cpp b/src/pico/main.cpp index dc16a649c..aff6092ba 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -663,14 +663,25 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c usb_host_devices[i].report_length = len - sizeof(header); if (usb_host_devices[i].type.sub_type == XINPUT_DRUMS) { - XInputGamepad_Data_t *gamepad = (XInputGamepad_Data_t *)&usb_host_devices[i].report; - if (gamepad->leftThumbClick) + if (usb_host_devices[i].type.drum_type == DRUM_UNKNOWN) { - usb_host_devices[i].type.sub_type = XINPUT_GH_DRUMS; + XInputGamepad_Data_t *gamepad = (XInputGamepad_Data_t *)&usb_host_devices[i].report; + if (gamepad->leftThumbClick) + { + usb_host_devices[i].type.sub_type = DRUM_GH; + } + else + { + usb_host_devices[i].type.sub_type = DRUM_RB1; + } } - else + if (usb_host_devices[i].type.drum_type == DRUM_RB1) { - usb_host_devices[i].type.sub_type = XINPUT_RB_DRUMS; + XInputRockBandDrums_Data_t *gamepad = (XInputRockBandDrums_Data_t *)&usb_host_devices[i].report; + if (gamepad->padFlag || gamepad->cymbalFlag) + { + usb_host_devices[i].type.sub_type = DRUM_RB2; + } } } } @@ -780,11 +791,11 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c { if (drums->leftThumbClick) { - usb_host_devices[i].type.sub_type = XINPUT_GH_DRUMS; + usb_host_devices[i].type.drum_type = DRUM_GH; } else { - usb_host_devices[i].type.sub_type = XINPUT_RB_DRUMS; + usb_host_devices[i].type.drum_type = DRUM_RB1; } } if (usb_host_devices[i].type.drum_type == DRUM_RB1) @@ -797,7 +808,7 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c } } } - + if (usb_host_devices[i].type.console_type == PS3 && usb_host_devices[i].type.sub_type == ROCK_BAND_DRUMS && usb_host_devices[i].type.drum_type == DRUM_RB1) { PS3RockBandDrums_Data_t *drums = (PS3RockBandDrums_Data_t *)&usb_host_devices[i].report; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index bd4723df2..faf81c289 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -34,19 +34,25 @@ #define BUFFER_SIZE_QUEUE 255 #define KEY_ERR_OVF 0x01 #define REQUIRE_LED_DEBOUNCE LED_COUNT || LED_COUNT_PERIPHERAL || LED_COUNT_STP || LED_COUNT_PERIPHERAL_STP || LED_COUNT_WS2812 || LED_COUNT_PERIPHERAL_WS2812 || HAS_LED_OUTPUT || LED_COUNT_MPR121 -struct { - union { +struct +{ + union + { signed int ltt : 6; - struct { + struct + { unsigned int ltt40 : 5; unsigned int ltt5 : 1; }; }; } ltt_t; -struct { - union { +struct +{ + union + { signed int rtt : 6; - struct { + struct + { unsigned int rtt0 : 1; unsigned int rtt21 : 2; unsigned int rtt43 : 2; @@ -56,13 +62,15 @@ struct { } rtt_t; unsigned long lastMidi = 0; Midi_Data_t midiData = {0}; -void onNote(uint8_t channel, uint8_t note, uint8_t velocity) { +void onNote(uint8_t channel, uint8_t note, uint8_t velocity) +{ // velocities are 7 bit // printf("Note ON ch=%d, note=%d, vel=%d\r\n", channel, note, velocity); velocity = velocity << 1; #if DEVICE_TYPE_IS_DRUM // drums, base inputs on triggers - if (velocity > midiData.midiVelocitiesTemp[note]) { + if (velocity > midiData.midiVelocitiesTemp[note]) + { midiData.midiVelocities[note] = velocity; midiData.midiVelocitiesTemp[note] = velocity; } @@ -74,7 +82,8 @@ void onNote(uint8_t channel, uint8_t note, uint8_t velocity) { lastMidi = millis(); } -void offNote(uint8_t channel, uint8_t note, uint8_t velocity) { +void offNote(uint8_t channel, uint8_t note, uint8_t velocity) +{ // printf("Note OFF ch=%d, note=%d, vel=%d\r\n", channel, note, velocity); // ignore note off for drums as we handle that ourselves, and not all drums send it #if !(DEVICE_TYPE_IS_DRUM) @@ -83,18 +92,22 @@ void offNote(uint8_t channel, uint8_t note, uint8_t velocity) { #endif } -void onControlChange(uint8_t channel, uint8_t b1, uint8_t b2) { +void onControlChange(uint8_t channel, uint8_t b1, uint8_t b2) +{ // cc are 7 bit printf("ControlChange ch=%d, b1=%d, b2=%d\r\n", channel, b1, b2); - if (b1 == MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL) { + if (b1 == MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL) + { midiData.midiSustainPedal = b2 << 1; } - if (b1 == MIDI_CONTROL_COMMAND_MOD_WHEEL) { + if (b1 == MIDI_CONTROL_COMMAND_MOD_WHEEL) + { midiData.midiModWheel = b2 << 1; } } -void onPitchBend(uint8_t channel, int pitch) { +void onPitchBend(uint8_t channel, int pitch) +{ // pitchbend is signed 14 bit printf("PitchBend ch=%d, pitch=%d\r\n", channel, pitch); midiData.midiPitchWheel = pitch << 2; @@ -141,11 +154,11 @@ long lastLed = 0; long lastSentGHLPoke = 0; long input_start = 0; long lastDebounce = 0; -long lastInputActivity = 0; // used for inactivity timeout(s) +long lastInputActivity = 0; // used for inactivity timeout(s) long lastHeartbeat = 0; long lastInactivityPulse = 0; -bool startedInactivityPulse = false; // used to ignore inputs while outputting pulse - // (for hardware wired with input and output via same pin) +bool startedInactivityPulse = false; // used to ignore inputs while outputting pulse + // (for hardware wired with input and output via same pin) uint16_t lastMpr121 = 0; bool hasTapBar = false; uint8_t ghl_sequence_number_host = 1; @@ -244,12 +257,16 @@ uint8_t gh5_mapping[] = { 0xAE, 0xAC, 0xFF, 0xFB, 0xFD, 0xF9, 0xFE, 0xFA, 0xFC, 0xF8, 0xE6, 0xE2, 0xE4, 0xE0, 0xE5, 0xE1, 0xE3, 0xDF}; -void setKey(uint8_t id, uint8_t key, USB_6KRO_Data_t *report) { - for (size_t i = 0; i < 6; i++) { - if (report->KeyCode[i] == key) { +void setKey(uint8_t id, uint8_t key, USB_6KRO_Data_t *report) +{ + for (size_t i = 0; i < 6; i++) + { + if (report->KeyCode[i] == key) + { return; } - if (!report->KeyCode[i]) { + if (!report->KeyCode[i]) + { report->KeyCode[i] = key; return; } @@ -259,7 +276,8 @@ void setKey(uint8_t id, uint8_t key, USB_6KRO_Data_t *report) { return; } uint8_t seq = 1; -void init_main(void) { +void init_main(void) +{ #if !DEVICE_TYPE_IS_GAMEPAD consoleType = UNIVERSAL; #endif @@ -297,11 +315,14 @@ void init_main(void) { } #ifdef SLAVE_TWI_PORT bool slave_initted = false; -void tick_slave() { - if (slave_initted) { +void tick_slave() +{ + if (slave_initted) + { return; } - if (!slaveInit()) { + if (!slaveInit()) + { return; } slave_initted = true; @@ -321,52 +342,73 @@ void tick_slave() { #endif } #endif -int16_t adc_i(uint8_t pin) { +int16_t adc_i(uint8_t pin) +{ int32_t ret = adc(pin); return ret - 32767; } -int16_t handle_calibration_xbox(int16_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, int16_t deadzone) { +int16_t handle_calibration_xbox(int16_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, int16_t deadzone) +{ int32_t val = orig_val; - if (val > INT16_MAX) { + if (val > INT16_MAX) + { val = INT16_MAX; } - if (val < INT16_MIN) { + if (val < INT16_MIN) + { val = INT16_MIN; } - if (val < center) { - if ((center - val) < deadzone) { + if (val < center) + { + if ((center - val) < deadzone) + { val = 0; - } else { + } + else + { val = map(val, min, center - deadzone, INT16_MIN, 0); } - - } else { - if ((val - center) < deadzone) { + } + else + { + if ((val - center) < deadzone) + { val = 0; - } else { + } + else + { val = map(val, center + deadzone, max, 0, INT16_MAX); } } - if (val > INT16_MAX) { + if (val > INT16_MAX) + { val = INT16_MAX; } - if (val < INT16_MIN) { + if (val < INT16_MIN) + { val = INT16_MIN; } - if (abs(val) > abs(previous)) { + if (abs(val) > abs(previous)) + { return val; } return previous; } -int16_t handle_calibration_xbox_whammy(int16_t previous, uint32_t orig_val, uint32_t min, int16_t multiplier, uint16_t deadzone) { +int16_t handle_calibration_xbox_whammy(int16_t previous, uint32_t orig_val, uint32_t min, int16_t multiplier, uint16_t deadzone) +{ int32_t val = orig_val; - if (multiplier > 0) { - if ((val - min) < deadzone) { + if (multiplier > 0) + { + if ((val - min) < deadzone) + { return INT16_MIN; } - } else { - if (val > min) { + } + else + { + if (val > min) + { return INT16_MIN; } } @@ -374,82 +416,107 @@ int16_t handle_calibration_xbox_whammy(int16_t previous, uint32_t orig_val, uint val *= multiplier; val /= 512; val += INT16_MIN; - if (val > INT16_MAX) { + if (val > INT16_MAX) + { val = INT16_MAX; } - if (val < INT16_MIN) { + if (val < INT16_MIN) + { val = INT16_MIN; } - if (val > previous) { + if (val > previous) + { return val; } return previous; } -uint16_t handle_calibration_xbox_one_trigger(uint16_t previous, uint16_t orig_val, uint32_t min, int16_t multiplier, uint16_t deadzone) { +uint16_t handle_calibration_xbox_one_trigger(uint16_t previous, uint16_t orig_val, uint32_t min, int16_t multiplier, uint16_t deadzone) +{ int32_t val = orig_val; - if (multiplier > 0) { - if ((val - min) < deadzone) { + if (multiplier > 0) + { + if ((val - min) < deadzone) + { return 0; } - } else { - if (val > min) { + } + else + { + if (val > min) + { return 0; } } val -= min; val *= multiplier; val /= 512; - if (val > UINT16_MAX) { + if (val > UINT16_MAX) + { val = UINT16_MAX; } - if (val < 0) { + if (val < 0) + { val = 0; } val = val >> 6; - if (val > previous) { + if (val > previous) + { return val; } return previous; } -uint16_t handle_calibration_drum(uint16_t previous, uint16_t orig_val, uint32_t min, int16_t multiplier, uint16_t deadzone) { +uint16_t handle_calibration_drum(uint16_t previous, uint16_t orig_val, uint32_t min, int16_t multiplier, uint16_t deadzone) +{ int32_t val = orig_val; - if (multiplier > 0) { - if ((val - min) < deadzone) { + if (multiplier > 0) + { + if ((val - min) < deadzone) + { return 0; } - } else { - if (val > min) { + } + else + { + if (val > min) + { return 0; } } val -= min; val *= multiplier; val /= 512; - if (val > UINT16_MAX) { + if (val > UINT16_MAX) + { val = UINT16_MAX; } - if (val < 0) { + if (val < 0) + { val = 0; } - if (val > previous) { + if (val > previous) + { return val; } return previous; } -uint8_t handle_calibration_ps3(uint8_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, int16_t deadzone) { +uint8_t handle_calibration_ps3(uint8_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, int16_t deadzone) +{ int8_t ret = handle_calibration_xbox((previous - PS3_STICK_CENTER) << 8, orig_val, min, max, center, deadzone) >> 8; return (uint8_t)(ret + PS3_STICK_CENTER); } -int8_t handle_calibration_mouse(int8_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, int16_t deadzone) { +int8_t handle_calibration_mouse(int8_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, int16_t deadzone) +{ return handle_calibration_xbox(previous << 8, orig_val, min, max, center, deadzone) >> 8; } -uint8_t handle_calibration_ps3_360_trigger(uint8_t previous, uint16_t orig_val, uint32_t min, int16_t multiplier, uint16_t deadzone) { +uint8_t handle_calibration_ps3_360_trigger(uint8_t previous, uint16_t orig_val, uint32_t min, int16_t multiplier, uint16_t deadzone) +{ return handle_calibration_xbox_one_trigger(previous << 2, orig_val, min, multiplier, deadzone) >> 2; } -uint16_t handle_calibration_ps3_accel(uint16_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, uint16_t deadzone) { +uint16_t handle_calibration_ps3_accel(uint16_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, uint16_t deadzone) +{ #if DEVICE_TYPE_IS_GUITAR || DEVICE_TYPE_IS_LIVE_GUITAR // For whatever reason, the acceleration for guitars swings between -128 to 128, not -512 to 512 // Also, the game is looking for the value going negative, not positive @@ -459,12 +526,14 @@ uint16_t handle_calibration_ps3_accel(uint16_t previous, int32_t orig_val, int16 #endif return PS3_ACCEL_CENTER + ret; } -uint8_t handle_calibration_arcade_accel(uint16_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, uint16_t deadzone) { +uint8_t handle_calibration_arcade_accel(uint16_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, uint16_t deadzone) +{ int8_t ret = handle_calibration_xbox((previous - 65) << 9, orig_val, min, max, center, deadzone) >> 9; return (uint8_t)(ret + 65); } long last_zero = 0; -uint8_t handle_calibration_ps3_whammy(uint8_t previous, uint16_t orig_val, uint32_t min, int16_t multiplier, uint16_t deadzone) { +uint8_t handle_calibration_ps3_whammy(uint8_t previous, uint16_t orig_val, uint32_t min, int16_t multiplier, uint16_t deadzone) +{ #if DEVICE_TYPE == ROCK_BAND_GUITAR // RB whammy is full range return handle_calibration_ps3_360_trigger(previous, orig_val, min, multiplier, deadzone); @@ -474,103 +543,126 @@ uint8_t handle_calibration_ps3_whammy(uint8_t previous, uint16_t orig_val, uint3 return ret + PS3_STICK_CENTER; #endif } -uint8_t handle_calibration_ps2_whammy(uint8_t previous, uint16_t orig_val, uint32_t min, int16_t multiplier, uint16_t deadzone) { +uint8_t handle_calibration_ps2_whammy(uint8_t previous, uint16_t orig_val, uint32_t min, int16_t multiplier, uint16_t deadzone) +{ // GH whammy ignores the negative half of the axis, so shift to get between 0 and 127, then subtract from center uint8_t ret = handle_calibration_ps3_360_trigger((0x7f - previous) << 1, orig_val, min, multiplier, deadzone) >> 1; return 0x7f - ret; } -uint8_t handle_calibration_turntable_ps3(uint8_t previous, int16_t orig_val, uint8_t multiplier) { +uint8_t handle_calibration_turntable_ps3(uint8_t previous, int16_t orig_val, uint8_t multiplier) +{ int32_t val = (orig_val * multiplier) >> 8; - if (val > INT8_MAX) { + if (val > INT8_MAX) + { val = INT8_MAX; } - if (val < INT8_MIN) { + if (val < INT8_MIN) + { val = INT8_MIN; } // previous is uint, convert to int to test - if (abs(val) > abs((int)previous - PS3_STICK_CENTER)) { + if (abs(val) > abs((int)previous - PS3_STICK_CENTER)) + { // ps3 wants uint, convert to uint return (uint8_t)(val + PS3_STICK_CENTER); } return previous; } -int16_t handle_calibration_turntable_360(int16_t previous, int16_t orig_val, uint8_t multiplier) { - if (consoleType == WINDOWS && WINDOWS_TURNTABLE_FULLRANGE) { +int16_t handle_calibration_turntable_360(int16_t previous, int16_t orig_val, uint8_t multiplier) +{ + if (consoleType == WINDOWS && WINDOWS_TURNTABLE_FULLRANGE) + { int32_t val = (orig_val * multiplier); - if (val > INT16_MAX) { + if (val > INT16_MAX) + { val = INT16_MAX; } - if (val < INT16_MIN) { + if (val < INT16_MIN) + { val = INT16_MIN; } - if (abs(val) > abs(previous)) { + if (abs(val) > abs(previous)) + { return (int16_t)val; } return previous; } int32_t val = (orig_val * multiplier) >> 8; - if (val > 128) { + if (val > 128) + { val = 128; } - if (val < -128) { + if (val < -128) + { val = -128; } - if (abs(val) > abs(previous)) { + if (abs(val) > abs(previous)) + { return (int16_t)val; } return previous; } uint16_t descriptor_index = 0; long reset_after_360 = 0; -uint8_t tick_xbox_one() { +uint8_t tick_xbox_one() +{ uint32_t serial = micros(); - switch (xbox_one_state) { - case Announce: - descriptor_index = 0; - xbox_one_state = WaitingDesc1; - memcpy(&combined_report, announce, sizeof(announce)); - memcpy(&combined_report.raw[7], &serial, 3); - return sizeof(announce); - case IdentDesc1: - xbox_one_state = WaitingDesc; - descriptor_index += 64; - memcpy(&combined_report, xb1_descriptor, 64); - return 64; - case IdentDesc: { - uint16_t len = sizeof(xb1_descriptor) - descriptor_index; - if (len > 64) { - len = 64; - } else { - xbox_one_state = WaitingDescEnd; - } - memcpy(&combined_report, xb1_descriptor + descriptor_index, len); - descriptor_index += len; - return len; - } - case IdentDescEnd: { - xbox_one_state = Auth; - memcpy(&combined_report, xb1_descriptor_end, sizeof(xb1_descriptor_end)); - return sizeof(xb1_descriptor_end); - } - case Auth: - if (data_from_controller_size) { - uint8_t size = data_from_controller_size; - data_from_controller_size = 0; - memcpy(&combined_report, data_from_controller, size); - return size; - } - return 0; - case Ready: - return 0; - default: - return 0; + switch (xbox_one_state) + { + case Announce: + descriptor_index = 0; + xbox_one_state = WaitingDesc1; + memcpy(&combined_report, announce, sizeof(announce)); + memcpy(&combined_report.raw[7], &serial, 3); + return sizeof(announce); + case IdentDesc1: + xbox_one_state = WaitingDesc; + descriptor_index += 64; + memcpy(&combined_report, xb1_descriptor, 64); + return 64; + case IdentDesc: + { + uint16_t len = sizeof(xb1_descriptor) - descriptor_index; + if (len > 64) + { + len = 64; + } + else + { + xbox_one_state = WaitingDescEnd; + } + memcpy(&combined_report, xb1_descriptor + descriptor_index, len); + descriptor_index += len; + return len; + } + case IdentDescEnd: + { + xbox_one_state = Auth; + memcpy(&combined_report, xb1_descriptor_end, sizeof(xb1_descriptor_end)); + return sizeof(xb1_descriptor_end); + } + case Auth: + if (data_from_controller_size) + { + uint8_t size = data_from_controller_size; + data_from_controller_size = 0; + memcpy(&combined_report, data_from_controller, size); + return size; + } + return 0; + case Ready: + return 0; + default: + return 0; } } -static uint8_t xinput_rb_velocity_positive(int16_t velocity) { +static uint8_t xinput_rb_velocity_positive(int16_t velocity) +{ return (uint8_t)(255 - (uint8_t)(velocity >> 7)); } -static uint8_t xinput_rb_velocity_negative(int16_t velocity) { +static uint8_t xinput_rb_velocity_negative(int16_t velocity) +{ if (velocity == 0) return 255; @@ -578,22 +670,233 @@ static uint8_t xinput_rb_velocity_negative(int16_t velocity) { } long lastTick; uint8_t keyboard_report = 0; -void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_type, USB_Host_Data_t *usb_host_data) { - switch (device_type.console_type) { - case STADIA: { - Stadia_Data_t *report = (Stadia_Data_t *)data; - uint8_t dpad = report->dpad >= 0x08 ? 0 : dpad_bindings_reverse[report->dpad]; - asm volatile("" :: - : "memory"); - bool up = dpad & UP; - bool left = dpad & LEFT; - bool down = dpad & DOWN; - bool right = dpad & RIGHT; +void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_type, USB_Host_Data_t *usb_host_data) +{ + switch (device_type.console_type) + { + case STADIA: + { + Stadia_Data_t *report = (Stadia_Data_t *)data; + uint8_t dpad = report->dpad >= 0x08 ? 0 : dpad_bindings_reverse[report->dpad]; + asm volatile("" :: + : "memory"); + bool up = dpad & UP; + bool left = dpad & LEFT; + bool down = dpad & DOWN; + bool right = dpad & RIGHT; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->capture |= report->capture; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->rightThumbClick |= report->rightThumbClick; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + if (report->leftTrigger) + { + usb_host_data->leftTrigger = report->leftTrigger << 8; + } + if (report->rightTrigger) + { + usb_host_data->rightTrigger = report->rightTrigger << 8; + } + if (report->leftStickX != PS3_STICK_CENTER) + { + usb_host_data->leftStickX = (report->leftStickX - PS3_STICK_CENTER) << 8; + } + if (report->leftStickY != PS3_STICK_CENTER) + { + usb_host_data->leftStickY = (((UINT8_MAX - report->leftStickY) - PS3_STICK_CENTER)) << 8; + } + if (report->rightStickX != PS3_STICK_CENTER) + { + usb_host_data->rightStickX = (report->rightStickX - PS3_STICK_CENTER) << 8; + } + if (report->rightStickY != PS3_STICK_CENTER) + { + usb_host_data->rightStickY = (((UINT8_MAX - report->rightStickY) - PS3_STICK_CENTER)) << 8; + } + } + case STREAM_DECK: + { + uint8_t offset = 1; + switch (device_type.sub_type) + { + case STREAM_DECK_XL: + case STREAM_DECK_MK2: + case STREAM_DECK_NEO: + case STREAM_DECK_V2: + case STREAM_DECK_XLV2: + case STREAM_DECK_PEDAL: + case STREAM_DECK_PLUS: + offset = 4; + break; + } + for (uint8_t i = 0; i + offset < len && i < 16; i++) + { + bit_write(data[i + offset], usb_host_data->genericButtons, i); + } + break; + } + case KEYBOARD: + { + USB_6KRO_Boot_Data_t *report = (USB_6KRO_Boot_Data_t *)data; + usb_host_data->keyboard.leftCtrl = report->leftCtrl; + usb_host_data->keyboard.leftShift = report->leftShift; + usb_host_data->keyboard.leftAlt = report->leftAlt; + usb_host_data->keyboard.lWin = report->lWin; + usb_host_data->keyboard.rightCtrl = report->rightCtrl; + usb_host_data->keyboard.rightShift = report->rightShift; + usb_host_data->keyboard.rightAlt = report->rightAlt; + usb_host_data->keyboard.rWin = report->rWin; + uint8_t *keyData = usb_host_data->keyboard.raw; + for (uint8_t i = 0; i < SIMULTANEOUS_KEYS; i++) + { + uint8_t keycode = report->KeyCode[i]; + // F24 is the last supported key in our nkro report + if (keycode && keycode <= KEYCODE_F24) + { + bit_set(keyData[keycode >> 3], keycode & 7); + } + } + break; + } + case MOUSE: + { + USB_Mouse_Boot_Data_t *report = (USB_Mouse_Boot_Data_t *)data; + memcpy(&usb_host_data->mouse, report, sizeof(USB_Mouse_Boot_Data_t)); + break; + } + case GENERIC: + { + USB_Host_Data_t *report = (USB_Host_Data_t *)data; + usb_host_data->genericAxisX = report->genericAxisX; + usb_host_data->genericAxisY = report->genericAxisY; + usb_host_data->genericAxisZ = report->genericAxisZ; + usb_host_data->genericAxisRx = report->genericAxisRx; + usb_host_data->genericAxisRy = report->genericAxisRy; + usb_host_data->genericAxisRz = report->genericAxisRz; + usb_host_data->genericAxisSlider = report->genericAxisSlider; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; + usb_host_data->genericButtons |= report->genericButtons; + break; + } + case RAPHNET: + { + switch (device_type.sub_type) + { + case GAMEPAD: + { + RaphnetGamepad_Data_t *report = (RaphnetGamepad_Data_t *)data; + usb_host_data->leftStickX = report->leftJoyX - 16000; + usb_host_data->leftStickY = report->leftJoyY - 16000; + usb_host_data->rightStickX = report->rightJoyX - 16000; + usb_host_data->rightStickY = report->rightJoyY - 16000; + usb_host_data->leftTrigger = report->leftTrigger; + usb_host_data->rightTrigger = report->rightTrigger; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->start |= report->start; + usb_host_data->back |= report->select; + usb_host_data->guide |= report->home; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->dpadLeft |= report->left; + usb_host_data->dpadRight |= report->right; + usb_host_data->dpadUp |= report->up; + usb_host_data->dpadDown |= report->down; + break; + } + case GUITAR_HERO_GUITAR: + { + RaphnetGuitar_Data_t *report = (RaphnetGuitar_Data_t *)data; + usb_host_data->leftStickX = report->joyX - 16000; + usb_host_data->leftStickY = report->joyY - 16000; + usb_host_data->whammy = report->whammy >> 8; + usb_host_data->start = report->plus; + usb_host_data->back = report->minus; + usb_host_data->green |= report->green; + usb_host_data->red |= report->red; + usb_host_data->yellow |= report->yellow; + usb_host_data->blue |= report->blue; + usb_host_data->orange |= report->orange; + usb_host_data->a |= report->green; + usb_host_data->b |= report->red; + usb_host_data->y |= report->yellow; + usb_host_data->x |= report->blue; + usb_host_data->leftShoulder |= report->orange; + usb_host_data->dpadUp |= report->up; + usb_host_data->dpadDown |= report->down; + break; + } + case GUITAR_HERO_DRUMS: + { + RaphnetDrum_Data_t *report = (RaphnetDrum_Data_t *)data; + usb_host_data->leftStickX = report->joyX - 16000; + usb_host_data->leftStickY = report->joyY - 16000; + usb_host_data->start = report->plus; + usb_host_data->back = report->minus; + usb_host_data->green |= report->green; + usb_host_data->red |= report->red; + usb_host_data->yellow |= report->yellow; + usb_host_data->blue |= report->blue; + usb_host_data->orange |= report->orange; + // TODO: figure out kick mappings for raphnet + // usb_host_data->kick1 |= report->kick1; + usb_host_data->a |= report->green; + usb_host_data->b |= report->red; + usb_host_data->y |= report->yellow; + usb_host_data->x |= report->blue; + usb_host_data->leftShoulder |= report->orange; + break; + } + } + break; + } + case SANTROLLER: + { + PCGamepad_Data_t *report = (PCGamepad_Data_t *)data; + uint8_t dpad = report->dpad >= 0x08 ? 0 : dpad_bindings_reverse[report->dpad]; + asm volatile("" :: + : "memory"); + bool up = dpad & UP; + bool left = dpad & LEFT; + bool down = dpad & DOWN; + bool right = dpad & RIGHT; + switch (device_type.sub_type) + { + case GAMEPAD: + case DANCE_PAD: + case STAGE_KIT: + { + PCGamepad_Data_t *report = (PCGamepad_Data_t *)data; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; usb_host_data->a |= report->a; usb_host_data->b |= report->b; usb_host_data->x |= report->x; usb_host_data->y |= report->y; - usb_host_data->capture |= report->capture; usb_host_data->leftShoulder |= report->leftShoulder; usb_host_data->rightShoulder |= report->rightShoulder; usb_host_data->back |= report->back; @@ -605,1608 +908,1689 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->dpadRight |= right; usb_host_data->dpadUp |= up; usb_host_data->dpadDown |= down; - if (report->leftTrigger) { + if (report->leftTrigger) + { usb_host_data->leftTrigger = report->leftTrigger << 8; } - if (report->rightTrigger) { + if (report->rightTrigger) + { usb_host_data->rightTrigger = report->rightTrigger << 8; } - if (report->leftStickX != PS3_STICK_CENTER) { + if (report->leftStickX != PS3_STICK_CENTER) + { usb_host_data->leftStickX = (report->leftStickX - PS3_STICK_CENTER) << 8; } - if (report->leftStickY != PS3_STICK_CENTER) { + if (report->leftStickY != PS3_STICK_CENTER) + { usb_host_data->leftStickY = (((UINT8_MAX - report->leftStickY) - PS3_STICK_CENTER)) << 8; } - if (report->rightStickX != PS3_STICK_CENTER) { + if (report->rightStickX != PS3_STICK_CENTER) + { usb_host_data->rightStickX = (report->rightStickX - PS3_STICK_CENTER) << 8; } - if (report->rightStickY != PS3_STICK_CENTER) { + if (report->rightStickY != PS3_STICK_CENTER) + { usb_host_data->rightStickY = (((UINT8_MAX - report->rightStickY) - PS3_STICK_CENTER)) << 8; } - } - case STREAM_DECK: { - uint8_t offset = 1; - switch (device_type.sub_type) { - case STREAM_DECK_XL: - case STREAM_DECK_MK2: - case STREAM_DECK_NEO: - case STREAM_DECK_V2: - case STREAM_DECK_XLV2: - case STREAM_DECK_PEDAL: - case STREAM_DECK_PLUS: - offset = 4; - break; - } - for (uint8_t i = 0; i + offset < len && i < 16; i++) { - bit_write(data[i + offset], usb_host_data->genericButtons, i); - } - break; - } - case KEYBOARD: { - USB_6KRO_Boot_Data_t *report = (USB_6KRO_Boot_Data_t *)data; - usb_host_data->keyboard.leftCtrl = report->leftCtrl; - usb_host_data->keyboard.leftShift = report->leftShift; - usb_host_data->keyboard.leftAlt = report->leftAlt; - usb_host_data->keyboard.lWin = report->lWin; - usb_host_data->keyboard.rightCtrl = report->rightCtrl; - usb_host_data->keyboard.rightShift = report->rightShift; - usb_host_data->keyboard.rightAlt = report->rightAlt; - usb_host_data->keyboard.rWin = report->rWin; - uint8_t *keyData = usb_host_data->keyboard.raw; - for (uint8_t i = 0; i < SIMULTANEOUS_KEYS; i++) { - uint8_t keycode = report->KeyCode[i]; - // F24 is the last supported key in our nkro report - if (keycode && keycode <= KEYCODE_F24) { - bit_set(keyData[keycode >> 3], keycode & 7); - } - } break; } - case MOUSE: { - USB_Mouse_Boot_Data_t *report = (USB_Mouse_Boot_Data_t *)data; - memcpy(&usb_host_data->mouse, report, sizeof(USB_Mouse_Boot_Data_t)); - break; - } - case GENERIC: { - USB_Host_Data_t *report = (USB_Host_Data_t *)data; - usb_host_data->genericAxisX = report->genericAxisX; - usb_host_data->genericAxisY = report->genericAxisY; - usb_host_data->genericAxisZ = report->genericAxisZ; - usb_host_data->genericAxisRx = report->genericAxisRx; - usb_host_data->genericAxisRy = report->genericAxisRy; - usb_host_data->genericAxisRz = report->genericAxisRz; - usb_host_data->genericAxisSlider = report->genericAxisSlider; - usb_host_data->dpadLeft |= report->dpadLeft; - usb_host_data->dpadRight |= report->dpadRight; - usb_host_data->dpadUp |= report->dpadUp; - usb_host_data->dpadDown |= report->dpadDown; - usb_host_data->genericButtons |= report->genericButtons; - break; - } - case RAPHNET: { - switch (device_type.sub_type) { - case GAMEPAD: { - RaphnetGamepad_Data_t *report = (RaphnetGamepad_Data_t *)data; - usb_host_data->leftStickX = report->leftJoyX - 16000; - usb_host_data->leftStickY = report->leftJoyY - 16000; - usb_host_data->rightStickX = report->rightJoyX - 16000; - usb_host_data->rightStickY = report->rightJoyY - 16000; - usb_host_data->leftTrigger = report->leftTrigger; - usb_host_data->rightTrigger = report->rightTrigger; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->start |= report->start; - usb_host_data->back |= report->select; - usb_host_data->guide |= report->home; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->dpadLeft |= report->left; - usb_host_data->dpadRight |= report->right; - usb_host_data->dpadUp |= report->up; - usb_host_data->dpadDown |= report->down; - break; - } - case GUITAR_HERO_GUITAR: { - RaphnetGuitar_Data_t *report = (RaphnetGuitar_Data_t *)data; - usb_host_data->leftStickX = report->joyX - 16000; - usb_host_data->leftStickY = report->joyY - 16000; - usb_host_data->whammy = report->whammy >> 8; - usb_host_data->start = report->plus; - usb_host_data->back = report->minus; - usb_host_data->green |= report->green; - usb_host_data->red |= report->red; - usb_host_data->yellow |= report->yellow; - usb_host_data->blue |= report->blue; - usb_host_data->orange |= report->orange; - usb_host_data->a |= report->green; - usb_host_data->b |= report->red; - usb_host_data->y |= report->yellow; - usb_host_data->x |= report->blue; - usb_host_data->leftShoulder |= report->orange; - usb_host_data->dpadUp |= report->up; - usb_host_data->dpadDown |= report->down; - break; - } - case GUITAR_HERO_DRUMS: { - RaphnetDrum_Data_t *report = (RaphnetDrum_Data_t *)data; - usb_host_data->leftStickX = report->joyX - 16000; - usb_host_data->leftStickY = report->joyY - 16000; - usb_host_data->start = report->plus; - usb_host_data->back = report->minus; - usb_host_data->green |= report->green; - usb_host_data->red |= report->red; - usb_host_data->yellow |= report->yellow; - usb_host_data->blue |= report->blue; - usb_host_data->orange |= report->orange; - // TODO: figure out kick mappings for raphnet - // usb_host_data->kick1 |= report->kick1; - usb_host_data->a |= report->green; - usb_host_data->b |= report->red; - usb_host_data->y |= report->yellow; - usb_host_data->x |= report->blue; - usb_host_data->leftShoulder |= report->orange; - break; - } + case GUITAR_HERO_GUITAR: + { + PCGuitarHeroGuitar_Data_t *report = (PCGuitarHeroGuitar_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + if (report->tilt != PS3_STICK_CENTER) + { + usb_host_data->tilt = (report->tilt - PS3_STICK_CENTER) << 8; } - break; - } - case SANTROLLER: { - PCGamepad_Data_t *report = (PCGamepad_Data_t *)data; - uint8_t dpad = report->dpad >= 0x08 ? 0 : dpad_bindings_reverse[report->dpad]; - asm volatile("" :: - : "memory"); - bool up = dpad & UP; - bool left = dpad & LEFT; - bool down = dpad & DOWN; - bool right = dpad & RIGHT; - switch (device_type.sub_type) { - case GAMEPAD: - case DANCE_PAD: - case STAGE_KIT: { - PCGamepad_Data_t *report = (PCGamepad_Data_t *)data; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->rightThumbClick |= report->rightThumbClick; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - if (report->leftTrigger) { - usb_host_data->leftTrigger = report->leftTrigger << 8; - } - if (report->rightTrigger) { - usb_host_data->rightTrigger = report->rightTrigger << 8; - } - if (report->leftStickX != PS3_STICK_CENTER) { - usb_host_data->leftStickX = (report->leftStickX - PS3_STICK_CENTER) << 8; - } - if (report->leftStickY != PS3_STICK_CENTER) { - usb_host_data->leftStickY = (((UINT8_MAX - report->leftStickY) - PS3_STICK_CENTER)) << 8; - } - if (report->rightStickX != PS3_STICK_CENTER) { - usb_host_data->rightStickX = (report->rightStickX - PS3_STICK_CENTER) << 8; - } - if (report->rightStickY != PS3_STICK_CENTER) { - usb_host_data->rightStickY = (((UINT8_MAX - report->rightStickY) - PS3_STICK_CENTER)) << 8; - } - break; - } - case GUITAR_HERO_GUITAR: { - PCGuitarHeroGuitar_Data_t *report = (PCGuitarHeroGuitar_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - if (report->tilt != PS3_STICK_CENTER) { - usb_host_data->tilt = (report->tilt - PS3_STICK_CENTER) << 8; - } - if (report->whammy) { - usb_host_data->whammy = report->whammy; - } - usb_host_data->slider = report->slider; - break; - } - case ROCK_BAND_GUITAR: { - PCRockBandGuitar_Data_t *report = (PCRockBandGuitar_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - if (report->tilt != PS3_STICK_CENTER) { - usb_host_data->tilt = (report->tilt - PS3_STICK_CENTER) << 8; - } - usb_host_data->soloGreen |= report->soloGreen; - usb_host_data->soloRed |= report->soloRed; - usb_host_data->soloYellow |= report->soloYellow; - usb_host_data->soloBlue |= report->soloBlue; - usb_host_data->soloOrange |= report->soloOrange; - - if (report->whammy) { - usb_host_data->whammy = report->whammy; - } - if (report->pickup) { - usb_host_data->pickup = report->pickup; - } - break; - } - case GUITAR_HERO_DRUMS: { - PCGuitarHeroDrums_Data_t *report = (PCGuitarHeroDrums_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->rightShoulder; - SET_GH_PADS(); - break; - } - case ROCK_BAND_DRUMS: { - PCRockBandDrums_Data_t *report = (PCRockBandDrums_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - uint8_t redVelocity = report->redVelocity; - uint8_t greenVelocity = report->greenVelocity; - uint8_t yellowVelocity = report->yellowVelocity; - uint8_t blueVelocity = report->blueVelocity; - bool kick1 = report->leftShoulder; - bool kick2 = report->rightShoulder; - SET_RB_PADS(); - break; - } - case LIVE_GUITAR: { - PCGHLGuitar_Data_t *report = (PCGHLGuitar_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - if (report->tilt != PS3_STICK_CENTER) { - usb_host_data->tilt = (report->tilt - PS3_STICK_CENTER) << 8; - } - if (report->whammy) { - usb_host_data->whammy = report->whammy; - } - break; - } - case DJ_HERO_TURNTABLE: { - PCTurntable_Data_t *report = (PCTurntable_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->leftBlue |= report->leftBlue; - usb_host_data->leftRed |= report->leftRed; - usb_host_data->leftGreen |= report->leftGreen; - usb_host_data->rightBlue |= report->rightBlue; - usb_host_data->rightRed |= report->rightRed; - usb_host_data->rightGreen |= report->rightGreen; - if (report->effectsKnob != PS3_ACCEL_CENTER) { - usb_host_data->effectsKnob = (report->effectsKnob - PS3_ACCEL_CENTER) << 6; - } - if (report->crossfader != PS3_ACCEL_CENTER) { - usb_host_data->crossfader = (report->crossfader - PS3_ACCEL_CENTER) << 6; - } - if (report->leftTableVelocity != PS3_STICK_CENTER) { - usb_host_data->leftTableVelocity = (report->leftTableVelocity - PS3_STICK_CENTER) << 8; - } - if (report->rightTableVelocity != PS3_STICK_CENTER) { - usb_host_data->rightTableVelocity = (report->rightTableVelocity - PS3_STICK_CENTER) << 8; - } - break; - } - case ROCK_BAND_PRO_KEYS: { - PCRockBandProKeyboard_Data_t *report = (PCRockBandProKeyboard_Data_t *)data; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - TRANSLATE_PRO_KEYS; - break; - } - case ROCK_BAND_PRO_GUITAR_SQUIRE: - case ROCK_BAND_PRO_GUITAR_MUSTANG: { - PCRockBandProGuitar_Data_t *report = (PCRockBandProGuitar_Data_t *)data; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - TRANSLATE_PRO_GUITAR; - break; - } + if (report->whammy) + { + usb_host_data->whammy = report->whammy; } + usb_host_data->slider = report->slider; break; } - case PS3: { - PS3Dpad_Data_t *report = (PS3Dpad_Data_t *)data; - uint8_t dpad = report->dpad >= 0x08 ? 0 : dpad_bindings_reverse[report->dpad]; - asm volatile("" :: - : "memory"); - bool up = dpad & UP; - bool left = dpad & LEFT; - bool down = dpad & DOWN; - bool right = dpad & RIGHT; - switch (device_type.sub_type) { - case GAMEPAD: { - PS3Gamepad_Data_t *report = (PS3Gamepad_Data_t *)data; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->rightThumbClick |= report->rightThumbClick; - usb_host_data->dpadLeft |= report->dpadLeft; - usb_host_data->dpadRight |= report->dpadRight; - usb_host_data->dpadUp |= report->dpadUp; - usb_host_data->dpadDown |= report->dpadDown; - if (report->leftTrigger) { - usb_host_data->leftTrigger = report->leftTrigger << 8; - } - if (report->rightTrigger) { - usb_host_data->rightTrigger = report->rightTrigger << 8; - } - if (report->leftStickX != PS3_STICK_CENTER) { - usb_host_data->leftStickX = (report->leftStickX - PS3_STICK_CENTER) << 8; - } - if (report->leftStickY != PS3_STICK_CENTER) { - usb_host_data->leftStickY = (((UINT8_MAX - report->leftStickY) - PS3_STICK_CENTER)) << 8; - } - if (report->rightStickX != PS3_STICK_CENTER) { - usb_host_data->rightStickX = (report->rightStickX - PS3_STICK_CENTER) << 8; - } - if (report->rightStickY != PS3_STICK_CENTER) { - usb_host_data->rightStickY = (((UINT8_MAX - report->rightStickY) - PS3_STICK_CENTER)) << 8; - } - if (report->pressureDpadUp) { - usb_host_data->pressureDpadUp = report->pressureDpadUp; - } - if (report->pressureDpadRight) { - usb_host_data->pressureDpadRight = report->pressureDpadRight; - } - if (report->pressureDpadDown) { - usb_host_data->pressureDpadDown = report->pressureDpadDown; - } - if (report->pressureDpadLeft) { - usb_host_data->pressureDpadLeft = report->pressureDpadLeft; - } - if (report->pressureL1) { - usb_host_data->pressureL1 = report->pressureL1; - } - if (report->pressureR1) { - usb_host_data->pressureR1 = report->pressureR1; - } - if (report->pressureTriangle) { - usb_host_data->pressureTriangle = report->pressureTriangle; - } - if (report->pressureCircle) { - usb_host_data->pressureCircle = report->pressureCircle; - } - if (report->pressureCross) { - usb_host_data->pressureCross = report->pressureCross; - } - if (report->pressureSquare) { - usb_host_data->pressureSquare = report->pressureSquare; - } - break; - } - - case ROCK_BAND_PRO_KEYS: { - PS3RockBandProKeyboard_Data_t *report = (PS3RockBandProKeyboard_Data_t *)data; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - TRANSLATE_PRO_KEYS; - break; - } - case ROCK_BAND_GUITAR: { - PS3RockBandGuitar_Data_t *report = (PS3RockBandGuitar_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - if (report->tilt) { - usb_host_data->tilt = INT16_MAX; - } - if (report->solo) { - usb_host_data->soloGreen |= report->a; - usb_host_data->soloRed |= report->b; - usb_host_data->soloYellow |= report->y; - usb_host_data->soloBlue |= report->x; - usb_host_data->soloOrange |= report->leftShoulder; - } - if (report->whammy) { - usb_host_data->whammy = (report->whammy - PS3_STICK_CENTER) << 1; - } - if (report->pickup) { - usb_host_data->pickup = report->pickup; - } - break; - } - case GUITAR_HERO_GUITAR_WT: - case GUITAR_HERO_GUITAR: { - PS3GuitarHeroGuitar_Data_t *report = (PS3GuitarHeroGuitar_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - if (report->tilt != PS3_ACCEL_CENTER) { - usb_host_data->tilt = (report->tilt - PS3_ACCEL_CENTER) << 6; - } - if (report->whammy) { - usb_host_data->whammy = (report->whammy - PS3_STICK_CENTER) << 1; - } - // Detect GH5 vs WT. Wait for a neutral input, then use that to detect instrument type - if (device_type.sub_type == GUITAR_HERO_GUITAR_WT) { - // Its WT, convert to GH5 - if (report->slider <= 0x2F) { - usb_host_data->slider = 0x15; - } else if (report->slider <= 0x3F) { - usb_host_data->slider = 0x30; - } else if (report->slider <= 0x5F) { - usb_host_data->slider = 0x4D; - } else if (report->slider <= 0x6F) { - usb_host_data->slider = 0x66; - } else if (report->slider <= 0x8F) { - usb_host_data->slider = 0x80; - } else if (report->slider <= 0x9F) { - usb_host_data->slider = 0x9A; - } else if (report->slider <= 0xAF) { - usb_host_data->slider = 0xAF; - } else if (report->slider <= 0xCF) { - usb_host_data->slider = 0xC9; - } else if (report->slider <= 0xEF) { - usb_host_data->slider = 0xE6; - } else { - usb_host_data->slider = 0x7F; - } - } else { - usb_host_data->slider = report->slider; - } - break; - } - case ROCK_BAND_DRUMS: { - PS3RockBandDrums_Data_t *report = (PS3RockBandDrums_Data_t *)data; - uint8_t redVelocity = ~report->redVelocity; - uint8_t greenVelocity = ~report->greenVelocity; - uint8_t yellowVelocity = ~report->yellowVelocity; - uint8_t blueVelocity = ~report->blueVelocity; - bool kick1 = report->leftShoulder; - bool kick2 = report->rightShoulder; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - SET_RB_PADS(); - break; - } - case GUITAR_HERO_DRUMS: { - PS3GuitarHeroDrums_Data_t *report = (PS3GuitarHeroDrums_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - SET_GH_PADS(); - // Forward any midi data we get - if ((report->midiByte0 & 0xF0) == 0x90) { - onNote(report->midiByte0 & 0x0F, report->midiByte1, report->midiByte2); - } else if ((report->midiByte0 & 0xF0) == 0x80) { - offNote(report->midiByte0 & 0x0F, report->midiByte1, report->midiByte2); - } - break; - } - case LIVE_GUITAR: { - PS3GHLGuitar_Data_t *report = (PS3GHLGuitar_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up || report->strumBar == 0x00; - usb_host_data->dpadDown |= down || report->strumBar == 0xFF; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - if (report->tilt != PS3_ACCEL_CENTER) { - usb_host_data->tilt = (report->tilt - PS3_ACCEL_CENTER) << 6; - } - if (report->whammy) { - usb_host_data->whammy = (report->whammy - PS3_STICK_CENTER) << 1; - } - break; - } - case DJ_HERO_TURNTABLE: { - PS3Turntable_Data_t *report = (PS3Turntable_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->leftBlue |= report->leftBlue; - usb_host_data->leftRed |= report->leftRed; - usb_host_data->leftGreen |= report->leftGreen; - usb_host_data->rightBlue |= report->rightBlue; - usb_host_data->rightRed |= report->rightRed; - usb_host_data->rightGreen |= report->rightGreen; - if (report->effectsKnob != PS3_ACCEL_CENTER) { - usb_host_data->effectsKnob = (report->effectsKnob - PS3_ACCEL_CENTER) << 6; - } - if (report->crossfader != PS3_ACCEL_CENTER) { - usb_host_data->crossfader = (report->crossfader - PS3_ACCEL_CENTER) << 6; - } - if (report->leftTableVelocity != PS3_STICK_CENTER) { - usb_host_data->leftTableVelocity = (report->leftTableVelocity - PS3_STICK_CENTER) << 8; - } - if (report->rightTableVelocity != PS3_STICK_CENTER) { - usb_host_data->rightTableVelocity = (report->rightTableVelocity - PS3_STICK_CENTER) << 8; - } - break; - } + case ROCK_BAND_GUITAR: + { + PCRockBandGuitar_Data_t *report = (PCRockBandGuitar_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + if (report->tilt != PS3_STICK_CENTER) + { + usb_host_data->tilt = (report->tilt - PS3_STICK_CENTER) << 8; + } + usb_host_data->soloGreen |= report->soloGreen; + usb_host_data->soloRed |= report->soloRed; + usb_host_data->soloYellow |= report->soloYellow; + usb_host_data->soloBlue |= report->soloBlue; + usb_host_data->soloOrange |= report->soloOrange; - case ROCK_BAND_PRO_GUITAR_SQUIRE: - case ROCK_BAND_PRO_GUITAR_MUSTANG: { - PS3RockBandProGuitar_Data_t *report = (PS3RockBandProGuitar_Data_t *)data; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; - TRANSLATE_PRO_GUITAR; - break; - } + if (report->whammy) + { + usb_host_data->whammy = report->whammy; + } + if (report->pickup) + { + usb_host_data->pickup = report->pickup; } break; } - case LTEK_ID: { - LTEK_Report_With_Id_Data_t *report = (LTEK_Report_With_Id_Data_t *)data; - usb_host_data->dpadLeft |= report->dpadLeft; - usb_host_data->dpadRight |= report->dpadRight; - usb_host_data->dpadUp |= report->dpadUp; - usb_host_data->dpadDown |= report->dpadDown; - usb_host_data->start |= report->start; + case GUITAR_HERO_DRUMS: + { + PCGuitarHeroDrums_Data_t *report = (PCGuitarHeroDrums_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->rightShoulder; + SET_GH_PADS(); break; } - case LTEK: { - LTEK_Report_Data_t *report = (LTEK_Report_Data_t *)data; - usb_host_data->dpadLeft |= report->dpadLeft; - usb_host_data->dpadRight |= report->dpadRight; - usb_host_data->dpadUp |= report->dpadUp; - usb_host_data->dpadDown |= report->dpadDown; - usb_host_data->start |= report->start; + case ROCK_BAND_DRUMS: + { + PCRockBandDrums_Data_t *report = (PCRockBandDrums_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + uint8_t redVelocity = report->redVelocity; + uint8_t greenVelocity = report->greenVelocity; + uint8_t yellowVelocity = report->yellowVelocity; + uint8_t blueVelocity = report->blueVelocity; + bool kick1 = report->leftShoulder; + bool kick2 = report->rightShoulder; + SET_RB_PADS(); break; } - case STEPMANIAX: { - StepManiaX_Report_Data_t *report = (StepManiaX_Report_Data_t *)data; - usb_host_data->dpadLeft |= report->dpadLeft; - usb_host_data->dpadRight |= report->dpadRight; - usb_host_data->dpadUp |= report->dpadUp; - usb_host_data->dpadDown |= report->dpadDown; + case LIVE_GUITAR: + { + PCGHLGuitar_Data_t *report = (PCGHLGuitar_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + if (report->tilt != PS3_STICK_CENTER) + { + usb_host_data->tilt = (report->tilt - PS3_STICK_CENTER) << 8; + } + if (report->whammy) + { + usb_host_data->whammy = report->whammy; + } break; } - case PS4: { - PS4Dpad_Data_t *dpad = (PS4Dpad_Data_t *)data; - usb_host_data->dpadLeft = dpad->dpad == 6 || dpad->dpad == 5 || dpad->dpad == 7; - usb_host_data->dpadRight = dpad->dpad == 3 || dpad->dpad == 2 || dpad->dpad == 1; - usb_host_data->dpadUp = dpad->dpad == 0 || dpad->dpad == 1 || dpad->dpad == 7; - usb_host_data->dpadDown = dpad->dpad == 5 || dpad->dpad == 4 || dpad->dpad == 3; - switch (device_type.sub_type) { - case GAMEPAD: { - PS4Gamepad_Data_t *report = (PS4Gamepad_Data_t *)data; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->rightThumbClick |= report->rightThumbClick; - usb_host_data->capture |= report->capture; - if (report->leftTrigger) { - usb_host_data->leftTrigger = report->leftTrigger << 8; - } - if (report->rightTrigger) { - usb_host_data->rightTrigger = report->rightTrigger << 8; - } - if (report->leftStickX != PS3_STICK_CENTER) { - usb_host_data->leftStickX = (report->leftStickX - PS3_STICK_CENTER) << 8; - } - if (report->leftStickY != PS3_STICK_CENTER) { - usb_host_data->leftStickY = (((UINT8_MAX - report->leftStickY) - PS3_STICK_CENTER)) << 8; - } - if (report->rightStickX != PS3_STICK_CENTER) { - usb_host_data->rightStickX = (report->rightStickX - PS3_STICK_CENTER) << 8; - } - if (report->rightStickY != PS3_STICK_CENTER) { - usb_host_data->rightStickY = (((UINT8_MAX - report->rightStickY) - PS3_STICK_CENTER)) << 8; - } - break; - } - case ROCK_BAND_GUITAR: { - PS4RockBandGuitar_Data_t *report = (PS4RockBandGuitar_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - if (report->tilt) { - usb_host_data->tilt = report->tilt << 7; - } - if (report->solo) { - usb_host_data->soloGreen |= report->a; - usb_host_data->soloRed |= report->b; - usb_host_data->soloYellow |= report->y; - usb_host_data->soloBlue |= report->x; - usb_host_data->soloOrange |= report->leftShoulder; - } - if (report->whammy) { - usb_host_data->whammy = report->whammy; - } - if (report->pickup) { - usb_host_data->pickup = report->pickup; - } - break; + case DJ_HERO_TURNTABLE: + { + PCTurntable_Data_t *report = (PCTurntable_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->leftBlue |= report->leftBlue; + usb_host_data->leftRed |= report->leftRed; + usb_host_data->leftGreen |= report->leftGreen; + usb_host_data->rightBlue |= report->rightBlue; + usb_host_data->rightRed |= report->rightRed; + usb_host_data->rightGreen |= report->rightGreen; + if (report->effectsKnob != PS3_ACCEL_CENTER) + { + usb_host_data->effectsKnob = (report->effectsKnob - PS3_ACCEL_CENTER) << 6; + } + if (report->crossfader != PS3_ACCEL_CENTER) + { + usb_host_data->crossfader = (report->crossfader - PS3_ACCEL_CENTER) << 6; + } + if (report->leftTableVelocity != PS3_STICK_CENTER) + { + usb_host_data->leftTableVelocity = (report->leftTableVelocity - PS3_STICK_CENTER) << 8; + } + if (report->rightTableVelocity != PS3_STICK_CENTER) + { + usb_host_data->rightTableVelocity = (report->rightTableVelocity - PS3_STICK_CENTER) << 8; + } + break; + } + case ROCK_BAND_PRO_KEYS: + { + PCRockBandProKeyboard_Data_t *report = (PCRockBandProKeyboard_Data_t *)data; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + TRANSLATE_PRO_KEYS; + break; + } + case ROCK_BAND_PRO_GUITAR_SQUIRE: + case ROCK_BAND_PRO_GUITAR_MUSTANG: + { + PCRockBandProGuitar_Data_t *report = (PCRockBandProGuitar_Data_t *)data; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + TRANSLATE_PRO_GUITAR; + break; + } + } + break; + } + case PS3: + { + PS3Dpad_Data_t *report = (PS3Dpad_Data_t *)data; + uint8_t dpad = report->dpad >= 0x08 ? 0 : dpad_bindings_reverse[report->dpad]; + asm volatile("" :: + : "memory"); + bool up = dpad & UP; + bool left = dpad & LEFT; + bool down = dpad & DOWN; + bool right = dpad & RIGHT; + switch (device_type.sub_type) + { + case GAMEPAD: + { + PS3Gamepad_Data_t *report = (PS3Gamepad_Data_t *)data; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->rightThumbClick |= report->rightThumbClick; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; + if (report->leftTrigger) + { + usb_host_data->leftTrigger = report->leftTrigger << 8; + } + if (report->rightTrigger) + { + usb_host_data->rightTrigger = report->rightTrigger << 8; + } + if (report->leftStickX != PS3_STICK_CENTER) + { + usb_host_data->leftStickX = (report->leftStickX - PS3_STICK_CENTER) << 8; + } + if (report->leftStickY != PS3_STICK_CENTER) + { + usb_host_data->leftStickY = (((UINT8_MAX - report->leftStickY) - PS3_STICK_CENTER)) << 8; + } + if (report->rightStickX != PS3_STICK_CENTER) + { + usb_host_data->rightStickX = (report->rightStickX - PS3_STICK_CENTER) << 8; + } + if (report->rightStickY != PS3_STICK_CENTER) + { + usb_host_data->rightStickY = (((UINT8_MAX - report->rightStickY) - PS3_STICK_CENTER)) << 8; + } + if (report->pressureDpadUp) + { + usb_host_data->pressureDpadUp = report->pressureDpadUp; + } + if (report->pressureDpadRight) + { + usb_host_data->pressureDpadRight = report->pressureDpadRight; + } + if (report->pressureDpadDown) + { + usb_host_data->pressureDpadDown = report->pressureDpadDown; + } + if (report->pressureDpadLeft) + { + usb_host_data->pressureDpadLeft = report->pressureDpadLeft; + } + if (report->pressureL1) + { + usb_host_data->pressureL1 = report->pressureL1; + } + if (report->pressureR1) + { + usb_host_data->pressureR1 = report->pressureR1; + } + if (report->pressureTriangle) + { + usb_host_data->pressureTriangle = report->pressureTriangle; + } + if (report->pressureCircle) + { + usb_host_data->pressureCircle = report->pressureCircle; + } + if (report->pressureCross) + { + usb_host_data->pressureCross = report->pressureCross; + } + if (report->pressureSquare) + { + usb_host_data->pressureSquare = report->pressureSquare; + } + break; + } + + case ROCK_BAND_PRO_KEYS: + { + PS3RockBandProKeyboard_Data_t *report = (PS3RockBandProKeyboard_Data_t *)data; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + TRANSLATE_PRO_KEYS; + break; + } + case ROCK_BAND_GUITAR: + { + PS3RockBandGuitar_Data_t *report = (PS3RockBandGuitar_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + if (report->tilt) + { + usb_host_data->tilt = INT16_MAX; + } + if (report->solo) + { + usb_host_data->soloGreen |= report->a; + usb_host_data->soloRed |= report->b; + usb_host_data->soloYellow |= report->y; + usb_host_data->soloBlue |= report->x; + usb_host_data->soloOrange |= report->leftShoulder; + } + if (report->whammy) + { + usb_host_data->whammy = (report->whammy - PS3_STICK_CENTER) << 1; + } + if (report->pickup) + { + usb_host_data->pickup = report->pickup; + } + break; + } + case GUITAR_HERO_GUITAR_WT: + case GUITAR_HERO_GUITAR: + { + PS3GuitarHeroGuitar_Data_t *report = (PS3GuitarHeroGuitar_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + if (report->tilt != PS3_ACCEL_CENTER) + { + usb_host_data->tilt = (report->tilt - PS3_ACCEL_CENTER) << 6; + } + if (report->whammy) + { + usb_host_data->whammy = (report->whammy - PS3_STICK_CENTER) << 1; + } + // Detect GH5 vs WT. Wait for a neutral input, then use that to detect instrument type + if (device_type.sub_type == GUITAR_HERO_GUITAR_WT) + { + // Its WT, convert to GH5 + if (report->slider <= 0x2F) + { + usb_host_data->slider = 0x15; } - case LIVE_GUITAR: { - PS4GHLGuitar_Data_t *report = (PS4GHLGuitar_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->dpadUp |= report->strumBar == 0x00; - usb_host_data->dpadDown |= report->strumBar == 0xFF; - if (report->tilt != PS3_ACCEL_CENTER) { - usb_host_data->tilt = (report->tilt - PS3_ACCEL_CENTER) << 6; - } - if (report->whammy) { - usb_host_data->whammy = report->whammy; - } - break; + else if (report->slider <= 0x3F) + { + usb_host_data->slider = 0x30; + } + else if (report->slider <= 0x5F) + { + usb_host_data->slider = 0x4D; + } + else if (report->slider <= 0x6F) + { + usb_host_data->slider = 0x66; + } + else if (report->slider <= 0x8F) + { + usb_host_data->slider = 0x80; + } + else if (report->slider <= 0x9F) + { + usb_host_data->slider = 0x9A; + } + else if (report->slider <= 0xAF) + { + usb_host_data->slider = 0xAF; } + else if (report->slider <= 0xCF) + { + usb_host_data->slider = 0xC9; + } + else if (report->slider <= 0xEF) + { + usb_host_data->slider = 0xE6; + } + else + { + usb_host_data->slider = 0x7F; + } + } + else + { + usb_host_data->slider = report->slider; + } + break; + } + case ROCK_BAND_DRUMS: + { + PS3RockBandDrums_Data_t *report = (PS3RockBandDrums_Data_t *)data; + uint8_t redVelocity = ~report->redVelocity; + uint8_t greenVelocity = ~report->greenVelocity; + uint8_t yellowVelocity = ~report->yellowVelocity; + uint8_t blueVelocity = ~report->blueVelocity; + bool kick1 = report->leftShoulder; + bool kick2 = report->rightShoulder; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + SET_RB_PADS(); + break; + } + case GUITAR_HERO_DRUMS: + { + PS3GuitarHeroDrums_Data_t *report = (PS3GuitarHeroDrums_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + SET_GH_PADS(); + // Forward any midi data we get + if ((report->midiByte0 & 0xF0) == 0x90) + { + onNote(report->midiByte0 & 0x0F, report->midiByte1, report->midiByte2); + } + else if ((report->midiByte0 & 0xF0) == 0x80) + { + offNote(report->midiByte0 & 0x0F, report->midiByte1, report->midiByte2); + } + break; + } + case LIVE_GUITAR: + { + PS3GHLGuitar_Data_t *report = (PS3GHLGuitar_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up || report->strumBar == 0x00; + usb_host_data->dpadDown |= down || report->strumBar == 0xFF; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + if (report->tilt != PS3_ACCEL_CENTER) + { + usb_host_data->tilt = (report->tilt - PS3_ACCEL_CENTER) << 6; + } + if (report->whammy) + { + usb_host_data->whammy = (report->whammy - PS3_STICK_CENTER) << 1; + } + break; + } + case DJ_HERO_TURNTABLE: + { + PS3Turntable_Data_t *report = (PS3Turntable_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->leftBlue |= report->leftBlue; + usb_host_data->leftRed |= report->leftRed; + usb_host_data->leftGreen |= report->leftGreen; + usb_host_data->rightBlue |= report->rightBlue; + usb_host_data->rightRed |= report->rightRed; + usb_host_data->rightGreen |= report->rightGreen; + if (report->effectsKnob != PS3_ACCEL_CENTER) + { + usb_host_data->effectsKnob = (report->effectsKnob - PS3_ACCEL_CENTER) << 6; + } + if (report->crossfader != PS3_ACCEL_CENTER) + { + usb_host_data->crossfader = (report->crossfader - PS3_ACCEL_CENTER) << 6; + } + if (report->leftTableVelocity != PS3_STICK_CENTER) + { + usb_host_data->leftTableVelocity = (report->leftTableVelocity - PS3_STICK_CENTER) << 8; + } + if (report->rightTableVelocity != PS3_STICK_CENTER) + { + usb_host_data->rightTableVelocity = (report->rightTableVelocity - PS3_STICK_CENTER) << 8; + } + break; + } + + case ROCK_BAND_PRO_GUITAR_SQUIRE: + case ROCK_BAND_PRO_GUITAR_MUSTANG: + { + PS3RockBandProGuitar_Data_t *report = (PS3RockBandProGuitar_Data_t *)data; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + TRANSLATE_PRO_GUITAR; + break; + } + } + break; + } + case LTEK_ID: + { + LTEK_Report_With_Id_Data_t *report = (LTEK_Report_With_Id_Data_t *)data; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; + usb_host_data->start |= report->start; + usb_host_data->back |= report->back; + break; + } + case LTEK: + { + LTEK_Report_Data_t *report = (LTEK_Report_Data_t *)data; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; + usb_host_data->start |= report->start; + usb_host_data->back |= report->back; + break; + } + case STEPMANIAX: + { + StepManiaX_Report_Data_t *report = (StepManiaX_Report_Data_t *)data; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; + break; + } + case PS4: + { + PS4Dpad_Data_t *dpad = (PS4Dpad_Data_t *)data; + usb_host_data->dpadLeft = dpad->dpad == 6 || dpad->dpad == 5 || dpad->dpad == 7; + usb_host_data->dpadRight = dpad->dpad == 3 || dpad->dpad == 2 || dpad->dpad == 1; + usb_host_data->dpadUp = dpad->dpad == 0 || dpad->dpad == 1 || dpad->dpad == 7; + usb_host_data->dpadDown = dpad->dpad == 5 || dpad->dpad == 4 || dpad->dpad == 3; + switch (device_type.sub_type) + { + case GAMEPAD: + { + PS4Gamepad_Data_t *report = (PS4Gamepad_Data_t *)data; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->rightThumbClick |= report->rightThumbClick; + usb_host_data->capture |= report->capture; + if (report->leftTrigger) + { + usb_host_data->leftTrigger = report->leftTrigger << 8; + } + if (report->rightTrigger) + { + usb_host_data->rightTrigger = report->rightTrigger << 8; + } + if (report->leftStickX != PS3_STICK_CENTER) + { + usb_host_data->leftStickX = (report->leftStickX - PS3_STICK_CENTER) << 8; + } + if (report->leftStickY != PS3_STICK_CENTER) + { + usb_host_data->leftStickY = (((UINT8_MAX - report->leftStickY) - PS3_STICK_CENTER)) << 8; + } + if (report->rightStickX != PS3_STICK_CENTER) + { + usb_host_data->rightStickX = (report->rightStickX - PS3_STICK_CENTER) << 8; + } + if (report->rightStickY != PS3_STICK_CENTER) + { + usb_host_data->rightStickY = (((UINT8_MAX - report->rightStickY) - PS3_STICK_CENTER)) << 8; + } + break; + } + case ROCK_BAND_GUITAR: + { + PS4RockBandGuitar_Data_t *report = (PS4RockBandGuitar_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + if (report->tilt) + { + usb_host_data->tilt = report->tilt << 7; + } + if (report->solo) + { + usb_host_data->soloGreen |= report->a; + usb_host_data->soloRed |= report->b; + usb_host_data->soloYellow |= report->y; + usb_host_data->soloBlue |= report->x; + usb_host_data->soloOrange |= report->leftShoulder; + } + if (report->whammy) + { + usb_host_data->whammy = report->whammy; + } + if (report->pickup) + { + usb_host_data->pickup = report->pickup; + } + break; + } + case LIVE_GUITAR: + { + PS4GHLGuitar_Data_t *report = (PS4GHLGuitar_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->dpadUp |= report->strumBar == 0x00; + usb_host_data->dpadDown |= report->strumBar == 0xFF; + if (report->tilt != PS3_ACCEL_CENTER) + { + usb_host_data->tilt = (report->tilt - PS3_ACCEL_CENTER) << 6; + } + if (report->whammy) + { + usb_host_data->whammy = report->whammy; + } + break; + } + } + break; + } + case PS5: + { + PS5Gamepad_Data_t *dpad = (PS5Gamepad_Data_t *)data; + usb_host_data->dpadLeft = dpad->dpad == 6 || dpad->dpad == 5 || dpad->dpad == 7; + usb_host_data->dpadRight = dpad->dpad == 3 || dpad->dpad == 2 || dpad->dpad == 1; + usb_host_data->dpadUp = dpad->dpad == 0 || dpad->dpad == 1 || dpad->dpad == 7; + usb_host_data->dpadDown = dpad->dpad == 5 || dpad->dpad == 4 || dpad->dpad == 3; + switch (device_type.sub_type) + { + case GAMEPAD: + { + PS5Gamepad_Data_t *report = (PS5Gamepad_Data_t *)data; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->rightThumbClick |= report->rightThumbClick; + if (report->leftTrigger) + { + usb_host_data->leftTrigger = report->leftTrigger << 8; + } + if (report->rightTrigger) + { + usb_host_data->rightTrigger = report->rightTrigger << 8; + } + if (report->leftStickX != PS3_STICK_CENTER) + { + usb_host_data->leftStickX = (report->leftStickX - PS3_STICK_CENTER) << 8; + } + if (report->leftStickY != PS3_STICK_CENTER) + { + usb_host_data->leftStickY = (((UINT8_MAX - report->leftStickY) - PS3_STICK_CENTER)) << 8; + } + if (report->rightStickX != PS3_STICK_CENTER) + { + usb_host_data->rightStickX = (report->rightStickX - PS3_STICK_CENTER) << 8; + } + if (report->rightStickY != PS3_STICK_CENTER) + { + usb_host_data->rightStickY = (((UINT8_MAX - report->rightStickY) - PS3_STICK_CENTER)) << 8; + } + break; + } + case ROCK_BAND_GUITAR: + { + PS5RockBandGuitar_Data_t *report = (PS5RockBandGuitar_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + if (report->tilt) + { + usb_host_data->tilt = report->tilt << 7; + } + if (report->solo) + { + usb_host_data->soloGreen |= report->a; + usb_host_data->soloRed |= report->b; + usb_host_data->soloYellow |= report->y; + usb_host_data->soloBlue |= report->x; + usb_host_data->soloOrange |= report->leftShoulder; + } + if (report->whammy) + { + usb_host_data->whammy = report->whammy; + } + break; + } + } + break; + } + case SWITCH: + { + switch (device_type.sub_type) + { + case GAMEPAD: + { + SwitchProGamepad_Data_t *report = (SwitchProGamepad_Data_t *)data; + usb_host_data->dpadLeft = report->dpad == 6 || report->dpad == 5 || report->dpad == 7; + usb_host_data->dpadRight = report->dpad == 3 || report->dpad == 2 || report->dpad == 1; + usb_host_data->dpadUp = report->dpad == 0 || report->dpad == 1 || report->dpad == 7; + usb_host_data->dpadDown = report->dpad == 5 || report->dpad == 4 || report->dpad == 3; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->capture |= report->capture; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->rightThumbClick |= report->rightThumbClick; + if (report->leftTrigger) + { + usb_host_data->leftTrigger = report->leftTrigger << 8; + } + if (report->rightTrigger) + { + usb_host_data->rightTrigger = report->rightTrigger << 8; + } + if (report->leftStickX != PS3_STICK_CENTER) + { + usb_host_data->leftStickX = (report->leftStickX - PS3_STICK_CENTER) << 8; + } + if (report->leftStickY != PS3_STICK_CENTER) + { + usb_host_data->leftStickY = (((UINT8_MAX - report->leftStickY) - PS3_STICK_CENTER)) << 8; + } + if (report->rightStickX != PS3_STICK_CENTER) + { + usb_host_data->rightStickX = (report->rightStickX - PS3_STICK_CENTER) << 8; + } + if (report->rightStickY != PS3_STICK_CENTER) + { + usb_host_data->rightStickY = (((UINT8_MAX - report->rightStickY) - PS3_STICK_CENTER)) << 8; } break; } - case PS5: { - PS5Gamepad_Data_t *dpad = (PS5Gamepad_Data_t *)data; - usb_host_data->dpadLeft = dpad->dpad == 6 || dpad->dpad == 5 || dpad->dpad == 7; - usb_host_data->dpadRight = dpad->dpad == 3 || dpad->dpad == 2 || dpad->dpad == 1; - usb_host_data->dpadUp = dpad->dpad == 0 || dpad->dpad == 1 || dpad->dpad == 7; - usb_host_data->dpadDown = dpad->dpad == 5 || dpad->dpad == 4 || dpad->dpad == 3; - switch (device_type.sub_type) { - case GAMEPAD: { - PS5Gamepad_Data_t *report = (PS5Gamepad_Data_t *)data; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->rightThumbClick |= report->rightThumbClick; - if (report->leftTrigger) { - usb_host_data->leftTrigger = report->leftTrigger << 8; - } - if (report->rightTrigger) { - usb_host_data->rightTrigger = report->rightTrigger << 8; - } - if (report->leftStickX != PS3_STICK_CENTER) { - usb_host_data->leftStickX = (report->leftStickX - PS3_STICK_CENTER) << 8; - } - if (report->leftStickY != PS3_STICK_CENTER) { - usb_host_data->leftStickY = (((UINT8_MAX - report->leftStickY) - PS3_STICK_CENTER)) << 8; - } - if (report->rightStickX != PS3_STICK_CENTER) { - usb_host_data->rightStickX = (report->rightStickX - PS3_STICK_CENTER) << 8; - } - if (report->rightStickY != PS3_STICK_CENTER) { - usb_host_data->rightStickY = (((UINT8_MAX - report->rightStickY) - PS3_STICK_CENTER)) << 8; - } - break; + case TAIKO: + { + SwitchTaiko_Data_t *report = (SwitchTaiko_Data_t *)data; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->rightThumbClick |= report->rightThumbClick; + usb_host_data->dpadLeft = report->dpad == 6 || report->dpad == 5 || report->dpad == 7; + usb_host_data->dpadRight = report->dpad == 3 || report->dpad == 2 || report->dpad == 1; + usb_host_data->dpadUp = report->dpad == 0 || report->dpad == 1 || report->dpad == 7; + usb_host_data->dpadDown = report->dpad == 5 || report->dpad == 4 || report->dpad == 3; + if (report->l2) + { + usb_host_data->leftTrigger = UINT16_MAX; + } + if (report->r2) + { + usb_host_data->rightTrigger = UINT16_MAX; + } + break; + } + } + break; + } + case SWITCH2: + { + switch (device_type.sub_type) + { + case GAMEPAD: + { + Switch2ProGamepad_Data_t *report = (Switch2ProGamepad_Data_t *)data; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->capture |= report->capture; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->rightThumbClick |= report->rightThumbClick; + if (report->leftTrigger) + { + usb_host_data->leftTrigger = report->leftTrigger << 8; + } + if (report->rightTrigger) + { + usb_host_data->rightTrigger = report->rightTrigger << 8; + } + if (report->leftStickX != SWITCH_2_STICK_CENTER) + { + usb_host_data->leftStickX = (report->leftStickX - SWITCH_2_STICK_CENTER) << 5; + } + if (report->leftStickY != SWITCH_2_STICK_CENTER) + { + usb_host_data->leftStickY = (((4096 - report->leftStickY) - SWITCH_2_STICK_CENTER)) << 5; + } + if (report->rightStickX != SWITCH_2_STICK_CENTER) + { + usb_host_data->rightStickX = (report->rightStickX - SWITCH_2_STICK_CENTER) << 5; + } + if (report->rightStickY != SWITCH_2_STICK_CENTER) + { + usb_host_data->rightStickY = (((4096 - report->rightStickY) - SWITCH_2_STICK_CENTER)) << 5; + } + break; + } + } + break; + } + case OG_XBOX: + { + OGXboxGamepad_Data_t *report = (OGXboxGamepad_Data_t *)data; + usb_host_data->a |= report->a > 0x20; + usb_host_data->b |= report->b > 0x20; + usb_host_data->x |= report->x > 0x20; + usb_host_data->y |= report->y > 0x20; + usb_host_data->leftShoulder |= report->leftShoulder > 0x20; + usb_host_data->rightShoulder |= report->rightShoulder > 0x20; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->rightThumbClick |= report->rightThumbClick; + usb_host_data->dpadLeft = report->dpadLeft; + usb_host_data->dpadRight = report->dpadRight; + usb_host_data->dpadUp = report->dpadUp; + usb_host_data->dpadDown = report->dpadDown; + if (report->leftTrigger) + { + usb_host_data->leftTrigger = report->leftTrigger << 8; + } + if (report->rightTrigger) + { + usb_host_data->rightTrigger = report->rightTrigger << 8; + } + if (report->leftStickX) + { + usb_host_data->leftStickX = report->leftStickX; + } + if (report->leftStickY) + { + usb_host_data->leftStickY = report->leftStickY; + } + if (report->rightStickX) + { + usb_host_data->rightStickX = report->rightStickX; + } + if (report->rightStickY) + { + usb_host_data->rightStickY = report->rightStickY; + } + if (report->leftShoulder) + { + usb_host_data->pressureL1 = report->leftShoulder; + } + if (report->rightShoulder) + { + usb_host_data->pressureR1 = report->rightShoulder; + } + if (report->y) + { + usb_host_data->pressureTriangle = report->y; + } + if (report->b) + { + usb_host_data->pressureCircle = report->b; + } + if (report->a) + { + usb_host_data->pressureCross = report->a; + } + if (report->x) + { + usb_host_data->pressureSquare = report->x; + } + break; + } + case XBOX360_BB: + { + XInputBigButton_Data_t *report = (XInputBigButton_Data_t *)data; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->rightThumbClick |= report->rightThumbClick; + usb_host_data->dpadLeft = report->dpadLeft; + usb_host_data->dpadRight = report->dpadRight; + usb_host_data->dpadUp = report->dpadUp; + usb_host_data->dpadDown = report->dpadDown; + break; + } + + case XINPUTCOMPAT: + { + XInputCompatGamepad_Data_t *report = (XInputCompatGamepad_Data_t *)data; + if (report->rid == 2) + { + usb_host_data->guide = data[1]; + break; + } + if (report->rid == 1) + { + uint8_t dpad = report->dpad - 1; + usb_host_data->dpadLeft = dpad == 6 || dpad == 5 || dpad == 7; + usb_host_data->dpadRight = dpad == 3 || dpad == 2 || dpad == 1; + usb_host_data->dpadUp = dpad == 0 || dpad == 1 || dpad == 7; + usb_host_data->dpadDown = dpad == 5 || dpad == 4 || dpad == 3; + // Festival pro mode mappings + usb_host_data->green |= dpad == 6 || dpad == 5 || dpad == 7; + usb_host_data->red |= dpad == 0 || dpad == 1 || dpad == 7; + usb_host_data->yellow |= report->x; + usb_host_data->blue |= report->y; + usb_host_data->orange |= report->b; + // Festival expert mappings + // usb_host_data->green |= dpad == 6 || dpad == 5 || dpad == 7; + // usb_host_data->red |= dpad == 3 || dpad == 2 || dpad == 1; + // usb_host_data->yellow |= report->x; + // usb_host_data->blue |= report->y; + // usb_host_data->orange |= report->b; + + // Festival easy/med/hard mappings + // usb_host_data->green |= dpad == 6 || dpad == 5 || dpad == 7; + // usb_host_data->red |= dpad == 3 || dpad == 2 || dpad == 1; + // usb_host_data->yellow |= report->x; + // usb_host_data->blue |= report->b; + // usb_host_data->orange |= report->y; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->rightThumbClick |= report->rightThumbClick; + if (report->leftTrigger) + { + usb_host_data->leftTrigger = report->leftTrigger << 6; + } + if (report->rightTrigger) + { + usb_host_data->rightTrigger = report->rightTrigger << 6; + } + if (report->leftStickX) + { + usb_host_data->leftStickX = report->leftStickX - INT16_MAX; + } + if (report->leftStickY) + { + usb_host_data->leftStickY = -(report->leftStickY - INT16_MAX); + } + if (report->rightStickX) + { + usb_host_data->rightStickX = report->rightStickX - INT16_MAX; + } + if (report->rightStickY) + { + usb_host_data->rightStickY = -(report->rightStickY - INT16_MAX); + } + } + break; + } + case XBOX360_W: + case XBOX360: + { + switch (device_type.sub_type) + { + case XINPUT_GUITAR_BASS: + case XINPUT_GUITAR: + { + XInputRockBandGuitar_Data_t *report = (XInputRockBandGuitar_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->dpadLeft = report->dpadLeft; + usb_host_data->dpadRight = report->dpadRight; + usb_host_data->dpadUp = report->dpadUp; + usb_host_data->dpadDown = report->dpadDown; + if (report->tilt) + { + usb_host_data->tilt = INT16_MAX; + } + if (report->solo) + { + usb_host_data->soloGreen |= report->a; + usb_host_data->soloRed |= report->b; + usb_host_data->soloYellow |= report->y; + usb_host_data->soloBlue |= report->x; + usb_host_data->soloOrange |= report->leftShoulder; + } + if (report->whammy) + { + usb_host_data->whammy = (report->whammy >> 8) - PS3_STICK_CENTER; + } + if (report->pickup) + { + usb_host_data->pickup = report->pickup; + } + break; + } + case XINPUT_GUITAR_WT: + case XINPUT_GUITAR_ALTERNATE: + { + XInputGuitarHeroGuitar_Data_t *report = (XInputGuitarHeroGuitar_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->dpadLeft = report->dpadLeft; + usb_host_data->dpadRight = report->dpadRight; + usb_host_data->dpadUp = report->dpadUp; + usb_host_data->dpadDown = report->dpadDown; + if (report->tilt) + { + usb_host_data->tilt = report->tilt; + } + if (report->whammy) + { + usb_host_data->whammy = (report->whammy >> 8) - PS3_STICK_CENTER; + } + + uint8_t slider = (report->slider >> 8) ^ 0x80; + + if (device_type.sub_type == XINPUT_GUITAR_WT) + { + if (slider < 0x2F) + { + usb_host_data->slider = 0x15; } - case ROCK_BAND_GUITAR: { - PS5RockBandGuitar_Data_t *report = (PS5RockBandGuitar_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - if (report->tilt) { - usb_host_data->tilt = report->tilt << 7; - } - if (report->solo) { - usb_host_data->soloGreen |= report->a; - usb_host_data->soloRed |= report->b; - usb_host_data->soloYellow |= report->y; - usb_host_data->soloBlue |= report->x; - usb_host_data->soloOrange |= report->leftShoulder; - } - if (report->whammy) { - usb_host_data->whammy = report->whammy; - } - break; + else if (slider <= 0x3F) + { + usb_host_data->slider = 0x30; + } + else if (slider <= 0x5F) + { + usb_host_data->slider = 0x4D; + } + else if (slider <= 0x6F) + { + usb_host_data->slider = 0x66; + } + else if (slider <= 0x8F) + { + usb_host_data->slider = 0x80; + } + else if (slider <= 0x9F) + { + usb_host_data->slider = 0x9A; + } + else if (slider <= 0xAF) + { + usb_host_data->slider = 0xAF; + } + else if (slider <= 0xCF) + { + usb_host_data->slider = 0xC9; + } + else if (slider <= 0xEF) + { + usb_host_data->slider = 0xE6; + } + else + { + usb_host_data->slider = 0xFF; } } break; } - case SWITCH: { - switch (device_type.sub_type) { - case GAMEPAD: { - SwitchProGamepad_Data_t *report = (SwitchProGamepad_Data_t *)data; - usb_host_data->dpadLeft = report->dpad == 6 || report->dpad == 5 || report->dpad == 7; - usb_host_data->dpadRight = report->dpad == 3 || report->dpad == 2 || report->dpad == 1; - usb_host_data->dpadUp = report->dpad == 0 || report->dpad == 1 || report->dpad == 7; - usb_host_data->dpadDown = report->dpad == 5 || report->dpad == 4 || report->dpad == 3; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->capture |= report->capture; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->rightThumbClick |= report->rightThumbClick; - if (report->leftTrigger) { - usb_host_data->leftTrigger = report->leftTrigger << 8; - } - if (report->rightTrigger) { - usb_host_data->rightTrigger = report->rightTrigger << 8; - } - if (report->leftStickX != PS3_STICK_CENTER) { - usb_host_data->leftStickX = (report->leftStickX - PS3_STICK_CENTER) << 8; - } - if (report->leftStickY != PS3_STICK_CENTER) { - usb_host_data->leftStickY = (((UINT8_MAX - report->leftStickY) - PS3_STICK_CENTER)) << 8; - } - if (report->rightStickX != PS3_STICK_CENTER) { - usb_host_data->rightStickX = (report->rightStickX - PS3_STICK_CENTER) << 8; - } - if (report->rightStickY != PS3_STICK_CENTER) { - usb_host_data->rightStickY = (((UINT8_MAX - report->rightStickY) - PS3_STICK_CENTER)) << 8; - } - break; + case XINPUT_DRUMS: + { + if (device_type.drum_type == DRUM_GH) + { + XInputGuitarHeroDrums_Data_t *report = (XInputGuitarHeroDrums_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->dpadLeft = report->dpadLeft; + usb_host_data->dpadRight = report->dpadRight; + usb_host_data->dpadUp = report->dpadUp; + usb_host_data->dpadDown = report->dpadDown; + SET_GH_PADS(); + // Forward any midi data we get + if ((report->midiPacket[0] & 0xF0) == 0x90) + { + onNote(report->midiPacket[0] & 0x0F, report->midiPacket[1], report->midiPacket[2]); } - case TAIKO: { - SwitchTaiko_Data_t *report = (SwitchTaiko_Data_t *)data; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->rightThumbClick |= report->rightThumbClick; - usb_host_data->dpadLeft = report->dpad == 6 || report->dpad == 5 || report->dpad == 7; - usb_host_data->dpadRight = report->dpad == 3 || report->dpad == 2 || report->dpad == 1; - usb_host_data->dpadUp = report->dpad == 0 || report->dpad == 1 || report->dpad == 7; - usb_host_data->dpadDown = report->dpad == 5 || report->dpad == 4 || report->dpad == 3; - if (report->l2) { - usb_host_data->leftTrigger = UINT16_MAX; - } - if (report->r2) { - usb_host_data->rightTrigger = UINT16_MAX; - } - break; + else if ((report->midiPacket[0] & 0xF0) == 0x80) + { + offNote(report->midiPacket[0] & 0x0F, report->midiPacket[1], report->midiPacket[2]); } } + else + { + XInputRockBandDrums_Data_t *report = (XInputRockBandDrums_Data_t *)data; + bool up = report->dpadUp; + bool down = report->dpadDown; + bool left = report->dpadLeft; + bool right = report->dpadRight; + bool kick1 = report->leftShoulder; + bool kick2 = report->leftThumbClick; + + uint8_t redVelocity = xinput_rb_velocity_positive(report->redVelocity); + uint8_t greenVelocity = xinput_rb_velocity_negative(report->greenVelocity); + uint8_t yellowVelocity = xinput_rb_velocity_negative(report->yellowVelocity); + uint8_t blueVelocity = xinput_rb_velocity_positive(report->blueVelocity); + + SET_RB_PADS(); + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->dpadLeft = report->dpadLeft; + usb_host_data->dpadRight = report->dpadRight; + usb_host_data->dpadUp = report->dpadUp; + usb_host_data->dpadDown = report->dpadDown; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + } break; } - case SWITCH2: { - switch (device_type.sub_type) { - case GAMEPAD: { - Switch2ProGamepad_Data_t *report = (Switch2ProGamepad_Data_t *)data; - usb_host_data->dpadLeft |= report->dpadLeft; - usb_host_data->dpadRight |= report->dpadRight; - usb_host_data->dpadUp |= report->dpadUp; - usb_host_data->dpadDown |= report->dpadDown; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->capture |= report->capture; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->rightThumbClick |= report->rightThumbClick; - if (report->leftTrigger) { - usb_host_data->leftTrigger = report->leftTrigger << 8; - } - if (report->rightTrigger) { - usb_host_data->rightTrigger = report->rightTrigger << 8; - } - if (report->leftStickX != SWITCH_2_STICK_CENTER) { - usb_host_data->leftStickX = (report->leftStickX - SWITCH_2_STICK_CENTER) << 5; - } - if (report->leftStickY != SWITCH_2_STICK_CENTER) { - usb_host_data->leftStickY = (((4096 - report->leftStickY) - SWITCH_2_STICK_CENTER)) << 5; - } - if (report->rightStickX != SWITCH_2_STICK_CENTER) { - usb_host_data->rightStickX = (report->rightStickX - SWITCH_2_STICK_CENTER) << 5; - } - if (report->rightStickY != SWITCH_2_STICK_CENTER) { - usb_host_data->rightStickY = (((4096 - report->rightStickY) - SWITCH_2_STICK_CENTER)) << 5; - } - break; + case XINPUT_GUITAR_HERO_LIVE: + { + XInputGHLGuitar_Data_t *report = (XInputGHLGuitar_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->dpadLeft = report->dpadLeft; + usb_host_data->dpadRight = report->dpadRight; + usb_host_data->dpadUp = report->dpadUp; + usb_host_data->dpadDown = report->dpadDown; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + if (report->tilt) + { + usb_host_data->tilt = report->tilt; + } + if (report->whammy) + { + usb_host_data->whammy = report->whammy; + } + break; + } + case XINPUT_TURNTABLE: + { + XInputTurntable_Data_t *report = (XInputTurntable_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->dpadLeft = report->dpadLeft; + usb_host_data->dpadRight = report->dpadRight; + usb_host_data->dpadUp = report->dpadUp; + usb_host_data->dpadDown = report->dpadDown; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->leftBlue |= report->leftBlue; + usb_host_data->leftRed |= report->leftRed; + usb_host_data->leftGreen |= report->leftGreen; + usb_host_data->rightBlue |= report->rightBlue; + usb_host_data->rightRed |= report->rightRed; + usb_host_data->rightGreen |= report->rightGreen; + if (report->effectsKnob) + { + usb_host_data->effectsKnob = report->effectsKnob; + } + if (report->crossfader) + { + usb_host_data->crossfader = report->crossfader; + } + if (report->leftTableVelocity) + { + if (report->leftTableVelocity > 127) + { + report->leftTableVelocity = 127; + } + if (report->leftTableVelocity < -127) + { + report->leftTableVelocity = -127; + } + usb_host_data->leftTableVelocity = report->leftTableVelocity << 8; + } + if (report->rightTableVelocity) + { + if (report->rightTableVelocity > 127) + { + report->rightTableVelocity = 127; } + if (report->rightTableVelocity < -127) + { + report->rightTableVelocity = -127; + } + usb_host_data->rightTableVelocity = report->rightTableVelocity << 8; } break; } - case OG_XBOX: { - OGXboxGamepad_Data_t *report = (OGXboxGamepad_Data_t *)data; - usb_host_data->a |= report->a > 0x20; - usb_host_data->b |= report->b > 0x20; - usb_host_data->x |= report->x > 0x20; - usb_host_data->y |= report->y > 0x20; - usb_host_data->leftShoulder |= report->leftShoulder > 0x20; - usb_host_data->rightShoulder |= report->rightShoulder > 0x20; + case XINPUT_PRO_KEYS: + { + XInputRockBandKeyboard_Data_t *report = (XInputRockBandKeyboard_Data_t *)data; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; + + TRANSLATE_PRO_KEYS; + break; + } + case XINPUT_PRO_GUITAR: + { + XInputRockBandProGuitar_Data_t *report = (XInputRockBandProGuitar_Data_t *)data; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; + TRANSLATE_PRO_GUITAR; + break; + } + // Any other subtypes we dont handle can just be read like gamepads. + default: + { + XInputGamepad_Data_t *report = (XInputGamepad_Data_t *)data; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; usb_host_data->back |= report->back; usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; usb_host_data->leftThumbClick |= report->leftThumbClick; usb_host_data->rightThumbClick |= report->rightThumbClick; usb_host_data->dpadLeft = report->dpadLeft; usb_host_data->dpadRight = report->dpadRight; usb_host_data->dpadUp = report->dpadUp; usb_host_data->dpadDown = report->dpadDown; - if (report->leftTrigger) { + if (report->leftTrigger) + { usb_host_data->leftTrigger = report->leftTrigger << 8; } - if (report->rightTrigger) { + if (report->rightTrigger) + { usb_host_data->rightTrigger = report->rightTrigger << 8; } - if (report->leftStickX) { + if (report->leftStickX) + { usb_host_data->leftStickX = report->leftStickX; } - if (report->leftStickY) { + if (report->leftStickY) + { usb_host_data->leftStickY = report->leftStickY; } - if (report->rightStickX) { + if (report->rightStickX) + { usb_host_data->rightStickX = report->rightStickX; } - if (report->rightStickY) { + if (report->rightStickY) + { usb_host_data->rightStickY = report->rightStickY; } - if (report->leftShoulder) { - usb_host_data->pressureL1 = report->leftShoulder; + break; + } + } + break; + } + case XBOXONE: + { + switch (device_type.sub_type) + { + case GAMEPAD: + { + XboxOneGamepad_Data_t *report = (XboxOneGamepad_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->rightThumbClick |= report->rightThumbClick; + usb_host_data->dpadLeft = report->dpadLeft; + usb_host_data->dpadRight = report->dpadRight; + usb_host_data->dpadUp = report->dpadUp; + usb_host_data->dpadDown = report->dpadDown; + // XB1 reports range from 0 - 1024 + if (report->leftTrigger) + { + usb_host_data->leftTrigger = report->leftTrigger << 6; } - if (report->rightShoulder) { - usb_host_data->pressureR1 = report->rightShoulder; + if (report->rightTrigger) + { + usb_host_data->rightTrigger = report->rightTrigger << 6; } - if (report->y) { - usb_host_data->pressureTriangle = report->y; + if (report->leftStickX) + { + usb_host_data->leftStickX = report->leftStickX; } - if (report->b) { - usb_host_data->pressureCircle = report->b; + if (report->leftStickY) + { + usb_host_data->leftStickY = report->leftStickY; } - if (report->a) { - usb_host_data->pressureCross = report->a; + if (report->rightStickX) + { + usb_host_data->rightStickX = report->rightStickX; } - if (report->x) { - usb_host_data->pressureSquare = report->x; + if (report->rightStickY) + { + usb_host_data->rightStickY = report->rightStickY; } break; } - case XBOX360_BB: { - XInputBigButton_Data_t *report = (XInputBigButton_Data_t *)data; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; + case ROCK_BAND_GUITAR: + { + XboxOneRockBandGuitar_Data_t *report = (XboxOneRockBandGuitar_Data_t *)data; usb_host_data->a |= report->a; usb_host_data->b |= report->b; usb_host_data->x |= report->x; usb_host_data->y |= report->y; usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; usb_host_data->back |= report->back; usb_host_data->start |= report->start; usb_host_data->guide |= report->guide; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->rightThumbClick |= report->rightThumbClick; + usb_host_data->green |= report->green; + usb_host_data->red |= report->red; + usb_host_data->yellow |= report->yellow; + usb_host_data->blue |= report->blue; + usb_host_data->orange |= report->orange; + usb_host_data->soloGreen |= report->soloGreen; + usb_host_data->soloRed |= report->soloRed; + usb_host_data->soloYellow |= report->soloYellow; + usb_host_data->soloBlue |= report->soloBlue; + usb_host_data->soloOrange |= report->soloOrange; usb_host_data->dpadLeft = report->dpadLeft; usb_host_data->dpadRight = report->dpadRight; usb_host_data->dpadUp = report->dpadUp; usb_host_data->dpadDown = report->dpadDown; - break; - } - - case XINPUTCOMPAT: { - XInputCompatGamepad_Data_t *report = (XInputCompatGamepad_Data_t *)data; - if (report->rid == 2) { - usb_host_data->guide = data[1]; - break; + if (report->tilt) + { + usb_host_data->tilt = report->tilt << 8; } - if (report->rid == 1) { - uint8_t dpad = report->dpad - 1; - usb_host_data->dpadLeft = dpad == 6 || dpad == 5 || dpad == 7; - usb_host_data->dpadRight = dpad == 3 || dpad == 2 || dpad == 1; - usb_host_data->dpadUp = dpad == 0 || dpad == 1 || dpad == 7; - usb_host_data->dpadDown = dpad == 5 || dpad == 4 || dpad == 3; - // Festival pro mode mappings - usb_host_data->green |= dpad == 6 || dpad == 5 || dpad == 7; - usb_host_data->red |= dpad == 0 || dpad == 1 || dpad == 7; - usb_host_data->yellow |= report->x; - usb_host_data->blue |= report->y; - usb_host_data->orange |= report->b; - // Festival expert mappings - // usb_host_data->green |= dpad == 6 || dpad == 5 || dpad == 7; - // usb_host_data->red |= dpad == 3 || dpad == 2 || dpad == 1; - // usb_host_data->yellow |= report->x; - // usb_host_data->blue |= report->y; - // usb_host_data->orange |= report->b; - - // Festival easy/med/hard mappings - // usb_host_data->green |= dpad == 6 || dpad == 5 || dpad == 7; - // usb_host_data->red |= dpad == 3 || dpad == 2 || dpad == 1; - // usb_host_data->yellow |= report->x; - // usb_host_data->blue |= report->b; - // usb_host_data->orange |= report->y; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->rightThumbClick |= report->rightThumbClick; - if (report->leftTrigger) { - usb_host_data->leftTrigger = report->leftTrigger << 6; - } - if (report->rightTrigger) { - usb_host_data->rightTrigger = report->rightTrigger << 6; - } - if (report->leftStickX) { - usb_host_data->leftStickX = report->leftStickX - INT16_MAX; - } - if (report->leftStickY) { - usb_host_data->leftStickY = -(report->leftStickY - INT16_MAX); - } - if (report->rightStickX) { - usb_host_data->rightStickX = report->rightStickX - INT16_MAX; - } - if (report->rightStickY) { - usb_host_data->rightStickY = -(report->rightStickY - INT16_MAX); - } + if (report->whammy) + { + usb_host_data->whammy = report->whammy; } - break; - } - case XBOX360_W: - case XBOX360: { - switch (device_type.sub_type) { - case XINPUT_GUITAR_BASS: - case XINPUT_GUITAR: { - XInputRockBandGuitar_Data_t *report = (XInputRockBandGuitar_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; - if (report->tilt) { - usb_host_data->tilt = INT16_MAX; - } - if (report->solo) { - usb_host_data->soloGreen |= report->a; - usb_host_data->soloRed |= report->b; - usb_host_data->soloYellow |= report->y; - usb_host_data->soloBlue |= report->x; - usb_host_data->soloOrange |= report->leftShoulder; - } - if (report->whammy) { - usb_host_data->whammy = (report->whammy >> 8) - PS3_STICK_CENTER; - } - if (report->pickup) { - usb_host_data->pickup = report->pickup; - } - break; - } - case XINPUT_GUITAR_WT: - case XINPUT_GUITAR_ALTERNATE: { - XInputGuitarHeroGuitar_Data_t *report = (XInputGuitarHeroGuitar_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; - if (report->tilt) { - usb_host_data->tilt = report->tilt; - } - if (report->whammy) { - usb_host_data->whammy = (report->whammy >> 8) - PS3_STICK_CENTER; - } - - uint8_t slider = (report->slider >> 8) ^ 0x80; - - if (device_type.sub_type == XINPUT_GUITAR_WT) { - if (slider < 0x2F) { - usb_host_data->slider = 0x15; - } else if (slider <= 0x3F) { - usb_host_data->slider = 0x30; - } else if (slider <= 0x5F) { - usb_host_data->slider = 0x4D; - } else if (slider <= 0x6F) { - usb_host_data->slider = 0x66; - } else if (slider <= 0x8F) { - usb_host_data->slider = 0x80; - } else if (slider <= 0x9F) { - usb_host_data->slider = 0x9A; - } else if (slider <= 0xAF) { - usb_host_data->slider = 0xAF; - } else if (slider <= 0xCF) { - usb_host_data->slider = 0xC9; - } else if (slider <= 0xEF) { - usb_host_data->slider = 0xE6; - } else { - usb_host_data->slider = 0xFF; - } - } - break; - } - case XINPUT_RB_DRUMS: { - XInputRockBandDrums_Data_t *report = (XInputRockBandDrums_Data_t *)data; - bool up = report->dpadUp; - bool down = report->dpadDown; - bool left = report->dpadLeft; - bool right = report->dpadRight; - bool kick1 = report->leftShoulder; - bool kick2 = report->leftThumbClick; - - uint8_t redVelocity = xinput_rb_velocity_positive(report->redVelocity); - uint8_t greenVelocity = xinput_rb_velocity_negative(report->greenVelocity); - uint8_t yellowVelocity = xinput_rb_velocity_negative(report->yellowVelocity); - uint8_t blueVelocity = xinput_rb_velocity_positive(report->blueVelocity); - - SET_RB_PADS(); - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - break; - } - case XINPUT_GH_DRUMS: { - XInputGuitarHeroDrums_Data_t *report = (XInputGuitarHeroDrums_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; - SET_GH_PADS(); - // Forward any midi data we get - if ((report->midiPacket[0] & 0xF0) == 0x90) { - onNote(report->midiPacket[0] & 0x0F, report->midiPacket[1], report->midiPacket[2]); - } else if ((report->midiPacket[0] & 0xF0) == 0x80) { - offNote(report->midiPacket[0] & 0x0F, report->midiPacket[1], report->midiPacket[2]); - } - break; - } - case XINPUT_GUITAR_HERO_LIVE: { - XInputGHLGuitar_Data_t *report = (XInputGHLGuitar_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - if (report->tilt) { - usb_host_data->tilt = report->tilt; - } - if (report->whammy) { - usb_host_data->whammy = report->whammy; - } - break; - } - case XINPUT_TURNTABLE: { - XInputTurntable_Data_t *report = (XInputTurntable_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->leftBlue |= report->leftBlue; - usb_host_data->leftRed |= report->leftRed; - usb_host_data->leftGreen |= report->leftGreen; - usb_host_data->rightBlue |= report->rightBlue; - usb_host_data->rightRed |= report->rightRed; - usb_host_data->rightGreen |= report->rightGreen; - if (report->effectsKnob) { - usb_host_data->effectsKnob = report->effectsKnob; - } - if (report->crossfader) { - usb_host_data->crossfader = report->crossfader; - } - if (report->leftTableVelocity) { - if (report->leftTableVelocity > 127) { - report->leftTableVelocity = 127; - } - if (report->leftTableVelocity < -127) { - report->leftTableVelocity = -127; - } - usb_host_data->leftTableVelocity = report->leftTableVelocity << 8; - } - if (report->rightTableVelocity) { - if (report->rightTableVelocity > 127) { - report->rightTableVelocity = 127; - } - if (report->rightTableVelocity < -127) { - report->rightTableVelocity = -127; - } - usb_host_data->rightTableVelocity = report->rightTableVelocity << 8; - } - break; - } - case XINPUT_PRO_KEYS: { - XInputRockBandKeyboard_Data_t *report = (XInputRockBandKeyboard_Data_t *)data; - usb_host_data->dpadLeft |= report->dpadLeft; - usb_host_data->dpadRight |= report->dpadRight; - usb_host_data->dpadUp |= report->dpadUp; - usb_host_data->dpadDown |= report->dpadDown; - - TRANSLATE_PRO_KEYS; - break; - } - case XINPUT_PRO_GUITAR: { - XInputRockBandProGuitar_Data_t *report = (XInputRockBandProGuitar_Data_t *)data; - usb_host_data->dpadLeft |= report->dpadLeft; - usb_host_data->dpadRight |= report->dpadRight; - usb_host_data->dpadUp |= report->dpadUp; - usb_host_data->dpadDown |= report->dpadDown; - TRANSLATE_PRO_GUITAR; - break; - } - // Any other subtypes we dont handle can just be read like gamepads. - default: { - XInputGamepad_Data_t *report = (XInputGamepad_Data_t *)data; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->rightThumbClick |= report->rightThumbClick; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; - if (report->leftTrigger) { - usb_host_data->leftTrigger = report->leftTrigger << 8; - } - if (report->rightTrigger) { - usb_host_data->rightTrigger = report->rightTrigger << 8; - } - if (report->leftStickX) { - usb_host_data->leftStickX = report->leftStickX; - } - if (report->leftStickY) { - usb_host_data->leftStickY = report->leftStickY; - } - if (report->rightStickX) { - usb_host_data->rightStickX = report->rightStickX; - } - if (report->rightStickY) { - usb_host_data->rightStickY = report->rightStickY; - } - break; - } + if (report->pickup) + { + usb_host_data->pickup = report->pickup; } break; } - case XBOXONE: { - switch (device_type.sub_type) { - case GAMEPAD: { - XboxOneGamepad_Data_t *report = (XboxOneGamepad_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->rightThumbClick |= report->rightThumbClick; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; - // XB1 reports range from 0 - 1024 - if (report->leftTrigger) { - usb_host_data->leftTrigger = report->leftTrigger << 6; - } - if (report->rightTrigger) { - usb_host_data->rightTrigger = report->rightTrigger << 6; - } - if (report->leftStickX) { - usb_host_data->leftStickX = report->leftStickX; - } - if (report->leftStickY) { - usb_host_data->leftStickY = report->leftStickY; - } - if (report->rightStickX) { - usb_host_data->rightStickX = report->rightStickX; - } - if (report->rightStickY) { - usb_host_data->rightStickY = report->rightStickY; - } - break; - } - case ROCK_BAND_GUITAR: { - XboxOneRockBandGuitar_Data_t *report = (XboxOneRockBandGuitar_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->green |= report->green; - usb_host_data->red |= report->red; - usb_host_data->yellow |= report->yellow; - usb_host_data->blue |= report->blue; - usb_host_data->orange |= report->orange; - usb_host_data->soloGreen |= report->soloGreen; - usb_host_data->soloRed |= report->soloRed; - usb_host_data->soloYellow |= report->soloYellow; - usb_host_data->soloBlue |= report->soloBlue; - usb_host_data->soloOrange |= report->soloOrange; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; - if (report->tilt) { - usb_host_data->tilt = report->tilt << 8; - } - if (report->whammy) { - usb_host_data->whammy = report->whammy; - } - if (report->pickup) { - usb_host_data->pickup = report->pickup; - } - break; - } - case ROCK_BAND_DRUMS: { - XboxOneRockBandDrums_Data_t *report = (XboxOneRockBandDrums_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; - if (report->greenVelocity) { - onNote(10, RB_MIDI_NOTE_GREEN, report->greenVelocity << 3); - } else { - offNote(10, RB_MIDI_NOTE_GREEN, 0); - } - if (report->redVelocity) { - onNote(10, RB_MIDI_NOTE_RED, report->redVelocity << 3); - } else { - offNote(10, RB_MIDI_NOTE_RED, 0); - } - if (report->yellowVelocity) { - onNote(10, RB_MIDI_NOTE_YELLOW, report->redVelocity << 3); - } else { - offNote(10, RB_MIDI_NOTE_YELLOW, 0); - } - if (report->blueVelocity) { - onNote(10, RB_MIDI_NOTE_BLUE, report->redVelocity << 3); - } else { - offNote(10, RB_MIDI_NOTE_BLUE, 0); - } - if (report->blueCymbalVelocity) { - onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, report->redVelocity << 3); - } else { - offNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, 0); - } - if (report->yellowCymbalVelocity) { - onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, report->redVelocity << 3); - } else { - offNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, 0); - } - if (report->greenCymbalVelocity) { - onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, report->redVelocity << 3); - } else { - offNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, 0); - } - if (report->leftShoulder) { - onNote(10, RB_MIDI_NOTE_KICK, 0x7F); - } else { - offNote(10, RB_MIDI_NOTE_KICK, 0); - } - if (report->rightShoulder) { - onNote(10, RB_MIDI_NOTE_KICK2, 0x7F); - } else { - offNote(10, RB_MIDI_NOTE_KICK2, 0); - } - break; - } + case ROCK_BAND_DRUMS: + { + XboxOneRockBandDrums_Data_t *report = (XboxOneRockBandDrums_Data_t *)data; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->dpadLeft = report->dpadLeft; + usb_host_data->dpadRight = report->dpadRight; + usb_host_data->dpadUp = report->dpadUp; + usb_host_data->dpadDown = report->dpadDown; + if (report->greenVelocity) + { + onNote(10, RB_MIDI_NOTE_GREEN, report->greenVelocity << 3); + } + else + { + offNote(10, RB_MIDI_NOTE_GREEN, 0); + } + if (report->redVelocity) + { + onNote(10, RB_MIDI_NOTE_RED, report->redVelocity << 3); + } + else + { + offNote(10, RB_MIDI_NOTE_RED, 0); + } + if (report->yellowVelocity) + { + onNote(10, RB_MIDI_NOTE_YELLOW, report->redVelocity << 3); + } + else + { + offNote(10, RB_MIDI_NOTE_YELLOW, 0); + } + if (report->blueVelocity) + { + onNote(10, RB_MIDI_NOTE_BLUE, report->redVelocity << 3); + } + else + { + offNote(10, RB_MIDI_NOTE_BLUE, 0); + } + if (report->blueCymbalVelocity) + { + onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, report->redVelocity << 3); + } + else + { + offNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, 0); + } + if (report->yellowCymbalVelocity) + { + onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, report->redVelocity << 3); + } + else + { + offNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, 0); + } + if (report->greenCymbalVelocity) + { + onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, report->redVelocity << 3); + } + else + { + offNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, 0); + } + if (report->leftShoulder) + { + onNote(10, RB_MIDI_NOTE_KICK, 0x7F); + } + else + { + offNote(10, RB_MIDI_NOTE_KICK, 0); + } + if (report->rightShoulder) + { + onNote(10, RB_MIDI_NOTE_KICK2, 0x7F); + } + else + { + offNote(10, RB_MIDI_NOTE_KICK2, 0); } break; } + } + break; + } } } #ifdef TICK_PS2 PS2_REPORT ps2Report; -void tick_ps2output() { +void tick_ps2output() +{ PS2_REPORT *report = &ps2Report; - if (!ps2_emu_tick(report)) { + if (!ps2_emu_tick(report)) + { return; } uint8_t packet_size = 0; @@ -2224,10 +2608,13 @@ void tick_ps2output() { #include "inputs/wt_neck.h" TICK_SHARED; - if (!startedInactivityPulse) { + if (!startedInactivityPulse) + { // check if any inputs are active, and if so set lastInputActivity to now - for (int i = 0; i < DIGITAL_COUNT; i++) { - if (debounce[i]) { + for (int i = 0; i < DIGITAL_COUNT; i++) + { + if (debounce[i]) + { lastInputActivity = millis(); } } @@ -2242,7 +2629,8 @@ void tick_ps2output() { } #endif #ifdef TICK_WII -void tick_wiioutput() { +void tick_wiioutput() +{ #include "inputs/accel.h" #include "inputs/clone_neck.h" #include "inputs/gh5_neck.h" @@ -2254,10 +2642,13 @@ void tick_wiioutput() { #include "inputs/wii.h" #include "inputs/wt_neck.h" TICK_SHARED; - if (!startedInactivityPulse) { + if (!startedInactivityPulse) + { // check if any inputs are active, and if so set lastInputActivity to now - for (int i = 0; i < DIGITAL_COUNT; i++) { - if (debounce[i]) { + for (int i = 0; i < DIGITAL_COUNT; i++) + { + if (debounce[i]) + { lastInputActivity = millis(); } } @@ -2326,9 +2717,12 @@ void tick_wiioutput() { report->buttonsLow = ~report->buttonsLow; report->buttonsHigh = ~report->buttonsHigh; uint8_t format = wii_data_format(); - if (format == 3) { + if (format == 3) + { memcpy(wii_data, report, sizeof(report)); - } else if (format == 2) { + } + else if (format == 2) + { WiiClassicDataFormat2_t *real_report = (WiiClassicDataFormat2_t *)wii_data; real_report->buttonsLow = report->buttonsLow; real_report->buttonsHigh = report->buttonsHigh; @@ -2338,7 +2732,9 @@ void tick_wiioutput() { real_report->rightStickY92 = report->rightStickY; real_report->leftTrigger = report->leftTrigger; real_report->rightTrigger = report->rightTrigger; - } else if (format == 1) { + } + else if (format == 1) + { // Similar to the turntable, classic format 1 is awful so we need to translate to an intermediate format first WiiIntermediateClassicDataFormat_t intermediate_report; intermediate_report.rightStickX = report->rightStickX >> 3; @@ -2359,7 +2755,8 @@ void tick_wiioutput() { #endif } #endif -void bluetooth_connected() { +void bluetooth_connected() +{ input_start = millis(); } uint8_t rbcount = 0; @@ -2370,7 +2767,8 @@ bool greenPad; bool yellowCymbal; bool blueCymbal; long lastCymbalOff; -uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t output_console_type) { +uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t output_console_type) +{ uint8_t packet_size = 0; Buffer_Report_t current_queue_report = {val : 0}; bool drumHit = false; @@ -2392,17 +2790,21 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #include "inputs/wt_neck.h" TICK_SHARED; - if (!startedInactivityPulse) { + if (!startedInactivityPulse) + { // check if any inputs are active, and if so set lastInputActivity to now - for (int i = 0; i < DIGITAL_COUNT; i++) { - if (debounce[i]) { + for (int i = 0; i < DIGITAL_COUNT; i++) + { + if (debounce[i]) + { lastInputActivity = millis(); } } } // give the user 2 second to jump between modes (aka, hold on plug in) - if ((millis() - input_start) < 2000 && (millis() - input_start) > 100) { + if ((millis() - input_start) < 2000 && (millis() - input_start) > 100) + { TICK_DETECTION; } #ifdef TICK_DETECTION_FESTIVAL @@ -2410,27 +2812,36 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #endif // We tick the guitar every 5ms to handle inputs if nothing is attempting to read, but this doesn't need to output that data anywhere. // if input queues are enabled, then we just tick as often as possible - if (!buf) { - if (INPUT_QUEUE) { - if (micros() - last_queue > 100) { + if (!buf) + { + if (INPUT_QUEUE) + { + if (micros() - last_queue > 100) + { last_queue = micros(); - for (int i = 0; i < DIGITAL_COUNT; i++) { - if (debounce[i]) { + for (int i = 0; i < DIGITAL_COUNT; i++) + { + if (debounce[i]) + { debounce[i]--; } } #if REQUIRE_LED_DEBOUNCE - for (int i = 0; i < LED_DEBOUNCE_COUNT; i++) { - if (ledDebounce[i]) { + for (int i = 0; i < LED_DEBOUNCE_COUNT; i++) + { + if (ledDebounce[i]) + { ledDebounce[i]--; } } #endif } - if (current_queue_report.val != last_queue_report.val) { + if (current_queue_report.val != last_queue_report.val) + { queue[queue_tail] = current_queue_report; last_queue_report = current_queue_report; - if (queue_size < BUFFER_SIZE_QUEUE) { + if (queue_size < BUFFER_SIZE_QUEUE) + { queue_size++; queue_tail++; } @@ -2439,7 +2850,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu return 0; } - if (INPUT_QUEUE && queue_size) { + if (INPUT_QUEUE && queue_size) + { current_queue_report = queue[queue_tail - queue_size]; queue_size--; } @@ -2448,73 +2860,88 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu // Then mouse, as it is an axis so it is more likley to have changes #if defined(TICK_NKRO) || defined(TICK_SIXKRO) #if !DEVICE_TYPE_IS_KEYBOARD - if (consoleType == KEYBOARD_MOUSE) { + if (consoleType == KEYBOARD_MOUSE) + { #endif void *lastReportToCheck; - for (int i = 1; i < REPORT_ID_END; i++) { + for (int i = 1; i < REPORT_ID_END; i++) + { #ifdef TICK_MOUSE - if (i == REPORT_ID_MOUSE) { + if (i == REPORT_ID_MOUSE) + { packet_size = sizeof(USB_Mouse_Data_t); memset(buf, 0, packet_size); USB_Mouse_Data_t *report = (USB_Mouse_Data_t *)buf; report->rid = REPORT_ID_MOUSE; TICK_MOUSE; - if (last_report) { + if (last_report) + { lastReportToCheck = &last_report->lastMouseReport; } } #endif #ifdef TICK_CONSUMER - if (i == REPORT_ID_CONSUMER) { + if (i == REPORT_ID_CONSUMER) + { packet_size = sizeof(USB_ConsumerControl_Data_t); memset(buf, 0, packet_size); USB_ConsumerControl_Data_t *report = (USB_ConsumerControl_Data_t *)buf; report->rid = REPORT_ID_CONSUMER; TICK_CONSUMER; - if (last_report) { + if (last_report) + { lastReportToCheck = &last_report->lastConsumerReport; } } #endif #ifdef TICK_NKRO - if (i == REPORT_ID_NKRO) { + if (i == REPORT_ID_NKRO) + { packet_size = sizeof(USB_NKRO_Data_t); memset(buf, 0, packet_size); USB_NKRO_Data_t *report = (USB_NKRO_Data_t *)buf; report->rid = REPORT_ID_NKRO; TICK_NKRO; - if (last_report) { + if (last_report) + { lastReportToCheck = &last_report->lastNKROReport; } } #endif #ifdef TICK_SIXKRO - if (i == REPORT_ID_NKRO) { + if (i == REPORT_ID_NKRO) + { packet_size = sizeof(USB_6KRO_Data_t); memset(buf, 0, packet_size); USB_6KRO_Data_t *report = (USB_6KRO_Data_t *)buf; report->rid = REPORT_ID_NKRO; TICK_SIXKRO; - if (last_report) { + if (last_report) + { lastReportToCheck = &last_report->last6KROReport; } } #endif // If we are directly asked for a HID report, always just reply with the NKRO one - if (lastReportToCheck && output_console_type != BLUETOOTH_REPORT) { + if (lastReportToCheck && output_console_type != BLUETOOTH_REPORT) + { uint8_t cmp = memcmp(lastReportToCheck, buf, packet_size); - if (cmp == 0) { + if (cmp == 0) + { packet_size = 0; continue; } memcpy(lastReportToCheck, buf, packet_size); break; - } else { + } + else + { break; } } - if (packet_size) { + if (packet_size) + { return packet_size; } #endif @@ -2529,7 +2956,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu uint8_t proKeyVelocities[25] = {0}; memset(proKeyVelocities, 0, sizeof(proKeyVelocities)); #if USB_HOST_STACK - if (output_console_type == XBOXONE) { + if (output_console_type == XBOXONE) + { XBOX_ONE_REPORT *report = (XBOX_ONE_REPORT *)buf; #if DEVICE_TYPE_IS_LIVE_GUITAR XboxOneGHLGuitarWithGamepad_Data_t *reportGHL = (XboxOneGHLGuitarWithGamepad_Data_t *)buf; @@ -2546,7 +2974,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu asm volatile("" :: : "memory"); - if (report->guide != lastXboxOneGuide) { + if (report->guide != lastXboxOneGuide) + { lastXboxOneGuide = report->guide; GipKeystroke_t *keystroke = (GipKeystroke_t *)buf; GIP_HEADER(keystroke, GIP_VIRTUAL_KEYCODE, true, keystroke_sequence_number++); @@ -2562,7 +2991,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #if DEVICE_TYPE_IS_LIVE_GUITAR packet_size = sizeof(XboxOneGHLGuitarWithGamepad_Data_t); uint8_t cmp = memcmp(last_report, report_data, report_size); - if (cmp == 0) { + if (cmp == 0) + { // gamepad report has not changed, so only send GHL report packet_size = sizeof(XboxOneGHLGuitar_Data_t); updateSequence = false; @@ -2574,7 +3004,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #endif } #endif - if (output_console_type == OG_XBOX) { + if (output_console_type == OG_XBOX) + { OG_XBOX_REPORT *report = (OG_XBOX_REPORT *)report_data; memset(report_data, 0, sizeof(OG_XBOX_REPORT)); report->rid = 0; @@ -2586,7 +3017,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu TICK_OG_XBOX; report_size = packet_size = sizeof(OG_XBOX_REPORT); } - if (output_console_type == WINDOWS || output_console_type == XBOX360) { + if (output_console_type == WINDOWS || output_console_type == XBOX360) + { XINPUT_REPORT *report = (XINPUT_REPORT *)report_data; memset(report_data, 0, sizeof(XINPUT_REPORT)); report->rid = 0; @@ -2598,7 +3030,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu TICK_XINPUT; #if DEVICE_TYPE == GUITAR_HERO_GUITAR - if (seen_rpcs3) { + if (seen_rpcs3) + { report->whammy = (INT16_MAX + (uint32_t)(report->whammy)) >> 1; } #endif @@ -2618,8 +3051,10 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #if DEVICE_TYPE == ROCK_BAND_PRO_KEYS bool key25 = report->key25; uint8_t currentVel = 0; - for (int i = 0; i < sizeof(proKeyVelocities) && currentVel <= 4; i++) { - if (proKeyVelocities[i]) { + for (int i = 0; i < sizeof(proKeyVelocities) && currentVel <= 4; i++) + { + if (proKeyVelocities[i]) + { report->velocities[currentVel] = proKeyVelocities[i] >> 1; currentVel++; } @@ -2632,12 +3067,14 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #endif report_size = packet_size = sizeof(XINPUT_REPORT); #if DEVICE_TYPE == ROCK_BAND_DRUMS - if (!report->cymbalFlag && ready_for_next_packet()) { + if (!report->cymbalFlag && ready_for_next_packet()) + { greenCymbal = false; yellowCymbal = false; blueCymbal = false; } - if (!report->padFlag && ready_for_next_packet()) { + if (!report->padFlag && ready_for_next_packet()) + { greenPad = false; } #endif @@ -2645,8 +3082,10 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu // Guitars and Drums can fall back to their PS3 versions, so don't even include the PS4 version there. // DJ Hero was never on ps4, so we can't really implement that either, so just fall back to PS3 there too. #if SUPPORTS_PS4 - if (output_console_type == PS4) { - if (millis() > 450000 && !auth_ps4_controller_found) { + if (output_console_type == PS4) + { + if (millis() > 450000 && !auth_ps4_controller_found) + { reset_usb(); } PS4_REPORT *report = (PS4_REPORT *)report_data; @@ -2658,7 +3097,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu gamepad->rightStickX = PS3_STICK_CENTER; gamepad->rightStickY = PS3_STICK_CENTER; // PS4 does not start using the controller until it sees a PS button press. - if (!report_requested) { + if (!report_requested) + { report->guide = true; } TICK_PS4; @@ -2680,8 +3120,10 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } #endif #ifdef TICK_FESTIVAL - if (output_console_type == IOS_FESTIVAL) { - if (!festival_gameplay_mode) { + if (output_console_type == IOS_FESTIVAL) + { + if (!festival_gameplay_mode) + { PS3GamepadGuitar_Data_t *report = (PS3GamepadGuitar_Data_t *)report_data; memset(report, 0, sizeof(PS3GamepadGuitar_Data_t)); report->reportId = 1; @@ -2695,7 +3137,9 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->rightStickY = PS3_STICK_CENTER; TICK_PS3_WITHOUT_CAPTURE; report_size = packet_size = sizeof(PS3GamepadGuitar_Data_t); - } else { + } + else + { PS3FestivalProGuitarLayer_Data_t *report = (PS3FestivalProGuitarLayer_Data_t *)report_data; memset(report, 0, sizeof(PS3FestivalProGuitarLayer_Data_t)); report->reportId = 0x01; @@ -2708,9 +3152,11 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } } #endif - if (output_console_type == BLUETOOTH_REPORT || output_console_type == UNIVERSAL) { + if (output_console_type == BLUETOOTH_REPORT || output_console_type == UNIVERSAL) + { #ifdef TICK_FESTIVAL - if (!festival_gameplay_mode) { + if (!festival_gameplay_mode) + { #endif PC_REPORT *report = (PC_REPORT *)report_data; report_size = packet_size = sizeof(PC_REPORT); @@ -2740,7 +3186,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->reportId = 1; TICK_PC; #if DEVICE_TYPE == GUITAR_HERO_GUITAR - if (seen_rpcs3) { + if (seen_rpcs3) + { report->whammy = PS3_STICK_CENTER + (report->whammy >> 1); } #endif @@ -2755,7 +3202,9 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu : "memory"); report->dpad = (report->dpad & 0xf) > 0x0a ? 0x08 : dpad_bindings[report->dpad]; #ifdef TICK_FESTIVAL - } else { + } + else + { PC_FESTIVAL_REPORT *report = (PC_FESTIVAL_REPORT *)report_data; report_size = packet_size = sizeof(PC_FESTIVAL_REPORT); memset(report, 0, sizeof(PC_FESTIVAL_REPORT)); @@ -2773,7 +3222,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } #if DEVICE_TYPE_IS_GUITAR - if (output_console_type == FNF) { + if (output_console_type == FNF) + { report_size = packet_size = sizeof(PCFortniteRockBandGuitar_Data_t); PCFortniteRockBandGuitar_Data_t *report = (PCFortniteRockBandGuitar_Data_t *)report_data; memset(report, 0, sizeof(PCFortniteRockBandGuitar_Data_t)); @@ -2786,12 +3236,14 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu asm volatile("" :: : "memory"); // alias tilt to dpad left so that tilt works - if (report->tilt > 200 || report->back) { + if (report->tilt > 200 || report->back) + { report->dpadLeft = true; } report->back = false; } - if (output_console_type == ARCADE) { + if (output_console_type == ARCADE) + { report_size = packet_size = sizeof(ArcadeGuitarHeroGuitar_Data_t); ArcadeGuitarHeroGuitar_Data_t *report = (ArcadeGuitarHeroGuitar_Data_t *)report_data; memset(report, 0, sizeof(ArcadeGuitarHeroGuitar_Data_t)); @@ -2801,22 +3253,32 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu TICK_ARCADE; asm volatile("" :: : "memory"); - if (report->dpadUp) { + if (report->dpadUp) + { report->dpad = 0; - } else if (report->dpadDown) { + } + else if (report->dpadDown) + { report->dpad = 2; - } else if (report->dpadLeft) { + } + else if (report->dpadLeft) + { report->dpad = 3; - } else if (report->dpadRight) { + } + else if (report->dpadRight) + { report->dpad = 1; - } else { + } + else + { report->dpad = 0xf; } } #endif // For gamepads, use the PS3 report format on PS3 #if DEVICE_TYPE == GAMEPAD - if (output_console_type == PS3) { + if (output_console_type == PS3) + { PS3Gamepad_Data_t *report = (PS3Gamepad_Data_t *)report_data; memset(report, 0, sizeof(PS3Gamepad_Data_t)); report->reportId = 1; @@ -2831,14 +3293,17 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu TICK_PS3_WITHOUT_CAPTURE; report_size = packet_size = sizeof(PS3Gamepad_Data_t); } - if (output_console_type != OG_XBOX && output_console_type != WINDOWS && output_console_type != XBOX360 && output_console_type != PS3 && output_console_type != BLUETOOTH_REPORT && output_console_type != UNIVERSAL && output_console_type != XBOXONE && output_console_type != PS4) { + if (output_console_type != OG_XBOX && output_console_type != WINDOWS && output_console_type != XBOX360 && output_console_type != PS3 && output_console_type != BLUETOOTH_REPORT && output_console_type != UNIVERSAL && output_console_type != XBOXONE && output_console_type != PS4) + { #else // For instruments, we instead use the below block, as all other console types use the below format - if ((output_console_type != OG_XBOX && output_console_type != ARCADE && output_console_type != WINDOWS && output_console_type != KEYBOARD_MOUSE && output_console_type != IOS_FESTIVAL && output_console_type != FNF && output_console_type != XBOX360 && output_console_type != PS4 && output_console_type != BLUETOOTH_REPORT && output_console_type != UNIVERSAL && output_console_type != XBOXONE) || updateHIDSequence) { + if ((output_console_type != OG_XBOX && output_console_type != ARCADE && output_console_type != WINDOWS && output_console_type != KEYBOARD_MOUSE && output_console_type != IOS_FESTIVAL && output_console_type != FNF && output_console_type != XBOX360 && output_console_type != PS4 && output_console_type != BLUETOOTH_REPORT && output_console_type != UNIVERSAL && output_console_type != XBOXONE) || updateHIDSequence) + { #endif report_size = sizeof(PS3_REPORT); // Do NOT update the size for XBONE, since the XBONE packets have a totally different size! - if (!updateHIDSequence) { + if (!updateHIDSequence) + { packet_size = report_size; } @@ -2860,7 +3325,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #endif #if DEVICE_TYPE == GUITAR_HERO_GUITAR - if (output_console_type == PS2_ON_PS3) { + if (output_console_type == PS2_ON_PS3) + { PS2GuitarOnPS3_Data_t *report = (PS2GuitarOnPS3_Data_t *)report_data; TICK_PS3; @@ -2871,10 +3337,13 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu : "memory"); gamepad->dpad = (gamepad->dpad & 0xf) > 0x0a ? 0x08 : dpad_bindings[gamepad->dpad]; - } else { + } + else + { #endif #ifdef TICK_FESTIVAL - if (!festival_gameplay_mode) { + if (!festival_gameplay_mode) + { #endif PS3_REPORT *report = (PS3_REPORT *)report_data; #if DEVICE_TYPE == ROCK_BAND_GUITAR @@ -2895,7 +3364,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu asm volatile("" :: : "memory"); #ifdef TICK_FESTIVAL - if (output_console_type == SWITCH) { + if (output_console_type == SWITCH) + { gamepad->accelX = PS3_ACCEL_CENTER; gamepad->accelY = PS3_ACCEL_CENTER; gamepad->accelZ = PS3_ACCEL_CENTER; @@ -2908,12 +3378,14 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #endif #if DEVICE_TYPE == ROCK_BAND_DRUMS - if (!report->cymbalFlag && ready_for_next_packet()) { + if (!report->cymbalFlag && ready_for_next_packet()) + { greenCymbal = false; yellowCymbal = false; blueCymbal = false; } - if (!report->padFlag && ready_for_next_packet()) { + if (!report->padFlag && ready_for_next_packet()) + { greenPad = false; } #endif @@ -2921,8 +3393,10 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #if DEVICE_TYPE == ROCK_BAND_PRO_KEYS bool key25 = report->key25; uint8_t currentVel = 0; - for (int i = 0; i < sizeof(proKeyVelocities) && currentVel <= 4; i++) { - if (proKeyVelocities[i]) { + for (int i = 0; i < sizeof(proKeyVelocities) && currentVel <= 4; i++) + { + if (proKeyVelocities[i]) + { report->velocities[currentVel] = proKeyVelocities[i] >> 1; currentVel++; } @@ -2930,7 +3404,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->key25 = key25; #endif gamepad->dpad = (gamepad->dpad & 0xf) > 0x0a ? 0x08 : dpad_bindings[gamepad->dpad]; - if (SWAP_SWITCH_FACE_BUTTONS && output_console_type == SWITCH) { + if (SWAP_SWITCH_FACE_BUTTONS && output_console_type == SWITCH) + { bool a = gamepad->a; bool b = gamepad->b; bool x = gamepad->x; @@ -2941,7 +3416,9 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu gamepad->y = x; } #ifdef TICK_FESTIVAL - } else { + } + else + { SwitchFestivalProGuitarLayer_Data_t *report = (SwitchFestivalProGuitarLayer_Data_t *)report_data; TICK_FESTIVAL; @@ -2957,16 +3434,19 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } TICK_RESET // Some hosts want packets sent every frame - if (last_report && output_console_type != ARCADE && output_console_type != OG_XBOX && output_console_type != PS4 && output_console_type != IOS_FESTIVAL && output_console_type != PS3 && output_console_type != BLUETOOTH_REPORT && output_console_type != XBOX360 && !updateHIDSequence) { + if (last_report && output_console_type != ARCADE && output_console_type != OG_XBOX && output_console_type != PS4 && output_console_type != IOS_FESTIVAL && output_console_type != PS3 && output_console_type != BLUETOOTH_REPORT && output_console_type != XBOX360 && !updateHIDSequence) + { uint8_t cmp = memcmp(last_report, report_data, report_size); - if (cmp == 0) { + if (cmp == 0) + { return 0; } memcpy(last_report, report_data, report_size); } // Standard PS4 controllers need a report counter, but we don't want to include that when comparing so we add it here #if SUPPORTS_PS4 - if (output_console_type == PS4) { + if (output_console_type == PS4) + { PS4Gamepad_Data_t *gamepad = (PS4Gamepad_Data_t *)report_data; gamepad->reportCounter = ps4_sequence_number++; } @@ -2974,16 +3454,20 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #if USB_HOST_STACK #if DEVICE_TYPE_IS_GAMEPAD - if (updateSequence) { + if (updateSequence) + { report_sequence_number++; - if (report_sequence_number == 0) { + if (report_sequence_number == 0) + { report_sequence_number = 1; } } #if DEVICE_TYPE_IS_LIVE_GUITAR - if (updateHIDSequence) { + if (updateHIDSequence) + { hid_sequence_number++; - if (hid_sequence_number == 0) { + if (hid_sequence_number == 0) + { hid_sequence_number = 1; } } @@ -2995,7 +3479,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } #ifdef BLUETOOTH_TX -bool tick_bluetooth(void) { +bool tick_bluetooth(void) +{ uint8_t size = tick_inputs(&bt_report, &last_report_bt, BLUETOOTH_REPORT); send_report(size, (uint8_t *)&bt_report); return size; @@ -3005,22 +3490,27 @@ bool windows_in_hid = false; unsigned long millis_at_boot = 0; uint8_t init_packet_skylanders[32] = {0x0b, 0x14, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}; uint8_t version_response_skylanders[32] = {0x0b, 0x14, 0x52, 0x02, 0x1B}; -bool tick_usb(void) { +bool tick_usb(void) +{ uint8_t size = 0; bool ready = ready_for_next_packet(); #ifdef BLUETOOTH_TX - if (!ready) { + if (!ready) + { return false; } #endif - if (millis_at_boot == 0 && read_device_desc) { + if (millis_at_boot == 0 && read_device_desc) + { millis_at_boot = millis(); } #if !DEVICE_TYPE_IS_KEYBOARD - if (!WINDOWS_USES_XINPUT) { + if (!WINDOWS_USES_XINPUT) + { // If we ended up here, then someone probably changed back to hid mode so we should jump back - if (consoleType == WINDOWS) { + if (consoleType == WINDOWS) + { consoleType = UNIVERSAL; reset_usb(); } @@ -3028,16 +3518,21 @@ bool tick_usb(void) { #endif #if DEVICE_TYPE_IS_GAMEPAD // PS2 / Wii / WiiU / Switch 2 do not read any of the string descriptors. - if (millis_at_boot && (millis() - millis_at_boot) > 5000 && consoleType == UNIVERSAL && !read_any_string && !seen_windows_xb1) { + if (millis_at_boot && (millis() - millis_at_boot) > 5000 && consoleType == UNIVERSAL && !read_any_string && !seen_windows_xb1) + { // Switch 2 does read the hid descriptor - if (seen_hid_descriptor_read) { + if (seen_hid_descriptor_read) + { consoleType = SWITCH; reset_usb(); - } else { + } + else + { // PS2 / Wii / WiiU does not read hid descriptor // The wii however will configure the usb device before it stops communicating #if DEVICE_TYPE == ROCK_BAND_GUITAR || DEVICE_TYPE == ROCK_BAND_DRUMS - if (usb_configured()) { + if (usb_configured()) + { set_console_type(WII_RB); } #endif @@ -3046,21 +3541,26 @@ bool tick_usb(void) { } } // Due to some quirks with how the PS3 detects controllers, we can also end up here for PS3, but in that case, we won't see any requests for controller data - if ((millis() - millis_at_boot) > 2000 && consoleType == PS4 && !seen_ps4) { + if ((millis() - millis_at_boot) > 2000 && consoleType == PS4 && !seen_ps4) + { set_console_type(PS3); } #endif - if (!ready) return 0; + if (!ready) + return 0; #if USB_HOST_STACK - if (data_from_console_size) { + if (data_from_console_size) + { USB_Device_Type_t type = get_device_address_for(XBOXONE); send_report_to_controller(type.dev_addr, type.instance, data_from_console, data_from_console_size); data_from_console_size = 0; } // If we have something pending to send to the xbox one controller, send it - if (consoleType == XBOXONE && xbox_one_state != Ready) { + if (consoleType == XBOXONE && xbox_one_state != Ready) + { size = tick_xbox_one(); - if (!size) { + if (!size) + { // We don't want the controller ticked due to usb being stated as "not ready" return true; } @@ -3090,25 +3590,29 @@ bool tick_usb(void) { // } // #endif #endif - if (!size) { + if (!size) + { size = tick_inputs(&combined_report, &last_report_usb, consoleType); } - if (size) { - lastSentPacket = millis(); // make 5ms idle ticking wait until 5ms after last report + if (size) + { + lastSentPacket = millis(); // make 5ms idle ticking wait until 5ms after last report send_report_to_pc(&combined_report, size); } report_requested = true; return size; } #if BLUETOOTH_RX -int tick_bluetooth_inputs(const void *data, uint8_t len, USB_Device_Type_t device_type) { +int tick_bluetooth_inputs(const void *data, uint8_t len, USB_Device_Type_t device_type) +{ memset(&bt_data, 0, sizeof(bt_data)); bt_data.slider = 0x80; convert_report((const uint8_t *)data, len, device_type, &bt_data); return 0; } #endif -void tick(void) { +void tick(void) +{ #ifdef SLAVE_TWI_PORT tick_slave(); #endif @@ -3121,21 +3625,25 @@ void tick(void) { #ifdef TICK_LED_BLUETOOTH TICK_LED_BLUETOOTH; #endif - if (reset_after_360 && millis() > reset_after_360) { + if (reset_after_360 && millis() > reset_after_360) + { reset_usb(); } // Only sleep if the timeout has passed and we aren't connected over USB - if (SLEEP_PIN != -1 && SLEEP_INACTIVITY_TIMEOUT_MS && millis() - lastInputActivity >= SLEEP_INACTIVITY_TIMEOUT_MS && !usb_configured()) { + if (SLEEP_PIN != -1 && SLEEP_INACTIVITY_TIMEOUT_MS && millis() - lastInputActivity >= SLEEP_INACTIVITY_TIMEOUT_MS && !usb_configured()) + { go_to_sleep(); } // Tick inputs constantly for detection for 2 seconds // Tick inputs constantly for xbox 360 wakeup if usb isnt configured - if ((millis() - input_start) < 2000 || !usb_configured()) { + if ((millis() - input_start) < 2000 || !usb_configured()) + { tick_inputs(NULL, NULL, consoleType); } #if DEVICE_TYPE != ROCK_BAND_PRO_KEYS - if ((millis() - lastMidi) > 1000) { + if ((millis() - lastMidi) > 1000) + { memset(midiData.midiVelocities, 0, sizeof(midiData.midiVelocities)); lastMidi = millis(); } @@ -3144,33 +3652,42 @@ void tick(void) { #ifdef TICK_LED_PERIPHERAL // If we are controlling peripheral leds, then we need to send the latest state when // the device is plugged in again - if (slave_initted) { - if (RGB_INACTIVITY_TIMEOUT_MS && millis() - lastInputActivity >= RGB_INACTIVITY_TIMEOUT_MS) { + if (slave_initted) + { + if (RGB_INACTIVITY_TIMEOUT_MS && millis() - lastInputActivity >= RGB_INACTIVITY_TIMEOUT_MS) + { memset(ledStatePeripheral, 0, sizeof(ledStatePeripheral)); } - if (memcmp(lastLedStatePeripheral, ledStatePeripheral, sizeof(ledStatePeripheral)) != 0) { + if (memcmp(lastLedStatePeripheral, ledStatePeripheral, sizeof(ledStatePeripheral)) != 0) + { memcpy(lastLedStatePeripheral, ledStatePeripheral, sizeof(ledStatePeripheral)); TICK_LED_PERIPHERAL; } - } else { + } + else + { memset(lastLedStatePeripheral, 0, sizeof(lastLedStatePeripheral)); } #endif #ifdef TICK_LED - if (RGB_INACTIVITY_TIMEOUT_MS && millis() - lastInputActivity >= RGB_INACTIVITY_TIMEOUT_MS) { + if (RGB_INACTIVITY_TIMEOUT_MS && millis() - lastInputActivity >= RGB_INACTIVITY_TIMEOUT_MS) + { memset(ledState, 0, sizeof(ledState)); } - if (memcmp(lastLedState, ledState, sizeof(ledState)) != 0) { + if (memcmp(lastLedState, ledState, sizeof(ledState)) != 0) + { memcpy(lastLedState, ledState, sizeof(ledState)); TICK_LED; } #endif #if LED_COUNT_MPR121 - if (RGB_INACTIVITY_TIMEOUT_MS && millis() - lastInputActivity >= RGB_INACTIVITY_TIMEOUT_MS) { + if (RGB_INACTIVITY_TIMEOUT_MS && millis() - lastInputActivity >= RGB_INACTIVITY_TIMEOUT_MS) + { ledStateMpr121 = 0; } - if (lastLedStateMpr121 != ledStateMpr121) { + if (lastLedStateMpr121 != ledStateMpr121) + { lastLedStateMpr121 = ledStateMpr121; twi_writeSingleToPointer(MPR121_TWI_PORT, MPR121_I2CADDR_DEFAULT, MPR121_GPIODATA, ledStateMpr121); } @@ -3178,38 +3695,48 @@ void tick(void) { #ifdef TICK_PS2 tick_ps2output(); #endif - if (!INPUT_QUEUE && micros() - lastDebounce > 1000) { + if (!INPUT_QUEUE && micros() - lastDebounce > 1000) + { // No benefit to ticking bluetooth faster than this! #ifdef BLUETOOTH_TX tick_bluetooth(); #endif lastDebounce = micros(); - for (int i = 0; i < DIGITAL_COUNT; i++) { - if (debounce[i]) { + for (int i = 0; i < DIGITAL_COUNT; i++) + { + if (debounce[i]) + { debounce[i]--; } } #if REQUIRE_LED_DEBOUNCE - for (int i = 0; i < LED_DEBOUNCE_COUNT; i++) { - if (ledDebounce[i]) { + for (int i = 0; i < LED_DEBOUNCE_COUNT; i++) + { + if (ledDebounce[i]) + { ledDebounce[i]--; } } #endif } #if DEVICE_TYPE_IS_GUITAR - if (consoleType == KEYBOARD_MOUSE || consoleType == FNF) { - if (!INPUT_QUEUE && (micros() - last_poll) < (4000)) { + if (consoleType == KEYBOARD_MOUSE || consoleType == FNF) + { + if (!INPUT_QUEUE && (micros() - last_poll) < (4000)) + { return; } } #endif - if (!INPUT_QUEUE && POLL_RATE && (micros() - last_poll) < (POLL_RATE * 1000)) { + if (!INPUT_QUEUE && POLL_RATE && (micros() - last_poll) < (POLL_RATE * 1000)) + { return; } #if DEVICE_TYPE == DJ_HERO_TURNTABLE - if (consoleType == PS3) { - if (!INPUT_QUEUE && (micros() - last_poll_dj_ps3) < (10000)) { + if (consoleType == PS3) + { + if (!INPUT_QUEUE && (micros() - last_poll_dj_ps3) < (10000)) + { tick_inputs(NULL, NULL, consoleType); return; } @@ -3222,48 +3749,57 @@ void tick(void) { bool ready = tick_usb(); // Input queuing is enabled, tick as often as possible - if (INPUT_QUEUE && !ready) { + if (INPUT_QUEUE && !ready) + { tick_inputs(NULL, NULL, consoleType); } last_poll = micros(); // Tick the controller every 1ms if this device is connected to a usb port and usb is not ready - if (!INPUT_QUEUE && !ready && usb_configured() && millis() - lastSentPacket >= 1) { + if (!INPUT_QUEUE && !ready && usb_configured() && millis() - lastSentPacket >= 1) + { lastSentPacket = millis(); tick_inputs(NULL, NULL, consoleType); } #if HEARTBEAT_PERIOD_MS - if ((lastHeartbeat == 0) || (millis() - lastHeartbeat >= HEARTBEAT_PERIOD_MS)) { + if ((lastHeartbeat == 0) || (millis() - lastHeartbeat >= HEARTBEAT_PERIOD_MS)) + { // heartbeat resets regularly regardless of activity lastHeartbeat = millis(); // trigger output only if inputs have been active though - if (millis() - lastInputActivity < HEARTBEAT_INACTIVITY_TIMEOUT_MS) { + if (millis() - lastInputActivity < HEARTBEAT_INACTIVITY_TIMEOUT_MS) + { uint8_t activeMask = HEARTBEAT_INVERT ? 0 : HEARTBEAT_GPIO_MASK; digital_write(HEARTBEAT_GPIO_PORT, HEARTBEAT_GPIO_MASK, activeMask); } } // unset heartbeat output if pulse is over - if (millis() - lastHeartbeat >= HEARTBEAT_PULSE_DURATION_MS) { + if (millis() - lastHeartbeat >= HEARTBEAT_PULSE_DURATION_MS) + { uint8_t activeMask = HEARTBEAT_INVERT ? HEARTBEAT_GPIO_MASK : 0; digital_write(HEARTBEAT_GPIO_PORT, HEARTBEAT_GPIO_MASK, activeMask); } -#endif // HEARTBEAT_PERIOD_MS +#endif // HEARTBEAT_PERIOD_MS #if INACTIVITY_OUTPUT_TIMEOUT_MS #if INACTIVITY_OUTPUT_NON_USB_ONLY - if (!usb_configured()) { -#endif // INACTIVITY_OUTPUT_NON_USB_ONLY - // unlike heartbeat, no regular resetting cycle - just a timeout for the - // inactivity output - if (millis() - lastInputActivity >= INACTIVITY_OUTPUT_TIMEOUT_MS) { + if (!usb_configured()) + { +#endif // INACTIVITY_OUTPUT_NON_USB_ONLY + // unlike heartbeat, no regular resetting cycle - just a timeout for the + // inactivity output + if (millis() - lastInputActivity >= INACTIVITY_OUTPUT_TIMEOUT_MS) + { #if INACTIVITY_OUTPUT_PULSE_COUNT // gate to check if already done outputting pulses // (technically not super ideal because lastInactivityPulse may slightly desynchronise, // but should be fine for intended purpose of a few fairly long pulses) - if (millis() - lastInputActivity - INACTIVITY_OUTPUT_TIMEOUT_MS < INACTIVITY_OUTPUT_PULSE_TOTAL_MS) { + if (millis() - lastInputActivity - INACTIVITY_OUTPUT_TIMEOUT_MS < INACTIVITY_OUTPUT_PULSE_TOTAL_MS) + { startedInactivityPulse = true; - if (millis() - lastInactivityPulse >= INACTIVITY_OUTPUT_PULSE_PERIOD_MS) { + if (millis() - lastInactivityPulse >= INACTIVITY_OUTPUT_PULSE_PERIOD_MS) + { lastInactivityPulse = millis(); // input activity has already been checked, so no need to recheck // - just set the output @@ -3271,22 +3807,27 @@ void tick(void) { digital_write(INACTIVITY_OUTPUT_GPIO_PORT, INACTIVITY_OUTPUT_GPIO_MASK, activeMask); } // unset output once current pulse's duration is over - if (millis() - lastInactivityPulse >= INACTIVITY_OUTPUT_PULSE_DURATION_MS) { + if (millis() - lastInactivityPulse >= INACTIVITY_OUTPUT_PULSE_DURATION_MS) + { uint8_t activeMask = INACTIVITY_OUTPUT_INVERT ? INACTIVITY_OUTPUT_GPIO_MASK : 0; digital_write(INACTIVITY_OUTPUT_GPIO_PORT, INACTIVITY_OUTPUT_GPIO_MASK, activeMask); } - } else { + } + else + { startedInactivityPulse = false; // unset output once all pulses are done uint8_t activeMask = INACTIVITY_OUTPUT_INVERT ? INACTIVITY_OUTPUT_GPIO_MASK : 0; digital_write(INACTIVITY_OUTPUT_GPIO_PORT, INACTIVITY_OUTPUT_GPIO_MASK, activeMask); } -#else // INACTIVITY_OUTPUT_PULSE_COUNT - // set output continuously on if no pulses +#else // INACTIVITY_OUTPUT_PULSE_COUNT + // set output continuously on if no pulses uint8_t activeMask = INACTIVITY_OUTPUT_INVERT ? 0 : INACTIVITY_OUTPUT_GPIO_MASK; digital_write(INACTIVITY_OUTPUT_GPIO_PORT, INACTIVITY_OUTPUT_GPIO_MASK, activeMask); -#endif // INACTIVITY_OUTPUT_PULSE_COUNT - } else { +#endif // INACTIVITY_OUTPUT_PULSE_COUNT + } + else + { startedInactivityPulse = false; // unset output when inputs have been active uint8_t activeMask = INACTIVITY_OUTPUT_INVERT ? INACTIVITY_OUTPUT_GPIO_MASK : 0; @@ -3294,14 +3835,17 @@ void tick(void) { } #if INACTIVITY_OUTPUT_NON_USB_ONLY } -#endif // INACTIVITY_OUTPUT_NON_USB_ONLY -#endif // INACTIVITY_OUTPUT_TIMEOUT_MS +#endif // INACTIVITY_OUTPUT_NON_USB_ONLY +#endif // INACTIVITY_OUTPUT_TIMEOUT_MS } -void device_reset(void) { +void device_reset(void) +{ #if USB_HOST_STACK - if (consoleType == XBOXONE) { - if (xbox_one_state != Announce && xbox_one_state != WaitingDesc1) { + if (consoleType == XBOXONE) + { + if (xbox_one_state != Announce && xbox_one_state != WaitingDesc1) + { powerMode.subcommand = 0x07; USB_Device_Type_t type = get_device_address_for(XBOXONE); send_report_to_controller(type.dev_addr, type.instance, (uint8_t *)&powerMode, sizeof(GipPowerMode_t)); @@ -3317,39 +3861,51 @@ void device_reset(void) { } uint8_t last_len = 0; -void receive_report_from_controller(uint8_t const *report, uint16_t len) { - if (report[0] == GIP_INPUT_REPORT) { +void receive_report_from_controller(uint8_t const *report, uint16_t len) +{ + if (report[0] == GIP_INPUT_REPORT) + { report_sequence_number = report[2] + 1; } const GipHeader_t *header = (const GipHeader_t *)report; - if (header->command == GIP_ARRIVAL) { + if (header->command == GIP_ARRIVAL) + { return; } - if (xbox_one_state != Auth) { + if (xbox_one_state != Auth) + { return; } data_from_controller_size = len; memcpy(data_from_controller, report, len); } -void xinput_controller_connected(uint16_t vid, uint16_t pid) { +void xinput_controller_connected(uint16_t vid, uint16_t pid) +{ handle_player_leds(0); - if (xbox_360_state == Authenticated) return; + if (xbox_360_state == Authenticated) + return; } -void xinput_w_controller_connected() { +void xinput_w_controller_connected() +{ handle_player_leds(0); } -void xone_controller_connected(uint8_t dev_addr, uint8_t instance) { +void xone_controller_connected(uint8_t dev_addr, uint8_t instance) +{ printf("Sending to controller %d\r\n", dev_addr); send_report_to_controller(dev_addr, instance, (uint8_t *)&powerMode, sizeof(GipPowerMode_t)); } -bool xone_controller_send_init_packet(uint8_t dev_addr, uint8_t instance, uint8_t id) { - if (id == 0) { +bool xone_controller_send_init_packet(uint8_t dev_addr, uint8_t instance, uint8_t id) +{ + if (id == 0) + { send_report_to_controller(dev_addr, instance, (uint8_t *)&ledOn, sizeof(ledOn)); return true; - } else if (id == 1 && consoleType != XBOXONE) { + } + else if (id == 1 && consoleType != XBOXONE) + { // When used for auth, the console will send this send_report_to_controller(dev_addr, instance, (uint8_t *)&authDonePacket, sizeof(authDonePacket)); return true; @@ -3357,22 +3913,27 @@ bool xone_controller_send_init_packet(uint8_t dev_addr, uint8_t instance, uint8_ return false; } -void host_controller_connected() { +void host_controller_connected() +{ // With input_usb_host, we need to run detection for a little bit after the input is detected #ifdef INPUT_USB_HOST input_start = millis(); #endif } -void ps4_controller_connected(uint8_t dev_addr, uint16_t vid, uint16_t pid) { - if (vid == SONY_VID && (pid == PS4_DS_PID_1 || pid == PS4_DS_PID_2 || pid == PS4_DS_PID_3)) { +void ps4_controller_connected(uint8_t dev_addr, uint16_t vid, uint16_t pid) +{ + if (vid == SONY_VID && (pid == PS4_DS_PID_1 || pid == PS4_DS_PID_2 || pid == PS4_DS_PID_3)) + { handle_player_leds(0); } auth_ps4_controller_found = true; } -void ps3_controller_connected(uint8_t dev_addr, uint16_t vid, uint16_t pid) { - if (vid == SONY_VID && pid == SONY_DS3_PID) { +void ps3_controller_connected(uint8_t dev_addr, uint16_t vid, uint16_t pid) +{ + if (vid == SONY_VID && pid == SONY_DS3_PID) + { // Enable PS3 reports uint8_t hid_command_enable[] = {0x42, 0x0c, 0x00, 0x00}; transfer_with_usb_controller(dev_addr, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x03F4, 0x00, sizeof(hid_command_enable), hid_command_enable, NULL); @@ -3380,286 +3941,319 @@ void ps3_controller_connected(uint8_t dev_addr, uint16_t vid, uint16_t pid) { } } -void ps4_controller_disconnected(void) { +void ps4_controller_disconnected(void) +{ auth_ps4_controller_found = false; } -void set_console_type(uint8_t new_console_type) { - if (consoleType == new_console_type && new_console_type != UNIVERSAL) return; +void set_console_type(uint8_t new_console_type) +{ + if (consoleType == new_console_type && new_console_type != UNIVERSAL) + return; consoleType = new_console_type; reset_usb(); } #if USB_HOST_STACK || BLUETOOTH_RX -void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_Device_Type_t *type) { - switch (vid) { - case STREAM_DECK_VID: { - type->console_type = STREAM_DECK; - type->sub_type = UNKNOWN; - switch (pid) { - case STREAM_DECK_OG_PID: - type->sub_type = STREAM_DECK_OG; - break; - case STREAM_DECK_MINI_PID: - type->sub_type = STREAM_DECK_MINI; - break; - case STREAM_DECK_XL_PID: - type->sub_type = STREAM_DECK_XL; - break; - case STREAM_DECK_V2_PID: - type->sub_type = STREAM_DECK_V2; - break; - case STREAM_DECK_MK2_PID: - type->sub_type = STREAM_DECK_MK2; - break; - case STREAM_DECK_PLUS_PID: - type->sub_type = STREAM_DECK_PLUS; - break; - case STREAM_DECK_PEDAL_PID: - type->sub_type = STREAM_DECK_PEDAL; - break; - case STREAM_DECK_XLV2_PID: - type->sub_type = STREAM_DECK_XLV2; - break; - case STREAM_DECK_MINIV2_PID: - type->sub_type = STREAM_DECK_MINIV2; - break; - case STREAM_DECK_NEO_PID: - type->sub_type = STREAM_DECK_NEO; - break; - } - break; - } - case NINTENDO_VID: { - if (pid == SWITCH_PRO_PID) { - type->console_type = SWITCH; - type->sub_type = GAMEPAD; - } - if (pid == SWITCH_2_PRO_PID) { - type->console_type = SWITCH2; - type->sub_type = GAMEPAD; - } - if (pid == SWITCH_2_GC_PID) { - type->console_type = SWITCH2; - type->sub_type = GAMEPAD; - } - if (pid == SWITCH_2_JOY_R_PID) { - type->console_type = SWITCH2; - type->sub_type = GAMEPAD; - } - if (pid == SWITCH_2_JOY_L_PID) { - type->console_type = SWITCH2; - type->sub_type = GAMEPAD; - } - break; - } - case ARDWIINO_VID: { - if (pid == ARDWIINO_PID) { - type->console_type = SANTROLLER; - type->sub_type = (version >> 8) & 0xFF; - } - break; - } - case RAPHNET_VID: { - type->console_type = RAPHNET; +void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_Device_Type_t *type) +{ + switch (vid) + { + case STREAM_DECK_VID: + { + type->console_type = STREAM_DECK; + type->sub_type = UNKNOWN; + switch (pid) + { + case STREAM_DECK_OG_PID: + type->sub_type = STREAM_DECK_OG; + break; + case STREAM_DECK_MINI_PID: + type->sub_type = STREAM_DECK_MINI; + break; + case STREAM_DECK_XL_PID: + type->sub_type = STREAM_DECK_XL; + break; + case STREAM_DECK_V2_PID: + type->sub_type = STREAM_DECK_V2; + break; + case STREAM_DECK_MK2_PID: + type->sub_type = STREAM_DECK_MK2; + break; + case STREAM_DECK_PLUS_PID: + type->sub_type = STREAM_DECK_PLUS; + break; + case STREAM_DECK_PEDAL_PID: + type->sub_type = STREAM_DECK_PEDAL; + break; + case STREAM_DECK_XLV2_PID: + type->sub_type = STREAM_DECK_XLV2; + break; + case STREAM_DECK_MINIV2_PID: + type->sub_type = STREAM_DECK_MINIV2; + break; + case STREAM_DECK_NEO_PID: + type->sub_type = STREAM_DECK_NEO; + break; + } + break; + } + case NINTENDO_VID: + { + if (pid == SWITCH_PRO_PID) + { + type->console_type = SWITCH; + type->sub_type = GAMEPAD; + } + if (pid == SWITCH_2_PRO_PID) + { + type->console_type = SWITCH2; + type->sub_type = GAMEPAD; + } + if (pid == SWITCH_2_GC_PID) + { + type->console_type = SWITCH2; + type->sub_type = GAMEPAD; + } + if (pid == SWITCH_2_JOY_R_PID) + { + type->console_type = SWITCH2; + type->sub_type = GAMEPAD; + } + if (pid == SWITCH_2_JOY_L_PID) + { + type->console_type = SWITCH2; + type->sub_type = GAMEPAD; + } + break; + } + case ARDWIINO_VID: + { + if (pid == ARDWIINO_PID) + { + type->console_type = SANTROLLER; + type->sub_type = (version >> 8) & 0xFF; + } + break; + } + case RAPHNET_VID: + { + type->console_type = RAPHNET; + type->sub_type = GAMEPAD; + break; + } + case MAGICBOOTS_PS4_VID: + { + if (pid == MAGICBOOTS_PS4_PID) + { + type->console_type = PS4; + type->sub_type = GAMEPAD; + } + break; + } + case ARDUINO_VID: + { + if (pid == STEPMANIA_X_PID) + { + type->console_type = STEPMANIAX; + type->sub_type = DANCE_PAD; + } + break; + } + case LTEK_LUFA_VID: + { + if (pid == LTEK_LUFA_PID) + { + type->console_type = LTEK_ID; + type->sub_type = DANCE_PAD; + } + break; + } + case LTEK_VID: + { + if (pid == LTEK_PID) + { + type->console_type = LTEK; + type->sub_type = DANCE_PAD; + } + break; + } + case SONY_VID: + switch (pid) + { + case SONY_DS3_PID: + type->console_type = PS3; + type->sub_type = GAMEPAD; + break; + case PS4_DS_PID_1: + case PS4_DS_PID_2: + case PS4_DS_PID_3: + type->console_type = PS4; + type->sub_type = GAMEPAD; + break; + case PS5_DS_PID: + type->console_type = PS5; type->sub_type = GAMEPAD; break; } - case MAGICBOOTS_PS4_VID: { - if (pid == MAGICBOOTS_PS4_PID) { - type->console_type = PS4; - type->sub_type = GAMEPAD; - } - break; - } - case ARDUINO_VID: { - if (pid == STEPMANIA_X_PID) { - type->console_type = STEPMANIAX; - type->sub_type = DANCE_PAD; - } - break; - } - case LTEK_LUFA_VID: { - if (pid == LTEK_LUFA_PID) { - type->console_type = LTEK_ID; - type->sub_type = DANCE_PAD; - } - break; - } - case LTEK_VID: { - if (pid == LTEK_PID) { - type->console_type = LTEK; - type->sub_type = DANCE_PAD; - } - break; - } - case SONY_VID: - switch (pid) { - case SONY_DS3_PID: - type->console_type = PS3; - type->sub_type = GAMEPAD; - break; - case PS4_DS_PID_1: - case PS4_DS_PID_2: - case PS4_DS_PID_3: - type->console_type = PS4; - type->sub_type = GAMEPAD; - break; - case PS5_DS_PID: - type->console_type = PS5; - type->sub_type = GAMEPAD; - break; - } - break; - case STADIA_VID: - if (pid == STADIA_PID) { - type->console_type = STADIA; - type->sub_type = GAMEPAD; - } - break; - case REDOCTANE_VID: - switch (pid) { - case PS3_GH_GUITAR_PID: - type->console_type = PS3; - type->sub_type = GUITAR_HERO_GUITAR; - break; - case PS3_GH_DRUM_PID: - type->console_type = PS3; - type->sub_type = GUITAR_HERO_DRUMS; - break; - case PS3_RB_GUITAR_PID: - type->console_type = PS3; - type->sub_type = ROCK_BAND_GUITAR; - break; - case PS3_RB_DRUM_PID: - type->console_type = PS3; - type->sub_type = ROCK_BAND_DRUMS; - break; - case PS3_DJ_TURNTABLE_PID: - type->console_type = PS3; - type->sub_type = DJ_HERO_TURNTABLE; - break; - case PS3WIIU_GHLIVE_DONGLE_PID: - type->console_type = PS3; - type->sub_type = LIVE_GUITAR; - break; - case PS3_MPA_KEYBOARD_PID: - case PS3_KEYBOARD_PID: - type->console_type = PS3; - type->sub_type = ROCK_BAND_PRO_KEYS; - break; - case PS3_MUSTANG_PID: - case PS3_MUSTANG_MPA_PID: - type->console_type = PS3; - type->sub_type = ROCK_BAND_PRO_GUITAR_MUSTANG; - break; - case PS3_SQUIRE_PID: - case PS3_SQUIRE_MPA_PID: - type->console_type = PS3; - type->sub_type = ROCK_BAND_PRO_GUITAR_SQUIRE; - break; - } - break; - case HORI_VID: - switch (pid) { - case HORI_SWITCH_TAIKO_PID: - type->console_type = SWITCH; - type->sub_type = TAIKO; - break; - } - - case HARMONIX_VID: - // Polled the same as PS3, so treat them as PS3 instruments - switch (pid) { - case WII_RB_GUITAR_PID: - case WII_RB_GUITAR_2_PID: - type->console_type = PS3; - type->sub_type = ROCK_BAND_GUITAR; - break; - - case WII_RB_DRUM_PID: - case WII_RB_DRUM_2_PID: - type->console_type = PS3; - type->sub_type = ROCK_BAND_DRUMS; - break; - case WII_KEYBOARD_PID: - case WII_MPA_KEYBOARD_PID: - type->console_type = PS3; - type->sub_type = ROCK_BAND_PRO_KEYS; - break; - case WII_MUSTANG_PID: - case WII_MUSTANG_MPA_PID: - type->console_type = PS3; - type->sub_type = ROCK_BAND_PRO_GUITAR_MUSTANG; - break; - case WII_SQUIRE_PID: - case WII_SQUIRE_MPA_PID: - type->console_type = PS3; - type->sub_type = ROCK_BAND_PRO_GUITAR_SQUIRE; - break; - } - - break; - case PDP_VID: - switch (pid) { - case XBOX_ONE_JAG_PID: - case XBOX_ONE_RIFFMASTER_PID: - type->console_type = XBOXONE; - type->sub_type = ROCK_BAND_GUITAR; - break; - case PS4_JAG_PID: - case PS4_RIFFMASTER_PID: - type->console_type = PS4; - type->sub_type = ROCK_BAND_GUITAR; - break; - case PS5_RIFFMASTER_PID: - type->console_type = PS5; - type->sub_type = ROCK_BAND_GUITAR; - break; - } - - break; - - case MAD_CATZ_VID: - switch (pid) { - case XBOX_ONE_RB_GUITAR_PID: - type->console_type = XBOXONE; - type->sub_type = ROCK_BAND_GUITAR; - break; - case XBOX_ONE_RB_DRUM_PID: - type->console_type = XBOXONE; - type->sub_type = ROCK_BAND_DRUMS; - break; - case PS4_STRAT_PID: - type->console_type = PS4; - type->sub_type = ROCK_BAND_GUITAR; - break; - } - - break; - - case XBOX_REDOCTANE_VID: - switch (pid) { - case XBOX_ONE_GHLIVE_DONGLE_PID: - type->console_type = XBOXONE; - type->sub_type = LIVE_GUITAR; - break; - case XBOX_360_GHLIVE_DONGLE_PID: - type->console_type = XBOX360; - type->sub_type = XINPUT_GUITAR_HERO_LIVE; - break; - case XBOX_360_WT_KIOSK_PID: - type->console_type = XBOX360; - type->sub_type = XINPUT_GUITAR_WT; - break; - } - break; - case XBOX_ONE_CONTROLLER_VID: - if (pid >= 0x02e0 && pid <= 0x02eF && type->console_type != XBOXONE) { - type->console_type = XINPUTCOMPAT; - type->sub_type = GAMEPAD; - break; - } + break; + case STADIA_VID: + if (pid == STADIA_PID) + { + type->console_type = STADIA; + type->sub_type = GAMEPAD; + } + break; + case REDOCTANE_VID: + switch (pid) + { + case PS3_GH_GUITAR_PID: + type->console_type = PS3; + type->sub_type = GUITAR_HERO_GUITAR; + break; + case PS3_GH_DRUM_PID: + type->console_type = PS3; + type->sub_type = GUITAR_HERO_DRUMS; + break; + case PS3_RB_GUITAR_PID: + type->console_type = PS3; + type->sub_type = ROCK_BAND_GUITAR; + break; + case PS3_RB_DRUM_PID: + type->console_type = PS3; + type->sub_type = ROCK_BAND_DRUMS; + break; + case PS3_DJ_TURNTABLE_PID: + type->console_type = PS3; + type->sub_type = DJ_HERO_TURNTABLE; + break; + case PS3WIIU_GHLIVE_DONGLE_PID: + type->console_type = PS3; + type->sub_type = LIVE_GUITAR; + break; + case PS3_MPA_KEYBOARD_PID: + case PS3_KEYBOARD_PID: + type->console_type = PS3; + type->sub_type = ROCK_BAND_PRO_KEYS; + break; + case PS3_MUSTANG_PID: + case PS3_MUSTANG_MPA_PID: + type->console_type = PS3; + type->sub_type = ROCK_BAND_PRO_GUITAR_MUSTANG; break; + case PS3_SQUIRE_PID: + case PS3_SQUIRE_MPA_PID: + type->console_type = PS3; + type->sub_type = ROCK_BAND_PRO_GUITAR_SQUIRE; + break; + } + break; + case HORI_VID: + switch (pid) + { + case HORI_SWITCH_TAIKO_PID: + type->console_type = SWITCH; + type->sub_type = TAIKO; + break; + } + + case HARMONIX_VID: + // Polled the same as PS3, so treat them as PS3 instruments + switch (pid) + { + case WII_RB_GUITAR_PID: + case WII_RB_GUITAR_2_PID: + type->console_type = PS3; + type->sub_type = ROCK_BAND_GUITAR; + break; + + case WII_RB_DRUM_PID: + case WII_RB_DRUM_2_PID: + type->console_type = PS3; + type->sub_type = ROCK_BAND_DRUMS; + break; + case WII_KEYBOARD_PID: + case WII_MPA_KEYBOARD_PID: + type->console_type = PS3; + type->sub_type = ROCK_BAND_PRO_KEYS; + break; + case WII_MUSTANG_PID: + case WII_MUSTANG_MPA_PID: + type->console_type = PS3; + type->sub_type = ROCK_BAND_PRO_GUITAR_MUSTANG; + break; + case WII_SQUIRE_PID: + case WII_SQUIRE_MPA_PID: + type->console_type = PS3; + type->sub_type = ROCK_BAND_PRO_GUITAR_SQUIRE; + break; + } + + break; + case PDP_VID: + switch (pid) + { + case XBOX_ONE_JAG_PID: + case XBOX_ONE_RIFFMASTER_PID: + type->console_type = XBOXONE; + type->sub_type = ROCK_BAND_GUITAR; + break; + case PS4_JAG_PID: + case PS4_RIFFMASTER_PID: + type->console_type = PS4; + type->sub_type = ROCK_BAND_GUITAR; + break; + case PS5_RIFFMASTER_PID: + type->console_type = PS5; + type->sub_type = ROCK_BAND_GUITAR; + break; + } + + break; + + case MAD_CATZ_VID: + switch (pid) + { + case XBOX_ONE_RB_GUITAR_PID: + type->console_type = XBOXONE; + type->sub_type = ROCK_BAND_GUITAR; + break; + case XBOX_ONE_RB_DRUM_PID: + type->console_type = XBOXONE; + type->sub_type = ROCK_BAND_DRUMS; + break; + case PS4_STRAT_PID: + type->console_type = PS4; + type->sub_type = ROCK_BAND_GUITAR; + break; + } + + break; + + case XBOX_REDOCTANE_VID: + switch (pid) + { + case XBOX_ONE_GHLIVE_DONGLE_PID: + type->console_type = XBOXONE; + type->sub_type = LIVE_GUITAR; + break; + case XBOX_360_GHLIVE_DONGLE_PID: + type->console_type = XBOX360; + type->sub_type = XINPUT_GUITAR_HERO_LIVE; + break; + case XBOX_360_WT_KIOSK_PID: + type->console_type = XBOX360; + type->sub_type = XINPUT_GUITAR_WT; + break; + } + break; + case XBOX_ONE_CONTROLLER_VID: + if (pid >= 0x02e0 && pid <= 0x02eF && type->console_type != XBOXONE) + { + type->console_type = XINPUTCOMPAT; + type->sub_type = GAMEPAD; + break; + } + break; } } #endif From 8b8eb1ffb249de032c7176bf58581b451496335e Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 24 Jun 2025 21:52:16 +1200 Subject: [PATCH 053/239] differenciate rb kits that we can --- src/pico/main.cpp | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index aff6092ba..25d6497b3 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -520,6 +520,13 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ type.sub_type = GUITAR_HERO_GUITAR_WT; } } + if (host_pid == WII_RB_DRUM_PID) { + type.drum_type = DRUM_RB1; + } + if (host_pid == WII_RB_DRUM_2_PID) { + type.drum_type = DRUM_RB2; + + } usb_host_devices[total_usb_host_devices].type = type; usb_host_devices[total_usb_host_devices].xone_init_id = millis(); total_usb_host_devices++; @@ -672,14 +679,7 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c } else { - usb_host_devices[i].type.sub_type = DRUM_RB1; - } - } - if (usb_host_devices[i].type.drum_type == DRUM_RB1) - { - XInputRockBandDrums_Data_t *gamepad = (XInputRockBandDrums_Data_t *)&usb_host_devices[i].report; - if (gamepad->padFlag || gamepad->cymbalFlag) - { + // RB2/3 kits are always wireless usb_host_devices[i].type.sub_type = DRUM_RB2; } } @@ -795,17 +795,10 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c } else { + // RB1 kits are always wired usb_host_devices[i].type.drum_type = DRUM_RB1; } } - if (usb_host_devices[i].type.drum_type == DRUM_RB1) - { - // RB2 and newer kits set pad flags, so we have a newer kit here - if (drums->padFlag || drums->cymbalFlag) - { - usb_host_devices[i].type.drum_type = DRUM_RB2; - } - } } } From e21a166390f915511eb966e1029925b79f0fa2b3 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 25 Jun 2025 09:43:48 +1200 Subject: [PATCH 054/239] better rb drum detection --- src/pico/main.cpp | 69 ++++++++------------------------- src/shared/main/shared_main.cpp | 8 ++++ 2 files changed, 25 insertions(+), 52 deletions(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 25d6497b3..456f8f56d 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -405,18 +405,6 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ tuh_descriptor_get_device_sync(dev_addr, buf, sizeof(USB_DEVICE_DESCRIPTOR)); USB_DEVICE_DESCRIPTOR *desc = (USB_DEVICE_DESCRIPTOR *)buf; get_usb_device_type_for(host_vid, host_pid, desc->bcdDevice, &type); - // XBOX 360 has other methods for determining drum type, so it inits as unknown - if (type.console_type != XBOX360) - { - if (type.sub_type == ROCK_BAND_DRUMS) - { - type.drum_type = DRUM_RB1; - } - if (type.sub_type == GUITAR_HERO_DRUMS) - { - type.drum_type = DRUM_GH; - } - } switch (type.console_type) { case XBOX360: @@ -520,13 +508,6 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ type.sub_type = GUITAR_HERO_GUITAR_WT; } } - if (host_pid == WII_RB_DRUM_PID) { - type.drum_type = DRUM_RB1; - } - if (host_pid == WII_RB_DRUM_2_PID) { - type.drum_type = DRUM_RB2; - - } usb_host_devices[total_usb_host_devices].type = type; usb_host_devices[total_usb_host_devices].xone_init_id = millis(); total_usb_host_devices++; @@ -668,20 +649,17 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c { memcpy(&usb_host_devices[i].report, report + sizeof(header), len - sizeof(header)); usb_host_devices[i].report_length = len - sizeof(header); - if (usb_host_devices[i].type.sub_type == XINPUT_DRUMS) + if (usb_host_devices[i].type.sub_type == XINPUT_DRUMS && usb_host_devices[i].type.drum_type == DRUM_UNKNOWN) { - if (usb_host_devices[i].type.drum_type == DRUM_UNKNOWN) + XInputGamepad_Data_t *gamepad = (XInputGamepad_Data_t *)&usb_host_devices[i].report; + if (gamepad->leftThumbClick) { - XInputGamepad_Data_t *gamepad = (XInputGamepad_Data_t *)&usb_host_devices[i].report; - if (gamepad->leftThumbClick) - { - usb_host_devices[i].type.sub_type = DRUM_GH; - } - else - { - // RB2/3 kits are always wireless - usb_host_devices[i].type.sub_type = DRUM_RB2; - } + usb_host_devices[i].type.sub_type = DRUM_GH; + } + else + { + // Only RB2/3 kits are wireless + usb_host_devices[i].type.sub_type = DRUM_RB2; } } } @@ -782,33 +760,20 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c memcpy(&usb_host_devices[i].report, report, len); usb_host_devices[i].report_length = len; // Xinput drum detection - if (usb_host_devices[i].type.console_type == XBOX360 && usb_host_devices[i].type.sub_type == XINPUT_DRUMS) + if (usb_host_devices[i].type.console_type == XBOX360 && usb_host_devices[i].type.sub_type == XINPUT_DRUMS && usb_host_devices[i].type.drum_type == DRUM_UNKNOWN) { XInputRockBandDrums_Data_t *drums = (XInputRockBandDrums_Data_t *)&usb_host_devices[i].report; if (drums->rsize == sizeof(XInputRockBandDrums_Data_t)) { - if (usb_host_devices[i].type.drum_type == DRUM_UNKNOWN) + if (drums->leftThumbClick) { - if (drums->leftThumbClick) - { - usb_host_devices[i].type.drum_type = DRUM_GH; - } - else - { - // RB1 kits are always wired - usb_host_devices[i].type.drum_type = DRUM_RB1; - } + usb_host_devices[i].type.drum_type = DRUM_GH; + } + else + { + // Only RB1 kits are wired + usb_host_devices[i].type.drum_type = DRUM_RB1; } - } - } - - if (usb_host_devices[i].type.console_type == PS3 && usb_host_devices[i].type.sub_type == ROCK_BAND_DRUMS && usb_host_devices[i].type.drum_type == DRUM_RB1) - { - PS3RockBandDrums_Data_t *drums = (PS3RockBandDrums_Data_t *)&usb_host_devices[i].report; - // RB2 and newer kits set pad flags, so we have a newer kit here - if (drums->padFlag || drums->cymbalFlag) - { - usb_host_devices[i].type.drum_type = DRUM_RB2; } } return; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index faf81c289..e1ba60cac 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -4113,6 +4113,7 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D case PS3_GH_DRUM_PID: type->console_type = PS3; type->sub_type = GUITAR_HERO_DRUMS; + type->drum_type = DRUM_GH; break; case PS3_RB_GUITAR_PID: type->console_type = PS3; @@ -4121,6 +4122,7 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D case PS3_RB_DRUM_PID: type->console_type = PS3; type->sub_type = ROCK_BAND_DRUMS; + type->drum_type = version == 0x1000 ? DRUM_RB1 : DRUM_RB2; break; case PS3_DJ_TURNTABLE_PID: type->console_type = PS3; @@ -4167,9 +4169,14 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D break; case WII_RB_DRUM_PID: + type->console_type = PS3; + type->sub_type = ROCK_BAND_DRUMS; + type->drum_type = DRUM_RB1; + break; case WII_RB_DRUM_2_PID: type->console_type = PS3; type->sub_type = ROCK_BAND_DRUMS; + type->drum_type = DRUM_RB2; break; case WII_KEYBOARD_PID: case WII_MPA_KEYBOARD_PID: @@ -4220,6 +4227,7 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D case XBOX_ONE_RB_DRUM_PID: type->console_type = XBOXONE; type->sub_type = ROCK_BAND_DRUMS; + type->drum_type = DRUM_RB2; break; case PS4_STRAT_PID: type->console_type = PS4; From e64b0423d53b6c8350ba0d78997b70a4695ac667 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 25 Jun 2025 09:44:34 +1200 Subject: [PATCH 055/239] better rb drum detection --- src/pico/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 456f8f56d..e534738ff 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -654,12 +654,12 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c XInputGamepad_Data_t *gamepad = (XInputGamepad_Data_t *)&usb_host_devices[i].report; if (gamepad->leftThumbClick) { - usb_host_devices[i].type.sub_type = DRUM_GH; + usb_host_devices[i].type.drum_type = DRUM_GH; } else { // Only RB2/3 kits are wireless - usb_host_devices[i].type.sub_type = DRUM_RB2; + usb_host_devices[i].type.drum_type = DRUM_RB2; } } } From 5ccd873b4dbb9c248cc5c6ac90e9be3f8a201f08 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 25 Jun 2025 20:00:25 +1200 Subject: [PATCH 056/239] handle rb1 drum pads as face buttons and not drum pads --- include/state_translation/drums.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/state_translation/drums.h b/include/state_translation/drums.h index 4e55b0178..767d41f9c 100644 --- a/include/state_translation/drums.h +++ b/include/state_translation/drums.h @@ -70,7 +70,7 @@ } \ } \ } \ - if (pad || device_type.drum_type == DRUM_RB1) { \ + if (pad) { \ if (yellow) { \ onNote(10, RB_MIDI_NOTE_YELLOW, yellowVelocity >> 1); \ } \ From 37aea8839acf7eeaa506db505b8672a0327c67af Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 26 Jun 2025 18:49:08 +1200 Subject: [PATCH 057/239] apply midi translation to wt and bh drums --- include/state_translation/drums.h | 231 ++++++++++++++++++++++-------- src/shared/main/bh_drum.cpp | 4 +- src/shared/main/shared_main.cpp | 2 + src/shared/main/wii.cpp | 45 +----- src/shared/main/wt_drum.cpp | 5 +- 5 files changed, 182 insertions(+), 105 deletions(-) diff --git a/include/state_translation/drums.h b/include/state_translation/drums.h index 767d41f9c..f4b4a1d5d 100644 --- a/include/state_translation/drums.h +++ b/include/state_translation/drums.h @@ -12,162 +12,277 @@ bool blue = report->x; \ bool pad = report->padFlag; \ bool cymbal = report->cymbalFlag; \ - if (!red) { \ + if (!red) \ + { \ offNote(10, RB_MIDI_NOTE_RED, 0); \ } \ - if (!green) { \ + if (!green) \ + { \ offNote(10, RB_MIDI_NOTE_GREEN, 0); \ offNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, 0); \ } \ - if (!yellow) { \ + if (!yellow) \ + { \ offNote(10, RB_MIDI_NOTE_YELLOW, 0); \ offNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, 0); \ } \ - if (!blue) { \ + if (!blue) \ + { \ offNote(10, RB_MIDI_NOTE_BLUE, 0); \ offNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, 0); \ } \ - if (pad && cymbal) { \ + if (pad && cymbal) \ + { \ /* The d-pad inputs let us resolve the ambiguity of a pad+cymbal hit \ Only d-pad is checked here since it is the only unique identifier due to hardware bugs \ (sometimes the color flag is released before the d-pad input is, particularly at high polling rates)*/ \ \ /* If you hit both the pad and cymbal of the same colour simultaneously, the velocity for the cymbal \ is placed in the redVelocity, but the red button won't be pressed. */ \ - if (!red && redVelocity) { \ - if (up) { \ + if (!red && redVelocity) \ + { \ + if (up) \ + { \ onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, redVelocity >> 1); \ onNote(10, RB_MIDI_NOTE_YELLOW, yellowVelocity >> 1); \ - } else if (down) { \ + } \ + else if (down) \ + { \ onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, redVelocity >> 1); \ onNote(10, RB_MIDI_NOTE_BLUE, blueVelocity >> 1); \ - } else { \ + } \ + else \ + { \ onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, redVelocity >> 1); \ onNote(10, RB_MIDI_NOTE_GREEN, greenVelocity >> 1); \ } \ pad = false; \ cymbal = false; \ - } else { \ + } \ + else \ + { \ /* Yellow */ \ - if (up) { \ + if (up) \ + { \ onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, yellowVelocity >> 1); \ yellow = false; \ cymbal = false; \ } \ \ /* Blue */ \ - if (down) { \ + if (down) \ + { \ onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, blueVelocity >> 1); \ blue = false; \ cymbal = false; \ } \ \ /* Green */ \ - if (!(up || down)) { \ + if (!(up || down)) \ + { \ onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, blueVelocity >> 1); \ green = false; \ cymbal = false; \ } \ } \ } \ - if (pad) { \ - if (yellow) { \ + if (pad) \ + { \ + if (yellow) \ + { \ onNote(10, RB_MIDI_NOTE_YELLOW, yellowVelocity >> 1); \ } \ - if (blue) { \ + if (blue) \ + { \ onNote(10, RB_MIDI_NOTE_BLUE, blueVelocity >> 1); \ } \ - if (red) { \ + if (red) \ + { \ onNote(10, RB_MIDI_NOTE_RED, redVelocity >> 1); \ } \ - if (green) { \ + if (green) \ + { \ onNote(10, RB_MIDI_NOTE_GREEN, greenVelocity >> 1); \ } \ } \ \ - if (cymbal) { \ - if (blue) { \ + if (cymbal) \ + { \ + if (blue) \ + { \ onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, blueVelocity >> 1); \ } \ - if (red) { \ + if (red) \ + { \ onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, redVelocity >> 1); \ } \ - if (green) { \ + if (green) \ + { \ onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, greenVelocity >> 1); \ } \ } \ - if (kick1) { \ + if (kick1) \ + { \ onNote(10, RB_MIDI_NOTE_KICK, 0x7F); \ - } else { \ + } \ + else \ + { \ offNote(10, RB_MIDI_NOTE_KICK, 0); \ } \ - if (kick2) { \ + if (kick2) \ + { \ onNote(10, RB_MIDI_NOTE_KICK2, 0x7F); \ - } else { \ + } \ + else \ + { \ offNote(10, RB_MIDI_NOTE_KICK2, 0); \ } #if DEVICE_TYPE == ROCK_BAND_DRUMS #define SET_GH_PADS() \ - if (report->greenVelocity) { \ + if (report->greenVelocity) \ + { \ onNote(10, RB_MIDI_NOTE_GREEN, report->greenVelocity); \ - } else { \ + } \ + else \ + { \ offNote(10, RB_MIDI_NOTE_GREEN, report->greenVelocity); \ } \ - if (report->redVelocity) { \ + if (report->redVelocity) \ + { \ onNote(10, RB_MIDI_NOTE_RED, report->redVelocity); \ - } else { \ + } \ + else \ + { \ offNote(10, RB_MIDI_NOTE_RED, report->redVelocity); \ } \ - if (report->yellowVelocity) { \ + if (report->yellowVelocity) \ + { \ onNote(10, RB_MIDI_NOTE_YELLOW, report->yellowVelocity); \ - } else { \ + } \ + else \ + { \ offNote(10, RB_MIDI_NOTE_YELLOW, report->yellowVelocity); \ } \ - if (report->blueVelocity) { \ + if (report->blueVelocity) \ + { \ onNote(10, RB_MIDI_NOTE_BLUE, report->blueVelocity); \ - } else { \ + } \ + else \ + { \ offNote(10, RB_MIDI_NOTE_BLUE, report->blueVelocity); \ } \ - if (report->orangeVelocity) { \ - onNote(10, RB_MIDI_NOTE_GREEN, report->orangeVelocity); \ - } else { \ - offNote(10, RB_MIDI_NOTE_GREEN, report->orangeVelocity); \ + if (report->orangeVelocity) \ + { \ + onNote(10, RB_MIDI_NOTE_GREEN, report->orangeVelocity); \ } \ - if (report->kickVelocity) { \ + else \ + { \ + offNote(10, RB_MIDI_NOTE_GREEN, report->orangeVelocity); \ + } \ + if (report->kickVelocity) \ + { \ onNote(10, RB_MIDI_NOTE_KICK, report->kickVelocity); \ - } else { \ + } \ + else \ + { \ offNote(10, RB_MIDI_NOTE_KICK, report->kickVelocity); \ } #else -#define SET_GH_PADS() \ - if (report->greenVelocity) { \ +#define SET_GH_PADS() \ + if (report->greenVelocity) \ + { \ onNote(10, GH_REM_MIDI_NOTE_GREEN, report->greenVelocity); \ - } else { \ + } \ + else \ + { \ offNote(10, GH_REM_MIDI_NOTE_GREEN, report->greenVelocity); \ - } \ - if (report->redVelocity) { \ + } \ + if (report->redVelocity) \ + { \ onNote(10, GH_REM_MIDI_NOTE_RED, report->redVelocity); \ - } else { \ + } \ + else \ + { \ offNote(10, GH_REM_MIDI_NOTE_RED, report->redVelocity); \ - } \ - if (report->yellowVelocity) { \ + } \ + if (report->yellowVelocity) \ + { \ onNote(10, GH_REM_MIDI_NOTE_YELLOW, report->yellowVelocity); \ - } else { \ + } \ + else \ + { \ offNote(10, GH_REM_MIDI_NOTE_YELLOW, report->yellowVelocity); \ - } \ - if (report->blueVelocity) { \ + } \ + if (report->blueVelocity) \ + { \ onNote(10, GH_REM_MIDI_NOTE_BLUE, report->blueVelocity); \ - } else { \ + } \ + else \ + { \ offNote(10, GH_REM_MIDI_NOTE_BLUE, report->blueVelocity); \ - } \ - if (report->orangeVelocity) { \ + } \ + if (report->orangeVelocity) \ + { \ onNote(10, GH_REM_MIDI_NOTE_ORANGE, report->orangeVelocity); \ - } else { \ + } \ + else \ + { \ offNote(10, GH_REM_MIDI_NOTE_ORANGE, report->orangeVelocity); \ - } \ - if (report->kickVelocity) { \ + } \ + if (report->kickVelocity) \ + { \ onNote(10, GH_REM_MIDI_NOTE_KICK, report->kickVelocity); \ - } else { \ + } \ + else \ + { \ offNote(10, GH_REM_MIDI_NOTE_KICK, report->kickVelocity); \ } +#endif + +#if DEVICE_TYPE == ROCK_BAND_DRUMS +#define TRANSLATE_GH_MIDI(channel, note, velocity, func) \ + switch (note) \ + { \ + case GH_MIDI_NOTE_GREEN: \ + func(channel, RB_MIDI_NOTE_GREEN, velocity); \ + break; \ + case GH_MIDI_NOTE_RED: \ + func(channel, RB_MIDI_NOTE_RED, velocity); \ + break; \ + case GH_MIDI_NOTE_YELLOW: \ + func(channel, RB_MIDI_NOTE_YELLOW, velocity); \ + break; \ + case GH_MIDI_NOTE_BLUE: \ + func(channel, RB_MIDI_NOTE_BLUE, velocity); \ + break; \ + case GH_MIDI_NOTE_ORANGE: \ + func(channel, RB_MIDI_NOTE_GREEN, velocity); \ + break; \ + default: \ + func(channel, note, velocity); \ + break; \ + } +#else +#define TRANSLATE_GH_MIDI(note, velocity) \ + switch (note) \ + { \ + case GH_MIDI_NOTE_GREEN: \ + func(channel, GH_REM_MIDI_NOTE_GREEN, velocity); \ + break; \ + case GH_MIDI_NOTE_RED: \ + func(channel, GH_REM_MIDI_NOTE_RED, velocity); \ + break; \ + case GH_MIDI_NOTE_YELLOW: \ + func(channel, GH_REM_MIDI_NOTE_YELLOW, velocity); \ + break; \ + case GH_MIDI_NOTE_BLUE: \ + func(channel, GH_REM_MIDI_NOTE_BLUE, velocity); \ + break; \ + case GH_MIDI_NOTE_ORANGE: \ + func(channel, GH_REM_MIDI_NOTE_ORANGE, velocity); \ + break; \ + default: \ + func(channel, note, velocity); \ + break; \ + } #endif \ No newline at end of file diff --git a/src/shared/main/bh_drum.cpp b/src/shared/main/bh_drum.cpp index 735c77546..c5dd899e3 100644 --- a/src/shared/main/bh_drum.cpp +++ b/src/shared/main/bh_drum.cpp @@ -21,11 +21,11 @@ void tickBhDrum() { if (type == 0x90) { uint8_t note = data[3]; uint8_t velocity = data[4]; - onNote(channel, note, velocity); + TRANSLATE_GH_MIDI(channel, note, velocity, onNote); } else if (type == 0x80) { uint8_t note = data[3]; uint8_t velocity = data[4]; - offNote(channel, note, velocity); + TRANSLATE_GH_MIDI(channel, note, velocity, offNote); } } } diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index e1ba60cac..b09c2b7c6 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2181,6 +2181,8 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t { usb_host_data->slider = 0xFF; } + } else { + usb_host_data->slider = slider; } break; } diff --git a/src/shared/main/wii.cpp b/src/shared/main/wii.cpp index 8462d5038..dd9d37d41 100644 --- a/src/shared/main/wii.cpp +++ b/src/shared/main/wii.cpp @@ -9,6 +9,7 @@ #include "controllers.h" #include "io.h" #include "shared_main.h" +#include "state_translation/drums.h" uint8_t wiiBytes; #ifdef INPUT_WII uint8_t wiiPointer = 0; @@ -176,49 +177,7 @@ uint8_t* tickWii() { note = 0x7F - note; if (velocity || note) { // map gh notes to their rb counterparts in rb mode -#if DEVICE_TYPE == ROCK_BAND_DRUMS - switch (note) { - case GH_MIDI_NOTE_GREEN: - onNote(channel, RB_MIDI_NOTE_GREEN, velocity); - break; - case GH_MIDI_NOTE_RED: - onNote(channel, RB_MIDI_NOTE_RED, velocity); - break; - case GH_MIDI_NOTE_YELLOW: - onNote(channel, RB_MIDI_NOTE_YELLOW, velocity); - break; - case GH_MIDI_NOTE_BLUE: - onNote(channel, RB_MIDI_NOTE_BLUE, velocity); - break; - case GH_MIDI_NOTE_ORANGE: - onNote(channel, RB_MIDI_NOTE_GREEN, velocity); - break; - default: - onNote(channel, note, velocity); - break; - } -#else - switch (note) { - case GH_MIDI_NOTE_GREEN: - onNote(channel, GH_REM_MIDI_NOTE_GREEN, velocity); - break; - case GH_MIDI_NOTE_RED: - onNote(channel, GH_REM_MIDI_NOTE_RED, velocity); - break; - case GH_MIDI_NOTE_YELLOW: - onNote(channel, GH_REM_MIDI_NOTE_YELLOW, velocity); - break; - case GH_MIDI_NOTE_BLUE: - onNote(channel, GH_REM_MIDI_NOTE_BLUE, velocity); - break; - case GH_MIDI_NOTE_ORANGE: - onNote(channel, GH_REM_MIDI_NOTE_ORANGE, velocity); - break; - default: - onNote(channel, note, velocity); - break; - } -#endif + TRANSLATE_GH_MIDI(channel, note, velocity, onNote); } } initialised = true; diff --git a/src/shared/main/wt_drum.cpp b/src/shared/main/wt_drum.cpp index 45e0be750..b0e78893e 100644 --- a/src/shared/main/wt_drum.cpp +++ b/src/shared/main/wt_drum.cpp @@ -3,6 +3,7 @@ #include "Arduino.h" #include "io.h" #include "shared_main.h" +#include "state_translation/drums.h" #ifdef WT_DRUM_SPI_PORT static long lastTick = 0; static int missing = 0; @@ -42,12 +43,12 @@ void tickWtDrum() { uint8_t note = spi_transfer(WT_DRUM_SPI_PORT, 0x00); delayMicroseconds(50); uint8_t velocity = spi_transfer(WT_DRUM_SPI_PORT, 0x00); - onNote(channel, note, velocity); + TRANSLATE_GH_MIDI(channel, note, velocity, onNote); } else if (type == 0x80) { uint8_t note = spi_transfer(WT_DRUM_SPI_PORT, 0x00); delayMicroseconds(50); uint8_t velocity = spi_transfer(WT_DRUM_SPI_PORT, 0x00); - offNote(channel, note, velocity); + TRANSLATE_GH_MIDI(channel, note, velocity, offNote); } delayMicroseconds(10); WT_DRUM_CS_SET(); From a9e4b0a672249726f82788ad4717227544cc417c Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 26 Jun 2025 18:51:18 +1200 Subject: [PATCH 058/239] apply midi translation to wt and bh drums --- src/shared/main/bh_drum.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shared/main/bh_drum.cpp b/src/shared/main/bh_drum.cpp index c5dd899e3..ff02dcc22 100644 --- a/src/shared/main/bh_drum.cpp +++ b/src/shared/main/bh_drum.cpp @@ -3,6 +3,7 @@ #include "Arduino.h" #include "io.h" #include "shared_main.h" +#include "state_translation/drums.h" #define DRUM_ADDR 0x0D #define BH_DRUM_PTR 0x10 #ifdef BH_DRUM_TWI_PORT From 4abae3497d19b16c0924ce2a61dc962ae5455cbd Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 26 Jun 2025 19:50:30 +1200 Subject: [PATCH 059/239] apply midi translation to wt and bh drums --- include/state_translation/drums.h | 44 +++++++++++++++---------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/include/state_translation/drums.h b/include/state_translation/drums.h index f4b4a1d5d..3a65f6161 100644 --- a/include/state_translation/drums.h +++ b/include/state_translation/drums.h @@ -240,30 +240,30 @@ #endif #if DEVICE_TYPE == ROCK_BAND_DRUMS -#define TRANSLATE_GH_MIDI(channel, note, velocity, func) \ - switch (note) \ - { \ - case GH_MIDI_NOTE_GREEN: \ - func(channel, RB_MIDI_NOTE_GREEN, velocity); \ - break; \ - case GH_MIDI_NOTE_RED: \ - func(channel, RB_MIDI_NOTE_RED, velocity); \ - break; \ - case GH_MIDI_NOTE_YELLOW: \ - func(channel, RB_MIDI_NOTE_YELLOW, velocity); \ - break; \ - case GH_MIDI_NOTE_BLUE: \ - func(channel, RB_MIDI_NOTE_BLUE, velocity); \ - break; \ - case GH_MIDI_NOTE_ORANGE: \ - func(channel, RB_MIDI_NOTE_GREEN, velocity); \ - break; \ - default: \ - func(channel, note, velocity); \ - break; \ +#define TRANSLATE_GH_MIDI(channel, note, velocity, func) \ + switch (note) \ + { \ + case GH_MIDI_NOTE_GREEN: \ + func(channel, RB_MIDI_NOTE_GREEN, velocity); \ + break; \ + case GH_MIDI_NOTE_RED: \ + func(channel, RB_MIDI_NOTE_RED, velocity); \ + break; \ + case GH_MIDI_NOTE_YELLOW: \ + func(channel, RB_MIDI_NOTE_YELLOW, velocity); \ + break; \ + case GH_MIDI_NOTE_BLUE: \ + func(channel, RB_MIDI_NOTE_BLUE, velocity); \ + break; \ + case GH_MIDI_NOTE_ORANGE: \ + func(channel, RB_MIDI_NOTE_GREEN, velocity); \ + break; \ + default: \ + func(channel, note, velocity); \ + break; \ } #else -#define TRANSLATE_GH_MIDI(note, velocity) \ +#define TRANSLATE_GH_MIDI(channel, note, velocity, func) \ switch (note) \ { \ case GH_MIDI_NOTE_GREEN: \ From c092fe6dbddadcd715ff836ac9d98123b753137a Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 26 Jun 2025 20:17:39 +1200 Subject: [PATCH 060/239] fix capabilities request --- include/defines.h | 8 ++++---- src/pico/main.cpp | 11 ++++++++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/include/defines.h b/include/defines.h index b8c288518..03afe23ca 100644 --- a/include/defines.h +++ b/include/defines.h @@ -28,13 +28,12 @@ #define XINPUT_PRO_KEYS 15 #define XINPUT_ARCADE_PAD 19 #define XINPUT_TURNTABLE 23 -// Not real, but its easier for us to match this way -#define XINPUT_GUITAR_HERO_LIVE 24 #define XINPUT_PRO_GUITAR 25 -// Also not real, but nice for matching -#define XINPUT_GUITAR_WT 26 #define XINPUT_DISNEY_INFINITY_AND_LEGO_DIMENSIONS 33 #define XINPUT_SKYLANDERS 36 +// Next few arent real, but its easier for us to match this way +#define XINPUT_GUITAR_HERO_LIVE 24 +#define XINPUT_GUITAR_WT 26 #define PS4_GAMEPAD 0 #define PS4_GUITAR 1 @@ -151,6 +150,7 @@ #define DRUM_RB1 1 #define DRUM_RB2 2 #define DRUM_GH 3 +#define GUITAR_CHECK 1 typedef enum { WII_NUNCHUK = 0x0000, diff --git a/src/pico/main.cpp b/src/pico/main.cpp index e534738ff..20ce33374 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -89,7 +89,7 @@ typedef struct } pio_usb_configuration_t; uint8_t prev_bt_report[32]; static const uint8_t capabilitiesRequest[] = {0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -static const uint8_t xbox360w_prescence[] = {0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uint8_t xbox360w_prescence[] = {0x08, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #if defined(INPUT_USB_HOST) || defined(INPUT_SERIAL_MIDI) using namespace usbMidi; #endif @@ -662,6 +662,11 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c usb_host_devices[i].type.drum_type = DRUM_RB2; } } + if (usb_host_devices[i].type.sub_type == XINPUT_GUITAR_ALTERNATE && usb_host_devices[i].type.drum_type == GUITAR_CHECK) { + // request capabilities + send_report_to_controller(dev_addr, instance, capabilitiesRequest, sizeof(capabilitiesRequest)); + usb_host_devices[i].type.drum_type == DRUM_UNKNOWN; + } } // Link report if (header->type == 0x0f) @@ -678,10 +683,10 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c // Request capabilities so we can figure out WT guitars if (sub_type == XINPUT_GUITAR_ALTERNATE) { - // request capabilities - send_report_to_controller(dev_addr, instance, capabilitiesRequest, sizeof(capabilitiesRequest)); + usb_host_devices[i].type.drum_type = GUITAR_CHECK; } } + // Capabilities report if (header->type == 0x05) { XBOX_WIRELESS_CAPABILITIES *caps = (XBOX_WIRELESS_CAPABILITIES *)report; From eac72eb1535c9bb7183eb97f589d6f55c8cbca50 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 26 Jun 2025 20:30:00 +1200 Subject: [PATCH 061/239] more things --- src/shared/usb/descriptors.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 1e97cbce7..ce7281678 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1312,6 +1312,7 @@ uint16_t descriptorRequest(const uint16_t wValue, else if (consoleType == PS3) { dev->idVendor = REDOCTANE_VID; dev->idProduct = PS3_TYPE; + dev->bcdDevice = 0x0108; } #elif DEVICE_TYPE == GAMEPAD else if (consoleType == PS3) { From 716c20866e01e81a9ca923cc88622e4bd465d6b5 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 26 Jun 2025 22:39:18 +1200 Subject: [PATCH 062/239] bcddevice not needed --- src/shared/usb/descriptors.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index ce7281678..1e97cbce7 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1312,7 +1312,6 @@ uint16_t descriptorRequest(const uint16_t wValue, else if (consoleType == PS3) { dev->idVendor = REDOCTANE_VID; dev->idProduct = PS3_TYPE; - dev->bcdDevice = 0x0108; } #elif DEVICE_TYPE == GAMEPAD else if (consoleType == PS3) { From d79661c315f3dab69b8f5f3c785fcc7445494725 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 27 Jun 2025 11:32:37 +1200 Subject: [PATCH 063/239] fix gh mapping --- include/defines.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/defines.h b/include/defines.h index 03afe23ca..74233626f 100644 --- a/include/defines.h +++ b/include/defines.h @@ -235,6 +235,6 @@ typedef enum { #define GH_REM_MIDI_NOTE_RED RB_MIDI_NOTE_RED #define GH_REM_MIDI_NOTE_GREEN RB_MIDI_NOTE_GREEN #define GH_REM_MIDI_NOTE_YELLOW RB_MIDI_NOTE_YELLOW_CYMBAL -#define GH_REM_MIDI_NOTE_BLUE RB_MIDI_NOTE_GREEN +#define GH_REM_MIDI_NOTE_BLUE RB_MIDI_NOTE_BLUE #define GH_REM_MIDI_NOTE_ORANGE RB_MIDI_NOTE_BLUE_CYMBAL #define GH_REM_MIDI_NOTE_KICK2 100 \ No newline at end of file From 987be615c720f86a9b42057d608b474ab1445900 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 28 Jun 2025 18:44:19 +1200 Subject: [PATCH 064/239] support switch 2 pro controller --- include/endpoints.h | 1 + src/pico/main.cpp | 71 +++++---- src/pico/xinput_host.cpp | 262 ++++++++++++++++++++++---------- src/shared/main/shared_main.cpp | 22 +-- 4 files changed, 239 insertions(+), 117 deletions(-) diff --git a/include/endpoints.h b/include/endpoints.h index ca9c698f5..aaca3d1a1 100644 --- a/include/endpoints.h +++ b/include/endpoints.h @@ -66,6 +66,7 @@ enum endpoints_t { #define PS3WIIU_GHLIVE_DONGLE_PID 0x074b #define PS4_GHLIVE_DONGLE_PID 0x07BB #define HARMONIX_VID 0x1bad +#define XBOX_360_ION_ROCKER_VID 0x0130 #define WII_RB_GUITAR_PID 0x0004 #define WII_RB_GUITAR_2_PID 0x3010 #define WII_RB_DRUM_PID 0x0005 diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 20ce33374..b18a2fb2d 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -136,10 +136,6 @@ static void tick_usb() #if USB_HOST_STACK tuh_task(); #endif - if (tud_suspended()) - { - tud_remote_wakeup(); - } tick(); #ifdef INPUT_USB_HOST MIDI.read(); @@ -186,6 +182,10 @@ void go_to_sleep() void wakeup_360() { + if (tud_suspended()) + { + tud_remote_wakeup(); + } if (usb_configured()) { return; @@ -486,7 +486,6 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ case STREAM_DECK: case PS5: case SWITCH: - case SWITCH2: case UNKNOWN: case GENERIC: case STEPMANIAX: @@ -498,6 +497,18 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ usb_host_devices[total_usb_host_devices].type = type; total_usb_host_devices++; break; + case SWITCH2: + printf("Found Switch 2 controller\r\n"); + usb_host_devices[total_usb_host_devices].type = type; + total_usb_host_devices++; + if (type.sub_type == NON_CONTROLLER) + { + uint8_t buf[] = {0x03, 0x91, 0x00, 0x0d, 0x00, 0x08, + 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + send_report_to_controller(dev_addr, instance, buf, sizeof(buf)); + } + break; + case PS3: // GHWT and GH5 guitars have the same vid and pid, but different tap bar functions. We can read the device name to actually determine what it is if (type.sub_type == GUITAR_HERO_GUITAR && XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(dev_addr, 0, buf, sizeof(buf))) @@ -567,6 +578,15 @@ void tuh_xinput_report_sent_cb(uint8_t dev_addr, uint8_t instance, uint8_t const usb_host_devices[i].xone_init_id++; } } + if (usb_host_devices[i].type.console_type == SWITCH2 && usb_host_devices[i].type.sub_type == NON_CONTROLLER) + { + if (!usb_host_devices[i].switch_sent_timeout) + { + usb_host_devices[i].switch_sent_timeout = true; + uint8_t buf[] = {0x09, 0x91, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0, 0}; + send_report_to_controller(dev_addr, instance, buf, sizeof(buf)); + } + } } } } @@ -662,7 +682,8 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c usb_host_devices[i].type.drum_type = DRUM_RB2; } } - if (usb_host_devices[i].type.sub_type == XINPUT_GUITAR_ALTERNATE && usb_host_devices[i].type.drum_type == GUITAR_CHECK) { + if (usb_host_devices[i].type.sub_type == XINPUT_GUITAR_ALTERNATE && usb_host_devices[i].type.drum_type == GUITAR_CHECK) + { // request capabilities send_report_to_controller(dev_addr, instance, capabilitiesRequest, sizeof(capabilitiesRequest)); usb_host_devices[i].type.drum_type == DRUM_UNKNOWN; @@ -742,23 +763,18 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c } if (usb_host_devices[i].type.console_type == SWITCH2 && usb_host_devices[i].type.sub_type == GAMEPAD) { - if (!usb_host_devices[i].switch_sent_handshake) - { - usb_host_devices[i].switch_sent_handshake = true; - uint8_t buf[] = {0x03, 0x91, 0x00, 0x0d, 0x00, 0x08, - 0x00, 0x00, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - send_report_to_controller(dev_addr, instance, buf, sizeof(buf)); - } - else if (!usb_host_devices[i].switch_sent_timeout) + if (report[0] != SWITCH_2_GC_FULL_REPORT_ID) { - usb_host_devices[i].switch_sent_timeout = true; - uint8_t buf[] = {0x09, 0x91, 0x00, 0x07, 0x00, 0x08, 0x00, 0x00, 0x01, 0, 0, 0, 0, 0, 0, 0}; - send_report_to_controller(dev_addr, instance, buf, sizeof(buf)); + continue; } + } + if (usb_host_devices[i].type.console_type == XBOX360) + { - if (report[0] != SWITCH_2_GC_FULL_REPORT_ID) + XInputGamepad_Data_t *gamepad = (XInputGamepad_Data_t *)&usb_host_devices[i].report; + if (len != sizeof(XInputGamepad_Data_t)) { - continue; + return; } } @@ -768,17 +784,14 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c if (usb_host_devices[i].type.console_type == XBOX360 && usb_host_devices[i].type.sub_type == XINPUT_DRUMS && usb_host_devices[i].type.drum_type == DRUM_UNKNOWN) { XInputRockBandDrums_Data_t *drums = (XInputRockBandDrums_Data_t *)&usb_host_devices[i].report; - if (drums->rsize == sizeof(XInputRockBandDrums_Data_t)) + if (drums->leftThumbClick) { - if (drums->leftThumbClick) - { - usb_host_devices[i].type.drum_type = DRUM_GH; - } - else - { - // Only RB1 kits are wired - usb_host_devices[i].type.drum_type = DRUM_RB1; - } + usb_host_devices[i].type.drum_type = DRUM_GH; + } + else + { + // Only RB1 kits are wired + usb_host_devices[i].type.drum_type = DRUM_RB1; } } return; diff --git a/src/pico/xinput_host.cpp b/src/pico/xinput_host.cpp index acf511fdc..77f3c7f6a 100644 --- a/src/pico/xinput_host.cpp +++ b/src/pico/xinput_host.cpp @@ -75,12 +75,15 @@ static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr); // Interface API //--------------------------------------------------------------------+ -uint8_t tuh_xinput_instance_count(uint8_t dev_addr) { +uint8_t tuh_xinput_instance_count(uint8_t dev_addr) +{ return get_dev(dev_addr)->inst_count; } -bool tuh_xinput_mounted(uint8_t dev_addr, uint8_t instance) { - if (get_dev(dev_addr)->inst_count < instance) return false; +bool tuh_xinput_mounted(uint8_t dev_addr, uint8_t instance) +{ + if (get_dev(dev_addr)->inst_count < instance) + return false; xinputh_interface_t *hid_itf = get_instance(dev_addr, instance); return (hid_itf->ep_in != 0) || (hid_itf->ep_out != 0); } @@ -89,13 +92,15 @@ bool tuh_xinput_mounted(uint8_t dev_addr, uint8_t instance) { // Interrupt Endpoint API //--------------------------------------------------------------------+ -bool tuh_xinput_receive_report(uint8_t dev_addr, uint8_t instance) { +bool tuh_xinput_receive_report(uint8_t dev_addr, uint8_t instance) +{ xinputh_interface_t *hid_itf = get_instance(dev_addr, instance); // claim endpoint TU_VERIFY(usbh_edpt_claim(dev_addr, hid_itf->ep_in)); - if (!usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size)) { + if (!usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size)) + { usbh_edpt_release(dev_addr, hid_itf->ep_in); return false; } @@ -103,19 +108,22 @@ bool tuh_xinput_receive_report(uint8_t dev_addr, uint8_t instance) { return true; } -bool tuh_xinput_ready(uint8_t dev_addr, uint8_t instance) { +bool tuh_xinput_ready(uint8_t dev_addr, uint8_t instance) +{ TU_VERIFY(tuh_xinput_mounted(dev_addr, instance)); xinputh_interface_t *hid_itf = get_instance(dev_addr, instance); return !usbh_edpt_busy(dev_addr, hid_itf->ep_in); } -bool tuh_xinput_send_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) { +bool tuh_xinput_send_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) +{ xinputh_interface_t *hid_itf = get_instance(dev_addr, instance); // claim endpoint TU_VERIFY(usbh_edpt_claim(dev_addr, hid_itf->ep_out)); memcpy(hid_itf->epout_buf, report, len); - if (!usbh_edpt_xfer(dev_addr, hid_itf->ep_out, hid_itf->epout_buf, len)) { + if (!usbh_edpt_xfer(dev_addr, hid_itf->ep_out, hid_itf->epout_buf, len)) + { usbh_edpt_release(dev_addr, hid_itf->ep_out); return false; } @@ -125,43 +133,52 @@ bool tuh_xinput_send_report(uint8_t dev_addr, uint8_t instance, uint8_t const *r //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ -bool xinputh_init(void) { +bool xinputh_init(void) +{ tu_memclr(_xinputh_dev, sizeof(_xinputh_dev)); return true; } - -void fill_generic_report_host(uint8_t dev_addr, uint8_t instance, const uint8_t *report, USB_Host_Data_t *out) { +void fill_generic_report_host(uint8_t dev_addr, uint8_t instance, const uint8_t *report, USB_Host_Data_t *out) +{ memset(out, 0, sizeof(USB_Host_Data_t)); xinputh_interface_t *hid_itf = get_instance(dev_addr, instance); fill_generic_report(hid_itf->info, report, out); } -bool xinputh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { +bool xinputh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ (void)result; uint8_t const dir = tu_edpt_dir(ep_addr); uint8_t const instance = get_instance_id_by_epaddr(dev_addr, ep_addr); xinputh_interface_t *hid_itf = get_instance(dev_addr, instance); - if (dir == TUSB_DIR_IN) { + if (dir == TUSB_DIR_IN) + { usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size); tuh_xinput_report_received_cb(dev_addr, instance, hid_itf->epin_buf, (uint16_t)xferred_bytes); - } else { + } + else + { tuh_xinput_report_sent_cb(dev_addr, instance, hid_itf->epin_buf, (uint16_t)xferred_bytes); } return true; } -void xinputh_close(uint8_t dev_addr) { +void xinputh_close(uint8_t dev_addr) +{ TU_VERIFY(dev_addr <= CFG_TUH_DEVICE_MAX, ); xinputh_device_t *hid_dev = get_dev(dev_addr); - for (uint8_t inst = 0; inst < hid_dev->inst_count; inst++) { - if (tuh_xinput_umount_cb) { + for (uint8_t inst = 0; inst < hid_dev->inst_count; inst++) + { + if (tuh_xinput_umount_cb) + { tuh_xinput_umount_cb(dev_addr, inst); } - if (hid_dev->instances[inst].info != NULL) { + if (hid_dev->instances[inst].info != NULL) + { USB_FreeReportInfo(hid_dev->instances[inst].info); } } @@ -169,15 +186,16 @@ void xinputh_close(uint8_t dev_addr) { tu_memclr(hid_dev, sizeof(xinputh_device_t)); } - //--------------------------------------------------------------------+ // Enumeration //--------------------------------------------------------------------+ -extern uint8_t transfer_with_usb_controller(const uint8_t dev_addr, const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, uint8_t *buffer, bool* status); -bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { +extern uint8_t transfer_with_usb_controller(const uint8_t dev_addr, const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, uint8_t *buffer, bool *status); +bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) +{ (void)rhport; (void)max_len; - if (dev_addr == 9) { + if (dev_addr == 9) + { return false; } // Some controllers need a delay here otherwise they don't initialise properly @@ -185,9 +203,11 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const TU_VERIFY(0x58 == desc_itf->bInterfaceClass || TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass || TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); xinputh_interface_t *p_xinput = NULL; uint8_t i = 0; - for (; i < CFG_TUH_XINPUT; i++) { + for (; i < CFG_TUH_XINPUT; i++) + { xinputh_interface_t *hid_itf = get_instance(dev_addr, i); - if (hid_itf->ep_in == 0 && hid_itf->ep_out == 0) { + if (hid_itf->ep_in == 0 && hid_itf->ep_out == 0) + { p_xinput = hid_itf; break; } @@ -196,7 +216,8 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const uint16_t drv_len = sizeof(tusb_desc_interface_t) + (desc_itf->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); // Support standard HID devices - if (TUSB_CLASS_HID == desc_itf->bInterfaceClass) { + if (TUSB_CLASS_HID == desc_itf->bInterfaceClass) + { TU_VERIFY(TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); uint8_t const *p_desc = (uint8_t const *)desc_itf; // Xinput reserved endpoint @@ -207,17 +228,21 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const TU_ASSERT(HID_DESCRIPTOR_HID == x_desc->bDescriptorType, 0); drv_len += x_desc->bLength; uint8_t endpoints = desc_itf->bNumEndpoints; - while (endpoints--) { + while (endpoints--) + { p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *)p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - if (desc_ep->bEndpointAddress & 0x80) { + if (desc_ep->bEndpointAddress & 0x80) + { p_xinput->ep_in = desc_ep->bEndpointAddress; p_xinput->epin_size = desc_ep->wMaxPacketSize; TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); usbh_edpt_xfer(dev_addr, p_xinput->ep_in, p_xinput->epin_buf, p_xinput->epin_size); - } else { + } + else + { p_xinput->ep_out = desc_ep->bEndpointAddress; p_xinput->epout_size = desc_ep->wMaxPacketSize; TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); @@ -226,21 +251,25 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_xinput->itf_num = desc_itf->bInterfaceNumber; p_xinput->type = GENERIC; - if (desc_itf->bInterfaceProtocol == HID_ITF_PROTOCOL_KEYBOARD) { + if (desc_itf->bInterfaceProtocol == HID_ITF_PROTOCOL_KEYBOARD) + { p_xinput->type = KEYBOARD; } - if (desc_itf->bInterfaceProtocol == HID_ITF_PROTOCOL_MOUSE) { + if (desc_itf->bInterfaceProtocol == HID_ITF_PROTOCOL_MOUSE) + { p_xinput->type = MOUSE; } // TODO: do we support nkro - if (p_xinput->type == GENERIC) { + if (p_xinput->type == GENERIC) + { uint8_t temp_buf[512]; uint8_t *current = temp_buf; uint8_t len = x_desc->wDescriptorLength; uint8_t last_id = 0; tuh_descriptor_get_hid_report(dev_addr, p_xinput->itf_num, x_desc->bDescrType, 0, temp_buf, x_desc->wDescriptorLength, NULL, (uintptr_t)temp_buf); // Seems that sometimes we miss the first byte? - if (!temp_buf[0] || temp_buf[0] == 4) { + if (!temp_buf[0] || temp_buf[0] == 4) + { temp_buf[0] = 0x05; } // printf("Report: \r\n"); @@ -252,13 +281,16 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const foundPS4 = false; foundPS5 = false; USB_ProcessHIDReport(temp_buf, x_desc->wDescriptorLength, &p_xinput->info); - if (foundPS5) { + if (foundPS5) + { p_xinput->type = PS5; } - if (foundPS4) { + if (foundPS4) + { p_xinput->type = PS4; } - if (foundPS3) { + if (foundPS3) + { p_xinput->type = PS3; } } @@ -267,23 +299,58 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_xinput->subtype = GAMEPAD; return true; } - uint8_t const *p_desc = (uint8_t const *)desc_itf; + if (0xFF == desc_itf->bInterfaceClass && desc_itf->bInterfaceSubClass == 0x00 && + desc_itf->bInterfaceProtocol == 0x00) + { + uint8_t endpoints = desc_itf->bNumEndpoints; + while (endpoints--) + { + p_desc = tu_desc_next(p_desc); + tusb_desc_endpoint_t const *desc_ep = + (tusb_desc_endpoint_t const *)p_desc; + TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); + if (desc_ep->bEndpointAddress & 0x80) + { + p_xinput->ep_in = desc_ep->bEndpointAddress; + p_xinput->epin_size = desc_ep->wMaxPacketSize; + TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); + usbh_edpt_xfer(dev_addr, p_xinput->ep_in, p_xinput->epin_buf, p_xinput->epin_size); + } + else + { + p_xinput->ep_out = desc_ep->bEndpointAddress; + p_xinput->epout_size = desc_ep->wMaxPacketSize; + TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); + } + } + p_xinput->itf_num = desc_itf->bInterfaceNumber; + + p_xinput->type = SWITCH2; + p_xinput->subtype = NON_CONTROLLER; + return true; + } + if (desc_itf->bInterfaceSubClass == 0x5D && - desc_itf->bInterfaceProtocol == 0x04) { + desc_itf->bInterfaceProtocol == 0x04) + { // Big button uint8_t endpoints = desc_itf->bNumEndpoints; - while (endpoints--) { + while (endpoints--) + { p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *)p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - if (desc_ep->bEndpointAddress & 0x80) { + if (desc_ep->bEndpointAddress & 0x80) + { p_xinput->ep_in = desc_ep->bEndpointAddress; p_xinput->epin_size = desc_ep->wMaxPacketSize; TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); usbh_edpt_xfer(dev_addr, p_xinput->ep_in, p_xinput->epin_buf, p_xinput->epin_size); - } else { + } + else + { p_xinput->ep_out = desc_ep->bEndpointAddress; p_xinput->epout_size = desc_ep->wMaxPacketSize; TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); @@ -294,10 +361,12 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_xinput->type = XBOX360_BB; p_xinput->subtype = GAMEPAD; return true; - } else if (desc_itf->bInterfaceSubClass == 0x5D && - (desc_itf->bInterfaceProtocol == 0x01 || - desc_itf->bInterfaceProtocol == 0x03 || - desc_itf->bInterfaceProtocol == 0x02)) { + } + else if (desc_itf->bInterfaceSubClass == 0x5D && + (desc_itf->bInterfaceProtocol == 0x01 || + desc_itf->bInterfaceProtocol == 0x03 || + desc_itf->bInterfaceProtocol == 0x02)) + { // Xinput reserved endpoint //-------------- Xinput Descriptor --------------// p_desc = tu_desc_next(p_desc); @@ -306,16 +375,20 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const TU_ASSERT(XINPUT_DESC_TYPE_RESERVED == x_desc->bDescriptorType, 0); drv_len += x_desc->bLength; uint8_t endpoints = desc_itf->bNumEndpoints; - while (endpoints--) { + while (endpoints--) + { p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *)p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - if (desc_ep->bEndpointAddress & 0x80) { + if (desc_ep->bEndpointAddress & 0x80) + { p_xinput->ep_in = desc_ep->bEndpointAddress; p_xinput->epin_size = desc_ep->wMaxPacketSize; TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); - } else { + } + else + { p_xinput->ep_out = desc_ep->bEndpointAddress; p_xinput->epout_size = desc_ep->wMaxPacketSize; TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); @@ -324,17 +397,21 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_xinput->itf_num = desc_itf->bInterfaceNumber; p_xinput->type = XBOX360; p_xinput->subtype = GAMEPAD; - if (desc_itf->bInterfaceProtocol == 0x01) { + if (desc_itf->bInterfaceProtocol == 0x01) + { p_xinput->subtype = x_desc->subtype; usbh_edpt_xfer(dev_addr, p_xinput->ep_in, p_xinput->epin_buf, p_xinput->epin_size); - } else { + } + else + { p_xinput->type = NON_CONTROLLER; } _xinputh_dev->inst_count++; return true; - - } else if (desc_itf->bInterfaceSubClass == 0xfD && - desc_itf->bInterfaceProtocol == 0x13) { + } + else if (desc_itf->bInterfaceSubClass == 0xfD && + desc_itf->bInterfaceProtocol == 0x13) + { // Xinput reserved endpoint //-------------- Xinput Descriptor --------------// p_desc = tu_desc_next(p_desc); @@ -348,19 +425,25 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_xinput->itf_num = desc_itf->bInterfaceNumber; _xinputh_dev->inst_count++; return true; - } else if (desc_itf->bInterfaceSubClass == 0x47 && - desc_itf->bInterfaceProtocol == 0xD0 && desc_itf->bNumEndpoints) { + } + else if (desc_itf->bInterfaceSubClass == 0x47 && + desc_itf->bInterfaceProtocol == 0xD0 && desc_itf->bNumEndpoints) + { uint8_t endpoints = desc_itf->bNumEndpoints; - while (endpoints--) { + while (endpoints--) + { p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *)p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - if (desc_ep->bEndpointAddress & 0x80) { + if (desc_ep->bEndpointAddress & 0x80) + { p_xinput->ep_in = desc_ep->bEndpointAddress; p_xinput->epin_size = desc_ep->wMaxPacketSize; TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); - } else { + } + else + { p_xinput->ep_out = desc_ep->bEndpointAddress; p_xinput->epout_size = desc_ep->wMaxPacketSize; TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); @@ -372,21 +455,27 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const _xinputh_dev->inst_count++; usbh_edpt_xfer(dev_addr, p_xinput->ep_in, p_xinput->epin_buf, p_xinput->epin_size); return true; - } else if (desc_itf->bInterfaceSubClass == 0x5D && - desc_itf->bInterfaceProtocol == 0x81) { + } + else if (desc_itf->bInterfaceSubClass == 0x5D && + desc_itf->bInterfaceProtocol == 0x81) + { // Skip over 0x22 descriptor p_desc = tu_desc_next(p_desc); uint8_t endpoints = desc_itf->bNumEndpoints; - while (endpoints--) { + while (endpoints--) + { p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *)p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - if (desc_ep->bEndpointAddress & 0x80) { + if (desc_ep->bEndpointAddress & 0x80) + { p_xinput->ep_in = desc_ep->bEndpointAddress; p_xinput->epin_size = desc_ep->wMaxPacketSize; TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); - } else { + } + else + { p_xinput->ep_out = desc_ep->bEndpointAddress; p_xinput->epout_size = desc_ep->wMaxPacketSize; TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); @@ -398,19 +487,25 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const _xinputh_dev->inst_count++; usbh_edpt_xfer(dev_addr, p_xinput->ep_in, p_xinput->epin_buf, p_xinput->epin_size); return true; - } else if (desc_itf->bInterfaceClass == 0x58) { + } + else if (desc_itf->bInterfaceClass == 0x58) + { uint8_t endpoints = desc_itf->bNumEndpoints; - while (endpoints--) { + while (endpoints--) + { p_desc = tu_desc_next(p_desc); tusb_desc_endpoint_t const *desc_ep = (tusb_desc_endpoint_t const *)p_desc; TU_ASSERT(TUSB_DESC_ENDPOINT == desc_ep->bDescriptorType); - if (desc_ep->bEndpointAddress & 0x80) { + if (desc_ep->bEndpointAddress & 0x80) + { p_xinput->ep_in = desc_ep->bEndpointAddress; p_xinput->epin_size = desc_ep->wMaxPacketSize; TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); usbh_edpt_xfer(dev_addr, p_xinput->ep_in, p_xinput->epin_buf, p_xinput->epin_size); - } else { + } + else + { p_xinput->ep_out = desc_ep->bEndpointAddress; p_xinput->epout_size = desc_ep->wMaxPacketSize; TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); @@ -421,7 +516,7 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_xinput->type = OG_XBOX; p_xinput->subtype = GAMEPAD; return true; - } + } return false; } @@ -429,7 +524,8 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const // Set Configure //--------------------------------------------------------------------+ -enum { +enum +{ CONFG_SET_IDLE, CONFIG_SET_PROTOCOL, CONFIG_GET_REPORT_DESC, @@ -439,13 +535,15 @@ enum { static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance); static void process_set_config(tuh_xfer_t *xfer); -bool xinputh_set_config(uint8_t dev_addr, uint8_t itf_num) { +bool xinputh_set_config(uint8_t dev_addr, uint8_t itf_num) +{ uint8_t instance = get_instance_id_by_itfnum(dev_addr, itf_num); config_driver_mount_complete(dev_addr, instance); return true; } -static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance) { +static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance) +{ xinputh_interface_t *hid_itf = get_instance(dev_addr, instance); // enumeration is complete tuh_xinput_mount_cb(dev_addr, instance, hid_itf->type, hid_itf->subtype); @@ -459,32 +557,40 @@ static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance) { //--------------------------------------------------------------------+ // Get Device by address -TU_ATTR_ALWAYS_INLINE static inline xinputh_device_t *get_dev(uint8_t dev_addr) { +TU_ATTR_ALWAYS_INLINE static inline xinputh_device_t *get_dev(uint8_t dev_addr) +{ return &_xinputh_dev[dev_addr - 1]; } // Get Interface by instance number -TU_ATTR_ALWAYS_INLINE static inline xinputh_interface_t *get_instance(uint8_t dev_addr, uint8_t instance) { +TU_ATTR_ALWAYS_INLINE static inline xinputh_interface_t *get_instance(uint8_t dev_addr, uint8_t instance) +{ return &_xinputh_dev[dev_addr - 1].instances[instance]; } // Get instance ID by interface number -static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf) { - for (uint8_t inst = 0; inst < CFG_TUH_XINPUT; inst++) { +static uint8_t get_instance_id_by_itfnum(uint8_t dev_addr, uint8_t itf) +{ + for (uint8_t inst = 0; inst < CFG_TUH_XINPUT; inst++) + { xinputh_interface_t *hid = get_instance(dev_addr, inst); - if ((hid->itf_num == itf)) return inst; + if ((hid->itf_num == itf)) + return inst; } return 0xff; } // Get instance ID by endpoint address -static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr) { - for (uint8_t inst = 0; inst < CFG_TUH_XINPUT; inst++) { +static uint8_t get_instance_id_by_epaddr(uint8_t dev_addr, uint8_t ep_addr) +{ + for (uint8_t inst = 0; inst < CFG_TUH_XINPUT; inst++) + { xinputh_interface_t *hid = get_instance(dev_addr, inst); - if ((ep_addr == hid->ep_in) || (ep_addr == hid->ep_out)) return inst; + if ((ep_addr == hid->ep_in) || (ep_addr == hid->ep_out)) + return inst; } return 0xff; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index b09c2b7c6..81643ffe4 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1876,19 +1876,19 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t } if (report->leftStickX != SWITCH_2_STICK_CENTER) { - usb_host_data->leftStickX = (report->leftStickX - SWITCH_2_STICK_CENTER) << 5; + usb_host_data->leftStickX = (report->leftStickX - SWITCH_2_STICK_CENTER) << 4; } if (report->leftStickY != SWITCH_2_STICK_CENTER) { - usb_host_data->leftStickY = (((4096 - report->leftStickY) - SWITCH_2_STICK_CENTER)) << 5; + usb_host_data->leftStickY = ((report->leftStickY - SWITCH_2_STICK_CENTER)) << 4; } if (report->rightStickX != SWITCH_2_STICK_CENTER) { - usb_host_data->rightStickX = (report->rightStickX - SWITCH_2_STICK_CENTER) << 5; + usb_host_data->rightStickX = (report->rightStickX - SWITCH_2_STICK_CENTER) << 4; } if (report->rightStickY != SWITCH_2_STICK_CENTER) { - usb_host_data->rightStickY = (((4096 - report->rightStickY) - SWITCH_2_STICK_CENTER)) << 5; + usb_host_data->rightStickY = ((report->rightStickY - SWITCH_2_STICK_CENTER)) << 4; } break; } @@ -2181,7 +2181,9 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t { usb_host_data->slider = 0xFF; } - } else { + } + else + { usb_host_data->slider = slider; } break; @@ -4004,27 +4006,22 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D if (pid == SWITCH_PRO_PID) { type->console_type = SWITCH; - type->sub_type = GAMEPAD; } if (pid == SWITCH_2_PRO_PID) { type->console_type = SWITCH2; - type->sub_type = GAMEPAD; } if (pid == SWITCH_2_GC_PID) { type->console_type = SWITCH2; - type->sub_type = GAMEPAD; } if (pid == SWITCH_2_JOY_R_PID) { type->console_type = SWITCH2; - type->sub_type = GAMEPAD; } if (pid == SWITCH_2_JOY_L_PID) { type->console_type = SWITCH2; - type->sub_type = GAMEPAD; } break; } @@ -4195,6 +4192,11 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D type->console_type = PS3; type->sub_type = ROCK_BAND_PRO_GUITAR_SQUIRE; break; + case XBOX_360_ION_ROCKER_VID: + type->console_type = XBOX360; + type->sub_type = ROCK_BAND_DRUMS; + type->drum_type = DRUM_RB2; + break; } break; From 5bfe4e780d4eba254e6a58d2846abd610e8ad9ac Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 28 Jun 2025 21:39:35 +1200 Subject: [PATCH 065/239] correct switch festival mappings --- include/reports/switch_reports.h | 8 +++++--- include/state_translation/drums.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/include/reports/switch_reports.h b/include/reports/switch_reports.h index b3cb2ff20..a4d30f166 100644 --- a/include/reports/switch_reports.h +++ b/include/reports/switch_reports.h @@ -146,14 +146,16 @@ typedef struct uint8_t dpadUp : 1; // leftShoulder, orange, l1 uint8_t dpadDown : 1; // rightShoulder, spPedal, r1 + uint8_t whammy : 1; // l2 + uint8_t tilt : 1; // r2 + uint8_t back : 1; // back, select uint8_t start : 1; // start + uint8_t : 2; uint8_t guide : 1; // ps uint8_t : 2; - uint8_t whammy : 1; - uint8_t tilt : 1; - uint8_t : 2; + // To make things easier, we use bitfields here, and then we map to a proper hat later union diff --git a/include/state_translation/drums.h b/include/state_translation/drums.h index 3a65f6161..140069b96 100644 --- a/include/state_translation/drums.h +++ b/include/state_translation/drums.h @@ -80,7 +80,7 @@ /* Green */ \ if (!(up || down)) \ { \ - onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, blueVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, greenVelocity >> 1); \ green = false; \ cymbal = false; \ } \ From fa7ac99ca4c00c498344472b946bbb35fb27ff93 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 28 Jun 2025 21:49:09 +1200 Subject: [PATCH 066/239] fix typo with rb yellow cymbal mappings --- include/state_translation/drums.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/state_translation/drums.h b/include/state_translation/drums.h index 140069b96..4a103a9d6 100644 --- a/include/state_translation/drums.h +++ b/include/state_translation/drums.h @@ -112,9 +112,9 @@ { \ onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, blueVelocity >> 1); \ } \ - if (red) \ + if (yellow) \ { \ - onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, redVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, yellowVelocity >> 1); \ } \ if (green) \ { \ From 830363f9f838746c89d9d0cdb4c78e7690a3198e Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 28 Jun 2025 21:49:57 +1200 Subject: [PATCH 067/239] fix typo with rb yellow cymbal mappings --- include/state_translation/drums.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/state_translation/drums.h b/include/state_translation/drums.h index 4a103a9d6..8d6d080e4 100644 --- a/include/state_translation/drums.h +++ b/include/state_translation/drums.h @@ -112,9 +112,9 @@ { \ onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, blueVelocity >> 1); \ } \ - if (yellow) \ + if (yellow) \ { \ - onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, yellowVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, yellowVelocity >> 1); \ } \ if (green) \ { \ From 0e4f8e0bb162665be7f349709c76d01c60d4b249 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 3 Jul 2025 14:22:49 +1200 Subject: [PATCH 068/239] fix sleep --- src/pico/main.cpp | 1 + src/shared/main/ps2.cpp | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index b18a2fb2d..ae331c354 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -247,6 +247,7 @@ void setup() windows_in_hid = false; xboxAuthValid = false; consoleType = UNIVERSAL; + pico_is_sleeping = false; } generateSerialString(&serialstring, consoleType); printf("ConsoleType: %d\r\n", consoleType); diff --git a/src/shared/main/ps2.cpp b/src/shared/main/ps2.cpp index 6d6043d16..ad1295e77 100644 --- a/src/shared/main/ps2.cpp +++ b/src/shared/main/ps2.cpp @@ -235,7 +235,6 @@ uint8_t *tickPS2() { // We only want to reinit if we recevied several bad packets in a row. if (initialised) { in = autoShiftData(port, commandPollInput, sizeof(commandPollInput)); - if (in != NULL) { invalidCount = 0; if (isConfigReply(in)) { From 02bc4c7ed4b635b2a78ea3d6924f6f41d6db8622 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 3 Jul 2025 20:07:23 +1200 Subject: [PATCH 069/239] handle xb1 guide in a more sane way --- include/shared_main.h | 1 + src/pico/main.cpp | 21 ++++++++------------- src/shared/main/shared_main.cpp | 4 +--- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/include/shared_main.h b/include/shared_main.h index cbe1d5a32..04070d5f3 100644 --- a/include/shared_main.h +++ b/include/shared_main.h @@ -39,6 +39,7 @@ typedef struct { uint8_t dev_addr; uint8_t instance; uint8_t drum_type; + bool xone_guide; } USB_Device_Type_t; void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_Device_Type_t *type); typedef struct { diff --git a/src/pico/main.cpp b/src/pico/main.cpp index ae331c354..5ec268858 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -564,7 +564,6 @@ void tuh_xinput_umount_cb(uint8_t dev_addr, uint8_t instance) // Probably should actulaly work out what was unplugged and all that total_usb_host_devices = 0; } -bool wasXb1Input = false; void tuh_xinput_report_sent_cb(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len) { // If there are xb1 init packets to send, send them @@ -620,18 +619,14 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c if (header->command == GIP_VIRTUAL_KEYCODE) { GipKeystroke_t *keystroke = (GipKeystroke_t *)report; - if (wasXb1Input) - { - XboxOneInputHeader_Data_t *gamepad = (XboxOneInputHeader_Data_t *)(&(usb_host_devices[i].report)); - gamepad->guide = keystroke->pressed; - } - return; + usb_host_devices[i].type.xone_guide = keystroke->pressed; + printf("%02x %02x\r\n", keystroke->keycode, keystroke->pressed); + continue; } if (header->command != GHL_HID_REPORT && header->command != GIP_INPUT_REPORT) { - return; + continue; } - wasXb1Input = header->command == GIP_INPUT_REPORT; } if ((millis() - usb_host_devices[i].xone_init_id) < 5000) { @@ -651,7 +646,7 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c // Corrupt report, ignore if (len < sizeof(XBOX_WIRELESS_HEADER)) { - return; + continue; } XBOX_WIRELESS_HEADER *header = (XBOX_WIRELESS_HEADER *)report; if (header->id == 0x08) @@ -696,7 +691,7 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c XBOX_WIRELESS_LINK_REPORT *linkReport = (XBOX_WIRELESS_LINK_REPORT *)report; if (linkReport->always_0xCC != 0xCC) { - return; + continue; } uint8_t sub_type = linkReport->subtype & ~0x80; usb_host_devices[i].type.sub_type = sub_type; @@ -714,7 +709,7 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c XBOX_WIRELESS_CAPABILITIES *caps = (XBOX_WIRELESS_CAPABILITIES *)report; if (caps->always_0x12 != 0x12) { - return; + continue; } printf("Found capabilities: %02x %02x\r\n", dev_addr, instance); if (caps->leftStickX == 0xFFC0 && caps->rightStickX == 0xFFC0) @@ -724,7 +719,7 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c } } } - return; + continue; } if (usb_host_devices[i].type.console_type == STREAM_DECK && report[0] != STREAM_DECK_INPUT_REPORT_ID) { diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 81643ffe4..830bf74e9 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2403,6 +2403,7 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t } case XBOXONE: { + usb_host_data->guide |= device_type.xone_guide; switch (device_type.sub_type) { case GAMEPAD: @@ -2421,7 +2422,6 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->rightShoulder |= report->rightShoulder; usb_host_data->back |= report->back; usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; usb_host_data->leftThumbClick |= report->leftThumbClick; usb_host_data->rightThumbClick |= report->rightThumbClick; usb_host_data->dpadLeft = report->dpadLeft; @@ -2465,7 +2465,6 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->leftShoulder |= report->leftShoulder; usb_host_data->back |= report->back; usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; usb_host_data->green |= report->green; usb_host_data->red |= report->red; usb_host_data->yellow |= report->yellow; @@ -2503,7 +2502,6 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->y |= report->y; usb_host_data->back |= report->back; usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; usb_host_data->dpadLeft = report->dpadLeft; usb_host_data->dpadRight = report->dpadRight; usb_host_data->dpadUp = report->dpadUp; From 5ac67ce82bfba2e14c6c4948434e128e6b98a5ee Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 3 Jul 2025 20:17:28 +1200 Subject: [PATCH 070/239] Add taiko ps2 device type --- include/defines.h | 1 + src/shared/main/ps2.cpp | 174 ++++++++++++++++++++++++++++------------ 2 files changed, 122 insertions(+), 53 deletions(-) diff --git a/include/defines.h b/include/defines.h index 74233626f..32f041120 100644 --- a/include/defines.h +++ b/include/defines.h @@ -196,6 +196,7 @@ typedef enum { PSX_GUNCON, PSX_FLIGHTSTICK, PSX_MOUSE, + PSX_TAIKO, PSX_NO_DEVICE } PsxControllerType_t; diff --git a/src/shared/main/ps2.cpp b/src/shared/main/ps2.cpp index ad1295e77..3b8e39d39 100644 --- a/src/shared/main/ps2.cpp +++ b/src/shared/main/ps2.cpp @@ -8,41 +8,51 @@ #include "util.h" #ifdef INPUT_PS2 -static inline bool isValidReply(const uint8_t *status) { +static inline bool isValidReply(const uint8_t *status) +{ return status[1] != 0xFF && (status[2] == 0x5A || status[2] == 0x00); } -static inline bool isFlightStickReply(const uint8_t *status) { +static inline bool isFlightStickReply(const uint8_t *status) +{ return (status[1] & 0xF0) == 0x50; } -static inline bool isNegconReply(const uint8_t *status) { +static inline bool isNegconReply(const uint8_t *status) +{ return status[1] == 0x23; } -static inline bool isJogconReply(const uint8_t *status) { +static inline bool isJogconReply(const uint8_t *status) +{ return (status[1] & 0xF0) == 0xE0; } -static inline bool isGunconReply(const uint8_t *status) { +static inline bool isGunconReply(const uint8_t *status) +{ return status[1] == 0x63; } -static inline bool isMouseReply(const uint8_t *status) { +static inline bool isMouseReply(const uint8_t *status) +{ return status[1] == 0x12; } -static inline bool isDualShockReply(const uint8_t *status) { +static inline bool isDualShockReply(const uint8_t *status) +{ return (status[1] & 0xF0) == 0x70; } -static inline bool isDualShock2Reply(const uint8_t *status) { +static inline bool isDualShock2Reply(const uint8_t *status) +{ return status[1] == 0x79; } -static inline bool isDigitalReply(const uint8_t *status) { +static inline bool isDigitalReply(const uint8_t *status) +{ return (status[1] & 0xF0) == 0x40; } -static inline bool isConfigReply(const uint8_t *status) { +static inline bool isConfigReply(const uint8_t *status) +{ return (status[1] & 0xF0) == 0xF0; } static const uint8_t commandEnterConfig[] = {0x43, 0x00, 0x01, 0x5A, @@ -55,7 +65,7 @@ static const uint8_t commandGetStatus[] = {0x45, 0x00, 0x00, 0x5A, 0x5A, 0x5A, 0x5A, 0x5A}; static const uint8_t commandGetExtra[] = {0x46, 0x00, 0x00, 0x5A, - 0x5A, 0xA, 0x5A, 0x5A}; + 0x5A, 0xA, 0x5A, 0x5A}; static const uint8_t commandGetExtra2[] = {0x46, 0x00, 0x00, 0x5A, 0x5A, 0xA, 0x5A, 0x5A}; @@ -89,29 +99,36 @@ static const uint8_t commandPollInput[] = {0x42, 0x00, 0xFF, 0xFF}; static bool initialised = false; static long last = 0; static uint8_t invalidCount = 0; -void noAttention(void) { +void noAttention(void) +{ spi_high(PS2_SPI_PORT); INPUT_PS2_ATT_SET(); delayMicroseconds(ATTN_DELAY); } -void signalAttention(void) { +void signalAttention(void) +{ INPUT_PS2_ATT_CLEAR(); delayMicroseconds(ATTN_DELAY); } -void shiftDataInOut(const uint8_t *out, uint8_t *in, const uint8_t len) { +void shiftDataInOut(const uint8_t *out, uint8_t *in, const uint8_t len) +{ unsigned long m; - for (uint8_t i = 0; i < len; ++i) { + for (uint8_t i = 0; i < len; ++i) + { uint8_t resp = spi_transfer(PS2_SPI_PORT, out != NULL ? out[i] : 0x5A); - if (in != NULL) { + if (in != NULL) + { in[i] = resp; } spi_acknowledged = false; m = micros(); - while (!spi_acknowledged) { + while (!spi_acknowledged) + { // If for some reason the controller doesn't respond to us, we need to // make sure we finish the transfer anyways - if (micros() - m > INTER_CMD_BYTE_DELAY) { + if (micros() - m > INTER_CMD_BYTE_DELAY) + { break; } } @@ -119,15 +136,18 @@ void shiftDataInOut(const uint8_t *out, uint8_t *in, const uint8_t len) { } static uint8_t inputBuffer[BUFFER_SIZE]; static uint8_t inputBuffer2[BUFFER_SIZE]; -uint8_t *autoShiftData(uint8_t port, const uint8_t *out, const uint8_t len) { +uint8_t *autoShiftData(uint8_t port, const uint8_t *out, const uint8_t len) +{ uint8_t *ret = NULL; - if (len >= 2 && len <= BUFFER_SIZE) { + if (len >= 2 && len <= BUFFER_SIZE) + { signalAttention(); // All commands have at least 3 bytes, so shift out those first shiftDataInOut(&port, inputBuffer, 1); shiftDataInOut(out, inputBuffer + 1, 2); - if (isValidReply(inputBuffer)) { + if (isValidReply(inputBuffer)) + { // Reply is good, get full length uint8_t replyLen = (inputBuffer[1] & 0x0F) * 2; @@ -135,14 +155,19 @@ uint8_t *autoShiftData(uint8_t port, const uint8_t *out, const uint8_t len) { // Shift out rest of command shiftDataInOut(out + 2, inputBuffer + 3, len - 2); - if (left == 0) { + if (left == 0) + { // The whole reply was gathered ret = inputBuffer; - } else if (len + left <= BUFFER_SIZE) { + } + else if (len + left <= BUFFER_SIZE) + { // Part of reply is still missing and we have space for it shiftDataInOut(NULL, inputBuffer + len + 1, left); ret = inputBuffer; - } else { + } + else + { // Reply incomplete but not enough space provided } } @@ -150,48 +175,60 @@ uint8_t *autoShiftData(uint8_t port, const uint8_t *out, const uint8_t len) { } return ret; } -bool sendCommand(uint8_t port, const uint8_t *buf, uint8_t len) { +bool sendCommand(uint8_t port, const uint8_t *buf, uint8_t len) +{ bool ret = false; unsigned long start = millis(); - do { + do + { uint8_t *in = autoShiftData(port, buf, len); /* We can't know if we have successfully enabled analog mode until * we get out of config mode, so let's just be happy if we get a few * consecutive valid replies */ - if (in != NULL) { - if (buf == commandEnterConfig) { + if (in != NULL) + { + if (buf == commandEnterConfig) + { ret = isConfigReply(in); - } else if (buf == commandExitConfig) { + } + else if (buf == commandExitConfig) + { ret = !isConfigReply(in); } } - if (!ret) { + if (!ret) + { delay(COMMAND_RETRY_INTERVAL); } } while (!ret && millis() - start <= COMMAND_TIMEOUT); return ret; } extern unsigned long millis_at_boot; -uint8_t *tickPS2() { +uint8_t *tickPS2() +{ uint8_t *in; // PS2 guitars die if you poll them too fast - if ((ps2ControllerType == PSX_GUITAR_HERO_CONTROLLER || ps2ControllerType == PSX_DUALSHOCK_1_CONTROLLER) && micros() - last < 3000) { + if ((ps2ControllerType == PSX_GUITAR_HERO_CONTROLLER || ps2ControllerType == PSX_DUALSHOCK_1_CONTROLLER) && micros() - last < 3000) + { return inputBuffer; } // If this is changed to a different port, you can talk to different devices // on a multitap. Not sure how useful this is unless we make a ps2 variant // that works with the multitap, and offers four devices uint8_t port = A; - if (!initialised) { - if (!autoShiftData(port, commandPollInput, sizeof(commandPollInput))) { + if (!initialised) + { + if (!autoShiftData(port, commandPollInput, sizeof(commandPollInput))) + { initialised = false; return NULL; } - if (sendCommand(port, commandEnterConfig, sizeof(commandEnterConfig))) { + if (sendCommand(port, commandEnterConfig, sizeof(commandEnterConfig))) + { // Enable analog sticks - sendCommand(port, commandSetMode, sizeof(commandSetMode)); + sendCommand(port, commandSetMode, sizeof(commandSetMode)); // Enable pressure sensitive buttons // Some PS2 controllers are stupid and *really* need to be told to enable pressure sensitivity // for (int i = 0; i < 20; i++) { @@ -201,51 +238,82 @@ uint8_t *tickPS2() { } uint8_t *in = autoShiftData(port, commandPollInput, sizeof(commandPollInput)); - if (isDualShock2Reply(in)) { + if (isDualShock2Reply(in)) + { uint16_t buttonWord = ~(((uint16_t)in[4] << 8) | in[3]); - if (bit_check(buttonWord, PSB_PAD_LEFT)) { + if (bit_check(buttonWord, PSB_PAD_LEFT)) + { ps2ControllerType = PSX_GUITAR_HERO_CONTROLLER; - } else { + } + else + { ps2ControllerType = PSX_DUALSHOCK_2_CONTROLLER; } - } else if (isDualShockReply(in)) { + } + else if (isDualShockReply(in)) + { uint16_t buttonWord = ~(((uint16_t)in[4] << 8) | in[3]); - if (bit_check(buttonWord, PSB_PAD_LEFT)) { + if (bit_check(buttonWord, PSB_PAD_LEFT)) + { ps2ControllerType = PSX_GUITAR_HERO_CONTROLLER; - } else { + } + else + { ps2ControllerType = PSX_DUALSHOCK_1_CONTROLLER; } - } else if (isFlightStickReply(in)) { + } + else if (isFlightStickReply(in)) + { ps2ControllerType = PSX_FLIGHTSTICK; - } else if (isNegconReply(in)) { + } + else if (isNegconReply(in)) + { ps2ControllerType = PSX_NEGCON; - } else if (isJogconReply(in)) { + } + else if (isJogconReply(in)) + { ps2ControllerType = PSX_JOGCON; - } else if (isGunconReply(in)) { + } + else if (isGunconReply(in)) + { ps2ControllerType = PSX_GUNCON; - } else if (isMouseReply(in)) { + } + else if (isMouseReply(in)) + { ps2ControllerType = PSX_MOUSE; - } else if (isDigitalReply(in)) { + } + else if (isDigitalReply(in)) + { +#if DEVICE_TYPE == TAIKO + ps2ControllerType = PSX_TAIKO; +#else ps2ControllerType = PSX_DIGITAL; +#endif } initialised = true; invalidCount = 0; } // Ocassionally, the controller returns a bad packet because it isn't ready. We should ignore that instead of reinitialisng, and // We only want to reinit if we recevied several bad packets in a row. - if (initialised) { + if (initialised) + { in = autoShiftData(port, commandPollInput, sizeof(commandPollInput)); - if (in != NULL) { + if (in != NULL) + { invalidCount = 0; - if (isConfigReply(in)) { + if (isConfigReply(in)) + { // We're stuck in config mode, try to get out sendCommand(port, commandExitConfig, sizeof(commandExitConfig)); } memcpy(inputBuffer2, inputBuffer, sizeof(inputBuffer)); last = micros(); - } else { + } + else + { invalidCount++; - if (invalidCount > 10) { + if (invalidCount > 10) + { initialised = false; } in = inputBuffer2; From 133cba84a9ad40c79c6c7513afbbbd000c7176e9 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 7 Jul 2025 09:53:41 +1200 Subject: [PATCH 071/239] fix rb PS3/Wii guitar over USB host --- src/shared/main/shared_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 830bf74e9..774cfe5f0 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1287,7 +1287,7 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t } if (report->whammy) { - usb_host_data->whammy = (report->whammy - PS3_STICK_CENTER) << 1; + usb_host_data->whammy = (report->whammy - PS3_STICK_CENTER); } if (report->pickup) { From 8d157f28cfe617f55f73fba4d148531ad7c0140d Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 7 Jul 2025 20:43:45 +1200 Subject: [PATCH 072/239] ignore buttons from rb kits if the pad or cymbal flags are set --- src/shared/main/shared_main.cpp | 57 +++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 774cfe5f0..043c91627 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1032,17 +1032,19 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t case ROCK_BAND_DRUMS: { PCRockBandDrums_Data_t *report = (PCRockBandDrums_Data_t *)data; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; + if (!report->padFlag && !report->cymbalFlag) { + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + } usb_host_data->back |= report->back; usb_host_data->start |= report->start; usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; uint8_t redVelocity = report->redVelocity; uint8_t greenVelocity = report->greenVelocity; uint8_t yellowVelocity = report->yellowVelocity; @@ -1384,17 +1386,20 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t uint8_t blueVelocity = ~report->blueVelocity; bool kick1 = report->leftShoulder; bool kick2 = report->rightShoulder; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; usb_host_data->back |= report->back; usb_host_data->start |= report->start; usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft |= left; - usb_host_data->dpadRight |= right; - usb_host_data->dpadUp |= up; - usb_host_data->dpadDown |= down; + if (!report->padFlag && !report->cymbalFlag) + { + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->dpadLeft |= left; + usb_host_data->dpadRight |= right; + usb_host_data->dpadUp |= up; + usb_host_data->dpadDown |= down; + } SET_RB_PADS(); break; } @@ -2232,14 +2237,18 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t uint8_t blueVelocity = xinput_rb_velocity_positive(report->blueVelocity); SET_RB_PADS(); - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; + + if (!report->padFlag && !report->cymbalFlag) + { + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->dpadLeft = report->dpadLeft; + usb_host_data->dpadRight = report->dpadRight; + usb_host_data->dpadUp = report->dpadUp; + usb_host_data->dpadDown = report->dpadDown; + } usb_host_data->back |= report->back; usb_host_data->start |= report->start; usb_host_data->guide |= report->guide; From 12900535b71a2dd4c4c15bfbdf7508a566ef771b Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 20 Jul 2025 16:20:58 +1200 Subject: [PATCH 073/239] Wake up PS3 MPA, drop invalid packets from 360 MPA --- src/pico/main.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 5ec268858..ce8426a74 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -620,7 +620,6 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c { GipKeystroke_t *keystroke = (GipKeystroke_t *)report; usb_host_devices[i].type.xone_guide = keystroke->pressed; - printf("%02x %02x\r\n", keystroke->keycode, keystroke->pressed); continue; } if (header->command != GHL_HID_REPORT && header->command != GIP_INPUT_REPORT) @@ -630,7 +629,7 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c } if ((millis() - usb_host_devices[i].xone_init_id) < 5000) { - if (usb_host_devices[i].type.console_type == PS3 && usb_host_devices[i].type.sub_type == ROCK_BAND_PRO_KEYS) + if (usb_host_devices[i].type.console_type == PS3 && (usb_host_devices[i].type.sub_type == ROCK_BAND_PRO_KEYS || usb_host_devices[i].type.sub_type == ROCK_BAND_PRO_GUITAR_MUSTANG || usb_host_devices[i].type.sub_type == ROCK_BAND_PRO_GUITAR_SQUIRE)) { uint8_t hid_command_enable[40] = { 0xE9, 0x00, 0x89, 0x1B, 0x00, 0x00, 0x00, 0x02, @@ -767,10 +766,11 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c if (usb_host_devices[i].type.console_type == XBOX360) { - XInputGamepad_Data_t *gamepad = (XInputGamepad_Data_t *)&usb_host_devices[i].report; - if (len != sizeof(XInputGamepad_Data_t)) + XInputGamepad_Data_t *gamepad = (XInputGamepad_Data_t *)report; + // Drop any corrupted or invalid packets + if (len != sizeof(XInputGamepad_Data_t) || gamepad->rsize != len) { - return; + continue; } } @@ -790,7 +790,6 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c usb_host_devices[i].type.drum_type = DRUM_RB1; } } - return; } } } From 87f367f04bebd12c28fb81cba8f896442ee5d3bd Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 21 Jul 2025 10:48:30 +1200 Subject: [PATCH 074/239] use sec for timeouts instead of ms, maybe implement sysex for pro guitar --- include/shared_main.h | 1 + src/pico/main.cpp | 2 + src/shared/main/shared_main.cpp | 97 +++++++++++++++++++++++++++++---- 3 files changed, 88 insertions(+), 12 deletions(-) diff --git a/include/shared_main.h b/include/shared_main.h index 04070d5f3..23c3b4f1f 100644 --- a/include/shared_main.h +++ b/include/shared_main.h @@ -27,6 +27,7 @@ void on_connect(void); void set_console_type(uint8_t new_console_type); void authentication_successful(void); void onNote(uint8_t channel, uint8_t note, uint8_t velocity); +void onSysEx(uint8_t* array, unsigned size); void offNote(uint8_t channel, uint8_t note, uint8_t velocity); diff --git a/src/pico/main.cpp b/src/pico/main.cpp index ce8426a74..73a7217c6 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -283,6 +283,7 @@ void setup() MIDI.setHandleNoteOff(offNote); MIDI.setHandleControlChange(onControlChange); MIDI.setHandlePitchBend(onPitchBend); + MIDI.setHandleSystemExclusive(onSysEx); #endif #ifdef INPUT_SERIAL_MIDI MIDI2.begin(0); @@ -290,6 +291,7 @@ void setup() MIDI2.setHandleNoteOff(offNote); MIDI2.setHandleControlChange(onControlChange); MIDI2.setHandlePitchBend(onPitchBend); + MIDI2.setHandleSystemExclusive(onSysEx); #endif #endif } diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 043c91627..7550d4c10 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -24,6 +24,12 @@ #include "util.h" #include "wii.h" #include "wt_drum.h" +#define UP 1 << 0 +#define DOWN 1 << 1 +#define LEFT 1 << 2 +#define RIGHT 1 << 3 +static const uint8_t dpad_bindings[] = {0x08, 0x00, 0x04, 0x08, 0x06, 0x07, 0x05, 0x08, 0x02, 0x01, 0x03}; +static const uint8_t dpad_bindings_reverse[] = {UP, UP | RIGHT, RIGHT, DOWN | RIGHT, DOWN, DOWN | LEFT, LEFT, UP | LEFT}; #define DJLEFT_ADDR 0x0E #define DJRIGHT_ADDR 0x0D #define DJ_BUTTONS_PTR 0x12 @@ -112,6 +118,76 @@ void onPitchBend(uint8_t channel, int pitch) printf("PitchBend ch=%d, pitch=%d\r\n", channel, pitch); midiData.midiPitchWheel = pitch << 2; } +PS3RockBandProGuitar_Data_t sysexGuitar = {0}; +void onSysEx(uint8_t *data, unsigned size) +{ +#if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE + uint8_t type, fret, velocity; + type = data[3]; + uint8_t string = (size >= 5) ? (data[4] - 1) % 6 : 0; + // changes to the fret state + if ((type == 0x01) && (size >= 6)) + { + fret = data[5]; + // offset fret numbers relative to the base note of each string + switch (string) + { + case 0: + sysexGuitar.lowEFret = fret - 0x40; + break; + case 1: + sysexGuitar.aFret = fret - 0x3B; + break; + case 2: + sysexGuitar.dFret = fret - 0x37; + break; + case 3: + sysexGuitar.gFret = fret - 0x32; + break; + case 4: + sysexGuitar.bFret = fret - 0x2D; + break; + case 5: + sysexGuitar.highEFret = fret - 0x28; + break; + } + } + // picking events + else if ((type == 0x05) && (size >= 6)) + { + velocity = data[5]; + switch (string) + { + case 0: + sysexGuitar.lowEFretVelocity = velocity; + break; + case 1: + sysexGuitar.aFretVelocity = velocity; + break; + case 2: + sysexGuitar.dFretVelocity = velocity; + break; + case 3: + sysexGuitar.gFretVelocity = velocity; + break; + case 4: + sysexGuitar.bFretVelocity = velocity; + break; + case 5: + sysexGuitar.highEFretVelocity = velocity; + break; + } + } + // button events + else if ((type == 0x08) && (size >= 7)) + { + // PS3 style report starts at byte 4 + memcpy(&sysexGuitar, data + 4, 3); + // tilt however is not in the same spot as a ps3 report + sysexGuitar.tilt = (data[6] & 0x40) ? 0x7f : 0x40; + } +#endif +} uint8_t tmp = 0; long clone_guitar_timer = 0; long clone_guitar_ready_timer = 0; @@ -244,12 +320,6 @@ uint8_t ledStateMpr121 = 0; uint8_t ledStateMpr121Select = 0; uint8_t lastLedStateMpr121 = 0; #endif -#define UP 1 << 0 -#define DOWN 1 << 1 -#define LEFT 1 << 2 -#define RIGHT 1 << 3 -static const uint8_t dpad_bindings[] = {0x08, 0x00, 0x04, 0x08, 0x06, 0x07, 0x05, 0x08, 0x02, 0x01, 0x03}; -static const uint8_t dpad_bindings_reverse[] = {UP, UP | RIGHT, RIGHT, DOWN | RIGHT, DOWN, DOWN | LEFT, LEFT, UP | LEFT}; uint8_t gh5_mapping[] = { 0x80, 0x15, 0x4D, 0x30, 0x9A, 0x99, 0x66, @@ -1032,7 +1102,8 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t case ROCK_BAND_DRUMS: { PCRockBandDrums_Data_t *report = (PCRockBandDrums_Data_t *)data; - if (!report->padFlag && !report->cymbalFlag) { + if (!report->padFlag && !report->cymbalFlag) + { usb_host_data->a |= report->a; usb_host_data->b |= report->b; usb_host_data->x |= report->x; @@ -2799,7 +2870,9 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #include "inputs/wii.h" #include "inputs/wt_drum.h" #include "inputs/wt_neck.h" - +#if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE + convert_report((uint8_t *)&sysexGuitar, sizeof(sysexGuitar), {PS3, ROCK_BAND_PRO_GUITAR_SQUIRE, 0, 0, 0, false}, &usb_host_data); +#endif TICK_SHARED; if (!startedInactivityPulse) { @@ -3641,7 +3714,7 @@ void tick(void) reset_usb(); } // Only sleep if the timeout has passed and we aren't connected over USB - if (SLEEP_PIN != -1 && SLEEP_INACTIVITY_TIMEOUT_MS && millis() - lastInputActivity >= SLEEP_INACTIVITY_TIMEOUT_MS && !usb_configured()) + if (SLEEP_PIN != -1 && SLEEP_INACTIVITY_TIMEOUT_SEC && millis() - lastInputActivity >= ((uint32_t)SLEEP_INACTIVITY_TIMEOUT_SEC * 1000) && !usb_configured()) { go_to_sleep(); } @@ -3665,7 +3738,7 @@ void tick(void) // the device is plugged in again if (slave_initted) { - if (RGB_INACTIVITY_TIMEOUT_MS && millis() - lastInputActivity >= RGB_INACTIVITY_TIMEOUT_MS) + if (RGB_INACTIVITY_TIMEOUT_SEC && millis() - lastInputActivity >= (((uint32_t)RGB_INACTIVITY_TIMEOUT_SEC) * 1000)) { memset(ledStatePeripheral, 0, sizeof(ledStatePeripheral)); } @@ -3681,7 +3754,7 @@ void tick(void) } #endif #ifdef TICK_LED - if (RGB_INACTIVITY_TIMEOUT_MS && millis() - lastInputActivity >= RGB_INACTIVITY_TIMEOUT_MS) + if (RGB_INACTIVITY_TIMEOUT_SEC && millis() - lastInputActivity >= (((uint32_t)RGB_INACTIVITY_TIMEOUT_SEC) * 1000)) { memset(ledState, 0, sizeof(ledState)); } @@ -3693,7 +3766,7 @@ void tick(void) #endif #if LED_COUNT_MPR121 - if (RGB_INACTIVITY_TIMEOUT_MS && millis() - lastInputActivity >= RGB_INACTIVITY_TIMEOUT_MS) + if (RGB_INACTIVITY_TIMEOUT_SEC && millis() - lastInputActivity >= (((uint32_t)RGB_INACTIVITY_TIMEOUT_SEC) * 1000)) { ledStateMpr121 = 0; } From c608cccbd35707ee44a0677779209c988c71d453 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 29 Jul 2025 09:15:36 +1200 Subject: [PATCH 075/239] ignore neutral positions for whammy and pickup --- src/shared/main/shared_main.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 7550d4c10..11f4c24c2 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -123,12 +123,12 @@ void onSysEx(uint8_t *data, unsigned size) { #if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE uint8_t type, fret, velocity; - type = data[3]; - uint8_t string = (size >= 5) ? (data[4] - 1) % 6 : 0; + type = data[5]; + uint8_t string = (size >= 5) ? (data[6] - 1) % 6 : 0; // changes to the fret state if ((type == 0x01) && (size >= 6)) { - fret = data[5]; + fret = data[7]; // offset fret numbers relative to the base note of each string switch (string) { @@ -155,7 +155,7 @@ void onSysEx(uint8_t *data, unsigned size) // picking events else if ((type == 0x05) && (size >= 6)) { - velocity = data[5]; + velocity = data[7]; switch (string) { case 0: @@ -182,9 +182,9 @@ void onSysEx(uint8_t *data, unsigned size) else if ((type == 0x08) && (size >= 7)) { // PS3 style report starts at byte 4 - memcpy(&sysexGuitar, data + 4, 3); + memcpy(&sysexGuitar, data + 6, 3); // tilt however is not in the same spot as a ps3 report - sysexGuitar.tilt = (data[6] & 0x40) ? 0x7f : 0x40; + sysexGuitar.tilt = (data[8] & 0x40) ? 0x7f : 0x40; } #endif } @@ -992,7 +992,7 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t } if (report->leftStickY != PS3_STICK_CENTER) { - usb_host_data->leftStickY = (((UINT8_MAX - report->leftStickY) - PS3_STICK_CENTER)) << 8; + usb_host_data->leftStickY = (report->leftStickY - PS3_STICK_CENTER) << 8; } if (report->rightStickX != PS3_STICK_CENTER) { @@ -1000,7 +1000,7 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t } if (report->rightStickY != PS3_STICK_CENTER) { - usb_host_data->rightStickY = (((UINT8_MAX - report->rightStickY) - PS3_STICK_CENTER)) << 8; + usb_host_data->rightStickY = (report->rightStickY - PS3_STICK_CENTER) << 8; } break; } @@ -1358,11 +1358,12 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->soloBlue |= report->x; usb_host_data->soloOrange |= report->leftShoulder; } - if (report->whammy) + // both whammy and pickup reset to a neutral state when not in use + if (report->whammy != 0x7F) { usb_host_data->whammy = (report->whammy - PS3_STICK_CENTER); } - if (report->pickup) + if (report->pickup != 0x7F) { usb_host_data->pickup = report->pickup; } From 662a3bb6a2283581ad69ca10a7b1903de118ff46 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 29 Jul 2025 09:18:00 +1200 Subject: [PATCH 076/239] ignore neutral positions for whammy and pickup --- src/shared/main/shared_main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 11f4c24c2..7c2150e55 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1358,12 +1358,12 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->soloBlue |= report->x; usb_host_data->soloOrange |= report->leftShoulder; } - // both whammy and pickup reset to a neutral state when not in use - if (report->whammy != 0x7F) + if (report->whammy) { usb_host_data->whammy = (report->whammy - PS3_STICK_CENTER); } - if (report->pickup != 0x7F) + // pickup resets to a neutral state when not in use + if (report->pickup && report->pickup != 0x7F) { usb_host_data->pickup = report->pickup; } From 489fcd0fc853037acb30f32d57231c3b0a974175 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 29 Jul 2025 12:51:27 +1200 Subject: [PATCH 077/239] ignore neutral positions for whammy and pickup --- include/shared_main.h | 2 ++ src/pico/main.cpp | 10 ++++++++++ src/shared/main/shared_main.cpp | 11 ++++++----- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/include/shared_main.h b/include/shared_main.h index 23c3b4f1f..dfe23068b 100644 --- a/include/shared_main.h +++ b/include/shared_main.h @@ -40,6 +40,8 @@ typedef struct { uint8_t dev_addr; uint8_t instance; uint8_t drum_type; + uint8_t pickup; + uint8_t whammy; bool xone_guide; } USB_Device_Type_t; void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_Device_Type_t *type); diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 73a7217c6..88e1687ef 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -775,6 +775,16 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c continue; } } + if (usb_host_devices[i].type.console_type == PS3 && usb_host_devices[i].type.sub_type == ROCK_BAND_GUITAR) { + PS3RockBandGuitar_Data_t *guitar = (PS3RockBandGuitar_Data_t *)report; + // ignore neutral value from whammy and pickup + if (guitar->whammy != 0x7F) { + usb_host_devices[i].type.whammy = guitar->whammy; + } + if (guitar->pickup != 0x7F) { + usb_host_devices[i].type.pickup = guitar->pickup; + } + } memcpy(&usb_host_devices[i].report, report, len); usb_host_devices[i].report_length = len; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 7c2150e55..bb1b64d49 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1358,14 +1358,15 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->soloBlue |= report->x; usb_host_data->soloOrange |= report->leftShoulder; } - if (report->whammy) + // whammy + pickup resets to a neutral state when not in use + // so we opt to store the last known state and use that when in neutral + if (device_type.whammy) { - usb_host_data->whammy = (report->whammy - PS3_STICK_CENTER); + usb_host_data->whammy = device_type.whammy; } - // pickup resets to a neutral state when not in use - if (report->pickup && report->pickup != 0x7F) + if (device_type.pickup) { - usb_host_data->pickup = report->pickup; + usb_host_data->pickup = device_type.pickup; } break; } From 0477100ca382c3ecfbcf02fb51da0982fe2a1956 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 29 Jul 2025 12:56:20 +1200 Subject: [PATCH 078/239] invert y axis for generic hid --- src/shared/main/shared_main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index bb1b64d49..dc8cb0f74 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -992,7 +992,7 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t } if (report->leftStickY != PS3_STICK_CENTER) { - usb_host_data->leftStickY = (report->leftStickY - PS3_STICK_CENTER) << 8; + usb_host_data->leftStickY = (((UINT8_MAX - report->leftStickY) - PS3_STICK_CENTER)) << 8; } if (report->rightStickX != PS3_STICK_CENTER) { @@ -1000,7 +1000,7 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t } if (report->rightStickY != PS3_STICK_CENTER) { - usb_host_data->rightStickY = (report->rightStickY - PS3_STICK_CENTER) << 8; + usb_host_data->rightStickY = (((UINT8_MAX - report->rightStickY) - PS3_STICK_CENTER)) << 8; } break; } From f28e75e0ad1ebb3a0a4df7f03b79d48ef2300140 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 30 Jul 2025 15:55:40 +1200 Subject: [PATCH 079/239] xb1 rb tilt incorrect shift --- src/shared/main/shared_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index dc8cb0f74..4e9d2f36f 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2563,7 +2563,7 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->dpadDown = report->dpadDown; if (report->tilt) { - usb_host_data->tilt = report->tilt << 8; + usb_host_data->tilt = report->tilt << 7; } if (report->whammy) { From 0c5dcaa9596df87d7769f2d7c7e909e7e2507126 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 1 Aug 2025 10:13:05 +1200 Subject: [PATCH 080/239] comment out some stuff i was testing --- src/shared/main/shared_main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 4e9d2f36f..d91290a77 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2872,9 +2872,9 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #include "inputs/wii.h" #include "inputs/wt_drum.h" #include "inputs/wt_neck.h" -#if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE - convert_report((uint8_t *)&sysexGuitar, sizeof(sysexGuitar), {PS3, ROCK_BAND_PRO_GUITAR_SQUIRE, 0, 0, 0, false}, &usb_host_data); -#endif +// #if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE +// convert_report((uint8_t *)&sysexGuitar, sizeof(sysexGuitar), {PS3, ROCK_BAND_PRO_GUITAR_SQUIRE, 0, 0, 0, false}, &usb_host_data); +// #endif TICK_SHARED; if (!startedInactivityPulse) { From e65e633b5bde16143e8188b694777c4fd1bdca6d Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 1 Aug 2025 15:52:15 +1200 Subject: [PATCH 081/239] more rb3 fixes --- src/shared/main/shared_main.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index d91290a77..c3d835128 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2851,6 +2851,7 @@ bool greenPad; bool yellowCymbal; bool blueCymbal; long lastCymbalOff; +long lastGreenOff = 0; uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t output_console_type) { uint8_t packet_size = 0; @@ -3466,13 +3467,17 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #if DEVICE_TYPE == ROCK_BAND_DRUMS if (!report->cymbalFlag && ready_for_next_packet()) { + if (greenCymbal) { + lastGreenOff = millis(); + } greenCymbal = false; yellowCymbal = false; blueCymbal = false; } - if (!report->padFlag && ready_for_next_packet()) + if (!report->padFlag && ready_for_next_packet() && greenPad) { greenPad = false; + lastGreenOff = millis(); } #endif From 80896aa87e9b29b16d63425f4e9ceaf318e02a2a Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 2 Aug 2025 11:27:22 +1200 Subject: [PATCH 082/239] fix tilt for ps3 gh guitars over usb host --- src/shared/main/shared_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index c3d835128..1079e441a 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1393,7 +1393,7 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->dpadDown |= down; if (report->tilt != PS3_ACCEL_CENTER) { - usb_host_data->tilt = (report->tilt - PS3_ACCEL_CENTER) << 6; + usb_host_data->tilt = (report->tilt - PS3_ACCEL_CENTER) << 8; } if (report->whammy) { From 219f785de9445615aad03e833c6ba2567e7f32ff Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 2 Aug 2025 13:59:22 +1200 Subject: [PATCH 083/239] lefty flip fix for xinput too --- src/shared/main/shared_main.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 1079e441a..106e04b5a 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3156,13 +3156,18 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #if DEVICE_TYPE == ROCK_BAND_DRUMS if (!report->cymbalFlag && ready_for_next_packet()) { + if (greenCymbal) { + lastGreenOff = millis(); + } greenCymbal = false; yellowCymbal = false; blueCymbal = false; + lastCymbalOff = millis(); } - if (!report->padFlag && ready_for_next_packet()) + if (!report->padFlag && ready_for_next_packet() && greenPad) { greenPad = false; + lastGreenOff = millis(); } #endif } @@ -3473,6 +3478,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu greenCymbal = false; yellowCymbal = false; blueCymbal = false; + lastCymbalOff = millis(); } if (!report->padFlag && ready_for_next_packet() && greenPad) { From 3587c40e2698d133f6674ca8de513d4d24dac06f Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 4 Aug 2025 12:13:04 +1200 Subject: [PATCH 084/239] fix things --- src/shared/main/shared_main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 106e04b5a..67df784fe 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2850,7 +2850,7 @@ bool greenCymbal; bool greenPad; bool yellowCymbal; bool blueCymbal; -long lastCymbalOff; +long lastCymbalOff = 0; long lastGreenOff = 0; uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t output_console_type) { @@ -3154,7 +3154,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #endif report_size = packet_size = sizeof(XINPUT_REPORT); #if DEVICE_TYPE == ROCK_BAND_DRUMS - if (!report->cymbalFlag && ready_for_next_packet()) + if (!report->cymbalFlag && ready_for_next_packet() && (greenCymbal || yellowCymbal || blueCymbal)) { if (greenCymbal) { lastGreenOff = millis(); From 2213e16d40a4f3b5dd1e32ffe6ba4928b0a5207d Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 7 Aug 2025 15:06:55 +1200 Subject: [PATCH 085/239] fix ps3 cymbal glitch fix --- src/shared/main/shared_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 67df784fe..4b91c70f5 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3470,7 +3470,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #endif #if DEVICE_TYPE == ROCK_BAND_DRUMS - if (!report->cymbalFlag && ready_for_next_packet()) + if (!report->cymbalFlag && ready_for_next_packet() && (greenCymbal || yellowCymbal || blueCymbal)) { if (greenCymbal) { lastGreenOff = millis(); From 6f1fe8b1a448f6a670d984788af52d7cb63db73f Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 14 Aug 2025 22:41:43 +1200 Subject: [PATCH 086/239] alpha level support for crkd neck --- include/io.h | 2 + include/reports/controller_reports.h | 136 ++++++++++++++---------- include/xbox.h | 5 +- src/avr/shared/io.cpp | 8 ++ src/avr/shared/io_define.h | 4 +- src/pico/io.cpp | 150 +++++++++++++++++++-------- src/pico/io_define.h | 6 +- src/shared/main/inputs/crkd.h | 3 + src/shared/main/shared_main.cpp | 5 + 9 files changed, 221 insertions(+), 98 deletions(-) create mode 100644 src/shared/main/inputs/crkd.h diff --git a/include/io.h b/include/io.h index faefcf9f5..2b7e95c6a 100644 --- a/include/io.h +++ b/include/io.h @@ -27,6 +27,8 @@ bool twi_writeSingleToPointer(TWI_BLOCK, uint8_t address, uint8_t pointer, uint8 bool twi_writeToPointer(TWI_BLOCK, uint8_t address, uint8_t pointer, uint8_t length, uint8_t *data); void spi_begin(); +void uart_begin(); +bool read_uart(UART_BLOCK block, uint8_t header, uint8_t size, uint8_t *dest); uint8_t spi_transfer(SPI_BLOCK block, uint8_t data); void spi_high(SPI_BLOCK block); void init_ack(); diff --git a/include/reports/controller_reports.h b/include/reports/controller_reports.h index 94609872e..db8ed97fa 100644 --- a/include/reports/controller_reports.h +++ b/include/reports/controller_reports.h @@ -21,11 +21,13 @@ #define NKRO_KEYS ((0x73 / 8) + 1) #define SIMULTANEOUS_MIDI 12 #define KEYCODE_F24 115 -typedef struct { +typedef struct +{ // TMIDI_EventPacket_t midi[SIMULTANEOUS_MIDI]; } USB_MIDI_Data_t; -typedef struct { +typedef struct +{ uint8_t rid; bool left : 1; bool right : 1; @@ -36,7 +38,8 @@ typedef struct { int8_t scrollY; /** Current scroll Y delta movement on the mouse */ int8_t scrollX; /** Current scroll X delta movement on the mouse */ } __attribute__((packed)) USB_Mouse_Data_t; -typedef struct { +typedef struct +{ uint8_t rid; bool mediaNextTrack : 1; bool mediaPreviousTrack : 1; @@ -48,7 +51,8 @@ typedef struct { bool : 1; } USB_ConsumerControl_Data_t; -typedef struct { +typedef struct +{ uint8_t rid; bool leftCtrl : 1; bool leftShift : 1; @@ -58,8 +62,10 @@ typedef struct { bool rightShift : 1; bool rightAlt : 1; bool rWin : 1; - union { - struct { + union + { + struct + { uint8_t : 4; bool a : 1; bool b : 1; @@ -107,7 +113,7 @@ typedef struct { bool oemOpenBrackets : 1; bool oemCloseBrackets : 1; bool oemPipe : 1; - bool : 1; // Unused ansi pipe + bool : 1; // Unused ansi pipe bool oemSemicolon : 1; bool oemQuotes : 1; bool oemTilde : 1; @@ -145,7 +151,7 @@ typedef struct { bool multiply : 1; bool subtract : 1; bool add : 1; - bool : 1; // numpad enter + bool : 1; // numpad enter bool numPad1 : 1; bool numPad2 : 1; bool numPad3 : 1; @@ -180,7 +186,8 @@ typedef struct { }; } __attribute__((packed)) USB_NKRO_Data_t; -typedef struct { +typedef struct +{ uint8_t rid; bool leftCtrl : 1; bool leftShift : 1; @@ -195,7 +202,8 @@ typedef struct { keys. */ } __attribute__((packed)) USB_6KRO_Data_t; -typedef struct { +typedef struct +{ bool leftCtrl : 1; bool leftShift : 1; bool leftAlt : 1; @@ -209,7 +217,8 @@ typedef struct { keys. */ } __attribute__((packed)) USB_6KRO_Boot_Data_t; -typedef struct { +typedef struct +{ bool left : 1; bool right : 1; bool middle : 1; @@ -220,7 +229,8 @@ typedef struct { int8_t scrollX; /** Current scroll X delta movement on the mouse */ } __attribute__((packed)) USB_Mouse_Boot_Data_t; -typedef union { +typedef union +{ #ifdef TICK_SIXKRO USB_6KRO_Data_t keyboard; #else @@ -231,33 +241,36 @@ typedef union { USB_Mouse_Data_t mouse; } USB_Report_Data_t; -typedef union { - struct { - bool x : 1; // square - bool a : 1; // cross - bool b : 1; // circle - bool y : 1; // triangle +typedef union +{ + struct + { + bool x : 1; // square + bool a : 1; // cross + bool b : 1; // circle + bool y : 1; // triangle - bool leftShoulder : 1; // l1 - bool rightShoulder : 1; // r1 + bool leftShoulder : 1; // l1 + bool rightShoulder : 1; // r1 }; uint8_t val; } Buffer_Report_t; -typedef struct { - uint8_t x : 1; // square - uint8_t a : 1; // cross - uint8_t b : 1; // circle - uint8_t y : 1; // triangle - uint8_t leftShoulder : 1; // l1 - uint8_t rightShoulder : 1; // r1 - uint8_t back : 1; // select +typedef struct +{ + uint8_t x : 1; // square + uint8_t a : 1; // cross + uint8_t b : 1; // circle + uint8_t y : 1; // triangle + uint8_t leftShoulder : 1; // l1 + uint8_t rightShoulder : 1; // r1 + uint8_t back : 1; // select uint8_t start : 1; - uint8_t leftThumbClick : 1; // l3 - uint8_t rightThumbClick : 1; // r3 - uint8_t guide : 1; // ps - uint8_t capture : 1; // switch capture button + uint8_t leftThumbClick : 1; // l3 + uint8_t rightThumbClick : 1; // r3 + uint8_t guide : 1; // ps + uint8_t capture : 1; // switch capture button uint8_t leftBlue : 1; uint8_t leftRed : 1; uint8_t leftGreen : 1; @@ -281,8 +294,10 @@ typedef struct { uint8_t dpadLeft : 1; uint8_t dpadRight : 1; - union { - struct { + union + { + struct + { uint16_t genericButton1 : 1; uint16_t genericButton2 : 1; uint16_t genericButton3 : 1; @@ -305,7 +320,6 @@ typedef struct { uint16_t leftTrigger; uint16_t rightTrigger; - int16_t leftStickX; int16_t leftStickY; int16_t rightStickX; @@ -355,36 +369,52 @@ typedef struct { uint8_t highEFretVelocity; } __attribute__((packed)) USB_Host_Data_t; - - -typedef struct { +typedef struct +{ uint8_t report_id; // 0x03 uint8_t dpad : 4; uint8_t : 4; - + uint8_t capture : 1; uint8_t assistant : 1; - uint8_t r2 : 1; // r2 - uint8_t l2 : 1; // l2 - uint8_t guide : 1; // ps - uint8_t start : 1; // menu - uint8_t back : 1; // options - uint8_t rightThumbClick : 1; // r3 + uint8_t r2 : 1; // r2 + uint8_t l2 : 1; // l2 + uint8_t guide : 1; // ps + uint8_t start : 1; // menu + uint8_t back : 1; // options + uint8_t rightThumbClick : 1; // r3 - uint8_t leftThumbClick : 1; // l3 + uint8_t leftThumbClick : 1; // l3 uint8_t rightShoulder : 1; // r1 uint8_t leftShoulder : 1; // l1 - uint8_t y : 1; // triangle - uint8_t x : 1; // square - uint8_t b : 1; // circle - uint8_t a : 1; // cross + uint8_t y : 1; // triangle + uint8_t x : 1; // square + uint8_t b : 1; // circle + uint8_t a : 1; // cross uint8_t : 1; uint8_t leftStickX; uint8_t leftStickY; uint8_t rightStickX; uint8_t rightStickY; - uint8_t leftTrigger; // pressure_l2 - uint8_t rightTrigger; // pressure_r2 -} __attribute__((packed)) Stadia_Data_t; \ No newline at end of file + uint8_t leftTrigger; // pressure_l2 + uint8_t rightTrigger; // pressure_r2 +} __attribute__((packed)) Stadia_Data_t; + +typedef struct +{ + uint8_t header; // {0xA5, 0x01};, though we are eating the first header byte + uint8_t len; // 0x0C; + uint8_t padding[2]; //{0x00, 0x00}; + uint8_t green : 1; + uint8_t red : 1; + uint8_t yellow : 1; + uint8_t blue : 1; + uint8_t orange : 1; + uint8_t : 3; + uint8_t dpadUpDown; // none: 0x80, up: 0x00, down: 0xFF + uint8_t dpadLeftRight; // none: 0x80, right: 0x00, left: 0xFF + uint8_t footer[3]; // {0x00, 0x01, 0x15}; + uint8_t crc; // CRC-8/MAXIM-DOW +} __attribute__((packed)) crkd_neck_t; \ No newline at end of file diff --git a/include/xbox.h b/include/xbox.h index b9151ea32..7d45d6fb4 100644 --- a/include/xbox.h +++ b/include/xbox.h @@ -2,10 +2,12 @@ #include "wcid.h" #include "reports/xinput_reports.h" #include "reports/og_xbox_reports.h" +// This actually just defines the supported report types! +// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-xusbi/3beba8eb-25f9-4f80-bca8-d4665dd5b767 typedef struct { uint8_t bLength; // Length of this descriptor. uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). - uint8_t reserved[2]; + uint8_t reserved[2]; //version uint8_t subtype; uint8_t reserved2; uint8_t bEndpointAddressIn; @@ -16,6 +18,7 @@ typedef struct { uint8_t reserved4[2]; } __attribute__((packed)) XBOX_ID_DESCRIPTOR; + typedef struct { uint8_t bLength; // Length of this descriptor. uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). diff --git a/src/avr/shared/io.cpp b/src/avr/shared/io.cpp index aaa25d107..f963fa168 100644 --- a/src/avr/shared/io.cpp +++ b/src/avr/shared/io.cpp @@ -40,7 +40,15 @@ static volatile unsigned int twi_reg_addr; static volatile unsigned char twi_first_addr_flag; // set address flag static volatile unsigned char twi_rw_len; // length of most recent operation +void uart_begin() { + // TODO: no +} +bool read_uart(uart_inst_t *uart, uint8_t header, uint8_t size, uint8_t *dest) +{ + // TODO: no again + return false; +} void spi_begin() { #ifdef GC_SPI_CLOCK uint8_t clockDiv; diff --git a/src/avr/shared/io_define.h b/src/avr/shared/io_define.h index c82ea080e..f6bc9d2d5 100644 --- a/src/avr/shared/io_define.h +++ b/src/avr/shared/io_define.h @@ -40,5 +40,7 @@ #define TWI_BLOCK void* #define SPI_BLOCK void* +#define UART_BLOCK void* #define GC_TWI NULL -#define GC_SPI NULL \ No newline at end of file +#define GC_SPI NULL +#define GC_UART NULL \ No newline at end of file diff --git a/src/pico/io.cpp b/src/pico/io.cpp index 9e9154b92..be2963641 100644 --- a/src/pico/io.cpp +++ b/src/pico/io.cpp @@ -16,7 +16,8 @@ #include "pico_slave.h" #include "wii.h" volatile bool spi_acknowledged = false; -void spi_begin_output() { +void spi_begin_output() +{ #ifdef SPI_0_OUTPUT #ifdef SPI_0_MOSI spi_init(spi0, SPI_0_CLOCK); @@ -50,7 +51,8 @@ void spi_begin_output() { spi_set_slave(spi1, true); #endif } -void spi_begin() { +void spi_begin() +{ #ifdef SPI_0_MOSI spi_init(spi0, SPI_0_CLOCK); spi_set_format(spi0, 8, (spi_cpol_t)SPI_0_CPOL, @@ -84,7 +86,32 @@ void spi_begin() { spi_set_slave(spi1, true); #endif } -static uint8_t revbits(uint8_t b) { +void uart_begin() +{ +#ifdef UART_0_TX + uart_init(uart0, 500000); + gpio_set_function(UART_0_TX, GPIO_FUNC_UART); + gpio_set_function(UART_0_RX, GPIO_FUNC_UART); +#endif +} +bool read_uart(UART_BLOCK uart, uint8_t header, uint8_t size, uint8_t *dest) +{ + if (!uart_is_readable(uart)) + { + return false; + } + while (uart_getc(uart) != header) + { + if (!uart_is_readable(uart)) + { + return false; + } + } + uart_read_blocking(uart0, dest, size); + return true; +} +static uint8_t revbits(uint8_t b) +{ b = (b & 0b11110000) >> 4 | (b & 0b00001111) << 4; b = (b & 0b11001100) >> 2 | (b & 0b00110011) << 2; b = (b & 0b10101010) >> 1 | (b & 0b01010101) << 1; @@ -94,27 +121,33 @@ static uint8_t revbits(uint8_t b) { volatile bool alarm_fired = false; #define ALARM_NUM 0 #define ALARM_IRQ TIMER_IRQ_0 -int64_t alarm_irq(alarm_id_t id, void *user_data) { +int64_t alarm_irq(alarm_id_t id, void *user_data) +{ alarm_fired = true; return 0; } -int __not_in_flash_func(spi_write_read_blocking_timeout)(spi_inst_t *spi, const uint8_t src) { +int __not_in_flash_func(spi_write_read_blocking_timeout)(spi_inst_t *spi, const uint8_t src) +{ // For PS2 communication we NEED timeouts. We can fake them by starting an alarm and resetting the SPI // hardware if the alarm fires. size_t rx_remaining = 1, tx_remaining = 1; uint8_t dst; alarm_fired = false; alarm_id_t alarm = add_alarm_in_us(50, alarm_irq, NULL, false); - while (rx_remaining || tx_remaining) { - if (tx_remaining && spi_is_writable(spi)) { + while (rx_remaining || tx_remaining) + { + if (tx_remaining && spi_is_writable(spi)) + { spi_get_hw(spi)->dr = (uint32_t)src; --tx_remaining; } - if (rx_remaining && spi_is_readable(spi)) { + if (rx_remaining && spi_is_readable(spi)) + { dst = (uint8_t)spi_get_hw(spi)->dr; --rx_remaining; } - if (alarm_fired) { + if (alarm_fired) + { spi_begin_output(); return 0; } @@ -123,50 +156,62 @@ int __not_in_flash_func(spi_write_read_blocking_timeout)(spi_inst_t *spi, const return dst; } // SINCE LSB_FIRST isn't supported, we need to invert bits ourselves when its set -uint8_t spi_transfer(SPI_BLOCK block, uint8_t data) { +uint8_t spi_transfer(SPI_BLOCK block, uint8_t data) +{ #if SPI_0_MSBFIRST == 0 - if (block == spi0) data = revbits(data); + if (block == spi0) + data = revbits(data); #endif #if SPI_1_MSBFIRST == 0 - if (block == spi1) data = revbits(data); + if (block == spi1) + data = revbits(data); #endif uint8_t resp; #ifdef SPI_1_OUTPUT - if (block == spi1) { + if (block == spi1) + { resp = spi_write_read_blocking_timeout(block, data); } #endif #ifndef SPI_1_OUTPUT - if (block == spi1) { + if (block == spi1) + { spi_write_read_blocking(block, &data, &resp, 1); } #endif #ifdef SPI_0_OUTPUT - if (block == spi0) { + if (block == spi0) + { resp = spi_write_read_blocking_timeout(block, data); } #endif #ifndef SPI_0_OUTPUT - if (block == spi0) { + if (block == spi0) + { spi_write_read_blocking(block, &data, &resp, 1); } #endif #if SPI_0_MSBFIRST == 0 - if (block == spi0) resp = revbits(resp); + if (block == spi0) + resp = revbits(resp); #endif #if SPI_1_MSBFIRST == 0 - if (block == spi1) resp = revbits(resp); + if (block == spi1) + resp = revbits(resp); #endif return resp; } void spi_high(SPI_BLOCK block) {} uint8_t addr; -void recv(int len) { +void recv(int len) +{ addr = RXWIRE.read(); // remove addr len -= 1; - if (len) { - for (int i = 0; i < len; i++) { + if (len) + { + for (int i = 0; i < len; i++) + { recv_data(addr + i, RXWIRE.read()); } recv_end(addr, len); @@ -174,11 +219,13 @@ void recv(int len) { } // Called when the I2C slave is read from -void req() { +void req() +{ // Auto increment address for repeated reads RXWIRE.write(req_data(addr++)); } -void twi_init() { +void twi_init() +{ #ifdef TWI_0_CLOCK i2c_init(i2c0, TWI_0_CLOCK); gpio_set_function(TWI_0_SDA, GPIO_FUNC_I2C); @@ -216,20 +263,24 @@ void twi_init() { #endif } bool twi_readFromPointerSlow(TWI_BLOCK block, uint8_t address, uint8_t pointer, uint8_t length, - uint8_t *data) { - if (!twi_writeTo(block, address, &pointer, 1, true, true)) return false; + uint8_t *data) +{ + if (!twi_writeTo(block, address, &pointer, 1, true, true)) + return false; delayMicroseconds(170); return twi_readFrom(block, address, data, length, true); } bool twi_readFrom(TWI_BLOCK block, uint8_t address, uint8_t *data, uint8_t length, - uint8_t sendStop) { + uint8_t sendStop) +{ int ret = i2c_read_timeout_us(block, address, data, length, !sendStop, 5000); return ret > 0 ? ret : 0; } bool twi_writeTo(TWI_BLOCK block, uint8_t address, uint8_t *data, uint8_t length, uint8_t wait, - uint8_t sendStop) { + uint8_t sendStop) +{ int ret = i2c_write_timeout_us(block, address, data, length, !sendStop, 5000); if (ret < 0) @@ -239,15 +290,18 @@ bool twi_writeTo(TWI_BLOCK block, uint8_t address, uint8_t *data, uint8_t length } #ifdef PS2_ACK -void callback(uint gpio, uint32_t events) { +void callback(uint gpio, uint32_t events) +{ spi_acknowledged = true; } -void init_ack() { +void init_ack() +{ gpio_set_irq_enabled_with_callback(PS2_ACK, GPIO_IRQ_EDGE_RISE, true, &callback); } #endif -void read_serial(uint8_t *id, uint8_t len) { +void read_serial(uint8_t *id, uint8_t len) +{ pico_get_unique_board_id_string((char *)id, len); } @@ -259,51 +313,63 @@ uint32_t lastWtSum[5] = {0}; uint32_t lastWtAvg[5][WT_BUFFER] = {0}; uint8_t nextWt[5] = {0}; uint32_t initialWt[5] = {0}; -uint32_t readWt(int pin) { +uint32_t readWt(int pin) +{ gpio_put_masked((1 << WT_PIN_S0) | (1 << WT_PIN_S1) | (1 << WT_PIN_S2), ((pin & (1 << 0)) << WT_PIN_S0 - 0) | ((pin & (1 << 1)) << (WT_PIN_S1 - 1)) | ((pin & (1 << 2)) << (WT_PIN_S2 - 2))); uint32_t m = rp2040.getCycleCount(); gpio_put(WT_PIN_INPUT, 1); gpio_set_dir(WT_PIN_INPUT, true); gpio_set_dir(WT_PIN_INPUT, false); gpio_set_pulls(WT_PIN_INPUT, false, false); - while (gpio_get(WT_PIN_INPUT)) { - if (rp2040.getCycleCount() - m > 10000) { + while (gpio_get(WT_PIN_INPUT)) + { + if (rp2040.getCycleCount() - m > 10000) + { break; } } m = rp2040.getCycleCount() - m; - if (pin >= 6) { + if (pin >= 6) + { return m; } lastWtSum[pin] -= lastWtAvg[pin][nextWt[pin]]; lastWtAvg[pin][nextWt[pin]] = m; lastWtSum[pin] += m; nextWt[pin]++; - if (nextWt[pin] >= WT_BUFFER) { + if (nextWt[pin] >= WT_BUFFER) + { nextWt[pin] = 0; } m = lastWtSum[pin] / WT_BUFFER; lastWt[pin] = m; return m; } -bool checkWt(int pin) { +bool checkWt(int pin) +{ return readWt(pin) > initialWt[pin]; } -void initWt() { +void initWt() +{ memset(initialWt, 0, sizeof(initialWt)); - for (int j = 0; j < 1000; j++) { - for (int i = 0; i < 5; i++) { + for (int j = 0; j < 1000; j++) + { + for (int i = 0; i < 5; i++) + { initialWt[i] += readWt(i); } } - for (int i = 0; i < 5; i++) { + for (int i = 0; i < 5; i++) + { initialWt[i] /= 1000; initialWt[i] += WT_SENSITIVITY; } } static bool wtInit = false; -uint8_t tickWt() { - if (!wtInit) { +uint8_t tickWt() +{ + if (!wtInit) + { wtInit = true; initWt(); } diff --git a/src/pico/io_define.h b/src/pico/io_define.h index 343e5506e..8c41df335 100644 --- a/src/pico/io_define.h +++ b/src/pico/io_define.h @@ -3,6 +3,7 @@ #include #include #include +#include #if BLUETOOTH #include #endif @@ -13,5 +14,8 @@ #define TWI_1 i2c1 #define SPI_0 spi0 #define SPI_1 spi1 +#define UART_0 uart0 +#define UART_1 uart1 #define TWI_BLOCK i2c_inst_t* -#define SPI_BLOCK spi_inst_t* \ No newline at end of file +#define SPI_BLOCK spi_inst_t* +#define UART_BLOCK uart_inst_t* \ No newline at end of file diff --git a/src/shared/main/inputs/crkd.h b/src/shared/main/inputs/crkd.h new file mode 100644 index 000000000..099499a08 --- /dev/null +++ b/src/shared/main/inputs/crkd.h @@ -0,0 +1,3 @@ +#ifdef INPUT_CRKD_NECK + lastCrkdWasSuccessful = read_uart(CRKD_UART_PORT, 0x65, 11, (uint8_t*)&lastCrkd); +#endif \ No newline at end of file diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 4b91c70f5..cfc509a29 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -66,6 +66,7 @@ struct }; }; } rtt_t; +crkd_neck_t lastCrkd; unsigned long lastMidi = 0; Midi_Data_t midiData = {0}; void onNote(uint8_t channel, uint8_t note, uint8_t velocity) @@ -253,6 +254,7 @@ bool lastTurntableWasSuccessfulLeft = false; bool lastTurntableWasSuccessfulRight = false; bool lastWiiWasSuccessful = false; bool lastPS2WasSuccessful = false; +bool lastCrkdWasSuccessful = false; bool overrideR2 = false; bool lastXboxOneGuide = false; bool disable_multiplexer = false; @@ -354,6 +356,7 @@ void init_main(void) initPins(); twi_init(); spi_begin(); + uart_begin(); GIP_HEADER((&powerMode), GIP_POWER_MODE_DEVICE_CONFIG, true, 1); powerMode.subcommand = GIP_POWER_ON; GIP_HEADER((&ledOn), GIP_CMD_LED, true, 1); @@ -2690,6 +2693,7 @@ void tick_ps2output() #include "inputs/usb_host.h" #include "inputs/wii.h" #include "inputs/wt_neck.h" +#include "inputs/crkd.h" TICK_SHARED; if (!startedInactivityPulse) @@ -2873,6 +2877,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #include "inputs/wii.h" #include "inputs/wt_drum.h" #include "inputs/wt_neck.h" +#include "inputs/crkd.h" // #if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE // convert_report((uint8_t *)&sysexGuitar, sizeof(sysexGuitar), {PS3, ROCK_BAND_PRO_GUITAR_SQUIRE, 0, 0, 0, false}, &usb_host_data); // #endif From 33bd5754909d17f8205316133f8cab10c4e72d93 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 16 Aug 2025 23:24:14 +1200 Subject: [PATCH 087/239] crkd neck support --- src/shared/main/inputs/crkd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/inputs/crkd.h b/src/shared/main/inputs/crkd.h index 099499a08..1a4f1ca53 100644 --- a/src/shared/main/inputs/crkd.h +++ b/src/shared/main/inputs/crkd.h @@ -1,3 +1,3 @@ #ifdef INPUT_CRKD_NECK - lastCrkdWasSuccessful = read_uart(CRKD_UART_PORT, 0x65, 11, (uint8_t*)&lastCrkd); + lastCrkdWasSuccessful = read_uart(CRKD_UART_PORT, 0xA5, 11, (uint8_t*)&lastCrkd); #endif \ No newline at end of file From 9c596638c9e8ccb2f2c3bcdbb3e221f821673f41 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 16 Aug 2025 23:31:27 +1200 Subject: [PATCH 088/239] crkd neck support --- include/io.h | 4 ++++ src/avr/shared/io.cpp | 6 +++++- src/pico/io.cpp | 10 ++++++++++ src/shared/main/inputs/crkd.h | 7 ++++++- src/shared/main/shared_main.cpp | 4 ++++ 5 files changed, 29 insertions(+), 2 deletions(-) diff --git a/include/io.h b/include/io.h index 2b7e95c6a..dfed9bb11 100644 --- a/include/io.h +++ b/include/io.h @@ -29,6 +29,10 @@ bool twi_writeToPointer(TWI_BLOCK, uint8_t address, uint8_t pointer, uint8_t len void spi_begin(); void uart_begin(); bool read_uart(UART_BLOCK block, uint8_t header, uint8_t size, uint8_t *dest); + +void send_uart(UART_BLOCK block, uint8_t *data, uint8_t size) { + +} uint8_t spi_transfer(SPI_BLOCK block, uint8_t data); void spi_high(SPI_BLOCK block); void init_ack(); diff --git a/src/avr/shared/io.cpp b/src/avr/shared/io.cpp index f963fa168..5ed86c328 100644 --- a/src/avr/shared/io.cpp +++ b/src/avr/shared/io.cpp @@ -44,11 +44,15 @@ void uart_begin() { // TODO: no } -bool read_uart(uart_inst_t *uart, uint8_t header, uint8_t size, uint8_t *dest) +bool read_uart(UART_BLOCK block, uint8_t header, uint8_t size, uint8_t *dest) { // TODO: no again return false; } +void send_uart(UART_BLOCK block, uint8_t *data, uint8_t size) { + + // TODO: no again part 2 +} void spi_begin() { #ifdef GC_SPI_CLOCK uint8_t clockDiv; diff --git a/src/pico/io.cpp b/src/pico/io.cpp index be2963641..c2ba43720 100644 --- a/src/pico/io.cpp +++ b/src/pico/io.cpp @@ -110,6 +110,16 @@ bool read_uart(UART_BLOCK uart, uint8_t header, uint8_t size, uint8_t *dest) uart_read_blocking(uart0, dest, size); return true; } + +void send_uart(UART_BLOCK block, uint8_t *data, uint8_t size) +{ + + if (!uart_is_writable(block)) + { + return; + } + uart_write_blocking(block, data, size); +} static uint8_t revbits(uint8_t b) { b = (b & 0b11110000) >> 4 | (b & 0b00001111) << 4; diff --git a/src/shared/main/inputs/crkd.h b/src/shared/main/inputs/crkd.h index 1a4f1ca53..6e97497ac 100644 --- a/src/shared/main/inputs/crkd.h +++ b/src/shared/main/inputs/crkd.h @@ -1,3 +1,8 @@ #ifdef INPUT_CRKD_NECK - lastCrkdWasSuccessful = read_uart(CRKD_UART_PORT, 0xA5, 11, (uint8_t*)&lastCrkd); +lastCrkdWasSuccessful = read_uart(CRKD_UART_PORT, 0xA5, 11, (uint8_t *)&lastCrkd); +if (millis() - last_poll_crkd >= 10) +{ + send_uart(CRKD_UART_PORT, crkd_magic_data, sizeof(crkd_magic_data)); + last_poll_crkd = millis(); +} #endif \ No newline at end of file diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index cfc509a29..475f66361 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -279,6 +279,7 @@ Gip_Led_On_t ledOn; Gip_Auth_Done_t authDonePacket; long last_poll = 0; long last_poll_dj_ps3 = 0; +long last_poll_crkd = 0; bool festival_gameplay_mode = false; long last_festival_toggle = 0; /* Magic data taken from GHLtarUtility: @@ -294,6 +295,9 @@ uint8_t ghl_ps3wiiu_magic_data[] = { uint8_t ghl_ps4_magic_data[] = { 0x30, 0x02, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00}; +// need to send this otherwise crkd neck wont give proper dpad data +uint8_t crkd_magic_data[] = {0xA5, 0x01, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E}; + uint8_t clone_data[] = {0x53, 0x10, 0x00, 0x01}; #if LED_COUNT_WS2812 Led_WS2812_t ledState[LED_COUNT_WS2812]; From 93819c8fd3ec3cfb51c337c4f51c1a403ace44a4 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 16 Aug 2025 23:34:51 +1200 Subject: [PATCH 089/239] crkd neck support --- include/io.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/io.h b/include/io.h index dfed9bb11..4a07df0f9 100644 --- a/include/io.h +++ b/include/io.h @@ -30,9 +30,7 @@ void spi_begin(); void uart_begin(); bool read_uart(UART_BLOCK block, uint8_t header, uint8_t size, uint8_t *dest); -void send_uart(UART_BLOCK block, uint8_t *data, uint8_t size) { - -} +void send_uart(UART_BLOCK block, uint8_t *data, uint8_t size); uint8_t spi_transfer(SPI_BLOCK block, uint8_t data); void spi_high(SPI_BLOCK block); void init_ack(); From d5fe2d1caa4d0a6aa53e3faff6bed295c8669bd1 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 16 Aug 2025 23:45:46 +1200 Subject: [PATCH 090/239] crkd neck support --- src/pico/io.cpp | 17 +++++++++++------ src/shared/main/inputs/crkd.h | 5 ----- src/shared/main/shared_main.cpp | 3 --- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/pico/io.cpp b/src/pico/io.cpp index c2ba43720..f921c0643 100644 --- a/src/pico/io.cpp +++ b/src/pico/io.cpp @@ -89,25 +89,30 @@ void spi_begin() void uart_begin() { #ifdef UART_0_TX - uart_init(uart0, 500000); + uart_init(uart0, UART_0_CLOCK); gpio_set_function(UART_0_TX, GPIO_FUNC_UART); gpio_set_function(UART_0_RX, GPIO_FUNC_UART); #endif +#ifdef UART_1_TX + uart_init(uart1, UART_1_CLOCK); + gpio_set_function(UART_1_TX, GPIO_FUNC_UART); + gpio_set_function(UART_1_RX, GPIO_FUNC_UART); +#endif } -bool read_uart(UART_BLOCK uart, uint8_t header, uint8_t size, uint8_t *dest) +bool read_uart(UART_BLOCK block, uint8_t header, uint8_t size, uint8_t *dest) { - if (!uart_is_readable(uart)) + if (!uart_is_readable(block)) { return false; } - while (uart_getc(uart) != header) + while (uart_getc(block) != header) { - if (!uart_is_readable(uart)) + if (!uart_is_readable(block)) { return false; } } - uart_read_blocking(uart0, dest, size); + uart_read_blocking(block, dest, size); return true; } diff --git a/src/shared/main/inputs/crkd.h b/src/shared/main/inputs/crkd.h index 6e97497ac..54c7dfac4 100644 --- a/src/shared/main/inputs/crkd.h +++ b/src/shared/main/inputs/crkd.h @@ -1,8 +1,3 @@ #ifdef INPUT_CRKD_NECK lastCrkdWasSuccessful = read_uart(CRKD_UART_PORT, 0xA5, 11, (uint8_t *)&lastCrkd); -if (millis() - last_poll_crkd >= 10) -{ - send_uart(CRKD_UART_PORT, crkd_magic_data, sizeof(crkd_magic_data)); - last_poll_crkd = millis(); -} #endif \ No newline at end of file diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 475f66361..6df40e5fb 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -295,9 +295,6 @@ uint8_t ghl_ps3wiiu_magic_data[] = { uint8_t ghl_ps4_magic_data[] = { 0x30, 0x02, 0x08, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00}; -// need to send this otherwise crkd neck wont give proper dpad data -uint8_t crkd_magic_data[] = {0xA5, 0x01, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E}; - uint8_t clone_data[] = {0x53, 0x10, 0x00, 0x01}; #if LED_COUNT_WS2812 Led_WS2812_t ledState[LED_COUNT_WS2812]; From 8bf9830092290e2c2da0769797f19f3392d7448c Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 16 Aug 2025 23:47:17 +1200 Subject: [PATCH 091/239] crkd neck support --- src/shared/main/shared_main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 6df40e5fb..cfc509a29 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -279,7 +279,6 @@ Gip_Led_On_t ledOn; Gip_Auth_Done_t authDonePacket; long last_poll = 0; long last_poll_dj_ps3 = 0; -long last_poll_crkd = 0; bool festival_gameplay_mode = false; long last_festival_toggle = 0; /* Magic data taken from GHLtarUtility: From 9e4463d1f4743f3936ec7ca20606486c71d9ff83 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 26 Aug 2025 12:19:01 +1200 Subject: [PATCH 092/239] fix lis3dh --- src/shared/main/accel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/accel.cpp b/src/shared/main/accel.cpp index 8097d3702..6da288d44 100644 --- a/src/shared/main/accel.cpp +++ b/src/shared/main/accel.cpp @@ -14,8 +14,8 @@ void init_lis3dh() { uint8_t id = 0; lis3dh_address = LIS3DH_ADDRESS; twi_readFromPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_WHOAMI, 1, &id); - lis3dh_address = LIS3DH_ADDRESS_2; if (id != LIS3DH_ID) { + lis3dh_address = LIS3DH_ADDRESS_2; twi_readFromPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_WHOAMI, 1, &id); if (id != LIS3DH_ID) { return; From e3abc17e17e3a4c392ea70a70902fe9ef11ba750 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 2 Sep 2025 14:47:00 +1200 Subject: [PATCH 093/239] remove arduino support --- platformio.ini | 237 -------- src/avr/lufa/LUFA.c | 3 - src/avr/lufa/reboot.c | 7 - src/avr/micro/detect/descriptors_detect.c | 191 ------- src/avr/micro/detect/descriptors_detect.h | 69 --- src/avr/micro/detect/main.c | 115 ---- src/avr/micro/main/main.cpp | 184 ------ src/avr/micro/shared/bootloader.c | 13 - src/avr/micro/shared/bootloader.h | 5 - src/avr/shared/io.cpp | 595 ------------------- src/avr/shared/io_define.h | 46 -- src/avr/shared/pins.cpp | 156 ----- src/avr/shared/ps2_emu.cpp | 240 -------- src/avr/shared/usb.cpp | 14 - src/avr/uno/main/bootloader.c | 6 - src/avr/uno/main/main.cpp | 275 --------- src/avr/uno/usb/main.c | 658 ---------------------- src/avr/uno/usb/serial_descriptors.c | 123 ---- src/avr/uno/usb/serial_descriptors.h | 21 - src/avr/uno/usb/serial_macros.h | 66 --- 20 files changed, 3024 deletions(-) delete mode 100644 src/avr/lufa/LUFA.c delete mode 100644 src/avr/lufa/reboot.c delete mode 100644 src/avr/micro/detect/descriptors_detect.c delete mode 100644 src/avr/micro/detect/descriptors_detect.h delete mode 100644 src/avr/micro/detect/main.c delete mode 100644 src/avr/micro/main/main.cpp delete mode 100644 src/avr/micro/shared/bootloader.c delete mode 100644 src/avr/micro/shared/bootloader.h delete mode 100644 src/avr/shared/io.cpp delete mode 100644 src/avr/shared/io_define.h delete mode 100644 src/avr/shared/pins.cpp delete mode 100644 src/avr/shared/ps2_emu.cpp delete mode 100644 src/avr/shared/usb.cpp delete mode 100644 src/avr/uno/main/bootloader.c delete mode 100644 src/avr/uno/main/main.cpp delete mode 100644 src/avr/uno/usb/main.c delete mode 100644 src/avr/uno/usb/serial_descriptors.c delete mode 100644 src/avr/uno/usb/serial_descriptors.h delete mode 100644 src/avr/uno/usb/serial_macros.h diff --git a/platformio.ini b/platformio.ini index 1ce96c8bc..dc20a442f 100644 --- a/platformio.ini +++ b/platformio.ini @@ -2,243 +2,6 @@ extra_scripts = pre:ardwiino_script_pre.py post:ardwiino_script_post.py -[micro] -build_flags = - -DUSB_HOST_SERIAL=Serial1 - -I src/avr/micro/shared - -I src/avr/shared - -include include/LUFAConfig.h -platform = atmelavr -board = micro -framework = arduino -board_upload.detect_frequency = true -board_upload.ardwiino_bootloader = true -board_upload.wait_for_upload_port = false -build_src_filter = - + - + - + - + - + -platform_packages = - framework-arduino-avr @ https://github.com/Santroller/framework-arduino-avr/archive/refs/heads/main.zip@5.1.0 - platformio/tool-avrdude@1.70200.0 - platformio/toolchain-atmelavr@3.70300.220127 -check_skip_packages = yes -lib_ignore = - Wire -lib_deps = - felis/USB-Host-Shield-20 @ ^1.6.0 - -[env:microdetect] -build_flags = - ${micro.build_flags} - -D DETECT -build_src_filter = - + - + - + -platform = atmelavr -board = micro -framework = arduino -platform_packages = - framework-arduino-avr @ https://github.com/Santroller/framework-arduino-avr/archive/refs/heads/main.zip@5.1.0 - platformio/tool-avrdude@1.70200.0 - platformio/toolchain-atmelavr@3.70300.220127 -check_skip_packages = yes -board_upload.wait_for_upload_port = false - - -[env:arduino_leonardo] -board = leonardo -build_flags = ${micro.build_flags} -extends = micro -board_upload.wait_for_upload_port = false - -[env:arduino_micro] -build_flags = ${micro.build_flags} -extends = micro -board_upload.wait_for_upload_port = false - -[env:sparkfun_promicro] -board = sparkfun_promicro16 -build_flags = ${micro.build_flags} -extends = micro -board_upload.wait_for_upload_port = false - -[env:sparkfun_promicro_8] -extends = env:sparkfun_promicro -board_upload.wait_for_upload_port = false -board_upload.detect_frequency = false -board_build.f_cpu=8000000L - -[env:sparkfun_promicro_16] -extends = env:sparkfun_promicro -board_upload.wait_for_upload_port = false -board_upload.detect_frequency = false -board_build.f_cpu=16000000L - -[env:arduino_micro_8] -extends = env:arduino_micro -board_upload.wait_for_upload_port = false -board_upload.detect_frequency = false -board_build.f_cpu=8000000L - -[env:arduino_micro_16] -extends = env:arduino_micro -board_upload.wait_for_upload_port = false -board_upload.detect_frequency = false -board_build.f_cpu=16000000L - -[env:arduino_leonardo_8] -extends = env:arduino_leonardo -board_upload.wait_for_upload_port = false -board_upload.detect_frequency = false -board_build.f_cpu=8000000L - -[env:arduino_leonardo_16] -extends = env:arduino_leonardo -board_upload.wait_for_upload_port = false -board_upload.detect_frequency = false -board_build.f_cpu=16000000L - - -[arduino_uno_mega_usb_parent] -platform = atmelavr -board = uno -build_src_filter = - + - + - + -platform_packages = - framework-arduino-avr @ https://github.com/Santroller/framework-arduino-avr/archive/refs/heads/main.zip@5.1.0 - platformio/toolchain-atmelavr@3.70300.220127 - platformio/tool-avrdude@1.70200.0 -check_skip_packages = yes -build_flags = - -DBOARD=BOARD_UNO - -Wl,--section-start=.data=0x800282 - -ffixed-r2 - -ffixed-r3 - -ffixed-r4 - -ffixed-r5 - -ffixed-r6 - -flto - -fuse-linker-plugin - -include include/LUFAConfig.h -upload_protocol = custom -upload_flags = - -F - -C - ${platformio.packages_dir}/tool-avrdude/avrdude.conf - -p - ${BOARD_MCU} - -c - flip1 - -u -upload_command = "${platformio.packages_dir}/tool-avrdude/avrdude" $UPLOAD_FLAGS -U flash:w:$SOURCE:i -lib_deps = https://github.com/Santroller/pio-bare-lufa/archive/refs/heads/main.zip@1.0.0 - -[env:arduino_uno_usb] -extends = arduino_uno_mega_usb_parent -build_flags = - ${arduino_uno_mega_usb_parent.build_flags} - -DPID=0x0001 -board_upload.detect_controller = true - -[env:arduino_mega_2560_usb] -extends = arduino_uno_mega_usb_parent -build_flags = - ${arduino_uno_mega_usb_parent.build_flags} - -DPID=0x0010 -board_upload.detect_controller = true - -[env:arduino_mega_adk_usb] -extends = arduino_uno_mega_usb_parent -build_flags = - ${arduino_uno_mega_usb_parent.build_flags} - -DPID=0x003f -board_upload.detect_controller = true - - -[env:arduino_uno_usb_serial] -extends = arduino_uno_mega_usb_parent -build_flags = - ${arduino_uno_mega_usb_parent.build_flags} - -DPID=0x0001 - -DSERIAL_ONLY=true -board_upload.detect_controller = true - -[env:arduino_mega_2560_usb_serial] -extends = arduino_uno_mega_usb_parent -build_flags = - ${arduino_uno_mega_usb_parent.build_flags} - -DPID=0x0010 - -DSERIAL_ONLY=true -board_upload.detect_controller = true - -[env:arduino_mega_adk_usb_serial] -extends = arduino_uno_mega_usb_parent -build_flags = - ${arduino_uno_mega_usb_parent.build_flags} - -DPID=0x003f - -DSERIAL_ONLY=true -board_upload.detect_controller = true - -[uno] -build_flags = - -I src/avr/uno/shared - -I src/avr/shared -platform = atmelavr -framework = arduino -build_src_filter = - + - + - + - + -check_skip_packages = yes -board_upload.wait_for_upload_port = false -lib_ignore = - Wire -lib_deps = - sukkopera/PsxNewLib@^0.4.0 - felis/USB-Host-Shield-20 @ ^1.6.0 -platform_packages = - framework-arduino-avr @ https://github.com/Santroller/framework-arduino-avr/archive/refs/heads/main.zip@5.1.0 - platformio/toolchain-atmelavr@3.70300.220127 - platformio/tool-avrdude@1.70200.0 - -[env:arduino_uno] -extends = uno -board = uno -board_upload.wait_for_upload_port = false - -[env:arduino_mega] -extends = uno -board_upload.wait_for_upload_port = false -build_flags = - ${uno.build_flags} - -DUSART_RX_vect=USART0_RX_vect - -DUSART_UDRE_vect=USART0_UDRE_vect -board = megaatmega1280 - -[env:arduino_mega_2560] -extends = uno -board_upload.wait_for_upload_port = false -build_flags = - ${uno.build_flags} - -DUSART_RX_vect=USART0_RX_vect - -DUSART_UDRE_vect=USART0_UDRE_vect -board = megaatmega2560 - -[env:arduino_mega_adk] -extends = uno -board_upload.wait_for_upload_port = false -build_flags = - ${uno.build_flags} - -DUSART_RX_vect=USART0_RX_vect - -DUSART_UDRE_vect=USART0_UDRE_vect -board = megaADK ; Raspberry Pi Pico boards [pico_parent] diff --git a/src/avr/lufa/LUFA.c b/src/avr/lufa/LUFA.c deleted file mode 100644 index bee5b7311..000000000 --- a/src/avr/lufa/LUFA.c +++ /dev/null @@ -1,3 +0,0 @@ -#include "LUFAConfig.h" - -#include diff --git a/src/avr/lufa/reboot.c b/src/avr/lufa/reboot.c deleted file mode 100644 index 6d6d7d3ec..000000000 --- a/src/avr/lufa/reboot.c +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include -void reboot(void) { - cli(); - wdt_enable(WDTO_15MS); - for (;;) {} -} \ No newline at end of file diff --git a/src/avr/micro/detect/descriptors_detect.c b/src/avr/micro/detect/descriptors_detect.c deleted file mode 100644 index 074689a56..000000000 --- a/src/avr/micro/detect/descriptors_detect.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2013. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2013 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * USB Device Descriptors, for library use when in USB device mode. Descriptors are special - * computer-readable structures which the host requests upon device enumeration, to determine - * the device's capabilities and functions. - */ - -#include "descriptors_detect.h" - -#include "progmem.h" -#include "wcid.h" - -uint8_t realFreq = 16; -const OS_DESCRIPTOR OSDescriptorString = { - bLength : sizeof(OS_DESCRIPTOR), - bDescriptorType : DTYPE_String, - Signature : {'M', 'S', 'F', 'T', '1', '0', '0'}, - VendorCode : REQ_GET_OS_FEATURE_DESCRIPTOR, - Reserved : 0 -}; -const USB_Descriptor_Device_t DeviceDescriptor = - { - .Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device}, - - .USBSpecification = VERSION_BCD(2, 0, 0), - .Class = 0x02, - .SubClass = 0x00, - .Protocol = 0x00, - - .Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE, - - .VendorID = 0x1209, - - .ProductID = 0x2886, - .ReleaseNumber = 0x0001, - - .ManufacturerStrIndex = STRING_ID_Manufacturer, - .ProductStrIndex = STRING_ID_Product, - .SerialNumStrIndex = USE_INTERNAL_SERIAL, - - .NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS}; - -const USB_Descriptor_Configuration_t ConfigurationDescriptor = - { - .Config = - { - .Header = {.Size = sizeof(USB_Descriptor_Configuration_Header_t), .Type = DTYPE_Configuration}, - - .TotalConfigurationSize = sizeof(USB_Descriptor_Configuration_t), - .TotalInterfaces = 1, - - .ConfigurationNumber = 1, - .ConfigurationStrIndex = NO_DESCRIPTOR, - - .ConfigAttributes = 0, - - .MaxPowerConsumption = USB_CONFIG_POWER_MA(100)}, - .Interface = { - Header : - {Size : sizeof(USB_Descriptor_Interface_t), Type : DTYPE_Interface}, - InterfaceNumber : INTERFACE_ID_Device, - AlternateSetting : 0, - TotalEndpoints : 0, - Class : 0xFF, - SubClass : 0xFF, - Protocol : 0xFF, - InterfaceStrIndex : NO_DESCRIPTOR - }, -}; - -/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests - * the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate - * via the language ID table available at USB.org what languages the device supports for its string descriptors. - */ -const USB_Descriptor_String_t LanguageString = - { - .Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String}, - - .UnicodeString = {LANGUAGE_ID_ENG}}; - -/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable - * form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device - * Descriptor. - */ -const USB_Descriptor_String_t ManufacturerString = - { - .Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String}, - - .UnicodeString = L"sanjay900"}; - -/** Product descriptor string. This is a Unicode string containing the product's details in human readable form, - * and is read out upon request by the host when the appropriate string ID is requested, listed in the Device - * Descriptor. - */ -const USB_Descriptor_String_t ProductString16 = - { - .Header = {.Size = USB_STRING_LEN(56), .Type = DTYPE_String}, - - .UnicodeString = L"Ardwiino - Detect - 16000000"}; - -const USB_Descriptor_String_t ProductString8 = - { - .Header = {.Size = USB_STRING_LEN(54), .Type = DTYPE_String}, - - .UnicodeString = L"Ardwiino - Detect - 8000000"}; - -/** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors" - * documentation) by the application code so that the address and size of a requested descriptor can be given - * to the USB library. When the device receives a Get Descriptor request on the control endpoint, this function - * is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the - * USB host. - */ -uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, - const uint16_t wIndex, - const void** const DescriptorAddress) { - const uint8_t DescriptorType = (wValue >> 8); - const uint8_t DescriptorNumber = (wValue & 0xFF); - - const void* Address = NULL; - uint16_t Size = NO_DESCRIPTOR; - - switch (DescriptorType) { - case DTYPE_Device: - Address = &DeviceDescriptor; - Size = sizeof(USB_Descriptor_Device_t); - break; - case DTYPE_Configuration: - Address = &ConfigurationDescriptor; - Size = sizeof(USB_Descriptor_Configuration_t); - break; - case DTYPE_String: - switch (DescriptorNumber) { - case STRING_ID_Language: - Address = &LanguageString; - Size = LanguageString.Header.Size; - break; - case STRING_ID_Manufacturer: - Address = &ManufacturerString; - Size = ManufacturerString.Header.Size; - break; - case STRING_ID_Product: - if (realFreq == 16) { - Address = &ProductString16; - Size = ProductString16.Header.Size; - } else { - Address = &ProductString8; - Size = ProductString8.Header.Size; - } - break; - case 0xEE: - Address = &OSDescriptorString; - Size = OSDescriptorString.bLength; - break; - } - - break; - } - - *DescriptorAddress = Address; - return Size; -} diff --git a/src/avr/micro/detect/descriptors_detect.h b/src/avr/micro/detect/descriptors_detect.h deleted file mode 100644 index 3b1be7b2c..000000000 --- a/src/avr/micro/detect/descriptors_detect.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2013. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2013 Dean Camera (dean [at] fourwalledcubicle [dot] com) - - Permission to use, copy, modify, distribute, and sell this - software and its documentation for any purpose is hereby granted - without fee, provided that the above copyright notice appear in - all copies and that both that the copyright notice and this - permission notice and warranty disclaimer appear in supporting - documentation, and that the name of the author not be used in - advertising or publicity pertaining to distribution of the - software without specific, written prior permission. - - The author disclaims all warranties with regard to this - software, including all implied warranties of merchantability - and fitness. In no event shall the author be liable for any - special, indirect or consequential damages or any damages - whatsoever resulting from loss of use, data or profits, whether - in an action of contract, negligence or other tortious action, - arising out of or in connection with the use or performance of - this software. -*/ - -/** \file - * - * Header file for Descriptors.c. - */ - -#ifndef _DESCRIPTORS_H_ -#define _DESCRIPTORS_H_ - -/* Includes: */ -#include "progmem.h" - -#include "endpoints.h" -#include "LUFAConfig.h" -#include - - -/* Type Defines: */ -/** Type define for the device configuration descriptor structure. This must be defined in the - * application code, as the configuration descriptor contains several sub-descriptors which - * vary between devices, and which describe the device's usage to the host. - */ -typedef struct -{ - USB_Descriptor_Configuration_Header_t Config; - - USB_Descriptor_Interface_t Interface; -} USB_Descriptor_Configuration_t; - -/** Enum for the device string descriptor IDs within the device. Each string descriptor should - * have a unique ID index associated with it, which can be used to refer to the string from - * other descriptors. - */ -enum StringDescriptors_t { - STRING_ID_Language = 0, /**< Supported Languages string descriptor ID (must be zero) */ - STRING_ID_Manufacturer = 1, /**< Manufacturer string ID */ - STRING_ID_Product = 2, /**< Product string ID */ -}; -extern uint8_t realFreq; -#endif diff --git a/src/avr/micro/detect/main.c b/src/avr/micro/detect/main.c deleted file mode 100644 index 4fe559a02..000000000 --- a/src/avr/micro/detect/main.c +++ /dev/null @@ -1,115 +0,0 @@ -/** - * You should have a LUFAConfig.h for this to work. - */ - -/** - * Include LUFA.h after LUFAConfig.h - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "commands.h" - -#include "bootloader.h" -#include "descriptors_detect.h" -#include "wcid.h" - -void SetupHardware(void); -char freqString[10]; -volatile bool waiting = true; - -const OS_COMPATIBLE_ID_DESCRIPTOR_SINGLE DevCompatIDs = { - TotalLength : sizeof(OS_COMPATIBLE_ID_DESCRIPTOR_SINGLE), - Version : 0x0100, - Index : DESC_EXTENDED_COMPATIBLE_ID_DESCRIPTOR, - TotalSections : 1, - Reserved : {0}, - CompatID : { - { - FirstInterfaceNumber : INTERFACE_ID_Device, - Reserved : 0x04, - CompatibleID : "WINUSB", - SubCompatibleID : {0}, - Reserved2 : {0} - }} -}; -void setup() { - GlobalInterruptEnable(); // enable global interrupts - wdt_reset(); - // Enable the watchdog timer, as it runs from an internal clock so it will not be affected by the crystal - MCUSR &= ~_BV(WDRF); - /* Start the WDT Config change sequence. */ - WDTCSR |= _BV(WDCE) | _BV(WDE); - /* Configure the prescaler and the WDT for interrupt mode only*/ - WDTCSR = _BV(WDIE) | WDTO_15MS; - sei(); - long timeSinceWDT = millis(); - while (waiting) { - } - timeSinceWDT = millis() - timeSinceWDT; - realFreq = 16; - // And now compare to what we expect - if (F_CPU == 16000000 && timeSinceWDT < 10) { - // if the user is running at 8mhz, then it will run at half speed, thus it will take less than 15ms - realFreq = 8; - } - PLLCSR = 0; - if (realFreq == 8) { - PLLCSR = (0 | (1 << PLLE)); - } else if (realFreq == 16) { - PLLCSR = ((1 << PINDIV) | (1 << PLLE)); - } - itoa(realFreq, freqString, 10); - freqString[strlen(freqString)] = '\n'; - SetupHardware(); // ask LUFA to setup the hardware -} - -void loop() { -} - -/** Configures the board hardware and chip peripherals for the demo's functionality. */ -void SetupHardware(void) { - /* Disable watchdog if enabled by bootloader/fuses */ - MCUSR &= ~(1 << WDRF); - wdt_disable(); - - /* Disable clock division */ - clock_prescale_set(clock_div_1); - - /* Hardware Initialization */ - USB_Init(); -} - -ISR(WDT_vect) { - wdt_disable(); - waiting = false; -} - -/** Event handler for the library USB Configuration Changed event. */ -void EVENT_USB_Device_ConfigurationChanged(void) { -} - -/** Event handler for the library USB Control Request reception event. */ -void EVENT_USB_Device_ControlRequest(void) { - if (USB_ControlRequest.bmRequestType == 0xC0 && USB_ControlRequest.bRequest == REQ_GET_OS_FEATURE_DESCRIPTOR && USB_ControlRequest.wIndex == DESC_EXTENDED_COMPATIBLE_ID_DESCRIPTOR) { - Endpoint_ClearSETUP(); - Endpoint_Write_Control_Stream_LE(&DevCompatIDs, sizeof(DevCompatIDs)); - Endpoint_ClearStatusStage(); - } - if (USB_ControlRequest.bmRequestType == 0x21) { - if (USB_ControlRequest.bRequest == COMMAND_REBOOT) { - reboot(); - } - if (USB_ControlRequest.bRequest == COMMAND_JUMP_BOOTLOADER) { - bootloader(); - } - } -} diff --git a/src/avr/micro/main/main.cpp b/src/avr/micro/main/main.cpp deleted file mode 100644 index 684529188..000000000 --- a/src/avr/micro/main/main.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/** - * You should have a LUFAConfig.h for this to work. - */ - -#include "LUFAConfig.h" -/** - * Include LUFA.h after LUFAConfig.h - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "commands.h" -#include "config.h" -#include "descriptors.h" -#include "hid.h" -#include "shared_main.h" - -typedef struct -{ - USB_Descriptor_Header_t Header; - uint16_t UnicodeString[(INTERNAL_SERIAL_LENGTH_BITS / 4) + 4]; -} __attribute__((packed)) SignatureDescriptor_t; -volatile uint16_t persistedConsoleType __attribute__((section(".noinit"))); -volatile uint16_t persistedConsoleTypeValid __attribute__((section(".noinit"))); -void SetupHardware(void); - -bool connected = false; -void EVENT_USB_Device_Connect(void) { -} - -void EVENT_USB_Device_Disconnect(void) { - connected = false; -} - -bool usb_configured() { - return connected; -} - -void setup() { - arcadeSide = EEPROM.read(0); - if (arcadeSide > 2) { - arcadeSide = 1; - } - init_main(); - if (persistedConsoleTypeValid == 0x3A2F) { - consoleType = persistedConsoleType; - } else { - consoleType = 0; - } - GlobalInterruptEnable(); // enable global interrupts - SetupHardware(); // ask LUFA to setup the hardware -} -void setArcadeSide(uint8_t side) { - arcadeSide = side; - EEPROM.write(0, side); -} - -uint8_t buf[255]; -void loop() { - tick(); - Endpoint_SelectEndpoint(DEVICE_EPADDR_OUT); - if (Endpoint_IsOUTReceived()) { - if (Endpoint_IsReadWriteAllowed()) { - uint8_t size = Endpoint_BytesInEndpoint(); - Endpoint_Read_Stream_LE(buf, size, NULL); - hid_set_report(buf, size, INTERRUPT_ID, INTERRUPT_ID); - } - Endpoint_ClearOUT(); - } -} -bool ready_for_next_packet() { - Endpoint_SelectEndpoint(DEVICE_EPADDR_IN); - return Endpoint_IsINReady(); -} -void send_report_to_pc(const void* report, uint8_t len) { - Endpoint_SelectEndpoint(DEVICE_EPADDR_IN); - Endpoint_Write_Stream_LE(report, len, NULL); - Endpoint_ClearIN(); -} - -void SetupHardware(void) { - /* Disable watchdog if enabled by bootloader/fuses */ - MCUSR &= ~(1 << WDRF); - wdt_disable(); - - /* Disable clock division */ - clock_prescale_set(clock_div_1); - - /* Hardware Initialization */ - USB_Init(); -} - -void EVENT_USB_Device_ControlRequest(void) { - if (controlRequestValid(USB_ControlRequest.bmRequestType, USB_ControlRequest.bRequest, USB_ControlRequest.wValue, USB_ControlRequest.wIndex, USB_ControlRequest.wLength)) { - if ((USB_ControlRequest.bmRequestType & CONTROL_REQTYPE_DIRECTION) == (REQDIR_DEVICETOHOST)) { - uint16_t len = controlRequest(USB_ControlRequest.bmRequestType, USB_ControlRequest.bRequest, USB_ControlRequest.wValue, USB_ControlRequest.wIndex, USB_ControlRequest.wLength, buf, NULL); - if (len) { - Endpoint_ClearSETUP(); - Endpoint_Write_Control_Stream_LE(buf, len); - Endpoint_ClearStatusStage(); - } - } else { - Endpoint_ClearSETUP(); - Endpoint_Read_Control_Stream_LE(buf, USB_ControlRequest.wLength); - controlRequest(USB_ControlRequest.bmRequestType, USB_ControlRequest.bRequest, USB_ControlRequest.wValue, USB_ControlRequest.wIndex, USB_ControlRequest.wLength, buf, NULL); - Endpoint_ClearStatusStage(); - } - } -} -void EVENT_USB_Device_ConfigurationChanged(void) { - uint8_t type = EP_TYPE_INTERRUPT; - uint8_t epsize = 0x20; - uint8_t epsizeOut = 0x08; - if (consoleType == WINDOWS || consoleType == XBOX360) { - epsizeOut = 0x20; - } - if (consoleType == MIDI_ID) { - type = EP_TYPE_BULK; - } - Endpoint_ConfigureEndpoint(DEVICE_EPADDR_IN, type, epsize, 2); - Endpoint_ConfigureEndpoint(DEVICE_EPADDR_OUT, type, epsizeOut, 2); - connected = true; -} - -static void USB_Device_GetInternalSerialDescriptor(void) { - SignatureDescriptor_t* desc = (SignatureDescriptor_t*)buf; - desc->Header.Type = DTYPE_String; - desc->Header.Size = USB_STRING_LEN((INTERNAL_SERIAL_LENGTH_BITS / 4) + 4); - - uint_reg_t CurrentGlobalInt = GetGlobalInterruptMask(); - GlobalInterruptDisable(); - - uint8_t SigReadAddress = INTERNAL_SERIAL_START_ADDRESS; - - for (uint8_t SerialCharNum = 0; SerialCharNum < (INTERNAL_SERIAL_LENGTH_BITS / 4); SerialCharNum++) { - uint8_t SerialByte = boot_signature_byte_get(SigReadAddress); - - if (SerialCharNum & 0x01) { - SerialByte >>= 4; - SigReadAddress++; - } - - SerialByte &= 0x0F; - - desc->UnicodeString[SerialCharNum] = cpu_to_le16((SerialByte >= 10) ? (('A' - 10) + SerialByte) : ('0' + SerialByte)); - } - - SetGlobalInterruptMask(CurrentGlobalInt); - - desc->UnicodeString[(INTERNAL_SERIAL_LENGTH_BITS / 4)] = '3'; - desc->UnicodeString[(INTERNAL_SERIAL_LENGTH_BITS / 4) + 1] = consoleType + '0'; -#if DEVICE_TYPE_IS_GAMEPAD - desc->UnicodeString[(INTERNAL_SERIAL_LENGTH_BITS / 4) + 2] = DEVICE_TYPE + '0'; - desc->UnicodeString[(INTERNAL_SERIAL_LENGTH_BITS / 4) + 3] = WINDOWS_USES_XINPUT + '0'; -#else - desc->UnicodeString[(INTERNAL_SERIAL_LENGTH_BITS / 4) + 2] = 'K'; - desc->UnicodeString[(INTERNAL_SERIAL_LENGTH_BITS / 4) + 3] = '0'; -#endif -} - -uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, - const uint16_t wIndex, - const void** const descriptorAddress) { - *descriptorAddress = buf; - if (wValue == ((DTYPE_String << 8) | 3)) { - USB_Device_GetInternalSerialDescriptor(); - return sizeof(SignatureDescriptor_t); - } - return descriptorRequest(wValue, wIndex, buf); -} -void reset_usb(void) { - persistedConsoleType = consoleType; - persistedConsoleTypeValid = 0x3A2F; - reboot(); -} \ No newline at end of file diff --git a/src/avr/micro/shared/bootloader.c b/src/avr/micro/shared/bootloader.c deleted file mode 100644 index fb421fcbd..000000000 --- a/src/avr/micro/shared/bootloader.c +++ /dev/null @@ -1,13 +0,0 @@ -#include -#include "endpoints.h" -#define MAGIC_KEY_POS 0x0800 -#define MAGIC_KEY 0x7777 -volatile uint16_t *const bootKeyPtr = (volatile uint16_t *)MAGIC_KEY_POS; -uint16_t bootKeyVal; - -void bootloader(void) { - // write magic key to ram - *bootKeyPtr = MAGIC_KEY; - - reboot(); -} \ No newline at end of file diff --git a/src/avr/micro/shared/bootloader.h b/src/avr/micro/shared/bootloader.h deleted file mode 100644 index 8bd77d0eb..000000000 --- a/src/avr/micro/shared/bootloader.h +++ /dev/null @@ -1,5 +0,0 @@ -#include -#include "endpoints.h" -#define MAGIC_KEY_POS 0x0800 -#define MAGIC_KEY 0x7777 -void bootloader(void); diff --git a/src/avr/shared/io.cpp b/src/avr/shared/io.cpp deleted file mode 100644 index 5ed86c328..000000000 --- a/src/avr/shared/io.cpp +++ /dev/null @@ -1,595 +0,0 @@ -#include "io.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "wii.h" - -#include "config.h" -#include "util.h" -#ifndef TWI_BUFFER_LENGTH -#include "string.h" -#define TWI_BUFFER_LENGTH 32 -#endif - -#define TWI_READY 0 -#define TWI_MRX 1 -#define TWI_MTX 2 -#define TWI_SRX 3 -#define TWI_STX 4 -volatile bool spi_acknowledged = false; - -static volatile uint8_t twi_state; -static volatile uint8_t twi_slarw; -static volatile uint8_t twi_sendStop; // should the transaction end with a stop -static volatile uint8_t twi_inRepStart; // in the middle of a repeated start - -static uint8_t twi_masterBuffer[TWI_BUFFER_LENGTH]; -static volatile uint8_t twi_masterBufferIndex; -static volatile uint8_t twi_masterBufferLength; - -static volatile uint8_t twi_error; -static volatile unsigned int twi_reg_addr; - -static volatile unsigned char twi_first_addr_flag; // set address flag -static volatile unsigned char twi_rw_len; // length of most recent operation -void uart_begin() { - // TODO: no -} - -bool read_uart(UART_BLOCK block, uint8_t header, uint8_t size, uint8_t *dest) -{ - // TODO: no again - return false; -} -void send_uart(UART_BLOCK block, uint8_t *data, uint8_t size) { - - // TODO: no again part 2 -} -void spi_begin() { -#ifdef GC_SPI_CLOCK - uint8_t clockDiv; - if (GC_SPI_CLOCK >= F_CPU / 2) { - clockDiv = 0; - } else if (GC_SPI_CLOCK >= F_CPU / 4) { - clockDiv = 1; - } else if (GC_SPI_CLOCK >= F_CPU / 8) { - clockDiv = 2; - } else if (GC_SPI_CLOCK >= F_CPU / 16) { - clockDiv = 3; - } else if (GC_SPI_CLOCK >= F_CPU / 32) { - clockDiv = 4; - } else if (GC_SPI_CLOCK >= F_CPU / 64) { - clockDiv = 5; - } else { - clockDiv = 7; - } - - // Invert the SPI2X bit - clockDiv ^= 0x1; - - uint8_t config = 0; -#if GC_SPI_CPHA == 1 - config |= _BV(CPHA); -#endif -#if GC_SPI_CPOL == 1 - config |= _BV(CPOL); -#endif -#if GC_SPI_MSBFIRST == 0 - config |= _BV(DORD); -#endif - SPCR = _BV(SPE) | _BV(MSTR) | config | ((clockDiv >> 1) & 0x03); - SPSR = clockDiv & 0x01; -#endif -} -uint8_t spi_transfer(SPI_BLOCK block, uint8_t data) { - SPDR = data; - asm volatile("nop"); - while (!(SPSR & _BV(SPIF))); - return SPDR; -} -void spi_high(SPI_BLOCK block) {} -void twi_init() { -#ifdef GC_TWI_CLOCK - twi_state = TWI_READY; - twi_sendStop = true; // default value - twi_inRepStart = false; - -// // activate internal pullups for twi. -#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || \ - defined(__AVR_ATmega328P__) - // activate internal pull-ups for twi - // as per note from atmega8 manual pg167 - sbi(PORTC, 4); - sbi(PORTC, 5); -#else - // activate internal pull-ups for twi - // as per note from atmega128 manual pg204 - sbi(PORTD, 0); - sbi(PORTD, 1); -#endif - - // initialize twi prescaler and bit rate - cbi(TWSR, TWPS0); - cbi(TWSR, TWPS1); -// No idea why, but the wii stuff just isnt stable at higher speeds than 15 on the 5v devices -// That does still end up being ~363636hz, which is pretty close to the 400000hz target -#if F_CPU == 16000000UL -#if ((F_CPU / GC_TWI_CLOCK) - 16) / 2 > 16 - TWBR = ((F_CPU / GC_TWI_CLOCK) - 16) / 2; -#else - TWBR = 16; -#endif -#else -// note: TWBR should be 10 or higher for master mode -#if ((F_CPU / GC_TWI_CLOCK) - 16) / 2 > 10 - TWBR = ((F_CPU / GC_TWI_CLOCK) - 16) / 2; -#else - TWBR = 10; -#endif -#endif - // enable twi module, acks, and twi interrupt - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); -#endif -#ifdef GC_TWI_RX - twi_reg_addr = 0; - - // set slave address - TWAR = WII_ADDR << 1; - - // enable twi module, acks, and twi interrupt - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA); -#endif -} - -#ifdef PS2_ACK -ISR(INTERRUPT_PS2_ACK_VECT) { - spi_acknowledged = true; -} -void init_ack() { - cli(); - EICRA |= INTERRUPT_PS2_ACK_EICRA; - EIMSK |= _BV(INTERRUPT_PS2_ACK); - sei(); -} -#endif - - -// === MODIFIED === -static uint16_t TIMEOUT = 32767; - -bool twi_readFromPointerSlow(TWI_BLOCK block, uint8_t address, uint8_t pointer, uint8_t length, - uint8_t *data) { - if (!twi_writeTo(block, address, &pointer, 1, true, true)) return false; - _delay_us(180); - return twi_readFrom(block, address, data, length, true); -} -bool twi_readFrom(TWI_BLOCK block, uint8_t address, uint8_t *data, uint8_t length, - uint8_t sendStop) { - // ensure data will fit into buffer - if (TWI_BUFFER_LENGTH < length) return 0; - - uint16_t timeoutCounter; - - // === MODIFIED === - // wait until twi is ready, become master receiver - if (TIMEOUT == 0) { - while (TWI_READY != twi_state) continue; - } else { - timeoutCounter = TIMEOUT; - while (TWI_READY != twi_state) { - //_delay_ms( TIMEOUT_TICK ); - timeoutCounter--; - if (timeoutCounter == 0) return 0; - } - } - /* - // wait until twi is ready, become master receiver - while(TWI_READY != twi_state){ - continue; - } - */ - - twi_state = TWI_MRX; - twi_sendStop = sendStop; - // reset error state (0xFF.. no error occured) - twi_error = 0xFF; - - // initialize buffer iteration vars - twi_masterBufferIndex = 0; - twi_masterBufferLength = length - 1; // This is not intuitive, read on... - // On receive, the previously configured ACK/NACK setting is transmitted in - // response to the received byte before the interrupt is signalled. - // Therefor we must actually set NACK when the _next_ to last byte is - // received, causing that NACK to be sent in response to receiving the last - // expected byte of data. - - // build sla+w, slave device address + w bit - twi_slarw = TW_READ; - twi_slarw |= address << 1; - - if (twi_inRepStart) { - // if we're in the repeated start state, then we've already sent the start, - // (@@@ we hope), and the TWI statemachine is just waiting for the address - // byte. We need to remove ourselves from the repeated start state before we - // enable interrupts, since the ISR is ASYNC, and we could get confused if - // we hit the ISR before cleaning up. Also, don't enable the START - // interrupt. There may be one pending from the repeated start that we sent - // ourselves, and that would really confuse things. - twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR - - // === MODIFIED === - if (TIMEOUT == 0) { - do { - TWDR = twi_slarw; - } while (TWCR & _BV(TWWC)); - } else { - timeoutCounter = TIMEOUT; - TWDR = twi_slarw; - while (TWCR & _BV(TWWC)) { - //_delay_ms( TIMEOUT_TICK ); - timeoutCounter--; - if (timeoutCounter == 0) return false; - TWDR = twi_slarw; - } - } - /* - do { - TWDR = twi_slarw; - } while(TWCR & _BV(TWWC)); - */ - TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | - _BV(TWIE); // enable INTs, but not START - } else { - // send start condition - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTA); - } - - // === MODIFIED === - // wait for read operation to complete - if (TIMEOUT == 0) { - while (TWI_MRX == twi_state) continue; - } else { - timeoutCounter = TIMEOUT; - while (TWI_MRX == twi_state) { - //_delay_ms( TIMEOUT_TICK ); - timeoutCounter--; - if (timeoutCounter == 0) return false; - } - } - /* - // wait for read operation to complete - while(TWI_MRX == twi_state){ - continue; - } - */ - - if (twi_masterBufferIndex < length) length = twi_masterBufferIndex; - // copy twi buffer to data - memcpy(data, twi_masterBuffer, length); - - return length; -} - -bool twi_writeTo(TWI_BLOCK block, uint8_t address, uint8_t *data, uint8_t length, uint8_t wait, - uint8_t sendStop) { - // ensure data will fit into buffer - if (TWI_BUFFER_LENGTH < length) return false; - - // === MODIFIED === - uint16_t timeoutCounter; - // wait until twi is ready, become master transmitter - if (TIMEOUT == 0) { - while (TWI_READY != twi_state) continue; - } else { - timeoutCounter = TIMEOUT; - while (TWI_READY != twi_state) { - //_delay_ms( TIMEOUT_TICK ); - timeoutCounter--; - if (timeoutCounter == 0) return false; - } - } - /* - // wait until twi is ready, become master transmitter - while( TWI_READY != twi_state ) { - continue; - } - */ - - twi_state = TWI_MTX; - twi_sendStop = sendStop; - // reset error state (0xFF.. no error occured) - twi_error = 0xFF; - - // initialize buffer iteration vars - twi_masterBufferIndex = 0; - twi_masterBufferLength = length; - - // copy data to twi buffer - memcpy(twi_masterBuffer, data, length); - // build sla+w, slave device address + w bit - twi_slarw = TW_WRITE; - twi_slarw |= address << 1; - - // if we're in a repeated start, then we've already sent the START - // in the ISR. Don't do it again. - if (twi_inRepStart) { - // if we're in the repeated start state, then we've already sent the start, - // (@@@ we hope), and the TWI statemachine is just waiting for the address - // byte. We need to remove ourselves from the repeated start state before we - // enable interrupts, since the ISR is ASYNC, and we could get confused if - // we hit the ISR before cleaning up. Also, don't enable the START - // interrupt. There may be one pending from the repeated start that we sent - // outselves, and that would really confuse things. - twi_inRepStart = false; // remember, we're dealing with an ASYNC ISR - - // === MODIFIED === - if (TIMEOUT == 0) { - do { - TWDR = twi_slarw; - } while (TWCR & _BV(TWWC)); - } else { - timeoutCounter = TIMEOUT; - TWDR = twi_slarw; - while (TWCR & _BV(TWWC)) { - //_delay_ms( TIMEOUT_TICK ); - timeoutCounter--; - if (timeoutCounter == 0) return false; - TWDR = twi_slarw; - } - } - /* - do { - TWDR = twi_slarw; - } while(TWCR & _BV(TWWC)); - */ - - TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | - _BV(TWIE); // enable INTs, but not START - } else { - // send start condition - TWCR = _BV(TWINT) | _BV(TWEA) | _BV(TWEN) | _BV(TWIE) | - _BV(TWSTA); // enable INTs - } - - // === MODIFIED === - // wait for write operation to complete - if (TIMEOUT == 0) { - while (wait && (TWI_MTX == twi_state)) continue; - } else { - timeoutCounter = TIMEOUT; - while (wait && (TWI_MTX == twi_state)) { - //_delay_ms( TIMEOUT_TICK ); - timeoutCounter--; - if (timeoutCounter == 0) return false; - } - } - /* - // wait for write operation to complete - while(wait && (TWI_MTX == twi_state)){ - continue; - }*/ - - return twi_error == 0xFF; -} - -void twi_reply(uint8_t ack) { - // transmit master read ready signal, with or without ack - if (ack) { - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT) | _BV(TWEA); - } else { - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWINT); - } -} - -void twi_releaseBus(void) { - // release bus - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT); - - // update twi state - twi_state = TWI_READY; -} - -bool twi_stop(void) { - // send stop condition - TWCR = _BV(TWEN) | _BV(TWIE) | _BV(TWEA) | _BV(TWINT) | _BV(TWSTO); - - // === MODIFIED === - // wait for stop condition to be exectued on bus - // TWINT is not set after a stop condition! - if (TIMEOUT == 0) { - while (TWCR & _BV(TWSTO)) continue; - } else { - uint16_t timeoutCounter = TIMEOUT; - while (TWCR & _BV(TWSTO)) { - //_delay_ms( TIMEOUT_TICK ); - timeoutCounter--; - if (timeoutCounter == 0) return false; - } - } - /* - while(TWCR & _BV(TWSTO)){ - continue; - } - */ - - // update twi state - twi_state = TWI_READY; - return true; -} - -ISR(TWI_vect) { - switch (TW_STATUS) { - // All Master - case TW_START: // sent start condition - case TW_REP_START: // sent repeated start condition - // copy device address and r/w bit to output register and ack - TWDR = twi_slarw; - twi_reply(1); - break; - - // Master Transmitter - case TW_MT_SLA_ACK: // slave receiver acked address - case TW_MT_DATA_ACK: // slave receiver acked data - // if there is data to send, send it, otherwise stop - if (twi_masterBufferIndex < twi_masterBufferLength) { - // copy data to output register and ack - TWDR = twi_masterBuffer[twi_masterBufferIndex++]; - twi_reply(1); - } else { - if (twi_sendStop) - twi_stop(); - else { - twi_inRepStart = true; // we're gonna send the START - // don't enable the interrupt. We'll generate the start, but we - // avoid handling the interrupt until we're in the next transaction, - // at the point where we would normally issue the start. - TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); - twi_state = TWI_READY; - } - } - break; - case TW_MT_SLA_NACK: // address sent, nack received - twi_error = TW_MT_SLA_NACK; - twi_stop(); - break; - case TW_MT_DATA_NACK: // data sent, nack received - twi_error = TW_MT_DATA_NACK; - twi_stop(); - break; - case TW_MT_ARB_LOST: // lost bus arbitration - twi_error = TW_MT_ARB_LOST; - twi_releaseBus(); - break; - - // Master Receiver - case TW_MR_DATA_ACK: // data received, ack sent - // put byte into buffer - twi_masterBuffer[twi_masterBufferIndex++] = TWDR; - case TW_MR_SLA_ACK: // address sent, ack received - // ack if more bytes are expected, otherwise nack - if (twi_masterBufferIndex < twi_masterBufferLength) { - twi_reply(1); - } else { - twi_reply(0); - } - break; - case TW_MR_DATA_NACK: // data received, nack sent - // put final byte into buffer - twi_masterBuffer[twi_masterBufferIndex++] = TWDR; - if (twi_sendStop) - twi_stop(); - else { - twi_inRepStart = true; // we're gonna send the START - // don't enable the interrupt. We'll generate the start, but we - // avoid handling the interrupt until we're in the next transaction, - // at the point where we would normally issue the start. - TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN); - twi_state = TWI_READY; - } - break; - case TW_MR_SLA_NACK: // address sent, nack received - twi_stop(); - break; - // TW_MR_ARB_LOST handled by TW_MT_ARB_LOST case - - // All - case TW_NO_INFO: // no state information - break; - case TW_BUS_ERROR: // bus error, illegal stop/start - twi_error = TW_BUS_ERROR; - twi_stop(); - break; -#ifdef GC_TWI_RX - // Slave Rx - case TW_SR_SLA_ACK: // addressed, returned ack - case TW_SR_GCALL_ACK: // addressed generally, returned ack - case TW_SR_ARB_LOST_SLA_ACK: // lost arbitration, returned ack - case TW_SR_ARB_LOST_GCALL_ACK: // lost arbitration generally, returned ack - // get ready to receive pointer - twi_first_addr_flag = 0; - // ack - twi_reply(1); - break; - case TW_SR_DATA_ACK: // data received, returned ack - case TW_SR_GCALL_DATA_ACK: // data received generally, returned ack - if (twi_first_addr_flag != 0) { - // put byte in register - unsigned char t = TWDR; - twi_reg_addr++; - twi_rw_len++; - } else { - // set address - twi_reg_addr = TWDR; - twi_first_addr_flag = 1; - twi_rw_len = 0; - } - twi_reply(1); // ack - break; - case TW_SR_STOP: // stop or repeated start condition received - // run user defined function - recv_end(twi_reg_addr - twi_rw_len, twi_rw_len); - twi_reply(1); // ack future responses - break; - case TW_SR_DATA_NACK: // data received, returned nack - case TW_SR_GCALL_DATA_NACK: // data received generally, returned nack - twi_reply(0); // nack back at master - break; - - // Slave Tx - case TW_ST_SLA_ACK: // addressed, returned ack - case TW_ST_ARB_LOST_SLA_ACK: // arbitration lost, returned ack - twi_rw_len = 0; - case TW_ST_DATA_ACK: // byte sent, ack returned - // ready output byte - TWDR = req_data(twi_reg_addr); - twi_reg_addr++; - twi_rw_len++; - twi_reply(1); // ack - break; - case TW_ST_DATA_NACK: // received nack, we are done - case TW_ST_LAST_DATA: // received ack, but we are done already! - // ack future responses - twi_reply(1); - break; - default: - twi_reply(0); - break; -#endif - } -} -#define INTERNAL_SERIAL_START_ADDRESS 0x0E -void read_serial(uint8_t *id, uint8_t len) { - uint8_t oldSREG = SREG; - cli(); - - uint8_t SigReadAddress = INTERNAL_SERIAL_START_ADDRESS; - - for (uint8_t SerialCharNum = 0; SerialCharNum < len; SerialCharNum++) { - uint8_t SerialByte = boot_signature_byte_get(SigReadAddress); - - if (SerialCharNum & 0x01) { - SerialByte >>= 4; - SigReadAddress++; - } - - SerialByte &= 0x0F; - - id[SerialCharNum] = (SerialByte >= 10) ? (('A' - 10) + SerialByte) : ('0' + SerialByte); - } - - SREG = oldSREG; -} -void go_to_sleep() { - // TODO: sleep is current pico only. -} -void wakeup_360() { - // TODO: waking up the 360 is pico only. -} \ No newline at end of file diff --git a/src/avr/shared/io_define.h b/src/avr/shared/io_define.h deleted file mode 100644 index f6bc9d2d5..000000000 --- a/src/avr/shared/io_define.h +++ /dev/null @@ -1,46 +0,0 @@ -#include -#ifdef __AVR_ATmega328P__ -#define NUM_TOTAL_PINS 24 -#define PORT_COUNT 3 -#define PORTS \ - { (uint16_t) &PORTB, (uint16_t)&PORTC, (uint16_t)&PORTD } -// PC0-5 -#define ANALOG_MASK \ - { 0, 0b11111, 0 } -#define ANALOG_PORT(chan) &PORTC -#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) -#define NUM_TOTAL_PINS 70 -#define PORT_COUNT 11 -#define PORTS \ - { (uint16_t) &PORTA, (uint16_t)&PORTB, (uint16_t)&PORTC, (uint16_t)&PORTD, (uint16_t)&PORTE, (uint16_t)&PORTF, (uint16_t)&PORTG, (uint16_t)&PORTH, (uint16_t)&PORTJ, (uint16_t)&PORTK, (uint16_t)&PORTL } -// PF and PK -#define ANALOG_MASK \ - { 0, 0, 0, 0, 0, 0xff, 0, 0, 0, 0xff, 0 } -#define ANALOG_PORT(chan) chan <= 7 ? &PORTF : &PORTK -#elif defined(__AVR_ATmega32U4__) -#define NUM_TOTAL_PINS 24 -#define PORT_COUNT 5 -#define PORTS \ - { (uint16_t) &PORTB, (uint16_t)&PORTC, (uint16_t)&PORTD, (uint16_t)&PORTE, (uint16_t)&PORTF } -// PF0-1 PF4-7 PB4-6 PD4,6,7 -#define ANALOG_MASK \ - { 0b0001111, 0, 0b00001011, 0, 0b1101111 } -#define ANALOG_PORT(chan) chan <= 7 ? &PORTF : (chan <= 10 ? &PORTD : &PORTB) -#elif defined(__AVR_AT90USB1286__) -#define NUM_TOTAL_PINS 44 -#define PORT_COUNT 6 -#define PORTS \ - { (uint16_t) &PORTA, (uint16_t) &PORTB, (uint16_t)&PORTC, (uint16_t)&PORTD, (uint16_t)&PORTE, (uint16_t)&PORTF } -// PF -#define ANALOG_MASK \ - { 0, 0, 0, 0, 0, 0xff } -#define ANALOG_PORT(chan) &PORTF -#endif - - -#define TWI_BLOCK void* -#define SPI_BLOCK void* -#define UART_BLOCK void* -#define GC_TWI NULL -#define GC_SPI NULL -#define GC_UART NULL \ No newline at end of file diff --git a/src/avr/shared/pins.cpp b/src/avr/shared/pins.cpp deleted file mode 100644 index cee2eb1e8..000000000 --- a/src/avr/shared/pins.cpp +++ /dev/null @@ -1,156 +0,0 @@ -#include -#include -#include - -#include "Arduino.h" -#include "config.h" -#include "io_define.h" -#include "progmem.h" -#include "util.h" - -volatile uint16_t adcReading[ADC_COUNT]; -const uint8_t analogPins[ADC_COUNT] = ADC_PINS; -const uint16_t PROGMEM ports[PORT_COUNT] = PORTS; -uint16_t adc(uint8_t pin) { - return adcReading[pin]; -} - -uint8_t digital_read(uint8_t port_num, uint8_t mask) { - volatile uint8_t* port = ((volatile uint8_t*)(pgm_read_word(ports + port_num))); - volatile uint8_t* ddr = port - 1; - volatile uint8_t* pin = port - 2; - uint8_t prevPort = *port; - uint8_t prevDdr = *ddr; - uint8_t oldSREG = SREG; - cli(); - // Set direction to input - *ddr &= ~mask; - // Enable pullup - *port |= mask; - delay(10); - uint8_t data = *pin; - // Revert the settings we changed - *port = prevPort; - *ddr = prevDdr; - SREG = oldSREG; - return data; -} - -void digital_write(uint8_t port_num, uint8_t mask, uint8_t activeMask) { - volatile uint8_t* port = ((volatile uint8_t*)(pgm_read_word(ports + port_num))); - volatile uint8_t* ddr = port - 1; - uint8_t oldSREG = SREG; - cli(); - // set pins in mask to output - *ddr |= mask; - *port &= ~mask; - // And then drive them high / low as necessary - *port |= activeMask; - SREG = oldSREG; -} - -uint16_t adc_read(uint8_t pin, uint8_t mask) { -#if ADC_COUNT != 0 - cbi(ADCSRA, ADIE); - while (bit_is_set(ADCSRA, ADSC)) - ; -#endif - // bit 7 is used as a flag for pin detection mode - bool detection = pin & (1 << 7); - pin &= ~(1 << 7); - - // When we are not doing pin detection, we don't want to be fiddling with the ports - volatile uint8_t* port = ANALOG_PORT(pin); - volatile uint8_t* ddr = port - 1; - uint8_t prevPort = *port; - uint8_t prevDdr = *ddr; - if (detection) { - uint8_t oldSREG = SREG; - cli(); - // Clear DDRx (input) - *ddr &= ~mask; - // Set PORTx (pull_up) - *port |= mask; - SREG = oldSREG; - } -#if defined(ADCSRB) && defined(MUX5) - // the MUX5 bit of ADCSRB selects whether we're reading from channels - // 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high). - ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5); -#endif - - // set the analog reference (high two bits of ADMUX) and select the - // channel (low 4 bits). this also sets ADLAR (left-adjust result) - // to 0 (the default). - - ADMUX = (1 << 6) | (pin & 0x07); - - // Give things time to settle - delayMicroseconds(10); - sbi(ADCSRA, ADSC); - while (bit_is_set(ADCSRA, ADSC)) - ; - uint16_t data = ADC << 6; - if (detection) { - // Revert the settings we changed - uint8_t oldSREG = SREG; - cli(); - *port = prevPort; - *ddr = prevDdr; - SREG = oldSREG; - } -#if ADC_COUNT != 0 - sbi(ADCSRA, ADIE); - sbi(ADCSRA, ADSC); -#endif - return data; -} -void initPins(void) { - PIN_INIT; - sbi(ADCSRA, ADPS2); - cbi(ADCSRA, ADPS1); - cbi(ADCSRA, ADPS0); -#if ADC_COUNT != 0 - uint8_t pin = analogPins[0]; - -#if defined(ADCSRB) && defined(MUX5) - // the MUX5 bit of ADCSRB selects whether we're reading from channels - // 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high). - ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5); -#endif - - // set the analog reference (high two bits of ADMUX) and select the - // channel (low 4 bits). this also sets ADLAR (left-adjust result) - // to 0 (the default). - - ADMUX = (1 << 6) | (pin & 0x07); - - sbi(ADCSRA, ADIE); - sbi(ADCSRA, ADSC); -#endif -} -int currentAnalog = 0; -#if ADC_COUNT != 0 -ISR(ADC_vect) { - adcReading[currentAnalog] = ADC << 6; - currentAnalog++; - if (currentAnalog == ADC_COUNT) { - currentAnalog = 0; - } - uint8_t pin = analogPins[currentAnalog]; - -#if defined(ADCSRB) && defined(MUX5) - // the MUX5 bit of ADCSRB selects whether we're reading from channels - // 0 to 7 (MUX5 low) or 8 to 15 (MUX5 high). - ADCSRB = (ADCSRB & ~(1 << MUX5)) | (((pin >> 3) & 0x01) << MUX5); -#endif - - // set the analog reference (high two bits of ADMUX) and select the - // channel (low 4 bits). this also sets ADLAR (left-adjust result) - // to 0 (the default). - - ADMUX = (1 << 6) | (pin & 0x07); - - sbi(ADCSRA, ADSC); -} -#endif \ No newline at end of file diff --git a/src/avr/shared/ps2_emu.cpp b/src/avr/shared/ps2_emu.cpp deleted file mode 100644 index af6caebb0..000000000 --- a/src/avr/shared/ps2_emu.cpp +++ /dev/null @@ -1,240 +0,0 @@ -#include - -#include "Arduino.h" -#include "config.h" -#include "io.h" -#include "ps2.h" -#include "util.h" - -#ifdef TICK_PS2 - -uint8_t configMode = 0; -uint8_t mode = 0x41; - -uint8_t receiveCommand() { - uint8_t modeByte = configMode ? 0xF3 : mode; - PS2_OUTPUT_ACK_SET(); - uint8_t ret = spi_transfer(PS2_OUTPUT_SPI_PORT, 0xFF); - PS2_OUTPUT_ACK_CLEAR(); - sleep_us(2); - PS2_OUTPUT_ACK_SET(); - if (ret != 1) { - return 0; - } - ret = spi_transfer(PS2_OUTPUT_SPI_PORT, mode); - PS2_OUTPUT_ACK_CLEAR(); - return ret; -} -uint8_t receiveAll(uint8_t* data, uint8_t len) { - for (int i = 0; i < len - 1; i++) { - PS2_OUTPUT_ACK_SET(); - data[i] = spi_transfer(PS2_OUTPUT_SPI_PORT, data[i]); - PS2_OUTPUT_ACK_CLEAR(); - sleep_us(2); - } - PS2_OUTPUT_ACK_SET(); - data[len - 1] = spi_transfer(PS2_OUTPUT_SPI_PORT, data[len - 1]); - return len; -} -uint8_t receiveAll2(uint8_t* data0, uint8_t* data1, uint8_t len) { - uint8_t* data = data0; - for (int i = 0; i < len - 1; i++) { - PS2_OUTPUT_ACK_SET(); - data0[i] = spi_transfer(PS2_OUTPUT_SPI_PORT, data[i]); - if (data0[1] == 1) { - data = data1; - } - PS2_OUTPUT_ACK_CLEAR(); - } - PS2_OUTPUT_ACK_SET(); - data[len - 1] = spi_transfer(PS2_OUTPUT_SPI_PORT, data[len - 1]); - return len; -} -int counter = 0; - -uint8_t buttons1 = 0xff; -uint8_t buttons2 = 0xff; - -uint8_t motorSetting1 = 0xff; -uint8_t motorSetting2 = 0xff; - -bool analogEnabled = 0; - -int timeoutCounter = 0; -uint8_t cmd; -uint8_t param1; -uint8_t param2; -uint8_t param3; -void ps2_emu_init() { - PS2_OUTPUT_ACK_SET(); - cmd = 0; - param1 = 0; - param2 = 0; - param3 = 0; -// Guitars need to hold dpad left -#if DEVICE_TYPE_IS_GUITAR - buttons1 &= ~0x80; -#endif - -} -bool ps2_emu_tick(PS2_REPORT* report) { - if (PS2_OUTPUT_ATT_READ()) { - timeoutCounter++; - if (timeoutCounter >= 30000) // we've been disconnected - { - mode = 0x41; - motorSetting1 = 0xff; - motorSetting2 = 0xff; - analogEnabled = 0; - configMode = 0; - timeoutCounter = 0; - } - return false; - } - timeoutCounter = 0; - while (1) { - cmd = receiveCommand(); - if (!cmd) - break; - - if (configMode) { - switch (cmd) { - case 0x40: { - uint8_t data[] = {0x5A, 0x00, 0x00, 0x02, 0x00, 0x00, 0x5A}; - receiveAll(data, sizeof(data)); - break; - } - case 0x41: // check response data - if (analogEnabled == 1) { - // button pressures byte mask, appears after 0x44 is called - uint8_t data[] = {0x5A, 0xFF, 0xFF, 0x03, 0x00, 0x00, 0x5A}; - receiveAll(data, sizeof(data)); - } else { - uint8_t data[] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - receiveAll(data, sizeof(data)); - } - break; - case 0x42: { - uint8_t data[] = {0x5A, buttons1, buttons2}; - receiveAll(data, sizeof(data)); - break; - } - case 0x43: { // exit config mode - uint8_t data[] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - receiveAll(data, sizeof(data)); - if (data[1] == 0) { - configMode = 0; - } - break; - } - case 0x44: { // turn on analog mode - uint8_t data[] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - receiveAll(data, sizeof(data)); - param1 = data[1]; - if (param1 == 1) { - mode = 0x73; - analogEnabled = 1; - } else { - mode = 0x41; // no analog button pressures - analogEnabled = 0; - } - break; - } - case 0x45: { // query model - if (analogEnabled) { - uint8_t data[] = {0x5A, 0x01, 0x02, 0x01, 0x02, 0x01, 0x00}; - receiveAll(data, sizeof(data)); - } else { - uint8_t data[] = {0x5A, 0x01, 0x02, 0x00, 0x02, 0x01, 0x00}; - receiveAll(data, sizeof(data)); - } - break; - } - case 0x46: { - uint8_t data0[] = {0x5A, 0x00, 0x00, 0x01, 0x02, 0x00, 0x0F}; - uint8_t data1[] = {0x5A, 0x00, 0x00, 0x01, 0x01, 0x01, 0x0F}; - receiveAll2(data0, data1, sizeof(data0)); - break; - } - case 0x47: { - uint8_t data[] = {0x5A, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00}; - receiveAll(data, sizeof(data)); - break; - } - case 0x4C: { - uint8_t data0[] = {0x5A, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00}; - uint8_t data1[] = {0x5A, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00}; - receiveAll2(data0, data1, sizeof(data0)); - break; - } - case 0x4D: { // setup motors - uint8_t data[] = {0x5A, motorSetting1, motorSetting2, 0xFF, 0xFF, 0xFF, 0xFF}; - receiveAll(data, sizeof(data)); - motorSetting1 = data[1]; - motorSetting2 = data[2]; - break; - } - case 0x4F: { // set pressure byte mask, extended pressures - mode = 0x79; // analog button pressures - uint8_t data[] = {0x5A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A}; - receiveAll(data, sizeof(data)); - break; - } - } - while (!PS2_OUTPUT_ATT_READ()) { - sleep_us(20); // conservative so we aren't still in ATT low at the top of the loop - } - continue; - } else { - if (mode == 0x41) // digital only - { - uint8_t data[3] = {0x5A}; - memcpy(data, report, sizeof(data)); - // Buttons are inverted - data[1] ^= 0xFF; - data[2] ^= 0xFF; - receiveAll(data, sizeof(data)); - param1 = data[1]; - param2 = data[2]; - } - if (mode == 0x73) // digital buttons, analog joysticks - { - uint8_t data[7] = {0x5A}; - memcpy(data, report, sizeof(data)); - // Buttons are inverted - data[1] ^= 0xFF; - data[2] ^= 0xFF; - receiveAll(data, sizeof(data)); - param1 = data[1]; - } - if (mode == 0x79) // analog joysticks, analog buttons - { - uint8_t data[19] = {0x5A}; - memcpy(data, report, sizeof(data)); - // Buttons are inverted - data[1] ^= 0xFF; - data[2] ^= 0xFF; - receiveAll(data, sizeof(data)); - param1 = data[1]; - } - // cmd should usually be 0x42 for polling - if (cmd == 0x43) { - if (param1 == 0x01) { - configMode = 1; - while (!PS2_OUTPUT_ATT_READ()) { - sleep_us(20); // conservative so we aren't still in ATT low at the top of the loop - } - continue; - } - } - break; - } - } - PS2_OUTPUT_ACK_SET(); - - while (!PS2_OUTPUT_ATT_READ()) { - sleep_us(20); // conservative so we aren't still in ATT low at the top of the loop - } - return true; -} -#endif diff --git a/src/avr/shared/usb.cpp b/src/avr/shared/usb.cpp deleted file mode 100644 index 717020bed..000000000 --- a/src/avr/shared/usb.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include "defines.h" -#if USB_HOST_STACK -void send_report_to_controller(uint8_t deviceType, const uint8_t *report, uint8_t len) { -} -USB_Device_Type_t get_device_address_for(uint8_t deviceType) { - return 0; -} -uint32_t transfer_with_usb_controller(const uint8_t dev_addr, const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, uint8_t *buffer, bool* status) { - return 0; -} -#endif -void authentication_successful() { -} \ No newline at end of file diff --git a/src/avr/uno/main/bootloader.c b/src/avr/uno/main/bootloader.c deleted file mode 100644 index 1707900e1..000000000 --- a/src/avr/uno/main/bootloader.c +++ /dev/null @@ -1,6 +0,0 @@ -void bootloader(void) { - // Handled by 8u2 / 16u2 -} -void reboot(void) { - // Handled by 8u2 / 16u2 -} \ No newline at end of file diff --git a/src/avr/uno/main/main.cpp b/src/avr/uno/main/main.cpp deleted file mode 100644 index e40b810e9..000000000 --- a/src/avr/uno/main/main.cpp +++ /dev/null @@ -1,275 +0,0 @@ -#include -#include -#include -#include -#include - -#include "Usb.h" -#include "commands.h" -#include -#include "config.h" -#include "defines.h" -#include "descriptors.h" -#include "hid.h" -#include "packets.h" -#include "reports/controller_reports.h" -#include "shared_main.h" -#define INTERNAL_SERIAL_START_ADDRESS 0x0E -#define INTERNAL_SERIAL_LENGTH_BITS 80 -/** \name Control Request Data Direction Masks */ -/**@{*/ -/** Request data direction mask, indicating that the request data will flow from host to device. - * - * \see \ref CONTROL_REQTYPE_DIRECTION macro. - */ -#define REQDIR_HOSTTODEVICE (0 << 7) - -/** Request data direction mask, indicating that the request data will flow from device to host. - * - * \see \ref CONTROL_REQTYPE_DIRECTION macro. - */ -#define REQDIR_DEVICETOHOST (1 << 7) -typedef struct -{ - uint8_t Size; /**< Size of the descriptor, in bytes. */ - uint8_t Type; /**< Type of the descriptor, either a value in \ref USB_DescriptorTypes_t or a value - * given by the specific class. - */ -} __attribute__((packed)) USB_Descriptor_Header_t; -typedef struct -{ - USB_Descriptor_Header_t Header; - uint16_t UnicodeString[(INTERNAL_SERIAL_LENGTH_BITS / 4) + 4]; -} __attribute__((packed)) SignatureDescriptor_t; - -volatile uint16_t persistedConsoleType __attribute__((section(".noinit"))); -volatile uint16_t persistedConsoleTypeValid __attribute__((section(".noinit"))); -SignatureDescriptor_t signature; -// Set up some arrays for storing received data / data to transmit -uint8_t buf[255]; -uint8_t buf2[255]; - -// Flag for if we have received a packet that needs to be processed -volatile bool ready = false; - -// pointer to data to send, along with the length of the data remaining to send -uint8_t* bufTX; -uint8_t idxTX = 0; - -// Some reinterpretations of the data receive / send array, so we can easily read and write packets -packet_header_t* header = (packet_header_t*)buf; -descriptor_request_t* desc = (descriptor_request_t*)buf; -control_request_t* ctr = (control_request_t*)buf; -data_transmit_packet_t* dt = (data_transmit_packet_t*)buf; - -// If we have been ticked by usb for new data, then this will be true -bool has_previous_data = false; -uint8_t previous_data_len = 0; -// reset_usb is called by other parts of the code if we need to trigger a usb reload -// we just trigger a flag here, as we can send it on our next usb transfer -bool should_reload_usb = false; -bool usb_ready = false; - -static void USB_Device_GetInternalSerialDescriptor(void) { - signature.Header.Type = 0x03; - signature.Header.Size = sizeof(SignatureDescriptor_t); - - uint8_t CurrentGlobalInt = SREG; - cli(); - - uint8_t SigReadAddress = INTERNAL_SERIAL_START_ADDRESS; - - for (uint8_t SerialCharNum = 0; SerialCharNum < (INTERNAL_SERIAL_LENGTH_BITS / 4); SerialCharNum++) { - uint8_t SerialByte = boot_signature_byte_get(SigReadAddress); - - if (SerialCharNum & 0x01) { - SerialByte >>= 4; - SigReadAddress++; - } - - SerialByte &= 0x0F; - - signature.UnicodeString[SerialCharNum] = (SerialByte >= 10) ? (('A' - 10) + SerialByte) : ('0' + SerialByte); - } - - SREG = CurrentGlobalInt; - signature.UnicodeString[(INTERNAL_SERIAL_LENGTH_BITS / 4)] = '3'; - signature.UnicodeString[(INTERNAL_SERIAL_LENGTH_BITS / 4) + 1] = consoleType + '0'; - -#if DEVICE_TYPE_IS_GAMEPAD - signature.UnicodeString[(INTERNAL_SERIAL_LENGTH_BITS / 4) + 2] = DEVICE_TYPE + '0'; - signature.UnicodeString[(INTERNAL_SERIAL_LENGTH_BITS / 4) + 3] = WINDOWS_USES_XINPUT + '0'; -#else - signature.UnicodeString[(INTERNAL_SERIAL_LENGTH_BITS / 4) + 2] = 'K'; - signature.UnicodeString[(INTERNAL_SERIAL_LENGTH_BITS / 4) + 3] = '0'; -#endif -} - -void reset_usb(void) { - persistedConsoleType = consoleType; - persistedConsoleTypeValid = 0x3A2F; - should_reload_usb = true; - USB_Device_GetInternalSerialDescriptor(); -} - -bool usb_configured(void) { - return usb_ready; -} - -void setup() { - arcadeSide = EEPROM.read(0); - if (arcadeSide > 2) { - arcadeSide = 1; - } - // Configure the UART for controller mode - UBRR0 = SERIAL_2X_UBBRVAL(BAUD); - UCSR0C = ((1 << UCSZ01) | (1 << UCSZ00)); - UCSR0A = (1 << U2X0); - UCSR0B = ((1 << TXEN0) | (1 << RXCIE0) | (1 << RXEN0)); - interrupts(); - - // Let the 8u2/16u2 know we are ready to receive data - UDR0 = READY; - init_main(); - if (persistedConsoleTypeValid == 0x3A2F) { - consoleType = persistedConsoleType; - } else { - consoleType = 0; - } - USB_Device_GetInternalSerialDescriptor(); -} -void setArcadeSide(uint8_t side) { - arcadeSide = side; - EEPROM.write(0, side); -} -bool ready_for_next_packet() { - return !has_previous_data; -} -void send_report_to_pc(const void* report, uint8_t len) { - // Write the controller input data - memcpy(buf2, report, len); - previous_data_len = len; - has_previous_data = true; -} -void loop() { - // Wait for a packet from the 8u2/16u2. - if (!ready) { - if (!usb_ready) { - // tick controller when usb isn't ready for console bindings. - tick(); - } - return; - } - ready = false; - // Now handle the packet - switch (header->id) { - case USB_READY: - usb_ready = dt->data[0]; - return; - case CONTROLLER_DATA_TRANSMIT_ID: - // We received a hid out request, we need to process it - hid_set_report(dt->data, header->len - sizeof(packet_header_t), INTERRUPT_ID, INTERRUPT_ID); - header->len = 0; - break; - case CONTROLLER_DATA_REQUEST_ID: { - header->len = 0; - tick(); - if (has_previous_data) { - has_previous_data = false; - memcpy(buf + sizeof(packet_header_t), buf2, previous_data_len); - header->len = previous_data_len; - } - break; - } - case DESCRIPTOR_ID: { - // Wlength will be overwritten in descriptorRequest so cache it - uint16_t wLength = desc->wLength; - // 8u2/16u2 wants a descriptor, so return it - // Serial number string descriptor, return one we prepared earlier - if (desc->wValue == ((0x03 << 8) | 3)) { - memcpy(dt->data, &signature, sizeof(SignatureDescriptor_t)); - uint16_t len = sizeof(SignatureDescriptor_t); - if (len > wLength) len = wLength; - header->len = len; - break; - } - uint16_t len = descriptorRequest(desc->wValue, desc->wIndex, dt->data); - if (len > wLength) len = wLength; - header->len = len; - break; - } - case CONTROL_REQUEST_VALIDATION_ID: { - // 8u2/16u2 wants to know if we handle a descriptor, so let it know that - bool valid = controlRequestValid(ctr->bmRequestType, ctr->request, ctr->wValue, ctr->wIndex, ctr->wLength); - dt->data[0] = valid; - header->len = 1; - break; - } - case CONTROL_REQUEST_ID: { - // Wlength will be overwritten in descriptorRequest so cache it - uint16_t wLength = ctr->wLength; - // Some of our commands really need up to date data, so do another poll. - if (ctr->request >= COMMAND_REBOOT && ctr->request < MAX) { - tick(); - } - uint8_t* buf = dt->data; - if ((ctr->bmRequestType & REQDIR_DEVICETOHOST) == REQDIR_HOSTTODEVICE) { - buf = ctr->data; - } - // 8u2/16u2 wants us to handle a control request. - uint16_t len = controlRequest(ctr->bmRequestType, ctr->request, ctr->wValue, ctr->wIndex, ctr->wLength, buf, NULL); - if (len > wLength) len = wLength; - header->len = len; - break; - } - case DEVICE_ID: - usb_ready = true; - // 8u2/16u2 wants to know the console type, so return that - dt->data[0] = consoleType; - header->len = 1; - break; - default: - // unknown packet, do nothing - return; - } - // We are reloading usb, so instead of sending data back, let the 8u2/16u2 know we want usb reset - if (should_reload_usb) { - header->id = CONTROLLER_DATA_RESTART_USB_ID; - header->len = 0; - should_reload_usb = false; - } - // Send back any data in the buffers. enable the interrupt for pushing out data - bufTX = buf; - idxTX = header->len + sizeof(packet_header_t); - UCSR0B = (_BV(RXCIE0) | _BV(TXEN0) | _BV(RXEN0) | _BV(UDRIE0)); -} - -// Data receive interrupt -// Keep track of what we have read so far -uint8_t idx = 0; -ISR(USART_RX_vect, ISR_BLOCK) { - buf[idx] = UDR0; - // Wait for something that looks like the start of a packet - if (idx == 0 && buf[0] != VALID_PACKET) { - return; - } - // We found the start of a packet, so read the header and then use the length from that to read the entire packet into buf - idx++; - if (idx >= sizeof(packet_header_t) && header->len == idx) { - // We are done. reset for the next packet, and let the main loop know there is something to do - idx = 0; - ready = true; - return; - } -} - -// Data transmit interrupt -ISR(USART_UDRE_vect, ISR_BLOCK) { - if (idxTX--) { - // There is something to send still, so send that byte, and decrement the count of bytes - UDR0 = *(bufTX++); - } else { - // We are out of things to send, disable this interrupt - UCSR0B = (_BV(RXCIE0) | _BV(TXEN0) | _BV(RXEN0)); - } -} diff --git a/src/avr/uno/usb/main.c b/src/avr/uno/usb/main.c deleted file mode 100644 index c3254834d..000000000 --- a/src/avr/uno/usb/main.c +++ /dev/null @@ -1,658 +0,0 @@ -// This include needs to be at the top -#include "LUFAConfig.h" -// And then all others after it -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "commands.h" -#include "defines.h" -#include "endpoints.h" -#include "packets.h" -#include "progmem.h" -#include "serial_descriptors.h" -#include "serial_macros.h" -#define JUMP 0xDE00 - -/* USBtoUSART_WritePtr needs to be visible to ISR. */ -/* USARTtoUSB_ReadPtr needs to be visible to CDC LineEncoding Event. */ -volatile uint8_t USBtoUSART_WritePtr = 0; -volatile uint8_t USARTtoUSB_ReadPtr = 0; -static CDC_LineEncoding_t LineEncoding = {.BaudRateBPS = 0, - .CharFormat = CDC_LINEENCODING_OneStopBit, - .ParityType = CDC_PARITY_None, - .DataBits = 8}; - -// if bootloaderState is set to JUMP, then the arduino will jump to bootloader -// mode after the next watchdog reset -volatile uint16_t bootloaderState __attribute__((section(".noinit"))); -// Are we in usbserial mode or controller mode -bool serial = false; - -// Handle receiving data from the 328p during a control request -int handleControlRequest() { - register uint16_t tmp; - INIT_TMP_SERIAL_TO_USB(tmp); - uint8_t state = STATE_NO_PACKET; - uint8_t type; - uint8_t packetCount = 0; - while (true) { - WAIT_FOR_BYTES(tmp, 1); - register uint8_t data; - READ_BYTE_FROM_BUF(data, tmp); - // First we need to read out the packet header - if (state == STATE_NO_PACKET && data == VALID_PACKET) { - state = STATE_READ_PACKET_TYPE; - } else if (state == STATE_READ_PACKET_TYPE) { - type = data; - state = STATE_READ_LENGTH; - } else if (state == STATE_READ_LENGTH) { - if (type == CONTROL_REQUEST_VALIDATION_ID || type == DEVICE_ID) { - state = STATE_READ_AND_RETURN; - continue; - } - if (type == CONTROLLER_DATA_RESTART_USB_ID) { - // The 328p wants to restart the usb layer, so just reboot the microcontroller - bootloaderState = 0; - reboot(); - } - // For host to device requests, we don't have any more data to read as the host was writing the data - if ((USB_ControlRequest.bmRequestType & REQDIR_DEVICETOHOST) == REQDIR_HOSTTODEVICE) { - FINISH_READ(tmp); - return 0; - } - packetCount = data; - break; - } else if (state == STATE_READ_AND_RETURN) { - // We are done - FINISH_READ(tmp); - return data; - } - } - // Header is read, acknowledge the setup packet, and start writing bytes out from the circular buffer. - Endpoint_ClearSETUP(); - if (!packetCount) { - Endpoint_ClearIN(); - } - WAIT_FOR_BYTES(tmp, packetCount); - bool lastPacketFull = false; - while (packetCount || lastPacketFull) { - if (Endpoint_IsOUTReceived()) - break; - if (Endpoint_IsSETUPReceived()) - break; - - if (Endpoint_IsINReady()) { - uint16_t bytesInEndpoint = Endpoint_BytesInEndpoint(); - - while (packetCount && (bytesInEndpoint < USB_Device_ControlEndpointSize)) { - register uint8_t data; - READ_BYTE_FROM_BUF(data, tmp); - Endpoint_Write_8(data); - packetCount--; - bytesInEndpoint++; - } - - lastPacketFull = (bytesInEndpoint == USB_Device_ControlEndpointSize); - Endpoint_ClearIN(); - } - } - Endpoint_ClearStatusStage(); - // If the packet ends early, we still need to finish reading everything out of the buffer - while (packetCount--) { - register uint8_t data; - READ_BYTE_FROM_BUF(data, tmp); - } - FINISH_READ(tmp); - return 0; -} - -// Handle writing data for the controller endpoints (both in and out) -void handleControllerData() { - uint8_t txcount; - uint8_t type; - register uint16_t tmp; - uint8_t state = STATE_NO_PACKET; - INIT_TMP_SERIAL_TO_USB(tmp); - // Read the header - while (true) { - WAIT_FOR_BYTES(tmp, 1); - register uint8_t data; - READ_BYTE_FROM_BUF(data, tmp); - if (state == STATE_NO_PACKET && data == VALID_PACKET) { - state = STATE_READ_PACKET_TYPE; - } else if (state == STATE_READ_PACKET_TYPE) { - type = data; - state = STATE_READ_LENGTH; - } else if (state == STATE_READ_LENGTH) { - txcount = data; - // If the packet was host to device, than we are done here as the data was written already - if (type == CONTROLLER_DATA_TRANSMIT_ID) { - FINISH_READ(tmp); - // Acknowledge the packet - Endpoint_ClearOUT(); - return; - } - // If the packet is empty, stop - if (type == CONTROLLER_DATA_REQUEST_ID && !txcount) { - FINISH_READ(tmp); - return; - } - if (type == CONTROLLER_DATA_RESTART_USB_ID) { - reboot(); - } - break; - } - } - // This is device to host, so write out all the data to the endpoint - WAIT_FOR_BYTES(tmp, txcount); - while (txcount--) { - register uint8_t data; - READ_BYTE_FROM_BUF(data, tmp); - Endpoint_Write_8(data); - } - FINISH_READ(tmp); - // Acknowledge the packet - Endpoint_ClearIN(); -} -int main(void) { - // Handle jumping to different states depending on bootloaderState (which is preserved on a reboot) - if (bootloaderState == (JUMP | COMMAND_JUMP_BOOTLOADER)) { - // We don't want to jump again after the bootloader returns control flow to - // us - bootloaderState = 0; - asm volatile("jmp 0x1000"); - } - -#ifdef SERIAL_ONLY - serial = true; -#else - if (bootloaderState == (JUMP | COMMAND_JUMP_BOOTLOADER_UNO)) { - serial = true; - } -#endif - // We don't want to jump again after the bootloader returns control flow to - // us - bootloaderState = 0; - - /* Disable watchdog if enabled by bootloader/fuses */ - MCUSR &= ~(1 << WDRF); - wdt_disable(); - - clock_prescale_set(clock_div_1); - - // Configure the serial port for controller mode, usbserial mode will reconfigure it later - UCSR1C = ((1 << UCSZ11) | (1 << UCSZ10)); - UCSR1A = (1 << U2X1); - UCSR1B = ((1 << TXEN1) | (1 << RXEN1)); - UBRR1 = SERIAL_2X_UBBRVAL(BAUD); - - // Make sure that the 328p is fully reset, as it sends us the ready byte on bootup - AVR_RESET_LINE_DDR |= AVR_RESET_LINE_MASK; - AVR_RESET_LINE_PORT |= AVR_RESET_LINE_MASK; - _delay_ms(1); - AVR_RESET_LINE_PORT &= ~AVR_RESET_LINE_MASK; - _delay_ms(1); - AVR_RESET_LINE_PORT |= AVR_RESET_LINE_MASK; - - sei(); - if (serial) { - // Enable a timer to rapidly flush bytes over serial - TCCR0B = (1 << CS02); - } else { - // Wait for the 328p / 1280 to boot (we receive a READY byte) - // If we don't get it in time, we can assume the 328p is missing its firmware or has a wonky config and drop to the 328p programming mode - uint16_t count = 0; - uint8_t count2 = 0; - while (!(UCSR1A & (1 << RXC1)) || UDR1 != READY) { - count++; - if (count > 0xFFFE) { - count2++; - count = 0; - } - if (count2 > 0x2F) { - bootloaderState = (JUMP | COMMAND_JUMP_BOOTLOADER_UNO); - reboot(); - } - } - } - // Now that we have the ready byte above, we can turn on the serial receive interrupt handler - UCSR1B = ((1 << TXEN1) | (1 << RXCIE1) | (1 << RXEN1)); - - USB_Init(); - - // Loop for handling serial data - if (serial) { - while (true) { - USB_USBTask(); - // Send any data from the serial out buffer over USB - Endpoint_SelectEndpoint(DEVICE_EPADDR_IN); - if (Endpoint_IsINReady()) { - uint16_t tmp; - INIT_TMP_SERIAL_TO_USB(tmp); - uint8_t txcount; - uint8_t count = USARTtoUSB_WritePtr - USARTtoUSB_ReadPtr; - // Check if the UART receive buffer flush timer has expired or the buffer is nearly full - if (!((TIFR0 & (1 << TOV0)) || (count >= (SERIAL_TX_SIZE - 1)))) { - continue; - } - TIFR0 = (1 << TOV0); - txcount = SERIAL_TX_SIZE - 1; - if (txcount > count) { - txcount = count; - } - while (txcount--) { - register uint8_t data; - READ_BYTE_FROM_BUF(data, tmp); - Endpoint_Write_8(data); - } - // Save new pointer position - FINISH_READ(tmp); - Endpoint_ClearIN(); - } - - // Send any data received from usb to the serial in buffer - Endpoint_SelectEndpoint(DEVICE_EPADDR_OUT); - uint8_t countRX = 0; - if (Endpoint_IsOUTReceived()) { - // Check if we received any new bytes - countRX = Endpoint_BytesInEndpoint(); - - // Acknowledge zero length packet - if (!countRX) - Endpoint_ClearOUT(); - } - // Check if there is space for the data to receive - uint8_t USBtoUSART_free = (USB2USART_BUFLEN - 1) - ((USBtoUSART_WritePtr - USBtoUSART_ReadPtr) & (USB2USART_BUFLEN - 1)); - if (countRX && countRX <= USBtoUSART_free) { - // There is space, receive the data - uint16_t tmp; - INIT_TMP_USB_TO_SERIAL(tmp); - while (countRX--) { - register uint8_t data = Endpoint_Read_8(); - WRITE_BYTE_TO_BUF(data, tmp); - } - // Acknowledge the read - Endpoint_ClearOUT(); - FINISH_WRITE(tmp); - } - } - } - - // Controller mode, construct packets that we will need to send later - packet_header_t requestData = { - VALID_PACKET, CONTROLLER_DATA_REQUEST_ID, sizeof(packet_header_t)}; - packet_header_t tx_header = { - VALID_PACKET, CONTROLLER_DATA_TRANSMIT_ID, sizeof(packet_header_t)}; - - // Loop for handling controller mode - while (true) { - USB_USBTask(); - - // Check if the host is ready to receive a controller packet - Endpoint_SelectEndpoint(DEVICE_EPADDR_IN); - if (Endpoint_IsINReady()) { - // It is, request one from the 328p and then send it - uint16_t tmp; - INIT_TMP_USB_TO_SERIAL(tmp); - WRITE_ARRAY_TO_BUF(tmp, &requestData, sizeof(packet_header_t)); - - // Now wait for and process the response from the 328p - FINISH_WRITE(tmp); - handleControllerData(); - } - - // Check if the host has sent us a controller packet (for example, LEDs or other controller info) - Endpoint_SelectEndpoint(DEVICE_EPADDR_OUT); - if (Endpoint_IsOUTReceived()) { - // It has, send the packet to the 328p for processing - uint16_t tmp; - INIT_TMP_USB_TO_SERIAL(tmp); - uint8_t count = Endpoint_BytesInEndpoint(); - tx_header.len = sizeof(packet_header_t) + count; - WRITE_ARRAY_TO_BUF(tmp, &tx_header, sizeof(packet_header_t)); - // Check if the packet is empty or has data - if (Endpoint_IsReadWriteAllowed()) { - while (count--) { - register uint8_t data = Endpoint_Read_8(); - WRITE_BYTE_TO_BUF(data, tmp); - } - } - - // Now wait for and process the response from the 328p - FINISH_WRITE(tmp); - handleControllerData(); - } - } -} - -void write_ready(bool ready) { - uint16_t tmp; - INIT_TMP_USB_TO_SERIAL(tmp); - packet_header_t control_request_packet = {VALID_PACKET, USB_READY, sizeof(usb_ready_t)}; - WRITE_ARRAY_TO_BUF(tmp, &control_request_packet, sizeof(packet_header_t)); - WRITE_ARRAY_TO_BUF(tmp, &ready, 1); - FINISH_WRITE(tmp); -} - -void EVENT_USB_Device_Connect(void) { -} - -void EVENT_USB_Device_Disconnect(void) { - write_ready(false); -} - -void EVENT_USB_Device_ControlRequest(void) { - if (!(Endpoint_IsSETUPReceived())) return; - // Standard requests NEED to shortcut this system! - if ((USB_ControlRequest.bmRequestType & (REQTYPE_VENDOR | REQTYPE_CLASS)) == REQTYPE_STANDARD) { - return; - } - // Handle usbserial related control requests - if (serial) { - if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { - if (USB_ControlRequest.bRequest == CDC_REQ_SetLineEncoding) { - Endpoint_ClearSETUP(); - - /* Read the line coding data in from the host into the global struct */ - Endpoint_Read_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t)); - Endpoint_ClearIN(); - - // Handle the "1200bps touch" that pro micros use for jumping to the bootloader, only we reuse it here to jump to dfu moode - if (LineEncoding.BaudRateBPS == 1200) { - bootloaderState = (JUMP | COMMAND_JUMP_BOOTLOADER); - reboot(); - } else if (LineEncoding.BaudRateBPS == 2400) { - // And we have our own "2400bps touch" that just reboots, which will jump from usbserial back to controller mode - reboot(); - } - - /* Keep the TX line held high (idle) while the USART is reconfigured */ - PORTD |= (1 << 3); - - /* Flush data that was about to be sent. */ - USBtoUSART_ReadPtr = 0; - USBtoUSART_WritePtr = 0; - USARTtoUSB_ReadPtr = 0; - USARTtoUSB_WritePtr = 0; - - // Reconfigure the USART based on the LineEncoding - int8_t ConfigMask = 0; - - switch (LineEncoding.ParityType) { - case CDC_PARITY_Odd: - ConfigMask = ((1 << UPM11) | (1 << UPM10)); - break; - case CDC_PARITY_Even: - ConfigMask = (1 << UPM11); - break; - } - - if (LineEncoding.CharFormat == CDC_LINEENCODING_TwoStopBits) - ConfigMask |= (1 << USBS1); - - switch (LineEncoding.DataBits) { - case 6: - ConfigMask |= (1 << UCSZ10); - break; - case 7: - ConfigMask |= (1 << UCSZ11); - break; - case 8: - ConfigMask |= ((1 << UCSZ11) | (1 << UCSZ10)); - break; - } - - // Set the new baud rate before configuring the USART - uint8_t clockSpeed = (1 << U2X1); - uint16_t brr = SERIAL_2X_UBBRVAL(LineEncoding.BaudRateBPS); - - // No need U2X or cant have U2X. - if ((brr & 1) || (brr > 4095)) { - brr >>= 1; - clockSpeed = 0; - } - - // Or special case 57600 baud for compatibility with the ATmega328 bootloader. - else if (brr == SERIAL_2X_UBBRVAL(57600)) { - brr = SERIAL_UBBRVAL(57600); - clockSpeed = 0; - } - - UBRR1 = brr; - - // Reconfigure the USART - UCSR1C = ConfigMask; - UCSR1A = clockSpeed; - UCSR1B = ((1 << RXCIE1) | (1 << TXEN1) | (1 << RXEN1)); - - /* Release the TX line after the USART has been reconfigured */ - PORTD &= ~(1 << 3); - } else if (USB_ControlRequest.bRequest == CDC_REQ_SetControlLineState) { - Endpoint_ClearSETUP(); - Endpoint_ClearStatusStage(); - - // Handle the DTR line resetting the UNO, as the arduino uno uses this for programming - if (USB_ControlRequest.wValue & CDC_CONTROL_LINE_OUT_DTR) { - AVR_RESET_LINE_PORT &= ~AVR_RESET_LINE_MASK; - } else { - AVR_RESET_LINE_PORT |= AVR_RESET_LINE_MASK; - } - } - } else if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE) && USB_ControlRequest.bRequest == CDC_REQ_GetLineEncoding) { - // If the host requests the current line encoding return it - Endpoint_ClearSETUP(); - Endpoint_Write_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t)); - Endpoint_ClearOUT(); - } - - return; - } - // Handle control requests for controller mode - // We uses a few control requests to jump between different modes on the uno, so handle that here - if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE)) { - if (USB_ControlRequest.bRequest >= COMMAND_REBOOT && USB_ControlRequest.bRequest <= COMMAND_JUMP_BOOTLOADER_UNO_USB_THEN_SERIAL) { - Endpoint_ClearSETUP(); - Endpoint_ClearStatusStage(); - // We cheat a little and use the commands for jumping as flags for when to jump to different modes - bootloaderState = (JUMP | USB_ControlRequest.bRequest); - reboot(); - } - } - - // Ask the 328p if wants to handle a control request, by sending it a validation header and the control request header - uint16_t tmp; - INIT_TMP_USB_TO_SERIAL(tmp); - packet_header_t control_request_packet = {VALID_PACKET, CONTROL_REQUEST_VALIDATION_ID, sizeof(control_request_t)}; - WRITE_ARRAY_TO_BUF(tmp, &control_request_packet, sizeof(packet_header_t)); - WRITE_ARRAY_TO_BUF(tmp, &USB_ControlRequest, sizeof(USB_ControlRequest)); - FINISH_WRITE(tmp); - if (!handleControlRequest()) { - // It does not want to handle the control request, return - return; - } - - // Handle the control request - control_request_packet.id = CONTROL_REQUEST_ID; - - // For host to device requests, we also send the data itself so increase the length - if ((USB_ControlRequest.bmRequestType & REQDIR_DEVICETOHOST) == REQDIR_HOSTTODEVICE) { - control_request_packet.len += USB_ControlRequest.wLength; - } - WRITE_ARRAY_TO_BUF(tmp, &control_request_packet, sizeof(packet_header_t)); - WRITE_ARRAY_TO_BUF(tmp, &USB_ControlRequest, sizeof(USB_ControlRequest)); - // For host to device requests, send the data from the host - if ((USB_ControlRequest.bmRequestType & REQDIR_DEVICETOHOST) == REQDIR_HOSTTODEVICE) { - Endpoint_ClearSETUP(); - uint8_t Length = USB_ControlRequest.wLength; - if (!(Length)) - Endpoint_ClearOUT(); - - while (Length) { - if (Endpoint_IsOUTReceived()) { - while (Length && Endpoint_BytesInEndpoint()) { - register uint8_t data = Endpoint_Read_8(); - WRITE_BYTE_TO_BUF(data, tmp); - Length--; - } - - Endpoint_ClearOUT(); - } - } - Endpoint_ClearStatusStage(); - } - - // Now wait for and process the response from the 328p. - FINISH_WRITE(tmp); - handleControlRequest(); -} -void EVENT_USB_Device_ConfigurationChanged(void) { - if (serial) { - // Configure endpoints for usbserial mode - Endpoint_ConfigureEndpoint(DEVICE_EPADDR_IN, EP_TYPE_BULK, SERIAL_TX_SIZE, 1); - Endpoint_ConfigureEndpoint(DEVICE_EPADDR_OUT, EP_TYPE_BULK, SERIAL_RX_SIZE, 1); - Endpoint_ConfigureEndpoint(CDC_NOTIFICATION, EP_TYPE_INTERRUPT, SERIAL_NOTIFICATION_SIZE, 1); - return; - } - // When in controller mode, we need to ask the 328p what type of controller we are emulating, so we can configure the endpoints correctly - uint16_t tmp; - INIT_TMP_USB_TO_SERIAL(tmp); - packet_header_t packet = { - VALID_PACKET, DEVICE_ID, sizeof(packet_header_t)}; - WRITE_ARRAY_TO_BUF(tmp, &packet, sizeof(packet_header_t)); - - // Now wait for and process the response from the 328p - FINISH_WRITE(tmp); - uint8_t consoleType = handleControlRequest(); - - // Now that we have the console type, we can configure the endpoints accordingly - uint8_t type = EP_TYPE_INTERRUPT; - uint8_t epsize = 0x20; - uint8_t epsizeOut = 0x08; - if (consoleType == WINDOWS || consoleType == XBOX360) { - epsizeOut = 0x20; - } - if (consoleType == MIDI_ID) { - type = EP_TYPE_BULK; - } - Endpoint_ConfigureEndpoint(DEVICE_EPADDR_IN, type, epsize, 2); - Endpoint_ConfigureEndpoint(DEVICE_EPADDR_OUT, type, epsizeOut, 2); - return; -} - -uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue, - const uint16_t wIndex, - const void** const descriptorAddress) { - if (serial) { - // For usbserial mode, we have descriptors from "serial_descriptors.h" that we send - const uint8_t descriptorType = (wValue >> 8); - const void* address = NULL; - uint16_t size = 0; - - switch (descriptorType) { - case DTYPE_Device: - address = &usbSerialDeviceDescriptor; - size = sizeof(USB_Descriptor_Device_t); - break; - case DTYPE_Configuration: - address = &usbSerialConfigurationDescriptor; - size = sizeof(USB_Descriptor_Configuration_t); - break; - } - if (address) { - // To avoid needing to enable support for different descriptor areas - // we can write the descriptor outselves and act like we don't have a descriptor to write - Endpoint_ClearSETUP(); - Endpoint_Write_Control_PStream_LE(address, size); - Endpoint_ClearOUT(); - } - return 0; - } - // pass request to 328p / mega - descriptor_request_t packet = { - header : {VALID_PACKET, DESCRIPTOR_ID, sizeof(descriptor_request_t)}, - wValue : wValue, - wIndex : wIndex, - wLength : USB_ControlRequest.wLength - }; - uint16_t tmp; - INIT_TMP_USB_TO_SERIAL(tmp); - WRITE_ARRAY_TO_BUF(tmp, &packet, sizeof(descriptor_request_t)); - - // wait for a response from the 328p. At this point we can handle it exactly the same was as a control request - FINISH_WRITE(tmp); - handleControlRequest(); - return 0; -} - -/** ISR to manage the reception of data from the serial port, placing received - * bytes into a circular buffer for later transmission to the host. - */ -ISR(USART1_RX_vect, ISR_NAKED) { - // This ISR doesnt change SREG. Whoa. - asm volatile( - "lds r3, %[UDR1_Reg]\n\t" // (1) Load new Serial byte (UDR1) into r3 - "movw r4, r30\n\t" // (1) Backup Z pointer (r30 -> r4, r31 -> r5) - "in r30, %[writePointer]\n\t" // (1) Load USARTtoUSB write buffer 8 bit - // pointer to lower Z pointer - "ldi r31, 0x01\n\t" // (1) Set higher Z pointer to 0x01 - "st Z+, r3\n\t" // (2) Save UDR1 in Z pointer (USARTtoUSB write buffer) - // and increment - "out %[writePointer], r30\n\t" // (1) Save back new USARTtoUSB buffer - // pointer location - "movw r30, r4\n\t" // (1) Restore backuped Z pointer - "reti\n\t" // (4) Exit ISR - - // Inputs: - ::[UDR1_Reg] "m"(UDR1), // Memory location of UDR1 - [writePointer] "I"(_SFR_IO_ADDR( - USARTtoUSB_WritePtr)) // 8 bit pointer to USARTtoUSB write buffer - ); -} - -ISR(USART1_UDRE_vect, ISR_NAKED) { - // Another SREG-less ISR. - asm volatile( - "movw r4, r30\n\t" // (1) Backup Z pointer (r30 -> r4, r31 -> r5) - "in r30, %[readPointer]\n\t" // (1) Load USBtoUSART read buffer 8 bit - // pointer to lower Z pointer - "ldi r31, 0x02\n\t" // (1) Set higher Z pointer to 0x02 - "ld r3, Z+\n\t" // (2) Load next byte from USBtoUSART buffer into r3 - "sts %[UDR1_Reg], r3\n\t" // (2) Save r3 (next byte) in UDR1 - "out %[readPointer], r30\n\t" // (1) Save back new USBtoUSART read - // buffer pointer location - "cbi %[readPointer], 7\n\t" // (2) Wrap around for 128 bytes - // smart after-the-fact andi 0x7F without using SREG - "movw r30, r4\n\t" // (1) Restore backuped Z pointer - "in r2, %[readPointer]\n\t" // (1) Load USBtoUSART read buffer 8 bit - // pointer to r2 - "lds r3, %[writePointer]\n\t" // (1) Load USBtoUSART write buffer to r3 - "cpse r2, r3\n\t" // (1/2) Check if USBtoUSART read buffer == USBtoUSART - // write buffer - "reti\n\t" // (4) They are not equal, more bytes coming soon! - "ldi r30, 0x98\n\t" // (1) Set r30 temporary to new UCSR1B setting - // ((1< -#include "progmem.h" -#include "endpoints.h" - -typedef struct -{ - USB_Descriptor_Configuration_Header_t Config; - USB_Descriptor_Interface_t CDC_CCI_Interface; - USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header; - USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM; - USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union; - USB_Descriptor_Endpoint_t CDC_NotificationEndpoint; - USB_Descriptor_Interface_t CDC_DCI_Interface; - USB_Descriptor_Endpoint_t CDC_DataOutEndpoint; - USB_Descriptor_Endpoint_t CDC_DataInEndpoint; -} USB_Descriptor_Configuration_t; - -extern const USB_Descriptor_Device_t usbSerialDeviceDescriptor; - -extern const USB_Descriptor_Configuration_t usbSerialConfigurationDescriptor; \ No newline at end of file diff --git a/src/avr/uno/usb/serial_macros.h b/src/avr/uno/usb/serial_macros.h deleted file mode 100644 index 039f19b7e..000000000 --- a/src/avr/uno/usb/serial_macros.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once -#include - -#define USBtoUSART_ReadPtr GPIOR0 // to use cbi() -#define USARTtoUSB_WritePtr GPIOR1 - -extern volatile uint8_t USBtoUSART_WritePtr; -extern volatile uint8_t USARTtoUSB_ReadPtr; - -#define USART2USB_BUFLEN 256 // 0xFF - 8bit -#define USB2USART_BUFLEN 128 // 0x7F - 7bit - -// A collection of asm snippets that get reused everywhere, so they are made into macros - -#define INIT_TMP_SERIAL_TO_USB(tmp_ptr) \ - asm( \ - "lds %A[tmp], %[readPtr]\n\t" /* (1) Copy read pointer into lower byte*/ /* Outputs */ \ - : [tmp] "=&e"(tmp_ptr) /* Pointer register, output only*/ /* Inputs */ \ - : [readPtr] "m"(USARTtoUSB_ReadPtr) /* Memory location */ \ - ) - -#define READ_BYTE_FROM_BUF(data_ptr, tmp_ptr) \ - asm( \ - "ldi %B[tmp] , 0x01\n\t" /* (1) Force high byte to 0x01 */ \ - "ld %[data] , %a[tmp] +\n\t" /* (2) Load next data byte, wraps around 255 */ /* Outputs */ \ - : [data] "=&r"(data_ptr), /* Output only */ \ - [tmp] "=e"(tmp_ptr) /* Input and output */ /* Inputs */ \ - : "1"(tmp_ptr)) - -#define INIT_TMP_USB_TO_SERIAL(tmp_ptr) \ - asm( \ - "ldi %B[tmp], 0x02\n\t" /* (1) Force high byte to 0x200 */ \ - "lds %A[tmp], %[writePtr]\n\t" /* (1) Load USBtoUSART_WritePtr into low byte */ /* Outputs */ \ - : [tmp] "=&e"(tmp_ptr) /* Pointer register, output only*/ /* Inputs */ \ - : [writePtr] "m"(USBtoUSART_WritePtr) /* Memory location */ \ - ) - -#define WRITE_BYTE_TO_BUF(data_ptr, tmp_ptr) \ - asm( \ - "st %a[tmp]+, %[data]\n\t" /* (2) Save byte in buffer and increment */ \ - "andi %A[tmp], 0x7F\n\t" /* (1) wrap around pointer, 128 bytes */ /* Outputs */ \ - : [tmp] "=e"(tmp_ptr) /* Input and output */ /* Inputs */ \ - : "0"(tmp_ptr), \ - [data] "r"(data_ptr)) - -#define WRITE_ARRAY_TO_BUF(tmp_ptr, buf_ptr, length) \ - { \ - uint8_t len = length; \ - uint8_t* buf = (uint8_t*)buf_ptr; \ - do { \ - register uint8_t data; \ - data = *(buf++); \ - WRITE_BYTE_TO_BUF(data, tmp_ptr); \ - } while (--len); \ - } - -#define FINISH_WRITE(tmp_ptr) \ - USBtoUSART_WritePtr = tmp_ptr & 0xFF; \ - UCSR1B = (_BV(RXCIE1) | _BV(TXEN1) | _BV(RXEN1) | _BV(UDRIE1)) - -#define FINISH_READ(tmp_ptr) \ - USARTtoUSB_ReadPtr = tmp_ptr & 0xFF - -#define WAIT_FOR_BYTES(tmp_ptr, n) \ - while (((USARTtoUSB_WritePtr - tmp_ptr) & 0xFF) < n) { \ - } From 8e836d06da2007e41e825b3fd3a88b7454b3518d Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 9 Sep 2025 21:06:42 +1200 Subject: [PATCH 094/239] fix ps3 wt detection --- src/pico/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 88e1687ef..1c99a2dd7 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -517,7 +517,7 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ if (type.sub_type == GUITAR_HERO_GUITAR && XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(dev_addr, 0, buf, sizeof(buf))) { uint16_t wtProduct[] = {'G', 'u', 'i', 't', 'a', 'r', ' ', 'H', 'e', 'r', 'o', '4'}; - if (memcmp(wtProduct, buf, sizeof(wtProduct)) || memcmp(wtProduct, buf + 1, sizeof(wtProduct))) + if (memcmp(wtProduct, buf, sizeof(wtProduct)) == 0 || memcmp(wtProduct, buf + 1, sizeof(wtProduct)) == 0) { type.sub_type = GUITAR_HERO_GUITAR_WT; } From 8f19094f26df1fc161689914ee8b906182579ce4 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 11 Sep 2025 23:41:29 +1200 Subject: [PATCH 095/239] fix report for procon 1 --- include/reports/switch_reports.h | 27 ++++++++++------------- src/pico/main.cpp | 37 ++++++++++++++++++++++++++------ src/shared/main/shared_main.cpp | 28 +++++++++++++----------- 3 files changed, 57 insertions(+), 35 deletions(-) diff --git a/include/reports/switch_reports.h b/include/reports/switch_reports.h index a4d30f166..4ee601941 100644 --- a/include/reports/switch_reports.h +++ b/include/reports/switch_reports.h @@ -52,14 +52,14 @@ typedef struct } __attribute__((packed)) Switch2ProGamepad_Data_t; typedef struct { - uint8_t connection_info : 4; - uint8_t battery_level : 4; + uint8_t reportId; // 0x0A + uint8_t packetId; // counts up for each packet + uint8_t status; // 0x80 uint8_t y : 1; uint8_t x : 1; uint8_t b : 1; uint8_t a : 1; - uint8_t dummy1 : 2; uint8_t rightShoulder : 1; uint8_t rightTrigger : 1; @@ -68,29 +68,24 @@ typedef struct { uint8_t start : 1; // plus uint8_t leftThumbClick : 1; // l3 uint8_t rightThumbClick : 1; // r3 - uint8_t guide : 1; // home uint8_t capture : 1; uint8_t dummy2 : 2; - uint8_t dpad : 4; + uint8_t dpadDown : 1; + uint8_t dpadUp : 1; + uint8_t dpadRight : 1; + uint8_t dpadLeft : 1; uint8_t dummy3 : 2; uint8_t leftShoulder : 1; uint8_t leftTrigger : 1; // Bytes 6-11 - uint8_t leftStickX; - uint8_t leftStickY; - uint8_t rightStickX; - uint8_t rightStickY; - - uint8_t vibratorInput; // What is this used for? - - // Bytes 13-48 - // Three samples of the IMU is sent in one message - // See: https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/imu_sensor_notes.md - ImuData imu[3]; + uint16_t leftStickX : 12; + uint16_t leftStickY : 12; + uint16_t rightStickX : 12; + uint16_t rightStickY : 12; } __attribute__((packed)) SwitchProGamepad_Data_t; typedef struct diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 1c99a2dd7..4f7900152 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -62,6 +62,8 @@ typedef struct uint8_t report_length; bool switch_sent_timeout; bool switch_sent_handshake; + bool switch_sent_timeout2; + bool switch_sent_handshake2; uint8_t xone_init_id; } Usb_Host_Device_t; @@ -488,7 +490,6 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ case MOUSE: case STREAM_DECK: case PS5: - case SWITCH: case UNKNOWN: case GENERIC: case STEPMANIAX: @@ -500,6 +501,14 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ usb_host_devices[total_usb_host_devices].type = type; total_usb_host_devices++; break; + case SWITCH: { + printf("Found Switch controller\r\n"); + usb_host_devices[total_usb_host_devices].type = type; + total_usb_host_devices++; + uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x02 /* PROCON_USB_HANDSHAKE */}; + send_report_to_controller(dev_addr, instance, buf, 2); + break; + } case SWITCH2: printf("Found Switch 2 controller\r\n"); usb_host_devices[total_usb_host_devices].type = type; @@ -740,19 +749,30 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c } if (usb_host_devices[i].type.console_type == SWITCH && usb_host_devices[i].type.sub_type == GAMEPAD) { - if (!usb_host_devices[i].switch_sent_handshake) + if (report[0] == 0x81 && report[1] == 0x01) { usb_host_devices[i].switch_sent_handshake = true; uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x02 /* PROCON_USB_HANDSHAKE */}; send_report_to_controller(dev_addr, instance, buf, 2); } - else if (!usb_host_devices[i].switch_sent_timeout) + else if (!usb_host_devices[i].switch_sent_timeout && report[0] == 0x81 && report[1] == 0x02) { usb_host_devices[i].switch_sent_timeout = true; + uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x03 /* PROCON_USB_ENABLE */}; + send_report_to_controller(dev_addr, instance, buf, 2); + } + else if (report[0] == 0x81 && report[1] == 0x03) + { + usb_host_devices[i].switch_sent_handshake2 = true; + uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x02 /* PROCON_USB_HANDSHAKE */}; + send_report_to_controller(dev_addr, instance, buf, 2); + } + else if (report[0] == 0x81 && report[1] == 0x02) + { + usb_host_devices[i].switch_sent_timeout2 = true; uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x04 /* PROCON_USB_ENABLE */}; send_report_to_controller(dev_addr, instance, buf, 2); } - if (report[0] != SWITCH_PRO_CON_FULL_REPORT_ID) { continue; @@ -775,13 +795,16 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c continue; } } - if (usb_host_devices[i].type.console_type == PS3 && usb_host_devices[i].type.sub_type == ROCK_BAND_GUITAR) { + if (usb_host_devices[i].type.console_type == PS3 && usb_host_devices[i].type.sub_type == ROCK_BAND_GUITAR) + { PS3RockBandGuitar_Data_t *guitar = (PS3RockBandGuitar_Data_t *)report; // ignore neutral value from whammy and pickup - if (guitar->whammy != 0x7F) { + if (guitar->whammy != 0x7F) + { usb_host_devices[i].type.whammy = guitar->whammy; } - if (guitar->pickup != 0x7F) { + if (guitar->pickup != 0x7F) + { usb_host_devices[i].type.pickup = guitar->pickup; } } diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index cfc509a29..7acbd26b4 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1835,11 +1835,15 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t { case GAMEPAD: { + for (int i = 0; i < 10; i++) { + printf("%02x, ", data[i]); + } + printf("\r\n"); SwitchProGamepad_Data_t *report = (SwitchProGamepad_Data_t *)data; - usb_host_data->dpadLeft = report->dpad == 6 || report->dpad == 5 || report->dpad == 7; - usb_host_data->dpadRight = report->dpad == 3 || report->dpad == 2 || report->dpad == 1; - usb_host_data->dpadUp = report->dpad == 0 || report->dpad == 1 || report->dpad == 7; - usb_host_data->dpadDown = report->dpad == 5 || report->dpad == 4 || report->dpad == 3; + usb_host_data->dpadLeft = report->dpadLeft; + usb_host_data->dpadRight = report->dpadRight; + usb_host_data->dpadUp = report->dpadUp; + usb_host_data->dpadDown = report->dpadDown; usb_host_data->green |= report->a; usb_host_data->red |= report->b; usb_host_data->yellow |= report->y; @@ -1865,21 +1869,21 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t { usb_host_data->rightTrigger = report->rightTrigger << 8; } - if (report->leftStickX != PS3_STICK_CENTER) + if (report->leftStickX != 0x800) { - usb_host_data->leftStickX = (report->leftStickX - PS3_STICK_CENTER) << 8; + usb_host_data->leftStickX = (report->leftStickX - 0x800) << 4; } - if (report->leftStickY != PS3_STICK_CENTER) + if (report->leftStickY != 0x800) { - usb_host_data->leftStickY = (((UINT8_MAX - report->leftStickY) - PS3_STICK_CENTER)) << 8; + usb_host_data->leftStickY = (((0xFFF - report->leftStickY) - 0x800)) << 4; } - if (report->rightStickX != PS3_STICK_CENTER) + if (report->rightStickX != 0x800) { - usb_host_data->rightStickX = (report->rightStickX - PS3_STICK_CENTER) << 8; + usb_host_data->rightStickX = (report->rightStickX - 0x800) << 4; } - if (report->rightStickY != PS3_STICK_CENTER) + if (report->rightStickY != 0x800) { - usb_host_data->rightStickY = (((UINT8_MAX - report->rightStickY) - PS3_STICK_CENTER)) << 8; + usb_host_data->rightStickY = (((0xFFF - report->rightStickY) - 0x800)) << 4; } break; } From 742ac77c62b2a31ee975c2e4be14b25ca7ca33b8 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 11 Sep 2025 23:42:18 +1200 Subject: [PATCH 096/239] fix report for procon 1 --- src/shared/main/shared_main.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 7acbd26b4..0a4813cd8 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1835,10 +1835,6 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t { case GAMEPAD: { - for (int i = 0; i < 10; i++) { - printf("%02x, ", data[i]); - } - printf("\r\n"); SwitchProGamepad_Data_t *report = (SwitchProGamepad_Data_t *)data; usb_host_data->dpadLeft = report->dpadLeft; usb_host_data->dpadRight = report->dpadRight; From 9a966ae65fc94cd04708a3774804264c49315e4b Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 13 Sep 2025 12:16:28 +1200 Subject: [PATCH 097/239] fully initialise device before sending out the first report request --- src/pico/main.cpp | 11 ++--------- src/pico/xinput_host.cpp | 4 +++- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 4f7900152..86bca4c69 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -61,9 +61,6 @@ typedef struct USB_LastReport_Data_t report; uint8_t report_length; bool switch_sent_timeout; - bool switch_sent_handshake; - bool switch_sent_timeout2; - bool switch_sent_handshake2; uint8_t xone_init_id; } Usb_Host_Device_t; @@ -501,12 +498,11 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ usb_host_devices[total_usb_host_devices].type = type; total_usb_host_devices++; break; - case SWITCH: { + case SWITCH: + { printf("Found Switch controller\r\n"); usb_host_devices[total_usb_host_devices].type = type; total_usb_host_devices++; - uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x02 /* PROCON_USB_HANDSHAKE */}; - send_report_to_controller(dev_addr, instance, buf, 2); break; } case SWITCH2: @@ -751,7 +747,6 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c { if (report[0] == 0x81 && report[1] == 0x01) { - usb_host_devices[i].switch_sent_handshake = true; uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x02 /* PROCON_USB_HANDSHAKE */}; send_report_to_controller(dev_addr, instance, buf, 2); } @@ -763,13 +758,11 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c } else if (report[0] == 0x81 && report[1] == 0x03) { - usb_host_devices[i].switch_sent_handshake2 = true; uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x02 /* PROCON_USB_HANDSHAKE */}; send_report_to_controller(dev_addr, instance, buf, 2); } else if (report[0] == 0x81 && report[1] == 0x02) { - usb_host_devices[i].switch_sent_timeout2 = true; uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x04 /* PROCON_USB_ENABLE */}; send_report_to_controller(dev_addr, instance, buf, 2); } diff --git a/src/pico/xinput_host.cpp b/src/pico/xinput_host.cpp index 77f3c7f6a..a6b312013 100644 --- a/src/pico/xinput_host.cpp +++ b/src/pico/xinput_host.cpp @@ -239,7 +239,6 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_xinput->ep_in = desc_ep->bEndpointAddress; p_xinput->epin_size = desc_ep->wMaxPacketSize; TU_ASSERT(tuh_edpt_open(dev_addr, desc_ep)); - usbh_edpt_xfer(dev_addr, p_xinput->ep_in, p_xinput->epin_buf, p_xinput->epin_size); } else { @@ -550,6 +549,9 @@ static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance) // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, hid_itf->itf_num); + if (hid_itf->ep_in) { + usbh_edpt_xfer(dev_addr, hid_itf->ep_in, hid_itf->epin_buf, hid_itf->epin_size); + } } //--------------------------------------------------------------------+ From 91bf6de62a77473a1c2acf4a01cbda6373985295 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 13 Sep 2025 20:41:26 +1200 Subject: [PATCH 098/239] add some usb retry, makes neo s work via hub --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index dc20a442f..935685993 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ board_upload.ardwiino_bootloader_teensy = true board_build.use_usb = 1 platform = https://github.com/maxgerhardt/platform-raspberrypi/archive/39b90392af50585e429941bd2561a91949a2ba46.zip@1.15.0 platform_packages = - framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.3-sanjay/rp2040-4.6.3-sanjay.zip@1.40404.0 + framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.4-sanjay/rp2040-4.6.4-sanjay.zip@1.40404.0 board = pico framework = arduino board_build.core = earlephilhower From 36201d8cb756f70f1127300e85516b91cdcb85bb Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 14 Sep 2025 13:17:22 +1200 Subject: [PATCH 099/239] change how we differenciate windows from switch 2, ps2, wii, wii u --- include/controllers.h | 1 + src/pico/main.cpp | 1 + src/shared/controllers/controllers.c | 1 + src/shared/main/shared_main.cpp | 4 ++-- src/shared/usb/descriptors.cpp | 2 ++ 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/include/controllers.h b/include/controllers.h index b9747de33..8ce5c10fb 100644 --- a/include/controllers.h +++ b/include/controllers.h @@ -37,6 +37,7 @@ extern bool descriptor_requested; // Use for configuring commands that are pc specific extern bool seen_windows_xb1; extern bool seen_windows; +extern bool seen_os_descriptor_read; extern bool read_any_string; // Used for detecting any connection at all diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 86bca4c69..3cdad97f9 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -356,6 +356,7 @@ void send_report_to_controller(uint8_t dev_addr, uint8_t instance, const uint8_t } extern "C" void tud_mount_cb(void) { + printf("mounted!\r\n"); device_reset(); } #if USB_HOST_STACK diff --git a/src/shared/controllers/controllers.c b/src/shared/controllers/controllers.c index b11bc13ed..868b6f73e 100644 --- a/src/shared/controllers/controllers.c +++ b/src/shared/controllers/controllers.c @@ -19,6 +19,7 @@ uint8_t hid_sequence_number; uint8_t ps4_sequence_number; uint8_t portal_state = 0; bool seen_windows_xb1 = 0; +bool seen_os_descriptor_read = 0; bool seen_windows = false; bool read_any_string = false; bool read_device_desc = false; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 0a4813cd8..e54db40b8 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3619,8 +3619,8 @@ bool tick_usb(void) } #endif #if DEVICE_TYPE_IS_GAMEPAD - // PS2 / Wii / WiiU / Switch 2 do not read any of the string descriptors. - if (millis_at_boot && (millis() - millis_at_boot) > 5000 && consoleType == UNIVERSAL && !read_any_string && !seen_windows_xb1) + // PS2 / Wii / WiiU / Switch 2 won't do WCID + if (millis_at_boot && (millis() - millis_at_boot) > 2000 && consoleType == UNIVERSAL && !seen_windows_xb1 && !seen_os_descriptor_read) { // Switch 2 does read the hid descriptor if (seen_hid_descriptor_read) diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 1e97cbce7..52ac3918e 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1245,6 +1245,7 @@ uint16_t descriptorRequest(const uint16_t wValue, void *descriptorBuffer) { const uint8_t descriptorType = (wValue >> 8); const uint8_t descriptorNumber = (wValue & 0xFF); + // printf("desc: %02x %02x\r\n", descriptorType, descriptorNumber); #if DEVICE_TYPE_IS_GAMEPAD #if USB_HOST_STACK if (consoleType == UNIVERSAL && seen_windows_xb1 && descriptorType != HID_DESCRIPTOR_REPORT) { @@ -1464,6 +1465,7 @@ uint16_t descriptorRequest(const uint16_t wValue, str = (uint8_t *)pgm_read_pointer(descriptorStrings + descriptorNumber); } else if (descriptorNumber == 0xEE) { str = (uint8_t *)&OSDescriptorString; + seen_os_descriptor_read = true; } else { break; } From 450e21448ca5a3da51b371acc2eb4d69966f0982 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 14 Sep 2025 13:33:57 +1200 Subject: [PATCH 100/239] change how we differenciate windows from switch 2, ps2, wii, wii u --- include/controllers.h | 2 +- src/shared/controllers/controllers.c | 2 +- src/shared/main/shared_main.cpp | 4 ++-- src/shared/usb/descriptors.cpp | 5 ++++- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/include/controllers.h b/include/controllers.h index 8ce5c10fb..4fedbb5c8 100644 --- a/include/controllers.h +++ b/include/controllers.h @@ -38,7 +38,7 @@ extern bool descriptor_requested; extern bool seen_windows_xb1; extern bool seen_windows; extern bool seen_os_descriptor_read; -extern bool read_any_string; +extern bool read_any_device_string; // Used for detecting any connection at all extern bool read_device_desc; diff --git a/src/shared/controllers/controllers.c b/src/shared/controllers/controllers.c index 868b6f73e..3d7dc978f 100644 --- a/src/shared/controllers/controllers.c +++ b/src/shared/controllers/controllers.c @@ -21,7 +21,7 @@ uint8_t portal_state = 0; bool seen_windows_xb1 = 0; bool seen_os_descriptor_read = 0; bool seen_windows = false; -bool read_any_string = false; +bool read_any_device_string = false; bool read_device_desc = false; bool lastEuphoriaLed = false; bool proButtonsEnabled = false; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index e54db40b8..43fdc6a29 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3619,8 +3619,8 @@ bool tick_usb(void) } #endif #if DEVICE_TYPE_IS_GAMEPAD - // PS2 / Wii / WiiU / Switch 2 won't do WCID - if (millis_at_boot && (millis() - millis_at_boot) > 2000 && consoleType == UNIVERSAL && !seen_windows_xb1 && !seen_os_descriptor_read) + // PS2 / Wii / WiiU / Switch 2 won't do WCID and wont try to read any actual strings + if (millis_at_boot && (millis() - millis_at_boot) > 2000 && consoleType == UNIVERSAL && !seen_windows_xb1 && !seen_os_descriptor_read && !read_any_device_string) { // Switch 2 does read the hid descriptor if (seen_hid_descriptor_read) diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 52ac3918e..bf8d0f9c7 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1453,7 +1453,10 @@ uint16_t descriptorRequest(const uint16_t wValue, break; } case USB_DESCRIPTOR_STRING: { - read_any_string = true; + // We only care for actual string reads, not the language id + if (descriptorNumber != 0) { + read_any_device_string = true; + } const uint8_t *str; if (descriptorNumber == 5) { str = (uint8_t *)&rtStringInput; From bd7a9b1a3b9bcab5299e958e4113fbf97d3f42d4 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 14 Sep 2025 17:00:06 +1200 Subject: [PATCH 101/239] stop console detection hanging the og xbox --- include/commands.h | 3 +++ include/controllers.h | 3 +++ src/shared/controllers/controllers.c | 1 + src/shared/hid/hid.cpp | 6 +++++ src/shared/main/shared_main.cpp | 37 ++++++++++++++++------------ src/shared/usb/descriptors.cpp | 8 ++---- 6 files changed, 36 insertions(+), 22 deletions(-) diff --git a/include/commands.h b/include/commands.h index 87b15294d..b7de6c75a 100644 --- a/include/commands.h +++ b/include/commands.h @@ -52,6 +52,7 @@ enum SerialCommands { COMMAND_READ_BLUETOOTH_INPUTS, COMMAND_WT_DRUM_VALID, COMMAND_BH_DRUM_VALID, + COMMAND_READ_CRKD, MAX=100 }; @@ -61,12 +62,14 @@ extern uint8_t lastSuccessfulTurntablePacketLeft[3]; extern uint8_t lastSuccessfulTurntablePacketRight[3]; extern uint8_t lastSuccessfulGH5Packet[2]; extern uint8_t lastSuccessfulClonePacket[4]; +extern crkd_neck_t lastCrkd; extern uint8_t wiiBytes; extern uint32_t lastWt[5]; extern uint8_t rawWt; extern uint8_t rawWtPeripheral; extern bool lastGH5WasSuccessful; extern bool lastCloneWasSuccessful; +extern bool lastCrkdWasSuccessful; extern bool lastTurntableWasSuccessfulLeft; extern bool lastTurntableWasSuccessfulRight; extern bool lastWiiWasSuccessful; diff --git a/include/controllers.h b/include/controllers.h index 4fedbb5c8..78be1ffbe 100644 --- a/include/controllers.h +++ b/include/controllers.h @@ -31,6 +31,9 @@ extern bool seen_ps4; // Used for detecting wii extern bool seen_hid_descriptor_read; +// Used for detecting og xbox +extern bool seen_og_xbox; + // Used for detecting pademu extern bool descriptor_requested; diff --git a/src/shared/controllers/controllers.c b/src/shared/controllers/controllers.c index 3d7dc978f..f9aea67c3 100644 --- a/src/shared/controllers/controllers.c +++ b/src/shared/controllers/controllers.c @@ -20,6 +20,7 @@ uint8_t ps4_sequence_number; uint8_t portal_state = 0; bool seen_windows_xb1 = 0; bool seen_os_descriptor_read = 0; +bool seen_og_xbox = false; bool seen_windows = false; bool read_any_device_string = false; bool read_device_desc = false; diff --git a/src/shared/hid/hid.cpp b/src/shared/hid/hid.cpp index bfa42e0d4..03fe48757 100644 --- a/src/shared/hid/hid.cpp +++ b/src/shared/hid/hid.cpp @@ -853,6 +853,12 @@ uint8_t handle_serial_command(uint8_t request, uint16_t wValue, uint8_t *respons } memcpy(response_buffer, &lastSuccessfulClonePacket, sizeof(lastSuccessfulClonePacket)); return sizeof(lastSuccessfulClonePacket); + case COMMAND_READ_CRKD: + if (!lastCrkdWasSuccessful) { + return 0; + } + memcpy(response_buffer, &lastCrkd, sizeof(lastCrkd)); + return sizeof(lastCrkd); #ifdef INPUT_WT_NECK case COMMAND_READ_GHWT: { volatile uint8_t *data = (volatile uint8_t *)lastWt; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 43fdc6a29..439fcb222 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2878,9 +2878,9 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #include "inputs/wt_drum.h" #include "inputs/wt_neck.h" #include "inputs/crkd.h" -// #if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE -// convert_report((uint8_t *)&sysexGuitar, sizeof(sysexGuitar), {PS3, ROCK_BAND_PRO_GUITAR_SQUIRE, 0, 0, 0, false}, &usb_host_data); -// #endif + // #if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE + // convert_report((uint8_t *)&sysexGuitar, sizeof(sysexGuitar), {PS3, ROCK_BAND_PRO_GUITAR_SQUIRE, 0, 0, 0, false}, &usb_host_data); + // #endif TICK_SHARED; if (!startedInactivityPulse) { @@ -3161,7 +3161,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #if DEVICE_TYPE == ROCK_BAND_DRUMS if (!report->cymbalFlag && ready_for_next_packet() && (greenCymbal || yellowCymbal || blueCymbal)) { - if (greenCymbal) { + if (greenCymbal) + { lastGreenOff = millis(); } greenCymbal = false; @@ -3477,7 +3478,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #if DEVICE_TYPE == ROCK_BAND_DRUMS if (!report->cymbalFlag && ready_for_next_packet() && (greenCymbal || yellowCymbal || blueCymbal)) { - if (greenCymbal) { + if (greenCymbal) + { lastGreenOff = millis(); } greenCymbal = false; @@ -3622,25 +3624,28 @@ bool tick_usb(void) // PS2 / Wii / WiiU / Switch 2 won't do WCID and wont try to read any actual strings if (millis_at_boot && (millis() - millis_at_boot) > 2000 && consoleType == UNIVERSAL && !seen_windows_xb1 && !seen_os_descriptor_read && !read_any_device_string) { + // og xbox does its own thing + if (seen_og_xbox) + { + consoleType = OG_XBOX; + reset_usb(); + } // Switch 2 does read the hid descriptor if (seen_hid_descriptor_read) { consoleType = SWITCH; reset_usb(); } - else - { - // PS2 / Wii / WiiU does not read hid descriptor - // The wii however will configure the usb device before it stops communicating + // PS2 / Wii / WiiU does not read hid descriptor + // The wii however will configure the usb device before it stops communicating #if DEVICE_TYPE == ROCK_BAND_GUITAR || DEVICE_TYPE == ROCK_BAND_DRUMS - if (usb_configured()) - { - set_console_type(WII_RB); - } -#endif - // But the PS2 does not. We also end up here on the wii/wiiu if a device does not have an explicit wii mode. - set_console_type(PS3); + if (usb_configured()) + { + set_console_type(WII_RB); } +#endif + // But the PS2 does not. We also end up here on the wii/wiiu if a device does not have an explicit wii mode. + set_console_type(PS3); } // Due to some quirks with how the PS3 detects controllers, we can also end up here for PS3, but in that case, we won't see any requests for controller data if ((millis() - millis_at_boot) > 2000 && consoleType == PS4 && !seen_ps4) diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index bf8d0f9c7..60d6f60af 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -902,12 +902,8 @@ bool cleared_output = false; uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, uint8_t *requestBuffer, bool *status) { // printf("%02x %04x %04x %04x %04x\r\n", requestType, request, wValue, wIndex, wLength); #if DEVICE_TYPE_IS_GAMEPAD - if (consoleType != OG_XBOX && requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && request == 6 && wValue == 0x4200) { - consoleType = OG_XBOX; - reset_usb(); - return 0; - } - if (consoleType == OG_XBOX && requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR)) { + if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR)) { + seen_og_xbox = true; if (request == 6 && wValue == 0x4200) { memcpy_P(requestBuffer, &DukeXIDDescriptor, sizeof(DukeXIDDescriptor)); return sizeof(DukeXIDDescriptor); From c19f226a6b7e155ce8af32a409a4969088cc1c76 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 14 Sep 2025 17:43:54 +1200 Subject: [PATCH 102/239] actually show crkd neck info in santroller --- include/commands.h | 1 + include/reports/controller_reports.h | 20 ++------------------ include/reports/crkd.h | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+), 18 deletions(-) create mode 100644 include/reports/crkd.h diff --git a/include/commands.h b/include/commands.h index b7de6c75a..f97c1a94a 100644 --- a/include/commands.h +++ b/include/commands.h @@ -1,5 +1,6 @@ #include #include "midi_descriptors.h" +#include "reports/crkd.h" #ifdef __cplusplus extern "C" { #endif diff --git a/include/reports/controller_reports.h b/include/reports/controller_reports.h index db8ed97fa..de28925e1 100644 --- a/include/reports/controller_reports.h +++ b/include/reports/controller_reports.h @@ -14,6 +14,7 @@ #include "reports/wii_reports.h" #include "reports/xbox_one_reports.h" #include "reports/xinput_reports.h" +#include "reports/crkd.h" #define STREAM_DECK_INPUT_REPORT_ID 1 #define STADIA_REPORT_ID 3 @@ -400,21 +401,4 @@ typedef struct uint8_t rightStickY; uint8_t leftTrigger; // pressure_l2 uint8_t rightTrigger; // pressure_r2 -} __attribute__((packed)) Stadia_Data_t; - -typedef struct -{ - uint8_t header; // {0xA5, 0x01};, though we are eating the first header byte - uint8_t len; // 0x0C; - uint8_t padding[2]; //{0x00, 0x00}; - uint8_t green : 1; - uint8_t red : 1; - uint8_t yellow : 1; - uint8_t blue : 1; - uint8_t orange : 1; - uint8_t : 3; - uint8_t dpadUpDown; // none: 0x80, up: 0x00, down: 0xFF - uint8_t dpadLeftRight; // none: 0x80, right: 0x00, left: 0xFF - uint8_t footer[3]; // {0x00, 0x01, 0x15}; - uint8_t crc; // CRC-8/MAXIM-DOW -} __attribute__((packed)) crkd_neck_t; \ No newline at end of file +} __attribute__((packed)) Stadia_Data_t; \ No newline at end of file diff --git a/include/reports/crkd.h b/include/reports/crkd.h new file mode 100644 index 000000000..7ab61a93d --- /dev/null +++ b/include/reports/crkd.h @@ -0,0 +1,18 @@ +#pragma once +#include "stdint.h" +typedef struct +{ + uint8_t header; // {0xA5, 0x01};, though we are eating the first header byte + uint8_t len; // 0x0C; + uint8_t padding[2]; //{0x00, 0x00}; + uint8_t green : 1; + uint8_t red : 1; + uint8_t yellow : 1; + uint8_t blue : 1; + uint8_t orange : 1; + uint8_t : 3; + uint8_t dpadUpDown; // none: 0x80, up: 0x00, down: 0xFF + uint8_t dpadLeftRight; // none: 0x80, right: 0x00, left: 0xFF + uint8_t footer[3]; // {0x00, 0x01, 0x15}; + uint8_t crc; // CRC-8/MAXIM-DOW +} __attribute__((packed)) crkd_neck_t; \ No newline at end of file From ceceed9122aa86405f79842dedd9100b9d9fcc39 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 19 Sep 2025 19:00:39 +1200 Subject: [PATCH 103/239] tick djh turntable at poll rate even if console isnt polling it that fast --- src/pico/quadrature_encoder.c | 68 +++++++++++++++ src/pico/quadrature_encoder.pio | 145 ++++++++++++++++++++++++++++++++ src/shared/main/shared_main.cpp | 5 +- 3 files changed, 215 insertions(+), 3 deletions(-) create mode 100644 src/pico/quadrature_encoder.c create mode 100644 src/pico/quadrature_encoder.pio diff --git a/src/pico/quadrature_encoder.c b/src/pico/quadrature_encoder.c new file mode 100644 index 000000000..0855eb9b2 --- /dev/null +++ b/src/pico/quadrature_encoder.c @@ -0,0 +1,68 @@ +/** + * Copyright (c) 2023 Raspberry Pi (Trading) Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "pico/stdlib.h" +#include "hardware/pio.h" +#include "hardware/timer.h" + +#include "quadrature_encoder.pio.h" + +// +// ---- quadrature encoder interface example +// +// the PIO program reads phase A/B of a quadrature encoder and increments or +// decrements an internal counter to keep the current absolute step count +// updated. At any point, the main code can query the current count by using +// the quadrature_encoder_*_count functions. The counter is kept in a full +// 32 bit register that just wraps around. Two's complement arithmetic means +// that it can be interpreted as a 32-bit signed or unsigned value, and it will +// work anyway. +// +// As an example, a two wheel robot being controlled at 100Hz, can use two +// state machines to read the two encoders and in the main control loop it can +// simply ask for the current encoder counts to get the absolute step count. It +// can also subtract the values from the last sample to check how many steps +// each wheel as done since the last sample period. +// +// One advantage of this approach is that it requires zero CPU time to keep the +// encoder count updated and because of that it supports very high step rates. +// + +// int main() { +// int new_value, delta, old_value = 0; +// int last_value = -1, last_delta = -1; + +// // Base pin to connect the A phase of the encoder. +// // The B phase must be connected to the next pin +// const uint PIN_AB = 10; + +// stdio_init_all(); +// printf("Hello from quadrature encoder\n"); + +// PIO pio = pio0; +// const uint sm = 0; + +// // we don't really need to keep the offset, as this program must be loaded +// // at offset 0 +// pio_add_program(pio, &quadrature_encoder_program); +// quadrature_encoder_program_init(pio, sm, PIN_AB, 0); + +// while (1) { +// // note: thanks to two's complement arithmetic delta will always +// // be correct even when new_value wraps around MAXINT / MININT +// new_value = quadrature_encoder_get_count(pio, sm); +// delta = new_value - old_value; +// old_value = new_value; + +// if (new_value != last_value || delta != last_delta ) { +// printf("position %8d, delta %6d\n", new_value, delta); +// last_value = new_value; +// last_delta = delta; +// } +// sleep_ms(100); +// } +// } \ No newline at end of file diff --git a/src/pico/quadrature_encoder.pio b/src/pico/quadrature_encoder.pio new file mode 100644 index 000000000..43fe58e62 --- /dev/null +++ b/src/pico/quadrature_encoder.pio @@ -0,0 +1,145 @@ +; +; Copyright (c) 2023 Raspberry Pi (Trading) Ltd. +; +; SPDX-License-Identifier: BSD-3-Clause +; +.pio_version 0 // only requires PIO version 0 + +.program quadrature_encoder + +; the code must be loaded at address 0, because it uses computed jumps +.origin 0 + + +; the code works by running a loop that continuously shifts the 2 phase pins into +; ISR and looks at the lower 4 bits to do a computed jump to an instruction that +; does the proper "do nothing" | "increment" | "decrement" action for that pin +; state change (or no change) + +; ISR holds the last state of the 2 pins during most of the code. The Y register +; keeps the current encoder count and is incremented / decremented according to +; the steps sampled + +; the program keeps trying to write the current count to the RX FIFO without +; blocking. To read the current count, the user code must drain the FIFO first +; and wait for a fresh sample (takes ~4 SM cycles on average). The worst case +; sampling loop takes 10 cycles, so this program is able to read step rates up +; to sysclk / 10 (e.g., sysclk 125MHz, max step rate = 12.5 Msteps/sec) + +; 00 state + JMP update ; read 00 + JMP decrement ; read 01 + JMP increment ; read 10 + JMP update ; read 11 + +; 01 state + JMP increment ; read 00 + JMP update ; read 01 + JMP update ; read 10 + JMP decrement ; read 11 + +; 10 state + JMP decrement ; read 00 + JMP update ; read 01 + JMP update ; read 10 + JMP increment ; read 11 + +; to reduce code size, the last 2 states are implemented in place and become the +; target for the other jumps + +; 11 state + JMP update ; read 00 + JMP increment ; read 01 +decrement: + ; note: the target of this instruction must be the next address, so that + ; the effect of the instruction does not depend on the value of Y. The + ; same is true for the "JMP X--" below. Basically "JMP Y--, " + ; is just a pure "decrement Y" instruction, with no other side effects + JMP Y--, update ; read 10 + + ; this is where the main loop starts +.wrap_target +update: + MOV ISR, Y ; read 11 + PUSH noblock + +sample_pins: + ; we shift into ISR the last state of the 2 input pins (now in OSR) and + ; the new state of the 2 pins, thus producing the 4 bit target for the + ; computed jump into the correct action for this state. Both the PUSH + ; above and the OUT below zero out the other bits in ISR + OUT ISR, 2 + IN PINS, 2 + + ; save the state in the OSR, so that we can use ISR for other purposes + MOV OSR, ISR + ; jump to the correct state machine action + MOV PC, ISR + + ; the PIO does not have a increment instruction, so to do that we do a + ; negate, decrement, negate sequence +increment: + MOV Y, ~Y + JMP Y--, increment_cont +increment_cont: + MOV Y, ~Y +.wrap ; the .wrap here avoids one jump instruction and saves a cycle too + + + +% c-sdk { + +#include "hardware/clocks.h" +#include "hardware/gpio.h" + +// max_step_rate is used to lower the clock of the state machine to save power +// if the application doesn't require a very high sampling rate. Passing zero +// will set the clock to the maximum + +static inline void quadrature_encoder_program_init(PIO pio, uint sm, uint pin, int max_step_rate) +{ + pio_sm_set_consecutive_pindirs(pio, sm, pin, 2, false); + pio_gpio_init(pio, pin); + pio_gpio_init(pio, pin + 1); + + gpio_pull_up(pin); + gpio_pull_up(pin + 1); + + pio_sm_config c = quadrature_encoder_program_get_default_config(0); + + sm_config_set_in_pins(&c, pin); // for WAIT, IN + sm_config_set_jmp_pin(&c, pin); // for JMP + // shift to left, autopull disabled + sm_config_set_in_shift(&c, false, false, 32); + // don't join FIFO's + sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_NONE); + + // passing "0" as the sample frequency, + if (max_step_rate == 0) { + sm_config_set_clkdiv(&c, 1.0); + } else { + // one state machine loop takes at most 10 cycles + float div = (float)clock_get_hz(clk_sys) / (10 * max_step_rate); + sm_config_set_clkdiv(&c, div); + } + + pio_sm_init(pio, sm, 0, &c); + pio_sm_set_enabled(pio, sm, true); +} + +static inline int32_t quadrature_encoder_get_count(PIO pio, uint sm) +{ + uint ret; + int n; + + // if the FIFO has N entries, we fetch them to drain the FIFO, + // plus one entry which will be guaranteed to not be stale + n = pio_sm_get_rx_fifo_level(pio, sm) + 1; + while (n > 0) { + ret = pio_sm_get_blocking(pio, sm); + n--; + } + return ret; +} + +%} \ No newline at end of file diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 439fcb222..c58a22d39 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2689,7 +2689,6 @@ void tick_ps2output() #include "inputs/mpr121.h" #include "inputs/ps2.h" #include "inputs/slave_tick.h" -#include "inputs/turntable.h" #include "inputs/usb_host.h" #include "inputs/wii.h" #include "inputs/wt_neck.h" @@ -2725,7 +2724,6 @@ void tick_wiioutput() #include "inputs/mpr121.h" #include "inputs/ps2.h" #include "inputs/slave_tick.h" -#include "inputs/turntable.h" #include "inputs/usb_host.h" #include "inputs/wii.h" #include "inputs/wt_neck.h" @@ -2872,7 +2870,6 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #include "inputs/mpr121.h" #include "inputs/ps2.h" #include "inputs/slave_tick.h" -#include "inputs/turntable.h" #include "inputs/usb_host.h" #include "inputs/wii.h" #include "inputs/wt_drum.h" @@ -3732,6 +3729,8 @@ void tick(void) #ifdef TICK_LED_BLUETOOTH TICK_LED_BLUETOOTH; #endif + +#include "inputs/turntable.h" if (reset_after_360 && millis() > reset_after_360) { reset_usb(); From 72ce5806ab2a715bc263d890c24aa5786d1604db Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 22 Sep 2025 15:01:39 +1200 Subject: [PATCH 104/239] revert djh test --- src/shared/main/shared_main.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index c58a22d39..3ed546664 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -69,6 +69,13 @@ struct crkd_neck_t lastCrkd; unsigned long lastMidi = 0; Midi_Data_t midiData = {0}; + +uint8_t *dj_left = lastSuccessfulTurntablePacketLeft; +uint8_t *dj_right = lastSuccessfulTurntablePacketRight; +int8_t dj_turntable_left = 0; +int8_t dj_turntable_right = 0; +bool djLeftValid = true; +bool djRightValid = true; void onNote(uint8_t channel, uint8_t note, uint8_t velocity) { // velocities are 7 bit @@ -2727,6 +2734,7 @@ void tick_wiioutput() #include "inputs/usb_host.h" #include "inputs/wii.h" #include "inputs/wt_neck.h" +#include "inputs/turntable.h" TICK_SHARED; if (!startedInactivityPulse) { @@ -2875,6 +2883,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #include "inputs/wt_drum.h" #include "inputs/wt_neck.h" #include "inputs/crkd.h" +#include "inputs/turntable.h" // #if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE // convert_report((uint8_t *)&sysexGuitar, sizeof(sysexGuitar), {PS3, ROCK_BAND_PRO_GUITAR_SQUIRE, 0, 0, 0, false}, &usb_host_data); // #endif @@ -3730,7 +3739,6 @@ void tick(void) TICK_LED_BLUETOOTH; #endif -#include "inputs/turntable.h" if (reset_after_360 && millis() > reset_after_360) { reset_usb(); From 524d0c228423ee0c958b03d7b084b9681f31461a Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 28 Sep 2025 13:27:06 +1300 Subject: [PATCH 105/239] fix crkd xbox guitars in pc mode --- src/pico/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 3cdad97f9..a7eeb0f44 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -784,7 +784,8 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c XInputGamepad_Data_t *gamepad = (XInputGamepad_Data_t *)report; // Drop any corrupted or invalid packets - if (len != sizeof(XInputGamepad_Data_t) || gamepad->rsize != len) + // crkd xbox guitars send extra bytes so we have to account for that. + if (gamepad->rsize != sizeof(XInputGamepad_Data_t) || (len != sizeof(XInputGamepad_Data_t) && len != 26)) { continue; } From 835fe63cf742bdfff0b7eafdea7b095c9da6ce91 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 28 Sep 2025 13:30:43 +1300 Subject: [PATCH 106/239] support crkd guitars in xb mode 9 --- include/endpoints.h | 2 ++ src/shared/main/shared_main.cpp | 9 +++++++++ 2 files changed, 11 insertions(+) diff --git a/include/endpoints.h b/include/endpoints.h index aaca3d1a1..3315115eb 100644 --- a/include/endpoints.h +++ b/include/endpoints.h @@ -45,6 +45,8 @@ enum endpoints_t { #define PS4_STRAT_PID 0x8261 #define MADCATZ_VID 0x0738 #define PDP_VID 0x0E6F +#define CRKD_VID 0x0351 +#define CRKD_XB_MODE9 0x4161 #define PS4_JAG_PID 0x0173 #define PS4_RIFFMASTER_PID 0x024A #define PS4_MADCATZ_DRUM_PID 0x8262 diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 3ed546664..367742b19 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -4309,6 +4309,15 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D break; } + break; + case CRKD_VID: + switch (pid) + { + case CRKD_XB_MODE9: + type->console_type = XBOXONE; + type->sub_type = ROCK_BAND_GUITAR; + break; + } break; case PDP_VID: switch (pid) From f780665cd660aaba5b5160dd1a5d727ca6ae469f Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 29 Sep 2025 10:40:48 +1300 Subject: [PATCH 107/239] make sure we center sticks for ps2 emulation --- src/shared/main/shared_main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 367742b19..2ab668b8c 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2714,6 +2714,10 @@ void tick_ps2output() } } memset(report, 0, sizeof(report)); + report->leftStickX = PS3_STICK_CENTER; + report->leftStickY = PS3_STICK_CENTER; + report->rightStickX = PS3_STICK_CENTER; + report->rightStickY = PS3_STICK_CENTER; #if DEVICE_TYPE_IS_GUITAR report->dpadLeft = true; report->whammy = 0x7f; From a81f460f35696c422af985885addcb30eab0fe80 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 30 Sep 2025 09:30:58 +1300 Subject: [PATCH 108/239] add ids ghl ps4 over usb host --- src/shared/main/inputs/midi_fader.h | 3 +++ src/shared/main/shared_main.cpp | 4 ++++ 2 files changed, 7 insertions(+) create mode 100644 src/shared/main/inputs/midi_fader.h diff --git a/src/shared/main/inputs/midi_fader.h b/src/shared/main/inputs/midi_fader.h new file mode 100644 index 000000000..82e748372 --- /dev/null +++ b/src/shared/main/inputs/midi_fader.h @@ -0,0 +1,3 @@ +#ifdef INPUT_MIDI_FADER +lastMidiFaderWasSuccessful = read_uart(MIDI_FADER_UART_PORT, 1, (uint8_t *)&lastMidiFader); +#endif \ No newline at end of file diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 2ab668b8c..a737f1736 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -4375,6 +4375,10 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D type->console_type = XBOX360; type->sub_type = XINPUT_GUITAR_HERO_LIVE; break; + case PS4_GHLIVE_DONGLE_PID: + type->console_type = PS4; + type->sub_type = LIVE_GUITAR; + break; case XBOX_360_WT_KIOSK_PID: type->console_type = XBOX360; type->sub_type = XINPUT_GUITAR_WT; From bd054019d7de3534ac0696c84c26faccc4b6917f Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 30 Sep 2025 09:43:25 +1300 Subject: [PATCH 109/239] fix ghl ps4 whammy and tilt being swapped --- include/reports/ps4_reports.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/reports/ps4_reports.h b/include/reports/ps4_reports.h index 457c41bec..90859789e 100644 --- a/include/reports/ps4_reports.h +++ b/include/reports/ps4_reports.h @@ -220,8 +220,8 @@ typedef struct uint8_t unused1; uint8_t strumBar; - uint8_t whammy; uint8_t tilt; + uint8_t whammy; // To make things easier we use bitfields here and them map to dpad later uint8_t dpadUp : 1; From bab66c366816382319bcc3dbf8a97b32a195ae2e Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 30 Sep 2025 09:55:53 +1300 Subject: [PATCH 110/239] add mappings for frets in ghl modes in case someone wants to use a ghl guitar for 5 fret --- src/shared/main/shared_main.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index a737f1736..26d916b20 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1144,6 +1144,12 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->y |= report->y; usb_host_data->leftShoulder |= report->leftShoulder; usb_host_data->rightShoulder |= report->rightShoulder; + + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; usb_host_data->leftThumbClick |= report->leftThumbClick; usb_host_data->back |= report->back; usb_host_data->start |= report->start; @@ -1522,6 +1528,12 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->y |= report->y; usb_host_data->leftShoulder |= report->leftShoulder; usb_host_data->rightShoulder |= report->rightShoulder; + + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; usb_host_data->dpadLeft |= left; usb_host_data->dpadRight |= right; usb_host_data->dpadUp |= up || report->strumBar == 0x00; @@ -1727,6 +1739,11 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->leftShoulder |= report->leftShoulder; usb_host_data->rightShoulder |= report->rightShoulder; usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; usb_host_data->back |= report->back; usb_host_data->start |= report->start; usb_host_data->guide |= report->guide; @@ -2347,6 +2364,11 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->y |= report->y; usb_host_data->leftShoulder |= report->leftShoulder; usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; usb_host_data->dpadLeft = report->dpadLeft; usb_host_data->dpadRight = report->dpadRight; usb_host_data->dpadUp = report->dpadUp; From 0ccde392274fe80320d8fd5d3ea041ad6034bf38 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 2 Oct 2025 16:57:56 +1300 Subject: [PATCH 111/239] fix ps2 outputs not compiling --- src/shared/main/shared_main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 26d916b20..f30bca7fd 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2736,10 +2736,12 @@ void tick_ps2output() } } memset(report, 0, sizeof(report)); +#if DEVICE_TYPE == GAMEPAD || DEVICE_TYPE == TAIKO report->leftStickX = PS3_STICK_CENTER; report->leftStickY = PS3_STICK_CENTER; report->rightStickX = PS3_STICK_CENTER; report->rightStickY = PS3_STICK_CENTER; +#endif #if DEVICE_TYPE_IS_GUITAR report->dpadLeft = true; report->whammy = 0x7f; From 0ccb38ec69ee989ab6d98f7a672fbe64c24e4dcf Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 5 Oct 2025 17:25:02 +1300 Subject: [PATCH 112/239] support connecting the IR sensor from djh tables directly to peripheral --- include/pico_slave.h | 2 ++ src/pico_slave/main.cpp | 38 +++++++++++++++++++++++++++++++-- src/shared/main/inputs/slave.h | 27 +++++++++++++++++++++++ src/shared/main/shared_main.cpp | 3 +++ 4 files changed, 68 insertions(+), 2 deletions(-) diff --git a/include/pico_slave.h b/include/pico_slave.h index f6ffcf392..ccb9fd792 100644 --- a/include/pico_slave.h +++ b/include/pico_slave.h @@ -10,6 +10,8 @@ #define SLAVE_COMMAND_GET_WT 0x0B #define SLAVE_COMMAND_GET_WT_RAW 0x0C #define SLAVE_COMMAND_INITIALISE 0x0D +#define SLAVE_COMMAND_INIT_QUAD 0x0E +#define SLAVE_COMMAND_GET_QUAD 0x0F #define PIN_MODE_INPUT_PULLUP 0 #define PIN_MODE_INPUT 1 diff --git a/src/pico_slave/main.cpp b/src/pico_slave/main.cpp index 4dc6b8fa9..a7f4e0190 100644 --- a/src/pico_slave/main.cpp +++ b/src/pico_slave/main.cpp @@ -2,6 +2,9 @@ #include #include #include +#include "hardware/pio.h" +#include "hardware/timer.h" +#include "quadrature_encoder.pio.h" #include "io.h" #include "pico_slave.h" @@ -16,10 +19,19 @@ volatile uint32_t mask = 0; volatile uint8_t wtS0Pin = 0; volatile uint8_t wtS1Pin = 0; volatile uint8_t wtS2Pin = 0; +volatile uint8_t quadAPin = 0; volatile uint16_t wt_sensitivity = 0; volatile uint8_t rawWt; volatile uint32_t lastWt[5] = {0}; +volatile bool wtShouldInit = false; +volatile bool quadShouldInit = false; volatile bool hasInitWt = false; +volatile bool hasInitQuad = false; +volatile int quadPollRate = 0; +volatile int new_value, delta, old_value = 0; +volatile int last_value = -1, last_delta = -1; +PIO pio = pio0; +const uint sm = 0; spi_inst_t* hardware; void recv(int len) { command = WIRE.read(); @@ -106,6 +118,13 @@ void recv(int len) { mask = (1 << wtS0Pin) | (1 << wtS1Pin) | (1 << wtS2Pin); wt_sensitivity = WIRE.read() << 8 | WIRE.read(); hasInitWt = false; + wtShouldInit = true; + break; + case SLAVE_COMMAND_INIT_QUAD: + quadAPin = WIRE.read(); + quadPollRate = WIRE.read(); + hasInitQuad = false; + quadShouldInit = true; break; } } @@ -122,6 +141,10 @@ void req() { WIRE.write((uint8_t*)&rawWt, sizeof(rawWt)); break; } + case SLAVE_COMMAND_GET_QUAD: { + WIRE.write((uint8_t*)&delta, sizeof(delta)); + break; + } case SLAVE_COMMAND_GET_WT_RAW: { volatile uint8_t* data = (volatile uint8_t*)lastWt; for (uint8_t i = 0; i < sizeof(lastWt); i++) { @@ -172,9 +195,9 @@ uint32_t readWtSlave(int pin) { bool checkWtSlave(int pin) { return readWtSlave(pin) > initialWt[pin]; } - +uint32_t lastQuadPoll = 0; void loop() { - if (wtS2Pin && !hasInitWt) { + if (wtShouldInit && !hasInitWt) { hasInitWt = true; memset(initialWt, 0, sizeof(initialWt)); for (int j = 0; j < 1000; j++) { @@ -187,10 +210,20 @@ void loop() { initialWt[i] += wt_sensitivity; } } + if (quadShouldInit && !hasInitQuad) { + hasInitQuad = true; + quadrature_encoder_program_init(pio, sm, quadAPin, 0); + } if (hasInitWt) { checkWtSlave(6); rawWt = checkWtSlave(1) | (checkWtSlave(0) << 1) | (checkWtSlave(2) << 2) | (checkWtSlave(3) << 3) | (checkWtSlave(4) << 4); } + if (hasInitQuad && (lastQuadPoll - millis()) > quadPollRate) { + lastQuadPoll = millis(); + new_value = quadrature_encoder_get_count(pio, sm); + delta = new_value - old_value; + old_value = new_value; + } } void setup() { #ifdef TWI_1_SDA @@ -213,4 +246,5 @@ void setup() { WIRE.begin(SLAVE_ADDR); WIRE.onReceive(recv); WIRE.onRequest(req); + pio_add_program(pio, &quadrature_encoder_program); } \ No newline at end of file diff --git a/src/shared/main/inputs/slave.h b/src/shared/main/inputs/slave.h index d546ba8b7..49649ac26 100644 --- a/src/shared/main/inputs/slave.h +++ b/src/shared/main/inputs/slave.h @@ -92,6 +92,33 @@ void slaveWriteLED(uint8_t data) { } } +void slaveInitQuad(uint8_t pin, uint8_t rate) { + if (!slave_initted) { + return; + } + uint8_t data[] = {pin, rate}; + for (int i = 0; i < RETRY_COUNT; i++) { + slave_initted = twi_writeToPointer(SLAVE_TWI_PORT, SLAVE_ADDR, SLAVE_COMMAND_INIT_QUAD, sizeof(data), data); + if (slave_initted) { + return; + } + } +} +int slaveReadQuad() { + if (!slave_initted) { + return 0; + } + for (int i = 0; i < RETRY_COUNT; i++) { + int data = 0; + slave_initted = twi_readFromPointer(SLAVE_TWI_PORT, SLAVE_ADDR, SLAVE_COMMAND_GET_QUAD, sizeof(data), (uint8_t*)&data); + + if (slave_initted) { + return data; + } + } + return 0; +} + uint8_t slaveReadWt() { if (!slave_initted) { return 0; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index f30bca7fd..d2d537747 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -420,6 +420,9 @@ void tick_slave() #ifdef INPUT_WT_SLAVE_NECK slaveInitWt(); #endif +#ifdef INPUT_QUAD_SLAVE + slaveInitQuad(INPUT_QUAD_SLAVE,1); +#endif } #endif int16_t adc_i(uint8_t pin) From 614777595a197e2c2997f46d864f0837c55135d2 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 7 Oct 2025 20:11:58 +1300 Subject: [PATCH 113/239] probably support encoders for non peripheral --- src/shared/main/inputs/turntable.h | 9 +++++++++ src/shared/main/shared_main.cpp | 11 +++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/shared/main/inputs/turntable.h b/src/shared/main/inputs/turntable.h index a8db8f837..65e822bd8 100644 --- a/src/shared/main/inputs/turntable.h +++ b/src/shared/main/inputs/turntable.h @@ -1,4 +1,13 @@ #include "config.h" + +#ifdef INPUT_QUAD + if ((lastQuadPoll - millis()) > 1) { + lastQuadPoll = millis(); + new_value = quadrature_encoder_get_count(pio, sm); + delta = new_value - old_value; + old_value = new_value; + } +#endif #ifdef INPUT_DJ_TURNTABLE uint8_t *dj_left = lastSuccessfulTurntablePacketLeft; uint8_t *dj_right = lastSuccessfulTurntablePacketRight; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index d2d537747..e4fad37fd 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -24,6 +24,7 @@ #include "util.h" #include "wii.h" #include "wt_drum.h" +#include "quadrature_encoder.pio.h" #define UP 1 << 0 #define DOWN 1 << 1 #define LEFT 1 << 2 @@ -354,12 +355,22 @@ void setKey(uint8_t id, uint8_t key, USB_6KRO_Data_t *report) memset(report->KeyCode, KEY_ERR_OVF, sizeof(report->KeyCode)); return; } +int new_value, delta, old_value = 0; +int last_value = -1, last_delta = -1; +PIO pio = pio1; +const uint sm = 0; +spi_inst_t* hardware; uint8_t seq = 1; +uint32_t lastQuadPoll = 0; void init_main(void) { #if !DEVICE_TYPE_IS_GAMEPAD consoleType = UNIVERSAL; #endif + +#ifdef INPUT_QUAD + quadrature_encoder_program_init(pio, sm, INPUT_QUAD, 0); +#endif initPins(); twi_init(); spi_begin(); From 402bb69af8659fa819ca69615537ea38332318a0 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 7 Oct 2025 20:30:29 +1300 Subject: [PATCH 114/239] probably support encoders for non peripheral --- src/shared/main/shared_main.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index e4fad37fd..e09bc8295 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -359,7 +359,7 @@ int new_value, delta, old_value = 0; int last_value = -1, last_delta = -1; PIO pio = pio1; const uint sm = 0; -spi_inst_t* hardware; +spi_inst_t *hardware; uint8_t seq = 1; uint32_t lastQuadPoll = 0; void init_main(void) @@ -369,6 +369,7 @@ void init_main(void) #endif #ifdef INPUT_QUAD + pio_add_program(pio, &quadrature_encoder_program); quadrature_encoder_program_init(pio, sm, INPUT_QUAD, 0); #endif initPins(); @@ -432,7 +433,7 @@ void tick_slave() slaveInitWt(); #endif #ifdef INPUT_QUAD_SLAVE - slaveInitQuad(INPUT_QUAD_SLAVE,1); + slaveInitQuad(INPUT_QUAD_SLAVE, 1); #endif } #endif From 69bff650e73fccaea1627fbbc22dc8c4d5863979 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 8 Oct 2025 10:00:46 +1300 Subject: [PATCH 115/239] don't respond with og xbox caps for 360 --- src/shared/usb/descriptors.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 60d6f60af..30523e8aa 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -902,7 +902,7 @@ bool cleared_output = false; uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, uint8_t *requestBuffer, bool *status) { // printf("%02x %04x %04x %04x %04x\r\n", requestType, request, wValue, wIndex, wLength); #if DEVICE_TYPE_IS_GAMEPAD - if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR)) { + if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && (consoleType == UNIVERSAL || consoleType == OG_XBOX)) { seen_og_xbox = true; if (request == 6 && wValue == 0x4200) { memcpy_P(requestBuffer, &DukeXIDDescriptor, sizeof(DukeXIDDescriptor)); From c5ce11333d9d03a983debb2a8c557002f35f1670 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 8 Oct 2025 16:08:24 +1300 Subject: [PATCH 116/239] limit bh brain polling to 20ms --- src/shared/main/bh_drum.cpp | 43 ++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/src/shared/main/bh_drum.cpp b/src/shared/main/bh_drum.cpp index ff02dcc22..acf8309ce 100644 --- a/src/shared/main/bh_drum.cpp +++ b/src/shared/main/bh_drum.cpp @@ -10,23 +10,32 @@ bool bh_drum_found = false; static long lastTick = 0; static int missing = 0; -void tickBhDrum() { - // BH Drum format: 0x10 0x0 - uint8_t data[5]; - bh_drum_found = twi_readFromPointer(BH_DRUM_TWI_PORT, DRUM_ADDR, BH_DRUM_PTR, sizeof(data), data); - if (bh_drum_found) { - uint8_t status = data[2]; - uint8_t type = (status & 0xf0); - uint8_t channel = status & 0x0f; - // TODO: CC and stuff, can the midi lib parse this all for us? - if (type == 0x90) { - uint8_t note = data[3]; - uint8_t velocity = data[4]; - TRANSLATE_GH_MIDI(channel, note, velocity, onNote); - } else if (type == 0x80) { - uint8_t note = data[3]; - uint8_t velocity = data[4]; - TRANSLATE_GH_MIDI(channel, note, velocity, offNote); +void tickBhDrum() +{ + if (micros() - lastTick > 20000) + { + lastTick = micros(); + // BH Drum format: 0x10 0x0 + uint8_t data[5]; + bh_drum_found = twi_readFromPointer(BH_DRUM_TWI_PORT, DRUM_ADDR, BH_DRUM_PTR, sizeof(data), data); + if (bh_drum_found) + { + uint8_t status = data[2]; + uint8_t type = (status & 0xf0); + uint8_t channel = status & 0x0f; + // TODO: CC and stuff, can the midi lib parse this all for us? + if (type == 0x90) + { + uint8_t note = data[3]; + uint8_t velocity = data[4]; + TRANSLATE_GH_MIDI(channel, note, velocity, onNote); + } + else if (type == 0x80) + { + uint8_t note = data[3]; + uint8_t velocity = data[4]; + TRANSLATE_GH_MIDI(channel, note, velocity, offNote); + } } } } From d0a6305b1e7c8357193b8066efdbc0bfae516f06 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 10 Oct 2025 08:09:41 +1300 Subject: [PATCH 117/239] allow specifying sections being mapped --- src/shared/main/shared_main.cpp | 50 ++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index e09bc8295..033711d84 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -442,7 +442,7 @@ int16_t adc_i(uint8_t pin) int32_t ret = adc(pin); return ret - 32767; } -int16_t handle_calibration_xbox(int16_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, int16_t deadzone) +int16_t handle_calibration_xbox(int16_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, int16_t deadzone, uint8_t section) { int32_t val = orig_val; if (val > INT16_MAX) @@ -453,27 +453,33 @@ int16_t handle_calibration_xbox(int16_t previous, int32_t orig_val, int16_t min, { val = INT16_MIN; } - if (val < center) - { - if ((center - val) < deadzone) - { - val = 0; - } - else - { - val = map(val, min, center - deadzone, INT16_MIN, 0); - } - } - else - { - if ((val - center) < deadzone) + if (section == 0) { + if (val < center) { - val = 0; + if ((center - val) < deadzone) + { + val = 0; + } + else + { + val = map(val, min, center - deadzone, INT16_MIN, 0); + } } else { - val = map(val, center + deadzone, max, 0, INT16_MAX); + if ((val - center) < deadzone) + { + val = 0; + } + else + { + val = map(val, center + deadzone, max, 0, INT16_MAX); + } } + } else if (section == 1) { + val = map(val, min, max, INT16_MIN, 0); + } else if (section == 2) { + val = map(val, min, max, 0, INT16_MAX); } if (val > INT16_MAX) { @@ -594,15 +600,15 @@ uint16_t handle_calibration_drum(uint16_t previous, uint16_t orig_val, uint32_t } return previous; } -uint8_t handle_calibration_ps3(uint8_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, int16_t deadzone) +uint8_t handle_calibration_ps3(uint8_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, int16_t deadzone, uint8_t section) { - int8_t ret = handle_calibration_xbox((previous - PS3_STICK_CENTER) << 8, orig_val, min, max, center, deadzone) >> 8; + int8_t ret = handle_calibration_xbox((previous - PS3_STICK_CENTER) << 8, orig_val, min, max, center, deadzone, section) >> 8; return (uint8_t)(ret + PS3_STICK_CENTER); } int8_t handle_calibration_mouse(int8_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, int16_t deadzone) { - return handle_calibration_xbox(previous << 8, orig_val, min, max, center, deadzone) >> 8; + return handle_calibration_xbox(previous << 8, orig_val, min, max, center, deadzone, 0) >> 8; } uint8_t handle_calibration_ps3_360_trigger(uint8_t previous, uint16_t orig_val, uint32_t min, int16_t multiplier, uint16_t deadzone) @@ -617,13 +623,13 @@ uint16_t handle_calibration_ps3_accel(uint16_t previous, int32_t orig_val, int16 // Also, the game is looking for the value going negative, not positive int16_t ret = (-(handle_calibration_xbox(-((previous - PS3_ACCEL_CENTER) << 8), orig_val, min, max, center, deadzone) >> 8)); #else - int16_t ret = handle_calibration_xbox((previous - PS3_ACCEL_CENTER) << 6, orig_val, min, max, center, deadzone) >> 6; + int16_t ret = handle_calibration_xbox((previous - PS3_ACCEL_CENTER) << 6, orig_val, min, max, center, deadzone, 0) >> 6; #endif return PS3_ACCEL_CENTER + ret; } uint8_t handle_calibration_arcade_accel(uint16_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, uint16_t deadzone) { - int8_t ret = handle_calibration_xbox((previous - 65) << 9, orig_val, min, max, center, deadzone) >> 9; + int8_t ret = handle_calibration_xbox((previous - 65) << 9, orig_val, min, max, center, deadzone, 0) >> 9; return (uint8_t)(ret + 65); } long last_zero = 0; From 45fc75955cedf2a919a35576ac277a7c9deca5b6 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 13 Oct 2025 09:15:46 +1300 Subject: [PATCH 118/239] add missing section --- src/shared/main/shared_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 033711d84..3bc88daf6 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -621,7 +621,7 @@ uint16_t handle_calibration_ps3_accel(uint16_t previous, int32_t orig_val, int16 #if DEVICE_TYPE_IS_GUITAR || DEVICE_TYPE_IS_LIVE_GUITAR // For whatever reason, the acceleration for guitars swings between -128 to 128, not -512 to 512 // Also, the game is looking for the value going negative, not positive - int16_t ret = (-(handle_calibration_xbox(-((previous - PS3_ACCEL_CENTER) << 8), orig_val, min, max, center, deadzone) >> 8)); + int16_t ret = (-(handle_calibration_xbox(-((previous - PS3_ACCEL_CENTER) << 8), orig_val, min, max, center, deadzone, 0) >> 8)); #else int16_t ret = handle_calibration_xbox((previous - PS3_ACCEL_CENTER) << 6, orig_val, min, max, center, deadzone, 0) >> 6; #endif From 64638547ae84143625b3decb83a5a8f0fa95628c Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 21 Oct 2025 21:49:55 +1300 Subject: [PATCH 119/239] we dont have arduinos anymore, simplify matrix --- include/ads1115.h | 80 +++++++++++++++++++++++++++++++++++++ include/commands.h | 1 + src/pico/pins.cpp | 14 +++---- src/shared/hid/hid.cpp | 8 ++++ src/shared/main/ads1115.cpp | 70 ++++++++++++++++++++++++++++++++ 5 files changed, 164 insertions(+), 9 deletions(-) create mode 100644 include/ads1115.h create mode 100644 src/shared/main/ads1115.cpp diff --git a/include/ads1115.h b/include/ads1115.h new file mode 100644 index 000000000..8a0abe5dd --- /dev/null +++ b/include/ads1115.h @@ -0,0 +1,80 @@ +#pragma once + +#include "io.h" +#define ADS1115_ADDRESS_ADDR_GND 0x48 // address pin low (GND) +#define ADS1115_ADDRESS_ADDR_VDD 0x49 // address pin high (VCC) +#define ADS1115_ADDRESS_ADDR_SDA 0x4A // address pin tied to SDA pin +#define ADS1115_ADDRESS_ADDR_SCL 0x4B // address pin tied to SCL pin +#define ADS1115_RA_CONVERSION 0x00 +#define ADS1115_RA_CONFIG 0x01 +#define ADS1115_RA_LO_THRESH 0x02 +#define ADS1115_RA_HI_THRESH 0x03 + +#define ADS1115_CFG_OS_BIT 15 +#define ADS1115_CFG_MUX_BIT 14 +#define ADS1115_CFG_MUX_LENGTH 3 +#define ADS1115_CFG_PGA_BIT 11 +#define ADS1115_CFG_PGA_LENGTH 3 +#define ADS1115_CFG_MODE_BIT 8 +#define ADS1115_CFG_DR_BIT 7 +#define ADS1115_CFG_DR_LENGTH 3 +#define ADS1115_CFG_COMP_MODE_BIT 4 +#define ADS1115_CFG_COMP_POL_BIT 3 +#define ADS1115_CFG_COMP_LAT_BIT 2 +#define ADS1115_CFG_COMP_QUE_BIT 1 +#define ADS1115_CFG_COMP_QUE_LENGTH 2 + + +#define ADS1115_MUX_P0_N1 0x00 // default +#define ADS1115_MUX_P0_N3 0x01 +#define ADS1115_MUX_P1_N3 0x02 +#define ADS1115_MUX_P2_N3 0x03 +#define ADS1115_MUX_P0_NG 0x04 +#define ADS1115_MUX_P1_NG 0x05 +#define ADS1115_MUX_P2_NG 0x06 +#define ADS1115_MUX_P3_NG 0x07 + +#define ADS1115_PGA_6P144 0x00 +#define ADS1115_PGA_4P096 0x01 +#define ADS1115_PGA_2P048 0x02 // default +#define ADS1115_PGA_1P024 0x03 +#define ADS1115_PGA_0P512 0x04 +#define ADS1115_PGA_0P256 0x05 +#define ADS1115_PGA_0P256B 0x06 +#define ADS1115_PGA_0P256C 0x07 + +#define ADS1115_MV_6P144 0.187500 +#define ADS1115_MV_4P096 0.125000 +#define ADS1115_MV_2P048 0.062500 // default +#define ADS1115_MV_1P024 0.031250 +#define ADS1115_MV_0P512 0.015625 +#define ADS1115_MV_0P256 0.007813 +#define ADS1115_MV_0P256B 0.007813 +#define ADS1115_MV_0P256C 0.007813 + +#define ADS1115_MODE_CONTINUOUS 0x00 +#define ADS1115_MODE_SINGLESHOT 0x01 // default + +#define ADS1115_RATE_8 0x00 +#define ADS1115_RATE_16 0x01 +#define ADS1115_RATE_32 0x02 +#define ADS1115_RATE_64 0x03 +#define ADS1115_RATE_128 0x04 // default +#define ADS1115_RATE_250 0x05 +#define ADS1115_RATE_475 0x06 +#define ADS1115_RATE_860 0x07 + +#define ADS1115_COMP_MODE_HYSTERESIS 0x00 // default +#define ADS1115_COMP_MODE_WINDOW 0x01 + +#define ADS1115_COMP_POL_ACTIVE_LOW 0x00 // default +#define ADS1115_COMP_POL_ACTIVE_HIGH 0x01 + +#define ADS1115_COMP_LAT_NON_LATCHING 0x00 // default +#define ADS1115_COMP_LAT_LATCHING 0x01 + +#define ADS1115_COMP_QUE_ASSERT1 0x00 +#define ADS1115_COMP_QUE_ASSERT2 0x01 +#define ADS1115_COMP_QUE_ASSERT4 0x02 +#define ADS1115_COMP_QUE_DISABLE 0x03 // default +#define ADS1115_REG_RESET_VAL 0b1100001111100000 \ No newline at end of file diff --git a/include/commands.h b/include/commands.h index f97c1a94a..086c48fa0 100644 --- a/include/commands.h +++ b/include/commands.h @@ -54,6 +54,7 @@ enum SerialCommands { COMMAND_WT_DRUM_VALID, COMMAND_BH_DRUM_VALID, COMMAND_READ_CRKD, + COMMAND_READ_MATRIX, MAX=100 }; diff --git a/src/pico/pins.cpp b/src/pico/pins.cpp index e59483d88..fad294134 100644 --- a/src/pico/pins.cpp +++ b/src/pico/pins.cpp @@ -103,14 +103,10 @@ uint16_t multiplexer_read(uint8_t pin, uint32_t mask, uint32_t bits) { } return 0; } - uint8_t matrix_read(uint8_t pin, uint8_t outPin) { - if (!disable_multiplexer) { - gpio_put(outPin, 0); - sleep_us(1); - uint8_t ret = gpio_get(pin); - gpio_put(outPin, 1); - return ret; - } - return 1; + gpio_put(outPin, 0); + sleep_us(1); + uint8_t ret = gpio_get(pin); + gpio_put(outPin, 1); + return ret; } \ No newline at end of file diff --git a/src/shared/hid/hid.cpp b/src/shared/hid/hid.cpp index 03fe48757..50f9e53c4 100644 --- a/src/shared/hid/hid.cpp +++ b/src/shared/hid/hid.cpp @@ -914,6 +914,14 @@ uint8_t handle_serial_command(uint8_t request, uint16_t wValue, uint8_t *respons } case COMMAND_DISABLE_MULTIPLEXER: { disable_multiplexer = response_buffer[0]; + return 0; + } + + case COMMAND_READ_MATRIX: { + uint8_t outPin = wValue & 0xff; + uint8_t pin = (wValue >> 8); + response_buffer[0] = matrix_read(pin, outPin); + return 1; } case COMMAND_READ_MIDI: { memcpy(response_buffer, &midiData.midiVelocities, (sizeof(Midi_Data_t) - offsetof(Midi_Data_t, midiVelocities))); diff --git a/src/shared/main/ads1115.cpp b/src/shared/main/ads1115.cpp new file mode 100644 index 000000000..07c121310 --- /dev/null +++ b/src/shared/main/ads1115.cpp @@ -0,0 +1,70 @@ +#include +#include "io.h" +#include "ads1115.h" +#ifdef ADS115_TWI_PORT +static uint16_t config; +static volatile bool rdy; +static bool connected = false; +static uint8_t current = 0; +static uint16_t inputs[4]; +bool writeRegister(uint8_t reg, uint16_t val) +{ + uint8_t data[] = {(uint8_t)((val >> 8) & 0xFF), (uint8_t)(val & 0xFF)}; + return twi_writeToPointer(ADS115_TWI_PORT, ADS1115_ADDRESS_ADDR_GND, reg, sizeof(data), data); +} +uint16_t readRegister(uint8_t reg) +{ + uint8_t data[2] = {}; + if (!twi_readFromPointer(ADS115_TWI_PORT, ADS1115_ADDRESS_ADDR_GND, reg, sizeof(data), data)) + { + return 0; + } + return (data[0] << 8) + data[1]; +} +void tick() +{ + if (!connected) + { + init(); + return; + } + config = readRegister(ADS1115_RA_CONFIG); + if (rdy) + { + rdy = false; + inputs[current] = readRegister(ADS1115_RA_CONVERSION) << 1; + current++; + if (current > 3) + { + current = 0; + } + config &= ~(0xF000); + config |= (0x4000 + (current * 0x1000)); + config |= 1<<15; + connected = writeRegister(ADS1115_RA_CONFIG, config); + + } +} +void cb(uint gpio, uint32_t event_mask) { + rdy = true; +} +void init() +{ + if (!readRegister(ADS1115_RA_CONFIG)) + { + connected = false; + return; + } + connected = true; + current = 0; + gpio_init(ADS115_ALERT); + gpio_set_dir(ADS115_ALERT, false); + gpio_pull_up(ADS115_ALERT); + + gpio_set_irq_enabled_with_callback(ADS115_ALERT, GPIO_IRQ_EDGE_FALL, true, &cb); + config = ADS1115_REG_RESET_VAL; + connected = writeRegister(ADS1115_RA_CONFIG, ADS1115_REG_RESET_VAL); + connected = writeRegister(ADS1115_RA_LO_THRESH, (0 << 15)); + connected = writeRegister(ADS1115_RA_HI_THRESH, (1 << 15)); +} +#endif \ No newline at end of file From 2770dd88d67a19b312260d71e9993348a4092931 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 8 Nov 2025 10:01:52 +1300 Subject: [PATCH 120/239] add missing ids --- include/endpoints.h | 2 ++ src/shared/main/shared_main.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/include/endpoints.h b/include/endpoints.h index 3315115eb..66650aed6 100644 --- a/include/endpoints.h +++ b/include/endpoints.h @@ -57,6 +57,7 @@ enum endpoints_t { #define PS3_GH_DRUM_PID 0x0120 #define PS3_RB_GUITAR_PID 0x0200 #define PS3_RB_DRUM_PID 0x0210 +#define PS3_MPA_DRUM_PID 0x0218 #define PS3_DJ_TURNTABLE_PID 0x0140 #define PS3_MUSTANG_PID 0x2430 #define PS3_SQUIRE_PID 0x2530 @@ -78,6 +79,7 @@ enum endpoints_t { #define WII_MUSTANG_MPA_PID 0x3438 #define WII_SQUIRE_MPA_PID 0x3538 #define WII_DRUMS_PID 0x3130 +#define WII_MPA_DRUMS_PID 0x3138 #define WII_MPA_KEYBOARD_PID 0x3338 #define WII_KEYBOARD_PID 0x3330 #define MAD_CATZ_VID 0x0738 diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 3bc88daf6..41d05d0de 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -4277,6 +4277,7 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D type->console_type = PS3; type->sub_type = ROCK_BAND_GUITAR; break; + case PS3_MPA_DRUM_PID: case PS3_RB_DRUM_PID: type->console_type = PS3; type->sub_type = ROCK_BAND_DRUMS; @@ -4332,6 +4333,7 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D type->drum_type = DRUM_RB1; break; case WII_RB_DRUM_2_PID: + case WII_MPA_DRUMS_PID: type->console_type = PS3; type->sub_type = ROCK_BAND_DRUMS; type->drum_type = DRUM_RB2; From 5901821aa267b9e9de27d3beb6522f374c49bc3c Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 8 Nov 2025 10:05:00 +1300 Subject: [PATCH 121/239] add missing ids --- src/shared/main/shared_main.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 41d05d0de..b3ac0aab1 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -4278,6 +4278,10 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D type->sub_type = ROCK_BAND_GUITAR; break; case PS3_MPA_DRUM_PID: + type->console_type = PS3; + type->sub_type = ROCK_BAND_DRUMS; + type->drum_type = DRUM_RB2; + break; case PS3_RB_DRUM_PID: type->console_type = PS3; type->sub_type = ROCK_BAND_DRUMS; From 75edf14f424028d0e8ee45d4b9c4f3268cc1ea77 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 9 Nov 2025 19:07:13 +1300 Subject: [PATCH 122/239] subtype is xinput drums not ps drums --- src/shared/main/shared_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index b3ac0aab1..ef2c88880 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -4359,7 +4359,7 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D break; case XBOX_360_ION_ROCKER_VID: type->console_type = XBOX360; - type->sub_type = ROCK_BAND_DRUMS; + type->sub_type = XINPUT_DRUMS; type->drum_type = DRUM_RB2; break; } From b91203f80d5d5323f0a29f6b4b4435a98caaebe2 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 9 Nov 2025 19:47:11 +1300 Subject: [PATCH 123/239] dont override subtype for ion 360 drum --- src/shared/main/shared_main.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index ef2c88880..c3241328e 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -4358,8 +4358,6 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D type->sub_type = ROCK_BAND_PRO_GUITAR_SQUIRE; break; case XBOX_360_ION_ROCKER_VID: - type->console_type = XBOX360; - type->sub_type = XINPUT_DRUMS; type->drum_type = DRUM_RB2; break; } From f54c8fc92b8df2d75483ccb6a1e6ed84841b128e Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 11 Nov 2025 09:31:44 +1300 Subject: [PATCH 124/239] more ion fixes --- include/defines.h | 1 + include/reports/xinput_reports.h | 10 +++++----- include/state_translation/drums.h | 18 +++++++----------- src/shared/main/shared_main.cpp | 16 +++++++++++++++- 4 files changed, 28 insertions(+), 17 deletions(-) diff --git a/include/defines.h b/include/defines.h index 32f041120..0ba5bb65c 100644 --- a/include/defines.h +++ b/include/defines.h @@ -150,6 +150,7 @@ #define DRUM_RB1 1 #define DRUM_RB2 2 #define DRUM_GH 3 +#define DRUM_ION 4 #define GUITAR_CHECK 1 typedef enum { diff --git a/include/reports/xinput_reports.h b/include/reports/xinput_reports.h index da1c19a4c..e9460d532 100644 --- a/include/reports/xinput_reports.h +++ b/include/reports/xinput_reports.h @@ -181,11 +181,11 @@ typedef struct uint8_t x : 1; // blue uint8_t y : 1; // yellow - uint8_t unused[2]; - int16_t redVelocity; - int16_t yellowVelocity; - int16_t blueVelocity; - int16_t greenVelocity; + uint8_t unused[2]; // trigger + int16_t redVelocity; // lx + int16_t yellowVelocity; // ly + int16_t blueVelocity; // rx + int16_t greenVelocity; // ry uint8_t reserved_1[6]; } __attribute__((packed)) XInputRockBandDrums_Data_t; diff --git a/include/state_translation/drums.h b/include/state_translation/drums.h index 8d6d080e4..0c3cb0dd6 100644 --- a/include/state_translation/drums.h +++ b/include/state_translation/drums.h @@ -124,18 +124,14 @@ if (kick1) \ { \ onNote(10, RB_MIDI_NOTE_KICK, 0x7F); \ - } \ - else \ - { \ - offNote(10, RB_MIDI_NOTE_KICK, 0); \ - } \ - if (kick2) \ + } \ + /*ion kits dont have the second pedal and send out signals like its always on, so ignore that*/ \ + if (device_type.drum_type != DRUM_ION) \ { \ - onNote(10, RB_MIDI_NOTE_KICK2, 0x7F); \ - } \ - else \ - { \ - offNote(10, RB_MIDI_NOTE_KICK2, 0); \ + if (kick2) \ + { \ + onNote(10, RB_MIDI_NOTE_KICK2, 0x7F); \ + } \ } #if DEVICE_TYPE == ROCK_BAND_DRUMS #define SET_GH_PADS() \ diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index c3241328e..e7a742378 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3173,6 +3173,13 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu // Whammy on the xbox guitars goes from min to max, so it needs to default to min #if DEVICE_TYPE_IS_GUITAR || DEVICE_TYPE_IS_LIVE_GUITAR report->whammy = INT16_MIN; +#endif +#if DEVICE_TYPE == ROCK_BAND_DRUMS +// rb drums have some weird logic so this is what we need to send when nothing is hit + report->redVelocity = -1; + report->blueVelocity = -1; + report->greenVelocity = 0; + report->yellowVelocity = 0; #endif TICK_XINPUT; @@ -3499,6 +3506,13 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu { #endif PS3_REPORT *report = (PS3_REPORT *)report_data; +// rb drums have inverted velocity so they start at 0 +#if DEVICE_TYPE == ROCK_BAND_DRUMS + report->redVelocity = 0; + report->blueVelocity = 0; + report->greenVelocity = 0; + report->yellowVelocity = 0; +#endif #if DEVICE_TYPE == ROCK_BAND_GUITAR report->whammy = 0; #endif @@ -4358,7 +4372,7 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D type->sub_type = ROCK_BAND_PRO_GUITAR_SQUIRE; break; case XBOX_360_ION_ROCKER_VID: - type->drum_type = DRUM_RB2; + type->drum_type = DRUM_ION; break; } From 9b2697553a8425ea95395e1f6304f208b121e80d Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 21 Nov 2025 08:14:33 +1300 Subject: [PATCH 125/239] xbox360 does not need reports every frame --- src/shared/main/shared_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index e7a742378..cd4d9d3bf 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3607,7 +3607,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } TICK_RESET // Some hosts want packets sent every frame - if (last_report && output_console_type != ARCADE && output_console_type != OG_XBOX && output_console_type != PS4 && output_console_type != IOS_FESTIVAL && output_console_type != PS3 && output_console_type != BLUETOOTH_REPORT && output_console_type != XBOX360 && !updateHIDSequence) + if (last_report && output_console_type != ARCADE && output_console_type != OG_XBOX && output_console_type != PS4 && output_console_type != IOS_FESTIVAL && output_console_type != PS3 && output_console_type != BLUETOOTH_REPORT && !updateHIDSequence) { uint8_t cmp = memcmp(last_report, report_data, report_size); if (cmp == 0) From 38383ba8f73adfa9f3fa98aedf7f323ad5de4982 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 5 Dec 2025 07:28:24 +1300 Subject: [PATCH 126/239] ignore slider if it is zeroed --- include/reports/pc_reports.h | 1 - src/shared/main/shared_main.cpp | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/reports/pc_reports.h b/include/reports/pc_reports.h index 5d881d84f..727b5734b 100644 --- a/include/reports/pc_reports.h +++ b/include/reports/pc_reports.h @@ -311,7 +311,6 @@ typedef struct uint8_t pickup; uint8_t tilt; } __attribute__((packed)) PCRockBandGuitar_Data_t; - typedef struct { uint8_t reportId; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index cd4d9d3bf..55cc397bb 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1063,7 +1063,9 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t { usb_host_data->whammy = report->whammy; } - usb_host_data->slider = report->slider; + if (report->slider != PS3_STICK_CENTER) { + usb_host_data->slider = report->slider; + } break; } case ROCK_BAND_GUITAR: From 8466e74ffd2ec79a9fae8f6a0c06c79f6110d19e Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 10 Dec 2025 11:07:04 +1300 Subject: [PATCH 127/239] see if reordering accelerometers helps mpu6050 --- src/shared/main/accel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/accel.cpp b/src/shared/main/accel.cpp index 6da288d44..50a8d734d 100644 --- a/src/shared/main/accel.cpp +++ b/src/shared/main/accel.cpp @@ -52,9 +52,9 @@ void init_mpu6050() { twi_writeSingleToPointer(ACCEL_TWI_PORT, MPU6050_ADDRESS, MPU6050_REG_PWR_MGMT_1, id); } void init_accel() { + init_mpu6050(); init_lis3dh(); init_adxl(); - init_mpu6050(); } void tick_accel() { if (!accel_found) { From b7818e0f14ad4ce2e56ec1dde4f5c58aea786586 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 10 Dec 2025 14:38:54 +1300 Subject: [PATCH 128/239] poll bh drums in a nicer way --- src/shared/main/bh_drum.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/shared/main/bh_drum.cpp b/src/shared/main/bh_drum.cpp index acf8309ce..55834bf02 100644 --- a/src/shared/main/bh_drum.cpp +++ b/src/shared/main/bh_drum.cpp @@ -8,32 +8,32 @@ #define BH_DRUM_PTR 0x10 #ifdef BH_DRUM_TWI_PORT bool bh_drum_found = false; -static long lastTick = 0; -static int missing = 0; void tickBhDrum() { - if (micros() - lastTick > 20000) + // Drum packet starts with some counter, and then the number of packets in the buffer + uint8_t data[2]; + bh_drum_found = twi_readFromPointer(BH_DRUM_TWI_PORT, DRUM_ADDR, BH_DRUM_PTR, sizeof(data), data); + if (bh_drum_found) { - lastTick = micros(); - // BH Drum format: 0x10 0x0 - uint8_t data[5]; - bh_drum_found = twi_readFromPointer(BH_DRUM_TWI_PORT, DRUM_ADDR, BH_DRUM_PTR, sizeof(data), data); - if (bh_drum_found) + // Stream out the rest of the packets byte by byte as the drums lock up otherwise. + uint8_t count = data[1] >> 4; + for (int i = 0; i < count; i++) { - uint8_t status = data[2]; + uint8_t status; + uint8_t note; + uint8_t velocity; + bh_drum_found = twi_readFrom(BH_DRUM_TWI_PORT, DRUM_ADDR, &status, 1, 1); + bh_drum_found = twi_readFrom(BH_DRUM_TWI_PORT, DRUM_ADDR, ¬e, 1, 1); + bh_drum_found = twi_readFrom(BH_DRUM_TWI_PORT, DRUM_ADDR, &velocity, 1, 1); uint8_t type = (status & 0xf0); uint8_t channel = status & 0x0f; // TODO: CC and stuff, can the midi lib parse this all for us? if (type == 0x90) { - uint8_t note = data[3]; - uint8_t velocity = data[4]; TRANSLATE_GH_MIDI(channel, note, velocity, onNote); } else if (type == 0x80) { - uint8_t note = data[3]; - uint8_t velocity = data[4]; TRANSLATE_GH_MIDI(channel, note, velocity, offNote); } } From 5d9ab89f55162c1f8522c38d2e1cdc7c533a3498 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 10 Dec 2025 22:08:28 +1300 Subject: [PATCH 129/239] better bh drums --- src/shared/main/bh_drum.cpp | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/shared/main/bh_drum.cpp b/src/shared/main/bh_drum.cpp index 55834bf02..24ee73a44 100644 --- a/src/shared/main/bh_drum.cpp +++ b/src/shared/main/bh_drum.cpp @@ -11,30 +11,26 @@ bool bh_drum_found = false; void tickBhDrum() { // Drum packet starts with some counter, and then the number of packets in the buffer - uint8_t data[2]; - bh_drum_found = twi_readFromPointer(BH_DRUM_TWI_PORT, DRUM_ADDR, BH_DRUM_PTR, sizeof(data), data); + uint8_t header[2]; + uint8_t data[3]; + bh_drum_found = twi_readFromPointer(BH_DRUM_TWI_PORT, DRUM_ADDR, BH_DRUM_PTR, sizeof(header), header); if (bh_drum_found) { // Stream out the rest of the packets byte by byte as the drums lock up otherwise. - uint8_t count = data[1] >> 4; + uint8_t count = header[1] >> 4; for (int i = 0; i < count; i++) { - uint8_t status; - uint8_t note; - uint8_t velocity; - bh_drum_found = twi_readFrom(BH_DRUM_TWI_PORT, DRUM_ADDR, &status, 1, 1); - bh_drum_found = twi_readFrom(BH_DRUM_TWI_PORT, DRUM_ADDR, ¬e, 1, 1); - bh_drum_found = twi_readFrom(BH_DRUM_TWI_PORT, DRUM_ADDR, &velocity, 1, 1); - uint8_t type = (status & 0xf0); - uint8_t channel = status & 0x0f; + bh_drum_found = twi_readFrom(BH_DRUM_TWI_PORT, DRUM_ADDR, data, sizeof(data), true); + uint8_t type = (data[0] & 0xf0); + uint8_t channel = data[0] & 0x0f; // TODO: CC and stuff, can the midi lib parse this all for us? if (type == 0x90) { - TRANSLATE_GH_MIDI(channel, note, velocity, onNote); + TRANSLATE_GH_MIDI(channel, data[1], data[2], onNote); } else if (type == 0x80) { - TRANSLATE_GH_MIDI(channel, note, velocity, offNote); + TRANSLATE_GH_MIDI(channel, data[1], data[2], offNote); } } } From 4268f09943639fb3c6d3fc78f4fe5b0d41d1ae10 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 10 Dec 2025 22:16:26 +1300 Subject: [PATCH 130/239] better gh5 neck --- include/gh5_neck.h | 1 + src/shared/main/gh5_neck.cpp | 28 ++++++++++++++++++++++++++++ src/shared/main/inputs/gh5_neck.h | 5 ++--- src/shared/main/shared_main.cpp | 4 ++-- 4 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 include/gh5_neck.h create mode 100644 src/shared/main/gh5_neck.cpp diff --git a/include/gh5_neck.h b/include/gh5_neck.h new file mode 100644 index 000000000..96cead4cc --- /dev/null +++ b/include/gh5_neck.h @@ -0,0 +1 @@ +void tickGh5Neck(void); \ No newline at end of file diff --git a/src/shared/main/gh5_neck.cpp b/src/shared/main/gh5_neck.cpp new file mode 100644 index 000000000..1c6b6fcbf --- /dev/null +++ b/src/shared/main/gh5_neck.cpp @@ -0,0 +1,28 @@ +#include + +#include "Arduino.h" +#include "io.h" +#include "shared_main.h" +#include "commands.h" +#define GH5NECK_ADDR 0x0D +#define GH5NECK_BUTTONS_PTR 0x10 +#ifdef GH5_TWI_PORT +bool lastGH5WasSuccessful = false; +void tickGh5Neck() +{ + // Drum packet starts with some counter, and then the number of packets in the buffer + uint8_t header[2]; + uint8_t data[2]; + lastGH5WasSuccessful = twi_readFromPointer(GH5_TWI_PORT, GH5NECK_ADDR, GH5NECK_BUTTONS_PTR, sizeof(header), header); + if (lastGH5WasSuccessful) + { + // Stream out the rest of the packets byte by byte as the drums lock up otherwise. + uint8_t count = header[1] >> 4; + for (int i = 0; i < count; i++) + { + lastGH5WasSuccessful = twi_readFrom(GH5_TWI_PORT, GH5NECK_ADDR, data, sizeof(data), true); + memcpy(lastSuccessfulGH5Packet, data, sizeof(data)); + } + } +} +#endif \ No newline at end of file diff --git a/src/shared/main/inputs/gh5_neck.h b/src/shared/main/inputs/gh5_neck.h index ff66d4e47..c66f4b29e 100644 --- a/src/shared/main/inputs/gh5_neck.h +++ b/src/shared/main/inputs/gh5_neck.h @@ -1,5 +1,4 @@ #ifdef INPUT_GH5_NECK - uint8_t *fivetar_buttons = lastSuccessfulGH5Packet; - bool gh5Valid = twi_readFromPointer(GH5_TWI_PORT, GH5NECK_ADDR, GH5NECK_BUTTONS_PTR, sizeof(lastSuccessfulGH5Packet), lastSuccessfulGH5Packet); - lastGH5WasSuccessful = gh5Valid; +uint8_t *fivetar_buttons = lastSuccessfulGH5Packet; +tickGh5Neck(); #endif \ No newline at end of file diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 55cc397bb..e43fcf0fc 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3,6 +3,7 @@ #include "Arduino.h" #include "accel.h" #include "bh_drum.h" +#include "gh5_neck.h" #include "bt.h" #include "config.h" #include "controllers.h" @@ -37,7 +38,7 @@ static const uint8_t dpad_bindings_reverse[] = {UP, UP | RIGHT, RIGHT, DOWN | RI #define GH5NECK_ADDR 0x0D #define CLONE_ADDR 0x10 #define CLONE_VALID_PACKET 0x52 -#define GH5NECK_BUTTONS_PTR 0x12 +#define GH5NECK_BUTTONS_PTR 0x10 #define BUFFER_SIZE_QUEUE 255 #define KEY_ERR_OVF 0x01 #define REQUIRE_LED_DEBOUNCE LED_COUNT || LED_COUNT_PERIPHERAL || LED_COUNT_STP || LED_COUNT_PERIPHERAL_STP || LED_COUNT_WS2812 || LED_COUNT_PERIPHERAL_WS2812 || HAS_LED_OUTPUT || LED_COUNT_MPR121 @@ -256,7 +257,6 @@ uint8_t lastSuccessfulClonePacket[4]; uint8_t lastSuccessfulTurntablePacketLeft[3]; uint8_t lastSuccessfulTurntablePacketRight[3]; long lastSuccessfulGHWTPacket; -bool lastGH5WasSuccessful = false; bool lastCloneWasSuccessful = false; bool lastTurntableWasSuccessfulLeft = false; bool lastTurntableWasSuccessfulRight = false; From 1c3c8c6f19836eef002ca02671c6b5e54dee7596 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 10 Dec 2025 22:21:54 +1300 Subject: [PATCH 131/239] better gh5 neck --- src/shared/main/gh5_neck.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/shared/main/gh5_neck.cpp b/src/shared/main/gh5_neck.cpp index 1c6b6fcbf..50afa5980 100644 --- a/src/shared/main/gh5_neck.cpp +++ b/src/shared/main/gh5_neck.cpp @@ -14,15 +14,10 @@ void tickGh5Neck() uint8_t header[2]; uint8_t data[2]; lastGH5WasSuccessful = twi_readFromPointer(GH5_TWI_PORT, GH5NECK_ADDR, GH5NECK_BUTTONS_PTR, sizeof(header), header); - if (lastGH5WasSuccessful) + if (lastGH5WasSuccessful && header[1]) { - // Stream out the rest of the packets byte by byte as the drums lock up otherwise. - uint8_t count = header[1] >> 4; - for (int i = 0; i < count; i++) - { - lastGH5WasSuccessful = twi_readFrom(GH5_TWI_PORT, GH5NECK_ADDR, data, sizeof(data), true); - memcpy(lastSuccessfulGH5Packet, data, sizeof(data)); - } + lastGH5WasSuccessful = twi_readFrom(GH5_TWI_PORT, GH5NECK_ADDR, data, sizeof(data), true); + memcpy(lastSuccessfulGH5Packet, data, sizeof(data)); } } #endif \ No newline at end of file From eeb36aaed7c5c57d807e0c22bf68bdac27a98cc6 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 10 Dec 2025 22:31:52 +1300 Subject: [PATCH 132/239] better gh5 neck --- src/shared/main/bh_drum.cpp | 2 +- src/shared/main/gh5_neck.cpp | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/shared/main/bh_drum.cpp b/src/shared/main/bh_drum.cpp index 24ee73a44..19ed796be 100644 --- a/src/shared/main/bh_drum.cpp +++ b/src/shared/main/bh_drum.cpp @@ -13,7 +13,7 @@ void tickBhDrum() // Drum packet starts with some counter, and then the number of packets in the buffer uint8_t header[2]; uint8_t data[3]; - bh_drum_found = twi_readFromPointer(BH_DRUM_TWI_PORT, DRUM_ADDR, BH_DRUM_PTR, sizeof(header), header); + bh_drum_found = twi_readFromPointerRepeatedStart(BH_DRUM_TWI_PORT, DRUM_ADDR, BH_DRUM_PTR, sizeof(header), header); if (bh_drum_found) { // Stream out the rest of the packets byte by byte as the drums lock up otherwise. diff --git a/src/shared/main/gh5_neck.cpp b/src/shared/main/gh5_neck.cpp index 50afa5980..9db1d5fb6 100644 --- a/src/shared/main/gh5_neck.cpp +++ b/src/shared/main/gh5_neck.cpp @@ -10,10 +10,9 @@ bool lastGH5WasSuccessful = false; void tickGh5Neck() { - // Drum packet starts with some counter, and then the number of packets in the buffer uint8_t header[2]; uint8_t data[2]; - lastGH5WasSuccessful = twi_readFromPointer(GH5_TWI_PORT, GH5NECK_ADDR, GH5NECK_BUTTONS_PTR, sizeof(header), header); + lastGH5WasSuccessful = twi_readFromPointerRepeatedStart(GH5_TWI_PORT, GH5NECK_ADDR, GH5NECK_BUTTONS_PTR, sizeof(header), header); if (lastGH5WasSuccessful && header[1]) { lastGH5WasSuccessful = twi_readFrom(GH5_TWI_PORT, GH5NECK_ADDR, data, sizeof(data), true); From 2dd271beb333cc3f032a046190c352a1a0238c42 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 11 Dec 2025 09:07:43 +1300 Subject: [PATCH 133/239] better gh5 neck --- src/shared/main/gh5_neck.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/shared/main/gh5_neck.cpp b/src/shared/main/gh5_neck.cpp index 9db1d5fb6..7b6697539 100644 --- a/src/shared/main/gh5_neck.cpp +++ b/src/shared/main/gh5_neck.cpp @@ -5,18 +5,16 @@ #include "shared_main.h" #include "commands.h" #define GH5NECK_ADDR 0x0D -#define GH5NECK_BUTTONS_PTR 0x10 +#define GH5NECK_BUTTONS_PTR 0x11 #ifdef GH5_TWI_PORT bool lastGH5WasSuccessful = false; void tickGh5Neck() { - uint8_t header[2]; - uint8_t data[2]; - lastGH5WasSuccessful = twi_readFromPointerRepeatedStart(GH5_TWI_PORT, GH5NECK_ADDR, GH5NECK_BUTTONS_PTR, sizeof(header), header); - if (lastGH5WasSuccessful && header[1]) + uint8_t header; + lastGH5WasSuccessful = twi_readFromPointerRepeatedStart(GH5_TWI_PORT, GH5NECK_ADDR, GH5NECK_BUTTONS_PTR, 1, &header); + if (lastGH5WasSuccessful && header) { - lastGH5WasSuccessful = twi_readFrom(GH5_TWI_PORT, GH5NECK_ADDR, data, sizeof(data), true); - memcpy(lastSuccessfulGH5Packet, data, sizeof(data)); + lastGH5WasSuccessful = twi_readFrom(GH5_TWI_PORT, GH5NECK_ADDR, lastSuccessfulGH5Packet, sizeof(lastSuccessfulGH5Packet), true); } } #endif \ No newline at end of file From bffcc70cc8dde28dfc742ce55199445328e7ecc8 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 11 Dec 2025 10:01:36 +1300 Subject: [PATCH 134/239] work on gh5 neck --- src/shared/main/gh5_neck.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/gh5_neck.cpp b/src/shared/main/gh5_neck.cpp index 7b6697539..45d478e5c 100644 --- a/src/shared/main/gh5_neck.cpp +++ b/src/shared/main/gh5_neck.cpp @@ -6,8 +6,8 @@ #include "commands.h" #define GH5NECK_ADDR 0x0D #define GH5NECK_BUTTONS_PTR 0x11 -#ifdef GH5_TWI_PORT bool lastGH5WasSuccessful = false; +#ifdef GH5_TWI_PORT void tickGh5Neck() { uint8_t header; From 07ec74ca25d33e7bbcfffcbf8369290009a9560a Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 18 Dec 2025 16:03:44 +1300 Subject: [PATCH 135/239] add ids for some mpu6050 clones --- include/accel.h | 1 + src/shared/main/accel.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/accel.h b/include/accel.h index 6f38ff806..2bb07227d 100644 --- a/include/accel.h +++ b/include/accel.h @@ -29,6 +29,7 @@ extern "C" { #define MPU6050_REG_ACCEL_CONFIG 0x1C #define MPU6050_REG_PWR_MGMT_1 0x6B #define MPU6050_ID 0x68 +#define MPU6050_ID2 0x98 void tick_accel(); #ifdef __cplusplus } diff --git a/src/shared/main/accel.cpp b/src/shared/main/accel.cpp index 50a8d734d..eb9df5514 100644 --- a/src/shared/main/accel.cpp +++ b/src/shared/main/accel.cpp @@ -41,7 +41,7 @@ void init_adxl() { void init_mpu6050() { uint8_t id = 0; twi_readFromPointer(ACCEL_TWI_PORT, MPU6050_ADDRESS, MPU6050_REG_WHO_AM_I, 1, &id); - if (id != MPU6050_ID) { + if (id != MPU6050_ID && id != MPU6050_ID2) { return; } type = MPU6050; From 15ef3a0da23772a9c64058fe76a9fd299315fae6 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 19 Dec 2025 20:20:14 +1300 Subject: [PATCH 136/239] skip auth when using xbone mode on windows --- include/config.h | 4 ++-- include/reports/xbox_one_reports.h | 4 ++++ src/pico/main.cpp | 7 ------- src/pico/xinput_device.cpp | 3 --- src/shared/config/config.c | 19 +++++++------------ src/shared/main/shared_main.cpp | 11 ++++++----- src/shared/usb/descriptors.cpp | 19 ++----------------- 7 files changed, 21 insertions(+), 46 deletions(-) diff --git a/include/config.h b/include/config.h index f365bd88c..33a138389 100644 --- a/include/config.h +++ b/include/config.h @@ -529,13 +529,13 @@ extern const uint8_t config[CONFIGURATION_LEN]; #if DEVICE_TYPE_IS_GUITAR #define XBOX_ONE_VID XBOX_ONE_RB_VID #define XBOX_ONE_PID XBOX_ONE_RB_GUITAR_PID -#define XBOX_ONE_DESCRIPTOR_SIZE 256 +#define XBOX_ONE_DESCRIPTOR_SIZE 279 #define PS4_VID PDP_VID #define PS4_PID PS4_JAG_PID #elif DEVICE_TYPE_IS_DRUMS #define XBOX_ONE_VID XBOX_ONE_RB_VID #define XBOX_ONE_PID XBOX_ONE_RB_DRUM_PID -#define XBOX_ONE_DESCRIPTOR_SIZE 224 +#define XBOX_ONE_DESCRIPTOR_SIZE 237 #define PS4_VID MADCATZ_VID #define PS4_PID PS4_MADCATZ_DRUM_PID #elif DEVICE_TYPE == LIVE_GUITAR diff --git a/include/reports/xbox_one_reports.h b/include/reports/xbox_one_reports.h index a0d73e1bb..b7bafe98d 100644 --- a/include/reports/xbox_one_reports.h +++ b/include/reports/xbox_one_reports.h @@ -139,6 +139,10 @@ typedef struct uint8_t : 3; uint8_t unknown[3]; + int16_t joystickX; + int16_t joystickY; + + uint8_t consoleFunctions[14]; } __attribute__((packed)) XboxOneRockBandGuitar_Data_t; typedef struct diff --git a/src/pico/main.cpp b/src/pico/main.cpp index a7eeb0f44..29f0931b9 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -124,13 +124,6 @@ bool authDone = false; long test3 = 0; static void tick_usb() { -#if USB_HOST_STACK - if (consoleType == XBOXONE && !foundXB) - { - tuh_task(); - return; - } -#endif tud_task(); #if USB_HOST_STACK tuh_task(); diff --git a/src/pico/xinput_device.cpp b/src/pico/xinput_device.cpp index 640bd1ea3..989210e64 100644 --- a/src/pico/xinput_device.cpp +++ b/src/pico/xinput_device.cpp @@ -279,12 +279,9 @@ bool xinputd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, if (consoleType == XBOX360 || consoleType == WINDOWS || consoleType == OG_XBOX) { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, 0x20)); - -#if USB_HOST_STACK } else if (consoleType == XBOXONE) { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, 0x40)); -#endif } else if (consoleType == ARCADE) { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, 0x40)); diff --git a/src/shared/config/config.c b/src/shared/config/config.c index c010dd0b4..6794eebe6 100644 --- a/src/shared/config/config.c +++ b/src/shared/config/config.c @@ -15,23 +15,18 @@ uint8_t consoleType = 0xFF; uint8_t arcadeSide = 1; #if DEVICE_TYPE_IS_GUITAR -const uint8_t announce[] = {0x02, 0x20, 0x01, 0x1c, 0x7e, 0xed, 0x81, TEMP, TEMP, TEMP, 0x00, 0x00, 0x38, 0x07, 0x61, 0x41, 0x01, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}; -const uint8_t xb1_descriptor[] = {0x04, 0xf0, 0x01, 0x3a, 0xe5, 0x01, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe5, 0x00, 0xa6, 0x00, 0x16, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x23, 0x00, 0x29, 0x00, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x06, 0x07, 0x05, 0x01, 0x04, 0x05, 0x06, 0x0a, 0x02, 0x04, 0xa0, 0x01, 0xba, 0x00, 0x3a, 0x20, 0x00, 0x4d, 0x61, 0x64, 0x43, 0x61, 0x74, 0x7a, 0x2e, 0x58, 0x62, 0x6f, 0x78, 0x2e, 0x47, 0x75, 0x69, 0x74, 0x61, 0x72, 0x2e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x63, 0x61, 0x73, 0x74, 0x65, 0x72, 0x27, 0x00, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2e, 0x58, 0x62, 0x6f, 0x78, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x2e, 0x4e, 0x61, 0x76, 0x04, 0xa0, 0x01, 0xba, 0x00, 0x74, 0x69, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x03, 0x38, 0xe4, 0x2a, 0x0d, 0x7d, 0x7f, 0x33, 0x49, 0x86, 0x93, 0x30, 0xfc, 0x55, 0x01, 0x8e, 0x77, 0xe7, 0x1f, 0xf3, 0xb8, 0x86, 0x73, 0xe9, 0x40, 0xa9, 0xf8, 0x2f, 0x21, 0x26, 0x3a, 0xcf, 0xb7, 0x56, 0xff, 0x76, 0x97, 0xfd, 0x9b, 0x81, 0x45, 0x04, 0xb0, 0x01, 0x37, 0xae, 0x01, 0xad, 0x45, 0xb6, 0x45, 0xbb, 0xa5, 0x26, 0xd6, 0x02, 0x17, 0x00, 0x20, 0x0e, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x21, 0x05, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -const uint8_t xb1_descriptor_end[] = {0x04, 0xa0, 0x01, 0x00, 0xe5, 0x01}; +const uint8_t announce[] = {0x02, 0x20, 0x01, 0x1c, 0x7e, 0xed, 0x81, TEMP, TEMP, TEMP, 0x00, 0x00, 0x6f, 0x0e, 0x48, 0x02, 0x01, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}; +const uint8_t xb1_descriptor[] = {0x04, 0xf0, 0x01, 0x3a, 0xf5, 0x01, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00, 0xb6, 0x00, 0x16, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x23, 0x00, 0x29, 0x00, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x06, 0x07, 0x05, 0x01, 0x04, 0x05, 0x06, 0x0a, 0x02, 0x04, 0xa0, 0x01, 0xba, 0x00, 0x3a, 0x20, 0x00, 0x4d, 0x61, 0x64, 0x43, 0x61, 0x74, 0x7a, 0x2e, 0x58, 0x62, 0x6f, 0x78, 0x2e, 0x47, 0x75, 0x69, 0x74, 0x61, 0x72, 0x2e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x63, 0x61, 0x73, 0x74, 0x65, 0x72, 0x27, 0x00, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2e, 0x58, 0x62, 0x6f, 0x78, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x2e, 0x4e, 0x61, 0x76, 0x04, 0xa0, 0x01, 0xba, 0x00, 0x74, 0x69, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x04, 0x38, 0xe4, 0x2a, 0x0d, 0x7d, 0x7f, 0x33, 0x49, 0x86, 0x93, 0x30, 0xfc, 0x55, 0x01, 0x8e, 0x77, 0xe7, 0x1f, 0xf3, 0xb8, 0x86, 0x73, 0xe9, 0x40, 0xa9, 0xf8, 0x2f, 0x21, 0x26, 0x3a, 0xcf, 0xb7, 0x56, 0xff, 0x76, 0x97, 0xfd, 0x9b, 0x81, 0x45, 0x04, 0xa0, 0x01, 0x3a, 0xae, 0x01, 0xad, 0x45, 0xb6, 0x45, 0xbb, 0xa5, 0x26, 0xd6, 0x77, 0xce, 0x34, 0x7a, 0xe2, 0x7d, 0xc6, 0x45, 0x8c, 0xa4, 0x00, 0x42, 0xc0, 0x8b, 0xd9, 0x4a, 0x02, 0x17, 0x00, 0x20, 0x20, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x21, 0x05, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x04, 0xb0, 0x01, 0x0d, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +const uint8_t xb1_descriptor_end[] = {0x04, 0xa0, 0x01, 0x00, 0xf5, 0x01}; #elif DEVICE_TYPE_IS_DRUM const uint8_t announce[] = {0x02, 0x20, 0x01, 0x1c, 0x7e, 0xed, 0x81, TEMP, TEMP, TEMP, 0x00, 0x00, 0x38, 0x07, 0x62, 0x42, 0x01, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}; -const uint8_t xb1_descriptor[] = {0x04, 0xf0, 0x01, 0x3a, 0xc5, 0x01, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc5, 0x00, 0x9d, 0x00, 0x16, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x23, 0x00, 0x29, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x06, 0x07, 0x05, 0x01, 0x04, 0x05, 0x06, 0x0a, 0x02, 0x04, 0xa0, 0x01, 0xba, 0x00, 0x3a, 0x17, 0x00, 0x4d, 0x61, 0x64, 0x43, 0x61, 0x74, 0x7a, 0x2e, 0x58, 0x62, 0x6f, 0x78, 0x2e, 0x44, 0x72, 0x75, 0x6d, 0x73, 0x2e, 0x47, 0x6c, 0x61, 0x6d, 0x27, 0x00, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2e, 0x58, 0x62, 0x6f, 0x78, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x2e, 0x4e, 0x61, 0x76, 0x69, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x04, 0xa0, 0x01, 0xba, 0x00, 0x74, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x03, 0x93, 0x28, 0x18, 0x06, 0xe0, 0xcc, 0x85, 0x4b, 0x92, 0x71, 0x0a, 0x10, 0xdb, 0xab, 0x7e, 0x07, 0xe7, 0x1f, 0xf3, 0xb8, 0x86, 0x73, 0xe9, 0x40, 0xa9, 0xf8, 0x2f, 0x21, 0x26, 0x3a, 0xcf, 0xb7, 0x56, 0xff, 0x76, 0x97, 0xfd, 0x9b, 0x81, 0x45, 0xad, 0x45, 0xb6, 0x45, 0xbb, 0xa5, 0x26, 0xd6, 0x01, 0x04, 0xb0, 0x01, 0x17, 0xae, 0x01, 0x17, 0x00, 0x20, 0x0a, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -const uint8_t xb1_descriptor_end[] = {0x04, 0xa0, 0x01, 0x00, 0xc5, 0x01}; +const uint8_t xb1_descriptor[] = {0x04, 0xf0, 0x01, 0x3a, 0xd5, 0x01, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x00, 0xad, 0x00, 0x16, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x23, 0x00, 0x29, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x06, 0x07, 0x05, 0x01, 0x04, 0x05, 0x06, 0x0a, 0x02, 0x04, 0xa0, 0x01, 0xba, 0x00, 0x3a, 0x17, 0x00, 0x4d, 0x61, 0x64, 0x43, 0x61, 0x74, 0x7a, 0x2e, 0x58, 0x62, 0x6f, 0x78, 0x2e, 0x44, 0x72, 0x75, 0x6d, 0x73, 0x2e, 0x47, 0x6c, 0x61, 0x6d, 0x27, 0x00, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2e, 0x58, 0x62, 0x6f, 0x78, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x2e, 0x4e, 0x61, 0x76, 0x69, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x04, 0xa0, 0x01, 0xba, 0x00, 0x74, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x04, 0x93, 0x28, 0x18, 0x06, 0xe0, 0xcc, 0x85, 0x4b, 0x92, 0x71, 0x0a, 0x10, 0xdb, 0xab, 0x7e, 0x07, 0xe7, 0x1f, 0xf3, 0xb8, 0x86, 0x73, 0xe9, 0x40, 0xa9, 0xf8, 0x2f, 0x21, 0x26, 0x3a, 0xcf, 0xb7, 0x56, 0xff, 0x76, 0x97, 0xfd, 0x9b, 0x81, 0x45, 0xad, 0x45, 0xb6, 0x45, 0xbb, 0xa5, 0x26, 0xd6, 0x77, 0x04, 0xb0, 0x01, 0x27, 0xae, 0x01, 0xce, 0x34, 0x7a, 0xe2, 0x7d, 0xc6, 0x45, 0x8c, 0xa4, 0x00, 0x42, 0xc0, 0x8b, 0xd9, 0x4a, 0x01, 0x17, 0x00, 0x20, 0x0a, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +const uint8_t xb1_descriptor_end[] = {0x04, 0xa0, 0x01, 0x00, 0xd5, 0x01}; #elif DEVICE_TYPE_IS_LIVE_GUITAR const uint8_t announce[] = {0x02, 0x20, 0x01, 0x1C, 0x7B, 0xED, 0x63, TEMP, TEMP, TEMP, 0x00, 0x00, 0x30, 0x14, 0x9B, 0x07, 0x01, 0x00, 0x00, 0x00, 0x10, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}; -const uint8_t xb1_descriptor[] = {0x04, 0xF0, 0x01, 0x3A, 0xA5, 0x02, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x01, 0xCF, 0x00, 0x16, 0x00, 0x1F, 0x00, 0x20, 0x00, 0x27, 0x00, 0x2D, 0x00, 0x8E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x06, 0x07, 0x05, 0x01, 0x04, - 0x04, 0xA0, 0x01, 0xBA, 0x00, 0x3A, 0x05, 0x06, 0x0A, 0x03, 0x19, 0x00, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x2E, 0x58, 0x62, 0x6F, 0x78, 0x2E, 0x49, 0x6E, 0x70, 0x75, 0x74, 0x2E, 0x47, 0x48, 0x37, 0x1A, 0x00, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x2E, 0x58, 0x62, 0x6F, 0x78, 0x2E, 0x49, 0x6E, 0x70, 0x75, 0x74, 0x2E, 0x47, 0x61, 0x6D, 0x65, 0x70, 0x61, - 0x04, 0xA0, 0x01, 0xBA, 0x00, 0x74, 0x64, 0x27, 0x00, 0x57, 0x69, 0x6E, 0x64, 0x6F, 0x77, 0x73, 0x2E, 0x58, 0x62, 0x6F, 0x78, 0x2E, 0x49, 0x6E, 0x70, 0x75, 0x74, 0x2E, 0x4E, 0x61, 0x76, 0x69, 0x67, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x6F, 0x6C, 0x6C, 0x65, 0x72, 0x04, 0xD9, 0xFD, 0x12, 0xFD, 0x73, 0x8E, 0xC7, 0x47, 0xA2, 0x31, 0x96, 0x26, 0x8C, 0x38, 0x00, - 0x04, 0xA0, 0x01, 0x3A, 0xAE, 0x01, 0x9A, 0x2C, 0x40, 0x2E, 0x08, 0xDF, 0x07, 0xE1, 0x45, 0xA5, 0xAB, 0xA3, 0x12, 0x7A, 0xF1, 0x97, 0xB5, 0xE7, 0x1F, 0xF3, 0xB8, 0x86, 0x73, 0xE9, 0x40, 0xA9, 0xF8, 0x2F, 0x21, 0x26, 0x3A, 0xCF, 0xB7, 0x56, 0xFF, 0x76, 0x97, 0xFD, 0x9B, 0x81, 0x45, 0xAD, 0x45, 0xB6, 0x45, 0xBB, 0xA5, 0x26, 0xD6, 0x03, 0x17, 0x00, 0x20, 0x0E, 0x00, 0x01, 0x00, 0x10, - 0x04, 0xA0, 0x01, 0x3A, 0xE8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x21, 0x20, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x22, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x04, 0xB0, 0x01, 0x03, 0xA2, 0x02, 0x00, 0x00, 0x00}; +const uint8_t xb1_descriptor[] = {0x04, 0xf0, 0x01, 0x3a, 0xa5, 0x02, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x25, 0x01, 0xcf, 0x00, 0x16, 0x00, 0x1f, 0x00, 0x20, 0x00, 0x27, 0x00, 0x2d, 0x00, 0x8e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x06, 0x07, 0x05, 0x01, 0x04, 0x04, 0xa0, 0x01, 0xba, 0x00, 0x3a, 0x05, 0x06, 0x0a, 0x03, 0x19, 0x00, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x2e, 0x58, 0x62, 0x6f, 0x78, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x2e, 0x47, 0x48, 0x37, 0x1a, 0x00, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2e, 0x58, 0x62, 0x6f, 0x78, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x2e, 0x47, 0x61, 0x6d, 0x65, 0x70, 0x61, 0x04, 0xa0, 0x01, 0xba, 0x00, 0x74, 0x64, 0x27, 0x00, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2e, 0x58, 0x62, 0x6f, 0x78, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x2e, 0x4e, 0x61, 0x76, 0x69, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x04, 0xd9, 0xfd, 0x12, 0xfd, 0x73, 0x8e, 0xc7, 0x47, 0xa2, 0x31, 0x96, 0x26, 0x8c, 0x38, 0x00, 0x04, 0xa0, 0x01, 0x3a, 0xae, 0x01, 0x9a, 0x2c, 0x40, 0x2e, 0x08, 0xdf, 0x07, 0xe1, 0x45, 0xa5, 0xab, 0xa3, 0x12, 0x7a, 0xf1, 0x97, 0xb5, 0xe7, 0x1f, 0xf3, 0xb8, 0x86, 0x73, 0xe9, 0x40, 0xa9, 0xf8, 0x2f, 0x21, 0x26, 0x3a, 0xcf, 0xb7, 0x77, 0xce, 0x34, 0x7a, 0xe2, 0x7d, 0xc6, 0x45, 0x8c, 0xa4, 0x00, 0x42, 0xc0, 0x8b, 0xd9, 0x4a, 0x03, 0x17, 0x00, 0x20, 0x0e, 0x00, 0x01, 0x00, 0x10, 0x04, 0xb0, 0x01, 0x3a, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x21, 0x20, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x22, 0x08, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xb0, 0x01, 0x03, 0xa2, 0x02, 0x00, 0x00, 0x00}; -const uint8_t xb1_descriptor_end[] = {0x04, 0xA0, 0x01, 0x00, 0xA5, 0x02}; +const uint8_t xb1_descriptor_end[] = {0x04, 0xa0, 0x01, 0x00, 0xa5, 0x02}; #elif DEVICE_TYPE == SKYLANDERS const uint8_t announce[] = {0x02, 0x20, 0x01, 0x1C, 0x5B, 0x9F, 0x9F, 0x96, 0x1B, 0x00, 0x00, 0x00, 0x30, 0x14, 0xAB, 0x09, 0x01, 0x00, 0x00, 0x00, 0x32, 0x02, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}; const uint8_t xb1_descriptor[] = {0x04, 0xF0, 0x01, 0x3A, 0x96, 0x01, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x6E, 0x00, 0x16, 0x00, 0x1B, 0x00, 0x1C, 0x00, 0x23, 0x00, 0x29, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x06, 0x1F, 0x05, 0x01, 0x04, 0x05, 0x06, 0x1F, 0x01, 0x04, 0xA0, 0x01, 0xBA, 0x00, 0x3A, 0x21, 0x00, 0x41, 0x63, 0x74, 0x69, 0x76, 0x69, 0x73, 0x69, 0x6F, 0x6E, 0x2E, 0x58, 0x62, 0x6F, 0x78, 0x2E, 0x53, 0x6B, 0x79, 0x6C, 0x61, 0x6E, 0x64, 0x65, 0x72, 0x73, 0x2E, 0x50, 0x6F, 0x72, 0x74, 0x61, 0x6C, 0x02, 0x00, 0xA2, 0x88, 0x77, 0x1F, 0x60, 0xB8, 0x40, 0x9B, 0x36, 0x26, 0xEC, 0x56, 0xC7, 0xC4, 0x52, 0x56, 0xFF, 0x76, 0x97, 0xFD, 0x9B, 0x04, 0xB0, 0x01, 0xA2, 0x00, 0x74, 0x81, 0x45, 0xAD, 0x45, 0xB6, 0x45, 0xBB, 0xA5, 0x26, 0xD6, 0x01, 0x17, 0x00, 0x21, 0x1E, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index e43fcf0fc..7fe5ed3a3 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3104,7 +3104,6 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu bool updateHIDSequence = false; uint8_t proKeyVelocities[25] = {0}; memset(proKeyVelocities, 0, sizeof(proKeyVelocities)); -#if USB_HOST_STACK if (output_console_type == XBOXONE) { XBOX_ONE_REPORT *report = (XBOX_ONE_REPORT *)buf; @@ -3118,6 +3117,10 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu packet_size = sizeof(XBOX_ONE_REPORT); report_size = packet_size - sizeof(GipHeader_t); memset(buf, 0, packet_size); + asm volatile("" :: + : "memory"); + report->joystickX = 0; + report->joystickY = 0; GIP_HEADER(report, GIP_INPUT_REPORT, false, report_sequence_number); TICK_XBOX_ONE; asm volatile("" :: @@ -3137,6 +3140,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu GipPacket_t *packet = (GipPacket_t *)report; report_data = (USB_Report_Data_t *)packet->data; updateSequence = true; + #if DEVICE_TYPE_IS_LIVE_GUITAR packet_size = sizeof(XboxOneGHLGuitarWithGamepad_Data_t); uint8_t cmp = memcmp(last_report, report_data, report_size); @@ -3152,7 +3156,6 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu updateHIDSequence = true; #endif } -#endif if (output_console_type == OG_XBOX) { OG_XBOX_REPORT *report = (OG_XBOX_REPORT *)report_data; @@ -3394,7 +3397,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->tilt = PS3_STICK_CENTER; #endif report->reportId = GIP_INPUT_REPORT; - TICK_XBOX_ONE; + // TICK_XBOX_ONE; asm volatile("" :: : "memory"); // alias tilt to dpad left so that tilt works @@ -3627,7 +3630,6 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } #endif -#if USB_HOST_STACK #if DEVICE_TYPE_IS_GAMEPAD if (updateSequence) { @@ -3648,7 +3650,6 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } #endif #endif -#endif #endif return packet_size; } diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 30523e8aa..72d740d25 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1172,13 +1172,10 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const } else if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_VENDOR) && request == REQ_GET_OS_FEATURE_DESCRIPTOR && wIndex == DESC_EXTENDED_COMPATIBLE_ID_DESCRIPTOR) { seen_windows_xb1 = true; memcpy_P(requestBuffer, &DevCompatIDs, sizeof(OS_COMPATIBLE_ID_DESCRIPTOR)); -#if USB_HOST_STACK if (consoleType == XBOXONE) { memcpy_P(requestBuffer, &DevCompatIDsOne, sizeof(DevCompatIDsOne)); return sizeof(DevCompatIDsOne); - } else -#endif - if (consoleType == WINDOWS || consoleType == XBOX360) { + } else if (consoleType == WINDOWS || consoleType == XBOX360) { OS_COMPATIBLE_ID_DESCRIPTOR *compat = (OS_COMPATIBLE_ID_DESCRIPTOR *)requestBuffer; compat->TotalSections = 4; compat->TotalLength = sizeof(OS_COMPATIBLE_ID_DESCRIPTOR); @@ -1243,7 +1240,6 @@ uint16_t descriptorRequest(const uint16_t wValue, const uint8_t descriptorNumber = (wValue & 0xFF); // printf("desc: %02x %02x\r\n", descriptorType, descriptorNumber); #if DEVICE_TYPE_IS_GAMEPAD -#if USB_HOST_STACK if (consoleType == UNIVERSAL && seen_windows_xb1 && descriptorType != HID_DESCRIPTOR_REPORT) { seen_windows_desc = true; } @@ -1257,12 +1253,6 @@ uint16_t descriptorRequest(const uint16_t wValue, set_console_type(XBOXONE); } } -#else - if (WINDOWS_USES_XINPUT && consoleType == UNIVERSAL && seen_windows_xb1 && descriptorType != HID_DESCRIPTOR_REPORT) { - set_console_type(WINDOWS); - } - -#endif #endif descriptor_requested = true; uint16_t size = NO_DESCRIPTOR; @@ -1283,7 +1273,6 @@ uint16_t descriptorRequest(const uint16_t wValue, dev->idVendor = 0x045E; dev->idProduct = 0x0289; } -#if USB_HOST_STACK else if (consoleType == XBOXONE) { dev->idVendor = XBOX_ONE_CONTROLLER_VID; dev->idProduct = XBOX_ONE_CONTROLLER_PID; @@ -1291,7 +1280,6 @@ uint16_t descriptorRequest(const uint16_t wValue, dev->bDeviceSubClass = 0x47; dev->bDeviceProtocol = 0xd0; } -#endif else if (consoleType == PS4) { dev->idVendor = PS4_VID; dev->idProduct = PS4_PID; @@ -1338,13 +1326,10 @@ uint16_t descriptorRequest(const uint16_t wValue, memcpy_P(descriptorBuffer, &UniversalConfigurationDescriptor, size); #else -#if USB_HOST_STACK if (consoleType == XBOXONE) { size = sizeof(XBOX_ONE_CONFIGURATION_DESCRIPTOR); memcpy_P(descriptorBuffer, &XBOXOneConfigurationDescriptor, size); - } else -#endif - if (consoleType == WINDOWS || consoleType == XBOX360) { + } else if (consoleType == WINDOWS || consoleType == XBOX360) { size = sizeof(XBOX_360_CONFIGURATION_DESCRIPTOR); memcpy_P(descriptorBuffer, &XBOX360ConfigurationDescriptor, size); } else if (consoleType == OG_XBOX) { From 4cbcc8ad717d374c82b263560c7cfcb1c970b92c Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 20 Dec 2025 09:49:10 +1300 Subject: [PATCH 137/239] fix xbox one mode not working without usb host --- src/shared/hid/hid.cpp | 2 -- src/shared/main/shared_main.cpp | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/shared/hid/hid.cpp b/src/shared/hid/hid.cpp index 50f9e53c4..87ba4d1a7 100644 --- a/src/shared/hid/hid.cpp +++ b/src/shared/hid/hid.cpp @@ -665,7 +665,6 @@ void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_ } #endif -#ifdef INPUT_USB_HOST // Handle Xbox 360 LEDs and rumble // Handle XBOX One Auth if ((consoleType == XBOXONE) && report_id != BLUETOOTH_REPORT) { @@ -704,7 +703,6 @@ void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_ } } } else -#endif // Bt reports are ALWAYS hid even if USB is in xinput mode if ((consoleType == XBOX360 || consoleType == WINDOWS) && report_id != BLUETOOTH_REPORT) { if (id == XBOX_LED_ID) { diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 7fe5ed3a3..88985e5a1 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3397,7 +3397,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->tilt = PS3_STICK_CENTER; #endif report->reportId = GIP_INPUT_REPORT; - // TICK_XBOX_ONE; + TICK_XBOX_ONE; asm volatile("" :: : "memory"); // alias tilt to dpad left so that tilt works @@ -3734,6 +3734,7 @@ bool tick_usb(void) send_report_to_controller(type.dev_addr, type.instance, data_from_console, data_from_console_size); data_from_console_size = 0; } +#endif // If we have something pending to send to the xbox one controller, send it if (consoleType == XBOXONE && xbox_one_state != Ready) { @@ -3768,7 +3769,6 @@ bool tick_usb(void) // } // } // #endif -#endif if (!size) { size = tick_inputs(&combined_report, &last_report_usb, consoleType); From 3b9bde58b8f94411e3245a511b62626601ad3ec9 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 20 Dec 2025 10:06:33 +1300 Subject: [PATCH 138/239] only recenter joysticks for xb1 guitars --- src/shared/main/shared_main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 88985e5a1..2a5db8ad9 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3119,8 +3119,10 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu memset(buf, 0, packet_size); asm volatile("" :: : "memory"); +#if DEVICE_TYPE == ROCK_BAND_GUITAR || DEVICE_TYPE == GUITAR_HERO_GUITAR report->joystickX = 0; report->joystickY = 0; +#endif GIP_HEADER(report, GIP_INPUT_REPORT, false, report_sequence_number); TICK_XBOX_ONE; asm volatile("" :: From bd9703d2247dec0ee1515991bc8689175b9a28da Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 9 Jan 2026 11:56:02 +1300 Subject: [PATCH 139/239] work towards mustang neck --- include/protar_neck.h | 2 ++ include/state_translation/pro_guitar.h | 23 ++++++++++++++++++++ src/shared/main/inputs/crkd.h | 7 +++++++ src/shared/main/inputs/mustang_neck.h | 3 +++ src/shared/main/mustang_neck.cpp | 29 ++++++++++++++++++++++++++ src/shared/main/shared_main.cpp | 5 +++++ 6 files changed, 69 insertions(+) create mode 100644 include/protar_neck.h create mode 100644 src/shared/main/inputs/mustang_neck.h create mode 100644 src/shared/main/mustang_neck.cpp diff --git a/include/protar_neck.h b/include/protar_neck.h new file mode 100644 index 000000000..055207155 --- /dev/null +++ b/include/protar_neck.h @@ -0,0 +1,2 @@ +#include "state_translation/pro_guitar.h" +protarneck_t tickMustangNeck(void); \ No newline at end of file diff --git a/include/state_translation/pro_guitar.h b/include/state_translation/pro_guitar.h index 1a121c95f..6bf586b7e 100644 --- a/include/state_translation/pro_guitar.h +++ b/include/state_translation/pro_guitar.h @@ -1,3 +1,26 @@ +#pragma once +typedef struct { + uint8_t header = 0; + uint16_t lowEFret : 5; + uint16_t aFret : 5; + uint16_t dFret : 5; + uint16_t : 1; // always 1 + + uint16_t gFret : 5; + uint16_t bFret : 5; + uint16_t highEFret : 5; + uint16_t : 1; // always 0 + + uint8_t : 1; // always 0 + uint8_t green :1; + uint8_t red :1; + uint8_t yellow :1; + uint8_t blue :1; + uint8_t orange :1; + uint8_t soloFlag : 1; + uint8_t : 1; // always 0 +} __attribute__((packed)) protarneck_t; + #define TRANSLATE_PRO_GUITAR \ usb_host_data->lowEFretVelocity = report->lowEFretVelocity; \ usb_host_data->aFretVelocity = report->aFretVelocity; \ diff --git a/src/shared/main/inputs/crkd.h b/src/shared/main/inputs/crkd.h index 54c7dfac4..17b3317f4 100644 --- a/src/shared/main/inputs/crkd.h +++ b/src/shared/main/inputs/crkd.h @@ -1,3 +1,10 @@ #ifdef INPUT_CRKD_NECK lastCrkdWasSuccessful = read_uart(CRKD_UART_PORT, 0xA5, 11, (uint8_t *)&lastCrkd); +if (lastCrkdWasSuccessful && millis() - lastCrkdSend > 10) + { + // kick the neck over to polling at 1ms + uint8_t data[] = {0xA5, 0xC1, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xD5}; + send_uart(CRKD_UART_PORT, data, sizeof(data)); + lastCrkdSend = millis(); + } #endif \ No newline at end of file diff --git a/src/shared/main/inputs/mustang_neck.h b/src/shared/main/inputs/mustang_neck.h new file mode 100644 index 000000000..ab9eac7b0 --- /dev/null +++ b/src/shared/main/inputs/mustang_neck.h @@ -0,0 +1,3 @@ +#ifdef MUSTANG_NECK_SPI_PORT +lastProtar = tickMustangNeck(); +#endif \ No newline at end of file diff --git a/src/shared/main/mustang_neck.cpp b/src/shared/main/mustang_neck.cpp new file mode 100644 index 000000000..d501b1e40 --- /dev/null +++ b/src/shared/main/mustang_neck.cpp @@ -0,0 +1,29 @@ +#include + +#include "Arduino.h" +#include "io.h" +#include "shared_main.h" +#include "state_translation/pro_guitar.h" +#ifdef MUSTANG_NECK_SPI_PORT +static long lastTick = 0; +static int missing = 0; +bool protar_found = false; +static protarneck_t neck; +protarneck_t tickMustangNeck() { + if (micros() - lastTick > 500) { + lastTick = micros(); + MUSTANG_NECK_CS_CLEAR(); + uint8_t resp = spi_transfer(MUSTANG_NECK_SPI_PORT, 0x01); + if (resp != 0x00) { + MUSTANG_NECK_CS_SET(); + return neck; + } + uint8_t* buf = (uint8_t*)&neck; + for (int i = 0; i < sizeof(neck); i++) { + *buf++ = spi_transfer(MUSTANG_NECK_SPI_PORT, 0x42); + } + MUSTANG_NECK_CS_SET(); + } + return neck; +} +#endif \ No newline at end of file diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 2a5db8ad9..b478374c8 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -68,7 +68,9 @@ struct }; }; } rtt_t; +unsigned long lastCrkdSend; crkd_neck_t lastCrkd; +protarneck_t lastProtar; unsigned long lastMidi = 0; Midi_Data_t midiData = {0}; @@ -2744,6 +2746,7 @@ void tick_ps2output() #include "inputs/usb_host.h" #include "inputs/wii.h" #include "inputs/wt_neck.h" +#include "inputs/mustang_neck.h" #include "inputs/crkd.h" TICK_SHARED; @@ -2785,6 +2788,7 @@ void tick_wiioutput() #include "inputs/usb_host.h" #include "inputs/wii.h" #include "inputs/wt_neck.h" +#include "inputs/mustang_neck.h" #include "inputs/turntable.h" TICK_SHARED; if (!startedInactivityPulse) @@ -2933,6 +2937,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #include "inputs/wii.h" #include "inputs/wt_drum.h" #include "inputs/wt_neck.h" +#include "inputs/mustang_neck.h" #include "inputs/crkd.h" #include "inputs/turntable.h" // #if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE From 04390d5de34e72fea2531ea31fd3368c95ebdd2e Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 9 Jan 2026 12:46:58 +1300 Subject: [PATCH 140/239] work towards mustang neck --- include/commands.h | 2 ++ src/shared/hid/hid.cpp | 5 +++ src/shared/main/mustang_neck.cpp | 2 +- src/shared/main/shared_main.cpp | 58 ++++++++++++++++++++++++++++++++ 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/include/commands.h b/include/commands.h index 086c48fa0..e163902a0 100644 --- a/include/commands.h +++ b/include/commands.h @@ -55,6 +55,7 @@ enum SerialCommands { COMMAND_BH_DRUM_VALID, COMMAND_READ_CRKD, COMMAND_READ_MATRIX, + COMMAND_MUSTANG_NECK_VALID, MAX=100 }; @@ -78,6 +79,7 @@ extern bool lastWiiWasSuccessful; extern bool lastPS2WasSuccessful; extern bool wt_drum_found; extern bool bh_drum_found; +extern bool mustang_neck_found; extern uint16_t wiiControllerType; extern uint8_t ps2ControllerType; extern bool overrideR2; diff --git a/src/shared/hid/hid.cpp b/src/shared/hid/hid.cpp index 87ba4d1a7..d21023afd 100644 --- a/src/shared/hid/hid.cpp +++ b/src/shared/hid/hid.cpp @@ -930,6 +930,11 @@ uint8_t handle_serial_command(uint8_t request, uint16_t wValue, uint8_t *respons response_buffer[0] = wt_drum_found; return 1; #endif +#ifdef MUSTANG_NECK_SPI_PORT + case COMMAND_MUSTANG_NECK_VALID: + response_buffer[0] = mustang_neck_found; + return 1; +#endif #ifdef BH_DRUM_TWI_PORT case COMMAND_BH_DRUM_VALID: response_buffer[0] = bh_drum_found; diff --git a/src/shared/main/mustang_neck.cpp b/src/shared/main/mustang_neck.cpp index d501b1e40..4679f4474 100644 --- a/src/shared/main/mustang_neck.cpp +++ b/src/shared/main/mustang_neck.cpp @@ -7,7 +7,7 @@ #ifdef MUSTANG_NECK_SPI_PORT static long lastTick = 0; static int missing = 0; -bool protar_found = false; +bool mustang_neck_found = false; static protarneck_t neck; protarneck_t tickMustangNeck() { if (micros() - lastTick > 500) { diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index b478374c8..9cb3246ca 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3206,6 +3206,20 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->autoCal_Light = report->tilt; report->autoCal_Microphone = report->tilt; #endif +#ifdef MUSTANG_NECK_SPI_PORT + report->lowEFret = lastProtar.lowEFret; + report->aFret = lastProtar.aFret; + report->dFret = lastProtar.dFret; + report->gFret = lastProtar.gFret; + report->bFret = lastProtar.bFret; + report->highEFret = lastProtar.highEFret; + report->green = lastProtar.green; + report->red = lastProtar.red; + report->yellow = lastProtar.yellow; + report->blue = lastProtar.blue; + report->orange = lastProtar.orange; + report->soloFlag = lastProtar.soloFlag; +#endif #if PRO_GUITAR && BLUETOOTH_RX TRANSLATE_TO_PRO_GUITAR(bt_data) report->autoCal_Light = report->tilt; @@ -3285,6 +3299,21 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->autoCal_Light = report->tilt; report->autoCal_Microphone = report->tilt; #endif + +#ifdef MUSTANG_NECK_SPI_PORT + report->lowEFret = lastProtar.lowEFret; + report->aFret = lastProtar.aFret; + report->dFret = lastProtar.dFret; + report->gFret = lastProtar.gFret; + report->bFret = lastProtar.bFret; + report->highEFret = lastProtar.highEFret; + report->green = lastProtar.green; + report->red = lastProtar.red; + report->yellow = lastProtar.yellow; + report->blue = lastProtar.blue; + report->orange = lastProtar.orange; + report->soloFlag = lastProtar.soloFlag; +#endif asm volatile("" :: : "memory"); gamepad->dpad = (gamepad->dpad & 0xf) > 0x0a ? 0x08 : dpad_bindings[gamepad->dpad]; @@ -3367,6 +3396,20 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #if PRO_GUITAR && USB_HOST_STACK TRANSLATE_TO_PRO_GUITAR(usb_host_data) #endif + +#ifdef MUSTANG_NECK_SPI_PORT + report->lowEFret = lastProtar.lowEFret; + report->aFret = lastProtar.aFret; + report->dFret = lastProtar.dFret; + report->gFret = lastProtar.gFret; + report->bFret = lastProtar.bFret; + report->highEFret = lastProtar.highEFret; + report->green = lastProtar.green; + report->red = lastProtar.red; + report->yellow = lastProtar.yellow; + report->blue = lastProtar.blue; + report->orange = lastProtar.orange; +#endif #if PRO_GUITAR && BLUETOOTH_RX TRANSLATE_TO_PRO_GUITAR(bt_data) #endif @@ -3535,6 +3578,21 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->autoCal_Light = report->tilt; report->autoCal_Microphone = report->tilt; #endif + +#ifdef MUSTANG_NECK_SPI_PORT + report->lowEFret = lastProtar.lowEFret; + report->aFret = lastProtar.aFret; + report->dFret = lastProtar.dFret; + report->gFret = lastProtar.gFret; + report->bFret = lastProtar.bFret; + report->highEFret = lastProtar.highEFret; + report->green = lastProtar.green; + report->red = lastProtar.red; + report->yellow = lastProtar.yellow; + report->blue = lastProtar.blue; + report->orange = lastProtar.orange; + report->soloFlag = lastProtar.soloFlag; +#endif #if PRO_GUITAR && BLUETOOTH_RX TRANSLATE_TO_PRO_GUITAR(bt_data) report->autoCal_Light = report->tilt; From 8554647ac1e326fd906718f24d6d1af32d52c499 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 9 Jan 2026 12:51:56 +1300 Subject: [PATCH 141/239] work towards mustang neck --- src/shared/main/shared_main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 9cb3246ca..2c840c564 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -26,6 +26,7 @@ #include "wii.h" #include "wt_drum.h" #include "quadrature_encoder.pio.h" +#include "protar_neck.h" #define UP 1 << 0 #define DOWN 1 << 1 #define LEFT 1 << 2 From 1dc3d5f2f8e9c9016f5d5d01b3bbe331be540533 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 9 Jan 2026 13:01:43 +1300 Subject: [PATCH 142/239] work towards mustang neck --- src/shared/main/mustang_neck.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shared/main/mustang_neck.cpp b/src/shared/main/mustang_neck.cpp index 4679f4474..9fd90c985 100644 --- a/src/shared/main/mustang_neck.cpp +++ b/src/shared/main/mustang_neck.cpp @@ -15,9 +15,11 @@ protarneck_t tickMustangNeck() { MUSTANG_NECK_CS_CLEAR(); uint8_t resp = spi_transfer(MUSTANG_NECK_SPI_PORT, 0x01); if (resp != 0x00) { + mustang_neck_found = false; MUSTANG_NECK_CS_SET(); return neck; } + mustang_neck_found = true; uint8_t* buf = (uint8_t*)&neck; for (int i = 0; i < sizeof(neck); i++) { *buf++ = spi_transfer(MUSTANG_NECK_SPI_PORT, 0x42); From 257f7c7fb73335b642461a3f039b6bfebdeec4b5 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 9 Jan 2026 20:40:54 +1300 Subject: [PATCH 143/239] header is already consumed, dont consume it twice --- include/state_translation/pro_guitar.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/state_translation/pro_guitar.h b/include/state_translation/pro_guitar.h index 6bf586b7e..4a337ca8e 100644 --- a/include/state_translation/pro_guitar.h +++ b/include/state_translation/pro_guitar.h @@ -1,6 +1,5 @@ #pragma once typedef struct { - uint8_t header = 0; uint16_t lowEFret : 5; uint16_t aFret : 5; uint16_t dFret : 5; From ee27b33930fc481751ef32ec735d0e65a0cbc26a Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 10 Jan 2026 21:01:35 +1300 Subject: [PATCH 144/239] differenciate ps4 from ps3 in a better way --- src/shared/usb/descriptors.cpp | 898 ++++++++++++++++++++------------- 1 file changed, 554 insertions(+), 344 deletions(-) diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 72d740d25..56023b892 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -749,7 +749,7 @@ const PROGMEM uint8_t ps3_feature_01[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const PROGMEM uint8_t ps3_feature_f2[] = { 0xf2, 0xff, 0xff, 0x00, - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // device bdaddr + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, // device bdaddr 0x00, 0x03, 0x50, 0x81, 0xd8, 0x01, 0x8a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x04, @@ -759,7 +759,7 @@ const PROGMEM uint8_t ps3_feature_f2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const PROGMEM uint8_t ps3_feature_f5[] = { 0x01, 0x00, - 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, // dummy PS3 bdaddr + 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, // dummy PS3 bdaddr 0xff, 0xf7, 0x00, 0x03, 0x50, 0x81, 0xd8, 0x01, 0x8a, 0x13, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x04, @@ -816,82 +816,112 @@ AuthPageSizeReport ps4_pagesize_report = { uint8_t idle_rate; uint8_t protocol_mode = HID_RPT_PROTOCOL; -bool controlRequestValid(const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength) { +bool controlRequestValid(const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength) +{ // printf("%02x %04x %04x %04x %04x\r\n", requestType, request, wValue, wIndex, wLength); - if (consoleType == UNIVERSAL && requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && request == 0x81) { + if (consoleType == UNIVERSAL && requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && request == 0x81) + { return true; } - if (consoleType != OG_XBOX && requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && request == 6 && wValue == 0x4200) { + if (consoleType != OG_XBOX && requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && request == 6 && wValue == 0x4200) + { return true; } - if (consoleType == OG_XBOX && requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR)) { - if (request == 6 && wValue == 0x4200) { + if (consoleType == OG_XBOX && requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR)) + { + if (request == 6 && wValue == 0x4200) + { return true; } - if (request == 1 && wValue == 0x0100) { + if (request == 1 && wValue == 0x0100) + { return true; } - if (request == 1 && wValue == 0x0200) { + if (request == 1 && wValue == 0x0200) + { return true; } } // Doing this actually *breaks* xb360 on pro micros. // But its necessary on the pico :/ #if SUPPORTS_PICO - switch (request) { - case 0x81: - case 0x82: - case 0x87: - case 0x83: - case 0x84: - case 0x86: - return true; + switch (request) + { + case 0x81: + case 0x82: + case 0x87: + case 0x83: + case 0x84: + case 0x86: + return true; } #endif - if (requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) { - switch (request) { - case HID_REQUEST_SET_PROTOCOL: - case HID_REQUEST_SET_IDLE: - case HID_REQUEST_SET_REPORT: - return true; + if (requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) + { + switch (request) + { + case HID_REQUEST_SET_PROTOCOL: + case HID_REQUEST_SET_IDLE: + case HID_REQUEST_SET_REPORT: + return true; } - if (request >= COMMAND_REBOOT && request < MAX) { + if (request >= COMMAND_REBOOT && request < MAX) + { return true; } } - if (requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS) && request == USB_REQUEST_GET_INTERFACE) { + if (requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS) && request == USB_REQUEST_GET_INTERFACE) + { return true; } - if (requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS) && request == USB_REQUEST_GET_STATUS) { + if (requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS) && request == USB_REQUEST_GET_STATUS) + { return true; } - if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS) && request == USB_REQUEST_SET_INTERFACE) { + if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS) && request == USB_REQUEST_SET_INTERFACE) + { return true; } - if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) { - switch (request) { - case HID_REQUEST_GET_PROTOCOL: - case HID_REQUEST_GET_IDLE: - case HID_REQUEST_GET_REPORT: - return true; - } - if (request >= COMMAND_REBOOT && request < MAX) { + if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) + { + switch (request) + { + case HID_REQUEST_GET_PROTOCOL: + case HID_REQUEST_GET_IDLE: + case HID_REQUEST_GET_REPORT: return true; } - } else if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR)) { - if (request == HID_REQUEST_GET_REPORT && wIndex == INTERFACE_ID_Device && wValue == VIBRATION_CAPABILITIES_WVALUE) { + if (request >= COMMAND_REBOOT && request < MAX) + { return true; - } else if (request == REQ_GET_OS_FEATURE_DESCRIPTOR && wIndex == DESC_EXTENDED_PROPERTIES_DESCRIPTOR && wValue == INTERFACE_ID_Config) { + } + } + else if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR)) + { + if (request == HID_REQUEST_GET_REPORT && wIndex == INTERFACE_ID_Device && wValue == VIBRATION_CAPABILITIES_WVALUE) + { return true; - } else if (request == HID_REQUEST_GET_REPORT && wIndex == INTERFACE_ID_Device && wValue == INPUT_CAPABILITIES_WVALUE) { + } + else if (request == REQ_GET_OS_FEATURE_DESCRIPTOR && wIndex == DESC_EXTENDED_PROPERTIES_DESCRIPTOR && wValue == INTERFACE_ID_Config) + { + return true; + } + else if (request == HID_REQUEST_GET_REPORT && wIndex == INTERFACE_ID_Device && wValue == INPUT_CAPABILITIES_WVALUE) + { return true; } - } else if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_VENDOR) && (consoleType == WINDOWS || consoleType == XBOX360) && request == HID_REQUEST_GET_REPORT && wIndex == 0x0000 && wValue == SERIAL_NUMBER_WVALUE) { + } + else if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_VENDOR) && (consoleType == WINDOWS || consoleType == XBOX360) && request == HID_REQUEST_GET_REPORT && wIndex == 0x0000 && wValue == SERIAL_NUMBER_WVALUE) + { return true; - } else if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_VENDOR) && request == REQ_GET_OS_FEATURE_DESCRIPTOR && wIndex == DESC_EXTENDED_COMPATIBLE_ID_DESCRIPTOR) { + } + else if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_VENDOR) && request == REQ_GET_OS_FEATURE_DESCRIPTOR && wIndex == DESC_EXTENDED_COMPATIBLE_ID_DESCRIPTOR) + { return true; - } else if (consoleType == UNIVERSAL && request == USB_REQUEST_CLEAR_FEATURE && (wIndex == DEVICE_EPADDR_IN || wIndex == DEVICE_EPADDR_OUT)) { + } + else if (consoleType == UNIVERSAL && request == USB_REQUEST_CLEAR_FEATURE && (wIndex == DEVICE_EPADDR_IN || wIndex == DEVICE_EPADDR_OUT)) + { return true; } return false; @@ -899,122 +929,150 @@ bool controlRequestValid(const uint8_t requestType, const uint8_t request, const uint8_t ps3_id_id = 4; bool cleared_input = false; bool cleared_output = false; -uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, uint8_t *requestBuffer, bool *status) { - // printf("%02x %04x %04x %04x %04x\r\n", requestType, request, wValue, wIndex, wLength); +uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, uint8_t *requestBuffer, bool *status) +{ + printf("%02x %04x %04x %04x %04x\r\n", requestType, request, wValue, wIndex, wLength); #if DEVICE_TYPE_IS_GAMEPAD - if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && (consoleType == UNIVERSAL || consoleType == OG_XBOX)) { + if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && (consoleType == UNIVERSAL || consoleType == OG_XBOX)) + { seen_og_xbox = true; - if (request == 6 && wValue == 0x4200) { + if (request == 6 && wValue == 0x4200) + { memcpy_P(requestBuffer, &DukeXIDDescriptor, sizeof(DukeXIDDescriptor)); return sizeof(DukeXIDDescriptor); } - if (request == 1 && wValue == 0x0100) { + if (request == 1 && wValue == 0x0100) + { memcpy_P(requestBuffer, &DukeXIDInputCapabilities, sizeof(DukeXIDInputCapabilities)); return sizeof(DukeXIDInputCapabilities); } - if (request == 1 && wValue == 0x0200) { + if (request == 1 && wValue == 0x0200) + { memcpy_P(requestBuffer, &DukeXIDVibrationCapabilities, sizeof(DukeXIDVibrationCapabilities)); return sizeof(DukeXIDVibrationCapabilities); } } #endif - if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && request == 0x83) { - if (xbox_360_state == Auth1) { + if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && request == 0x83) + { + if (xbox_360_state == Auth1) + { xbox_360_state = Auth2; - } else if (xbox_360_state == Auth2) { + } + else if (xbox_360_state == Auth2) + { xbox_360_state = Auth3; - } else if (xbox_360_state == Auth3) { + } + else if (xbox_360_state == Auth3) + { xbox_360_state = Authenticated; handle_auth_led(); - if (consoleType != XBOX360) { + if (consoleType != XBOX360) + { consoleType = XBOX360; reset_after_360 = millis() + 100; } } } - if (seen_windows_xb1 && !(requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_VENDOR) && request == REQ_GET_OS_FEATURE_DESCRIPTOR && wIndex == DESC_EXTENDED_COMPATIBLE_ID_DESCRIPTOR)) { + if (seen_windows_xb1 && !(requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_VENDOR) && request == REQ_GET_OS_FEATURE_DESCRIPTOR && wIndex == DESC_EXTENDED_COMPATIBLE_ID_DESCRIPTOR)) + { seen_windows = true; } - if (requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) { - if (request == COMMAND_REBOOT) { + if (requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) + { + if (request == COMMAND_REBOOT) + { reboot(); } - if (request == COMMAND_JUMP_BOOTLOADER) { + if (request == COMMAND_JUMP_BOOTLOADER) + { bootloader(); } - if (request >= COMMAND_REBOOT && request < MAX) { + if (request >= COMMAND_REBOOT && request < MAX) + { bool success; return handle_serial_command(request, wValue, requestBuffer, &success); } } - if (requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS) && request == USB_REQUEST_GET_INTERFACE) { + if (requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS) && request == USB_REQUEST_GET_INTERFACE) + { ((uint8_t *)requestBuffer)[0] = 0; return 1; } - if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS) && request == USB_REQUEST_SET_INTERFACE) { + if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS) && request == USB_REQUEST_SET_INTERFACE) + { return 0; } #if DEVICE_TYPE_IS_GAMEPAD #if SUPPORTS_PICO - switch (request) { - case 0x81: - uint8_t serial[0x0C]; - read_serial(serial, sizeof(serial)); - xsm3_set_vid_pid(serial, ARDWIINO_VID, ARDWIINO_PID); - xsm3_initialise_state(); - xsm3_set_identification_data(xsm3_id_data_ms_controller); - memcpy(requestBuffer, xsm3_id_data_ms_controller, sizeof(xsm3_id_data_ms_controller)); - return sizeof(xsm3_id_data_ms_controller); - case 0x82: - xsm3_do_challenge_init((uint8_t *)requestBuffer); - return 0; - case 0x87: - xsm3_do_challenge_verify((uint8_t *)requestBuffer); - return 0; - case 0x84: - return 0; - case 0x83: - memcpy(requestBuffer, xsm3_challenge_response, sizeof(xsm3_challenge_response)); - return wLength; - case 0x86: - short state = 2; // 1 = in-progress, 2 = complete - memcpy(requestBuffer, &state, sizeof(state)); - return sizeof(state); + switch (request) + { + case 0x81: + uint8_t serial[0x0C]; + read_serial(serial, sizeof(serial)); + xsm3_set_vid_pid(serial, ARDWIINO_VID, ARDWIINO_PID); + xsm3_initialise_state(); + xsm3_set_identification_data(xsm3_id_data_ms_controller); + memcpy(requestBuffer, xsm3_id_data_ms_controller, sizeof(xsm3_id_data_ms_controller)); + return sizeof(xsm3_id_data_ms_controller); + case 0x82: + xsm3_do_challenge_init((uint8_t *)requestBuffer); + return 0; + case 0x87: + xsm3_do_challenge_verify((uint8_t *)requestBuffer); + return 0; + case 0x84: + return 0; + case 0x83: + memcpy(requestBuffer, xsm3_challenge_response, sizeof(xsm3_challenge_response)); + return wLength; + case 0x86: + short state = 2; // 1 = in-progress, 2 = complete + memcpy(requestBuffer, &state, sizeof(state)); + return sizeof(state); } #else - if (consoleType == UNIVERSAL && requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && request == 0x81) { + if (consoleType == UNIVERSAL && requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && request == 0x81) + { consoleType = XBOX360; reset_usb(); return 0; } - switch (request) { - case 0x81: - case 0x82: - case 0x87: - case 0x84: - case 0x83: - case 0x86: - return 0; + switch (request) + { + case 0x81: + case 0x82: + case 0x87: + case 0x84: + case 0x83: + case 0x86: + return 0; } #endif #endif - if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) { + if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) + { #if DEVICE_TYPE_IS_GAMEPAD // PS3s request this as some form of controller id - if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x0300 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT && wLength == 0x08) { + if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x0300 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT && wLength == 0x08) + { // Pro instruments use a different init flow #if DEVICE_TYPE_IS_PRO - if (proButtonsEnabled) { + if (proButtonsEnabled) + { memcpy_P(requestBuffer, enabled_response[ps3_id_id], sizeof(enabled_response[ps3_id_id])); - } else { + } + else + { memcpy_P(requestBuffer, disabled_response[ps3_id_id], sizeof(disabled_response[ps3_id_id])); } ps3_id_id++; - if (ps3_id_id > 4) ps3_id_id = 4; + if (ps3_id_id > 4) + ps3_id_id = 4; return 8; #else memcpy_P(requestBuffer, ps3_init, sizeof(ps3_init)); @@ -1022,42 +1080,53 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const #endif } // Fakemote sends this, so we know to jump to PS3 mode - if ((consoleType == UNIVERSAL || consoleType == WINDOWS) && wValue == 0x03f2 && (wIndex == INTERFACE_ID_Device || wIndex == INTERFACE_ID_Config) && request == HID_REQUEST_GET_REPORT && wLength == 0x11) { - if (RPCS3_COMPAT) { + if ((consoleType == UNIVERSAL || consoleType == WINDOWS) && wValue == 0x03f2 && (wIndex == INTERFACE_ID_Device || wIndex == INTERFACE_ID_Config) && request == HID_REQUEST_GET_REPORT && wLength == 0x11) + { + if (RPCS3_COMPAT) + { consoleType = PS3; reset_usb(); } } // RPCS3 sends this. Jump any devices with RPCS3 compat enabled - if ((consoleType == UNIVERSAL || consoleType == WINDOWS) && wValue == 0x03f2 && wIndex == INTERFACE_ID_Config && request == HID_REQUEST_GET_REPORT) { - if (RPCS3_COMPAT) { + if ((consoleType == UNIVERSAL || consoleType == WINDOWS) && wValue == 0x03f2 && wIndex == INTERFACE_ID_Config && request == HID_REQUEST_GET_REPORT) + { + if (RPCS3_COMPAT) + { consoleType = PS3; reset_usb(); } seen_rpcs3 = true; } - if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x03f8 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT) { + if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x03f8 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT) + { memcpy_P(requestBuffer, ps3_feature_f8, sizeof(ps3_feature_f8)); requestBuffer[7] = ef_byte; return sizeof(ps3_feature_f8); } - if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x03f7 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT) { + if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x03f7 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT) + { memcpy_P(requestBuffer, ps3_feature_f7, sizeof(ps3_feature_f7)); return sizeof(ps3_feature_f7); } - if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x03f2 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT) { + if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x03f2 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT) + { memcpy_P(requestBuffer, ps3_feature_f2, sizeof(ps3_feature_f2)); return sizeof(ps3_feature_f2); } - if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x03f5 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT) { + if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x03f5 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT) + { memcpy_P(requestBuffer, ps3_feature_f5, sizeof(ps3_feature_f5)); - if (f5_state == 0) { + if (f5_state == 0) + { /* * First request, tell that the bdaddr is not the one of the PS3. */ f5_state = 1; - } else { + } + else + { /* * Next requests, tell that the bdaddr is the one of the PS3. */ @@ -1065,166 +1134,228 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const } return sizeof(ps3_feature_f5); } - if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x03ef && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT) { + if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x03ef && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT) + { memcpy_P(requestBuffer, ps3_feature_ef, sizeof(ps3_feature_ef)); requestBuffer[7] = ef_byte; return sizeof(ps3_feature_ef); } // PS3 sends this for a gamepad - if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x0301 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT && wLength == 0x40) { + if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x0301 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT && wLength == 0x40) + { memcpy_P(requestBuffer, ps3_feature_01, sizeof(ps3_feature_01)); return sizeof(ps3_feature_01); } // PS3 and PS4 send this - if (consoleType == UNIVERSAL && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT && wValue == 0x0303) { + if (consoleType == UNIVERSAL && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT && wValue == 0x0303) + { + seen_ps4 = true; + memcpy_P(requestBuffer, ps4_feature_config, sizeof(ps4_feature_config)); + return sizeof(ps4_feature_config); // PS3 Drums and Guitars get used on both consoles, so we can jump straight to PS3 mode #if DEVICE_TYPE_IS_INSTRUMENT && !SUPPORTS_PS4 consoleType = PS3; reset_usb(); #else - // the PS3 and PS4 will end up here. PS4 mode will jump back to PS3 mode on a PS3 later. - consoleType = PS4; - reset_usb(); + if (wLength == sizeof(ps4_feature_config)) + { + consoleType = PS4; + reset_usb(); + } else { + consoleType = PS3; + reset_usb(); + } + #endif } - if (consoleType == PS4 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT) { - switch (wValue) { - case 0x0303: - seen_ps4 = true; - memcpy_P(requestBuffer, ps4_feature_config, sizeof(ps4_feature_config)); - return sizeof(ps4_feature_config); + if (consoleType == PS4 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT) + { + switch (wValue) + { + case 0x0303: + seen_ps4 = true; + memcpy_P(requestBuffer, ps4_feature_config, sizeof(ps4_feature_config)); + return sizeof(ps4_feature_config); #if USB_HOST_STACK - case GET_RESPONSE: { - return transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); - } - case GET_AUTH_STATUS: { - return transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); - } - case GET_AUTH_PAGE_SIZE: { - // Don't start the auth process until we see a controller - if (get_device_address_for(PS4).dev_addr == 0) { - return 0; - } - // Attempt to read the page size from the connected controller - // On a DS4, this will fail but we have the default page size report for that scenario. - transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_GET_REPORT, GET_AUTH_PAGE_SIZE, INTERFACE_ID_Device, sizeof(AuthPageSizeReport), (uint8_t *)&ps4_pagesize_report, NULL); - memcpy_P(requestBuffer, &ps4_pagesize_report, sizeof(ps4_pagesize_report)); - return sizeof(ps4_pagesize_report); + case GET_RESPONSE: + { + return transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); + } + case GET_AUTH_STATUS: + { + return transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); + } + case GET_AUTH_PAGE_SIZE: + { + // Don't start the auth process until we see a controller + if (get_device_address_for(PS4).dev_addr == 0) + { + return 0; } + // Attempt to read the page size from the connected controller + // On a DS4, this will fail but we have the default page size report for that scenario. + transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_GET_REPORT, GET_AUTH_PAGE_SIZE, INTERFACE_ID_Device, sizeof(AuthPageSizeReport), (uint8_t *)&ps4_pagesize_report, NULL); + memcpy_P(requestBuffer, &ps4_pagesize_report, sizeof(ps4_pagesize_report)); + return sizeof(ps4_pagesize_report); + } #else - case GET_AUTH_PAGE_SIZE: { - memcpy_P(requestBuffer, &ps4_pagesize_report, sizeof(ps4_pagesize_report)); - return sizeof(ps4_pagesize_report); - } + case GET_AUTH_PAGE_SIZE: + { + memcpy_P(requestBuffer, &ps4_pagesize_report, sizeof(ps4_pagesize_report)); + return sizeof(ps4_pagesize_report); + } #endif } } - if (wValue == 0x0101 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT && wLength == 0x80) { + if (wValue == 0x0101 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT && wLength == 0x80) + { return tick_inputs(requestBuffer, NULL, consoleType); } - if (consoleType == OG_XBOX && wValue == 0x0100 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT && wLength == sizeof(OG_XBOX_REPORT)) { + if (consoleType == OG_XBOX && wValue == 0x0100 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT && wLength == sizeof(OG_XBOX_REPORT)) + { return tick_inputs(requestBuffer, NULL, consoleType); } #endif bool test = true; uint8_t size = handle_serial_command(request, wValue, requestBuffer, &test); - if (test) { + if (test) + { return size; } - } else if (request == HID_REQUEST_SET_REPORT && wValue == SET_CHALLENGE && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) { + } + else if (request == HID_REQUEST_SET_REPORT && wValue == SET_CHALLENGE && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) + { #if USB_HOST_STACK return transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); #else return 0; #endif - } else if (request == HID_REQUEST_SET_REPORT && wValue == 0x03F2 && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) { + } + else if (request == HID_REQUEST_SET_REPORT && wValue == 0x03F2 && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) + { return 1; - } else if (request == HID_REQUEST_SET_REPORT && wValue == 0x03F4 && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) { + } + else if (request == HID_REQUEST_SET_REPORT && wValue == 0x03F4 && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) + { // pademu sends this, so we know to jump to PS3 mode - if (consoleType == UNIVERSAL && wLength == 0x04) { + if (consoleType == UNIVERSAL && wLength == 0x04) + { consoleType = PS3; reset_usb(); } return 1; - } else if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x03ef && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_SET_REPORT) { + } + else if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x03ef && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_SET_REPORT) + { ef_byte = requestBuffer[6]; return 1; - } else if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x03f5 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_SET_REPORT) { + } + else if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x03f5 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_SET_REPORT) + { memcpy(master_bd_addr, requestBuffer + 2, sizeof(master_bd_addr)); printf("Master bd address set\r\n"); return 1; - } else if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR)) { - if (request == HID_REQUEST_GET_REPORT && wIndex == INTERFACE_ID_Device && wValue == VIBRATION_CAPABILITIES_WVALUE) { + } + else if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR)) + { + if (request == HID_REQUEST_GET_REPORT && wIndex == INTERFACE_ID_Device && wValue == VIBRATION_CAPABILITIES_WVALUE) + { memcpy_P(requestBuffer, &XInputVibrationCapabilities, sizeof(XInputVibrationCapabilities)); return sizeof(XInputVibrationCapabilities); - } else if (request == REQ_GET_OS_FEATURE_DESCRIPTOR && wIndex == DESC_EXTENDED_PROPERTIES_DESCRIPTOR) { + } + else if (request == REQ_GET_OS_FEATURE_DESCRIPTOR && wIndex == DESC_EXTENDED_PROPERTIES_DESCRIPTOR) + { memcpy_P(requestBuffer, &ExtendedIDs, ExtendedIDs.TotalLength); return ExtendedIDs.TotalLength; - } else if (request == HID_REQUEST_GET_REPORT && wIndex == INTERFACE_ID_Device && wValue == INPUT_CAPABILITIES_WVALUE) { + } + else if (request == HID_REQUEST_GET_REPORT && wIndex == INTERFACE_ID_Device && wValue == INPUT_CAPABILITIES_WVALUE) + { memcpy_P(requestBuffer, &XInputInputCapabilities, sizeof(XInputInputCapabilities)); return sizeof(XInputInputCapabilities); } - } else if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_VENDOR) && (consoleType == WINDOWS || consoleType == XBOX360) && request == HID_REQUEST_GET_REPORT && wIndex == 0x0000 && wValue == SERIAL_NUMBER_WVALUE) { + } + else if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_VENDOR) && (consoleType == WINDOWS || consoleType == XBOX360) && request == HID_REQUEST_GET_REPORT && wIndex == 0x0000 && wValue == SERIAL_NUMBER_WVALUE) + { uint32_t serial = micros(); memcpy(requestBuffer, &serial, sizeof(serial)); return sizeof(XInputSerialNumber_t); - } else if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_VENDOR) && request == REQ_GET_OS_FEATURE_DESCRIPTOR && wIndex == DESC_EXTENDED_COMPATIBLE_ID_DESCRIPTOR) { + } + else if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_DEVICE | USB_SETUP_TYPE_VENDOR) && request == REQ_GET_OS_FEATURE_DESCRIPTOR && wIndex == DESC_EXTENDED_COMPATIBLE_ID_DESCRIPTOR) + { seen_windows_xb1 = true; memcpy_P(requestBuffer, &DevCompatIDs, sizeof(OS_COMPATIBLE_ID_DESCRIPTOR)); - if (consoleType == XBOXONE) { + if (consoleType == XBOXONE) + { memcpy_P(requestBuffer, &DevCompatIDsOne, sizeof(DevCompatIDsOne)); return sizeof(DevCompatIDsOne); - } else if (consoleType == WINDOWS || consoleType == XBOX360) { + } + else if (consoleType == WINDOWS || consoleType == XBOX360) + { OS_COMPATIBLE_ID_DESCRIPTOR *compat = (OS_COMPATIBLE_ID_DESCRIPTOR *)requestBuffer; compat->TotalSections = 4; compat->TotalLength = sizeof(OS_COMPATIBLE_ID_DESCRIPTOR); return sizeof(OS_COMPATIBLE_ID_DESCRIPTOR); - } else if (consoleType == PS3 || consoleType == WII_RB) { + } + else if (consoleType == PS3 || consoleType == WII_RB) + { memcpy_P(requestBuffer, &DevCompatIDsPS3, sizeof(OS_COMPATIBLE_ID_DESCRIPTOR_SINGLE)); return sizeof(OS_COMPATIBLE_ID_DESCRIPTOR_SINGLE); - } else if (consoleType != UNIVERSAL) { + } + else if (consoleType != UNIVERSAL) + { return 0; } memcpy_P(requestBuffer, &DevCompatIDsUniversal, sizeof(DevCompatIDsUniversal)); return sizeof(DevCompatIDsUniversal); - } else if (request == HID_REQUEST_SET_PROTOCOL && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) { + } + else if (request == HID_REQUEST_SET_PROTOCOL && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) + { protocol_mode = (uint8_t)wValue; return 0; - } else if (request == HID_REQUEST_SET_IDLE && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) { + } + else if (request == HID_REQUEST_SET_IDLE && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) + { idle_rate = (wValue >> 8) & 0xff; return 0; - } else if (consoleType == UNIVERSAL && request == USB_REQUEST_CLEAR_FEATURE && (wIndex == DEVICE_EPADDR_IN || wIndex == DEVICE_EPADDR_OUT)) { + } + else if (consoleType == UNIVERSAL && request == USB_REQUEST_CLEAR_FEATURE && (wIndex == DEVICE_EPADDR_IN || wIndex == DEVICE_EPADDR_OUT)) + { // Switch clears a halt on both endpoints cleared_input |= wIndex == DEVICE_EPADDR_IN; cleared_output |= wIndex == DEVICE_EPADDR_OUT; - if (cleared_input && cleared_output) { + if (cleared_input && cleared_output) + { consoleType = SWITCH; reset_usb(); return 0; } - } else if (request == HID_REQUEST_SET_REPORT && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) { + } + else if (request == HID_REQUEST_SET_REPORT && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) + { const uint8_t reportType = (wValue >> 8); const uint8_t reportId = (wValue & 0xFF); hid_set_report((uint8_t *)requestBuffer, wLength, reportType, reportId); #if DEVICE_TYPE_IS_PRO - if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x0300 && wIndex == INTERFACE_ID_Device && wLength == 0x28) { + if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x0300 && wIndex == INTERFACE_ID_Device && wLength == 0x28) + { // for (int i = 0; i < 0x28; i++) { // printf("%02x, ", requestBuffer[i]); // } // printf("\r\n"); - switch (requestBuffer[2]) { - case 0x89: - printf("MIDI data enabled\r\n"); - proButtonsEnabled = true; - ps3_id_id = 0; - break; - case 0x81: - printf("MIDI data disabled\r\n"); - proButtonsEnabled = false; - ps3_id_id = 0; - break; + switch (requestBuffer[2]) + { + case 0x89: + printf("MIDI data enabled\r\n"); + proButtonsEnabled = true; + ps3_id_id = 0; + break; + case 0x81: + printf("MIDI data disabled\r\n"); + proButtonsEnabled = false; + ps3_id_id = 0; + break; } } #endif @@ -1235,228 +1366,307 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const bool seen_windows_desc = false; uint16_t descriptorRequest(const uint16_t wValue, const uint16_t wIndex, - void *descriptorBuffer) { + void *descriptorBuffer) +{ const uint8_t descriptorType = (wValue >> 8); const uint8_t descriptorNumber = (wValue & 0xFF); // printf("desc: %02x %02x\r\n", descriptorType, descriptorNumber); #if DEVICE_TYPE_IS_GAMEPAD - if (consoleType == UNIVERSAL && seen_windows_xb1 && descriptorType != HID_DESCRIPTOR_REPORT) { + if (consoleType == UNIVERSAL && seen_windows_xb1 && descriptorType != HID_DESCRIPTOR_REPORT) + { seen_windows_desc = true; } - if (consoleType == UNIVERSAL && seen_windows_xb1 && descriptorType == HID_DESCRIPTOR_REPORT) { - if (seen_windows_desc) { - if (WINDOWS_USES_XINPUT) { + if (consoleType == UNIVERSAL && seen_windows_xb1 && descriptorType == HID_DESCRIPTOR_REPORT) + { + if (seen_windows_desc) + { + if (WINDOWS_USES_XINPUT) + { set_console_type(WINDOWS); } - } else { + } + else + { set_console_type(XBOXONE); } } #endif descriptor_requested = true; uint16_t size = NO_DESCRIPTOR; - switch (descriptorType) { - case USB_DESCRIPTOR_DEVICE: { - read_device_desc = true; - size = sizeof(USB_DEVICE_DESCRIPTOR); - memcpy_P(descriptorBuffer, &deviceDescriptor, size); - USB_DEVICE_DESCRIPTOR *dev = (USB_DEVICE_DESCRIPTOR *)descriptorBuffer; + switch (descriptorType) + { + case USB_DESCRIPTOR_DEVICE: + { + read_device_desc = true; + size = sizeof(USB_DEVICE_DESCRIPTOR); + memcpy_P(descriptorBuffer, &deviceDescriptor, size); + USB_DEVICE_DESCRIPTOR *dev = (USB_DEVICE_DESCRIPTOR *)descriptorBuffer; #if DEVICE_TYPE_IS_GAMEPAD - if (consoleType == SWITCH) { - dev->idVendor = HORI_VID; - dev->idProduct = HORI_POKKEN_TOURNAMENT_DX_PRO_PAD_PID; - } else if (consoleType == XBOX360) { - dev->idVendor = ARDWIINO_VID; - dev->idProduct = ARDWIINO_PID; - } else if (consoleType == OG_XBOX) { - dev->idVendor = 0x045E; - dev->idProduct = 0x0289; - } - else if (consoleType == XBOXONE) { - dev->idVendor = XBOX_ONE_CONTROLLER_VID; - dev->idProduct = XBOX_ONE_CONTROLLER_PID; - dev->bDeviceClass = 0xff; - dev->bDeviceSubClass = 0x47; - dev->bDeviceProtocol = 0xd0; - } - else if (consoleType == PS4) { - dev->idVendor = PS4_VID; - dev->idProduct = PS4_PID; - } else if (consoleType == IOS_FESTIVAL) { - dev->idVendor = SONY_VID; - dev->idProduct = SONY_DS3_PID; - } + if (consoleType == SWITCH) + { + dev->idVendor = HORI_VID; + dev->idProduct = HORI_POKKEN_TOURNAMENT_DX_PRO_PAD_PID; + } + else if (consoleType == XBOX360) + { + dev->idVendor = ARDWIINO_VID; + dev->idProduct = ARDWIINO_PID; + } + else if (consoleType == OG_XBOX) + { + dev->idVendor = 0x045E; + dev->idProduct = 0x0289; + } + else if (consoleType == XBOXONE) + { + dev->idVendor = XBOX_ONE_CONTROLLER_VID; + dev->idProduct = XBOX_ONE_CONTROLLER_PID; + dev->bDeviceClass = 0xff; + dev->bDeviceSubClass = 0x47; + dev->bDeviceProtocol = 0xd0; + } + else if (consoleType == PS4) + { + dev->idVendor = PS4_VID; + dev->idProduct = PS4_PID; + } + else if (consoleType == IOS_FESTIVAL) + { + dev->idVendor = SONY_VID; + dev->idProduct = SONY_DS3_PID; + } #ifdef WII_TYPE - else if (consoleType == WII_RB) { - dev->idVendor = HARMONIX_VID; - dev->idProduct = WII_TYPE; - } + else if (consoleType == WII_RB) + { + dev->idVendor = HARMONIX_VID; + dev->idProduct = WII_TYPE; + } #endif #ifdef PS3_TYPE - else if (consoleType == PS3) { - dev->idVendor = REDOCTANE_VID; - dev->idProduct = PS3_TYPE; - } + else if (consoleType == PS3) + { + dev->idVendor = REDOCTANE_VID; + dev->idProduct = PS3_TYPE; + } #elif DEVICE_TYPE == GAMEPAD - else if (consoleType == PS3) { - dev->idVendor = SONY_VID; - dev->idProduct = SONY_DS3_PID; - } + else if (consoleType == PS3) + { + dev->idVendor = SONY_VID; + dev->idProduct = SONY_DS3_PID; + } #endif #endif #if DEVICE_TYPE == ROCK_BAND_GUITAR || DEVICE_TYPE == GUITAR_HERO_GUITAR - if (consoleType == FNF) { - dev->idVendor = PDP_VID; - dev->idProduct = XBOX_ONE_JAG_PID; - } + if (consoleType == FNF) + { + dev->idVendor = PDP_VID; + dev->idProduct = XBOX_ONE_JAG_PID; + } #endif - if (consoleType == ARCADE) { - dev->idVendor = 0x0c70; - dev->idProduct = 0x0777; - } - break; + if (consoleType == ARCADE) + { + dev->idVendor = 0x0c70; + dev->idProduct = 0x0777; } - case USB_DESCRIPTOR_CONFIGURATION: { + break; + } + case USB_DESCRIPTOR_CONFIGURATION: + { #if CONSOLE_TYPE == MIDI_ID - size = sizeof(MIDI_CONFIGURATION_DESCRIPTOR); - memcpy_P(descriptorBuffer, &MIDIConfigurationDescriptor, size); + size = sizeof(MIDI_CONFIGURATION_DESCRIPTOR); + memcpy_P(descriptorBuffer, &MIDIConfigurationDescriptor, size); #elif DEVICE_TYPE_IS_KEYBOARD - size = sizeof(UNIVERSAL_CONFIGURATION_DESCRIPTOR); - memcpy_P(descriptorBuffer, &UniversalConfigurationDescriptor, size); + size = sizeof(UNIVERSAL_CONFIGURATION_DESCRIPTOR); + memcpy_P(descriptorBuffer, &UniversalConfigurationDescriptor, size); #else - if (consoleType == XBOXONE) { - size = sizeof(XBOX_ONE_CONFIGURATION_DESCRIPTOR); - memcpy_P(descriptorBuffer, &XBOXOneConfigurationDescriptor, size); - } else if (consoleType == WINDOWS || consoleType == XBOX360) { - size = sizeof(XBOX_360_CONFIGURATION_DESCRIPTOR); - memcpy_P(descriptorBuffer, &XBOX360ConfigurationDescriptor, size); - } else if (consoleType == OG_XBOX) { - size = sizeof(OG_XBOX_CONFIGURATION_DESCRIPTOR); - memcpy_P(descriptorBuffer, &OGXBOXConfigurationDescriptor, size); - } else if (consoleType == ARCADE) { - size = sizeof(GH_ARCADE_CONFIGURATION_DESCRIPTOR); - memcpy_P(descriptorBuffer, &GHArcadeConfigurationDescriptor, size); - } else { - size = sizeof(UNIVERSAL_CONFIGURATION_DESCRIPTOR); - memcpy_P(descriptorBuffer, &UniversalConfigurationDescriptor, size); - UNIVERSAL_CONFIGURATION_DESCRIPTOR *desc = (UNIVERSAL_CONFIGURATION_DESCRIPTOR *)descriptorBuffer; + if (consoleType == XBOXONE) + { + size = sizeof(XBOX_ONE_CONFIGURATION_DESCRIPTOR); + memcpy_P(descriptorBuffer, &XBOXOneConfigurationDescriptor, size); + } + else if (consoleType == WINDOWS || consoleType == XBOX360) + { + size = sizeof(XBOX_360_CONFIGURATION_DESCRIPTOR); + memcpy_P(descriptorBuffer, &XBOX360ConfigurationDescriptor, size); + } + else if (consoleType == OG_XBOX) + { + size = sizeof(OG_XBOX_CONFIGURATION_DESCRIPTOR); + memcpy_P(descriptorBuffer, &OGXBOXConfigurationDescriptor, size); + } + else if (consoleType == ARCADE) + { + size = sizeof(GH_ARCADE_CONFIGURATION_DESCRIPTOR); + memcpy_P(descriptorBuffer, &GHArcadeConfigurationDescriptor, size); + } + else + { + size = sizeof(UNIVERSAL_CONFIGURATION_DESCRIPTOR); + memcpy_P(descriptorBuffer, &UniversalConfigurationDescriptor, size); + UNIVERSAL_CONFIGURATION_DESCRIPTOR *desc = (UNIVERSAL_CONFIGURATION_DESCRIPTOR *)descriptorBuffer; - if (consoleType == PS4) { - desc->HIDDescriptor.wDescriptorLength = sizeof(ps4_descriptor); - desc->EndpointOutHID.wMaxPacketSize = 64; - desc->EndpointInHID.wMaxPacketSize = 64; - } else if (consoleType == IOS_FESTIVAL) { - desc->HIDDescriptor.wDescriptorLength = sizeof(ps3_descriptor); - desc->EndpointOutHID.wMaxPacketSize = 64; - desc->EndpointInHID.wMaxPacketSize = 64; + if (consoleType == PS4) + { + desc->HIDDescriptor.wDescriptorLength = sizeof(ps4_descriptor); + desc->EndpointOutHID.wMaxPacketSize = 64; + desc->EndpointInHID.wMaxPacketSize = 64; + } + else if (consoleType == IOS_FESTIVAL) + { + desc->HIDDescriptor.wDescriptorLength = sizeof(ps3_descriptor); + desc->EndpointOutHID.wMaxPacketSize = 64; + desc->EndpointInHID.wMaxPacketSize = 64; #if DEVICE_TYPE_IS_INSTRUMENT #if defined(TICK_NKRO) || defined(TICK_SIXKRO) - } else if (consoleType == KEYBOARD_MOUSE) { - desc->HIDDescriptor.wDescriptorLength = sizeof(keyboard_mouse_descriptor); + } + else if (consoleType == KEYBOARD_MOUSE) + { + desc->HIDDescriptor.wDescriptorLength = sizeof(keyboard_mouse_descriptor); #endif #if DEVICE_TYPE == ROCK_BAND_GUITAR || DEVICE_TYPE == GUITAR_HERO_GUITAR - } else if (consoleType == FNF) { - desc->HIDDescriptor.wDescriptorLength = sizeof(fnf_descriptor); + } + else if (consoleType == FNF) + { + desc->HIDDescriptor.wDescriptorLength = sizeof(fnf_descriptor); #endif - } else { - desc->HIDDescriptor.wDescriptorLength = sizeof(ps3_instrument_descriptor); - } + } + else + { + desc->HIDDescriptor.wDescriptorLength = sizeof(ps3_instrument_descriptor); + } #else - } else if (consoleType == PS3) { - desc->HIDDescriptor.wDescriptorLength = sizeof(ps3_descriptor); - desc->EndpointOutHID.wMaxPacketSize = 64; - desc->EndpointInHID.wMaxPacketSize = 64; - } else { - desc->HIDDescriptor.wDescriptorLength = sizeof(ps3_instrument_descriptor); - } -#endif - if (consoleType == UNIVERSAL) { - desc->HIDDescriptor.wDescriptorLength = sizeof(pc_descriptor); - } else { - // Strip out all the extra interfaces used for configuring / x360 compat, consoles dont need them - desc->Config.bNumInterfaces = 1; - desc->Config.wTotalLength = sizeof(HID_CONFIGURATION_DESCRIPTOR); - } + } + else if (consoleType == PS3) + { + desc->HIDDescriptor.wDescriptorLength = sizeof(ps3_descriptor); + desc->EndpointOutHID.wMaxPacketSize = 64; + desc->EndpointInHID.wMaxPacketSize = 64; + } + else + { + desc->HIDDescriptor.wDescriptorLength = sizeof(ps3_instrument_descriptor); } #endif - break; + if (consoleType == UNIVERSAL) + { + desc->HIDDescriptor.wDescriptorLength = sizeof(pc_descriptor); + } + else + { + // Strip out all the extra interfaces used for configuring / x360 compat, consoles dont need them + desc->Config.bNumInterfaces = 1; + desc->Config.wTotalLength = sizeof(HID_CONFIGURATION_DESCRIPTOR); + } } - case HID_DESCRIPTOR_REPORT: { - const void *address; - seen_hid_descriptor_read = true; +#endif + break; + } + case HID_DESCRIPTOR_REPORT: + { + const void *address; + seen_hid_descriptor_read = true; #if DEVICE_TYPE_IS_KEYBOARD - address = keyboard_mouse_descriptor; - size = sizeof(keyboard_mouse_descriptor); + address = keyboard_mouse_descriptor; + size = sizeof(keyboard_mouse_descriptor); #elif DEVICE_TYPE_IS_GAMEPAD - if (consoleType == ARCADE) { - address = gha_descriptor; - size = sizeof(gha_descriptor); - } else if (consoleType == PS4) { - address = ps4_descriptor; - size = sizeof(ps4_descriptor); - } else if (consoleType == IOS_FESTIVAL) { - address = ps3_descriptor; - size = sizeof(ps3_descriptor); + if (consoleType == ARCADE) + { + address = gha_descriptor; + size = sizeof(gha_descriptor); + } + else if (consoleType == PS4) + { + address = ps4_descriptor; + size = sizeof(ps4_descriptor); + } + else if (consoleType == IOS_FESTIVAL) + { + address = ps3_descriptor; + size = sizeof(ps3_descriptor); #if DEVICE_TYPE == ROCK_BAND_GUITAR || DEVICE_TYPE == GUITAR_HERO_GUITAR - } else if (consoleType == FNF) { - address = fnf_descriptor; - size = sizeof(fnf_descriptor); + } + else if (consoleType == FNF) + { + address = fnf_descriptor; + size = sizeof(fnf_descriptor); #endif #if defined(TICK_NKRO) || defined(TICK_SIXKRO) - } else if (consoleType == KEYBOARD_MOUSE) { - address = keyboard_mouse_descriptor; - size = sizeof(keyboard_mouse_descriptor); + } + else if (consoleType == KEYBOARD_MOUSE) + { + address = keyboard_mouse_descriptor; + size = sizeof(keyboard_mouse_descriptor); #endif - } else if (consoleType != UNIVERSAL) { + } + else if (consoleType != UNIVERSAL) + { #if DEVICE_TYPE_IS_INSTRUMENT + address = ps3_instrument_descriptor; + size = sizeof(ps3_instrument_descriptor); +#else + if (consoleType == PS3) + { + address = ps3_descriptor; + size = sizeof(ps3_descriptor); + } + else + { address = ps3_instrument_descriptor; size = sizeof(ps3_instrument_descriptor); -#else - if (consoleType == PS3) { - address = ps3_descriptor; - size = sizeof(ps3_descriptor); - } else { - address = ps3_instrument_descriptor; - size = sizeof(ps3_instrument_descriptor); - } -#endif - } else { - address = pc_descriptor; - size = sizeof(pc_descriptor); } +#endif + } + else + { + address = pc_descriptor; + size = sizeof(pc_descriptor); + } #else - address = ps3_instrument_descriptor; - size = sizeof(ps3_instrument_descriptor); + address = ps3_instrument_descriptor; + size = sizeof(ps3_instrument_descriptor); #endif - memcpy_P(descriptorBuffer, address, size); - break; + memcpy_P(descriptorBuffer, address, size); + break; + } + case USB_DESCRIPTOR_STRING: + { + // We only care for actual string reads, not the language id + if (descriptorNumber != 0) + { + read_any_device_string = true; } - case USB_DESCRIPTOR_STRING: { - // We only care for actual string reads, not the language id - if (descriptorNumber != 0) { - read_any_device_string = true; - } - const uint8_t *str; - if (descriptorNumber == 5) { - str = (uint8_t *)&rtStringInput; - } else if (descriptorNumber == 6) { - str = (uint8_t *)&rtStringLED; - } else if (descriptorNumber == 4) { - str = (uint8_t *)&xboxString; - } else if (descriptorNumber < 4) { - str = (uint8_t *)pgm_read_pointer(descriptorStrings + descriptorNumber); - } else if (descriptorNumber == 0xEE) { - str = (uint8_t *)&OSDescriptorString; - seen_os_descriptor_read = true; - } else { - break; - } - size = pgm_read_byte(str + offsetof(STRING_DESCRIPTOR, bLength)); - memcpy_P(descriptorBuffer, str, size); + const uint8_t *str; + if (descriptorNumber == 5) + { + str = (uint8_t *)&rtStringInput; + } + else if (descriptorNumber == 6) + { + str = (uint8_t *)&rtStringLED; + } + else if (descriptorNumber == 4) + { + str = (uint8_t *)&xboxString; + } + else if (descriptorNumber < 4) + { + str = (uint8_t *)pgm_read_pointer(descriptorStrings + descriptorNumber); + } + else if (descriptorNumber == 0xEE) + { + str = (uint8_t *)&OSDescriptorString; + seen_os_descriptor_read = true; + } + else + { break; } + size = pgm_read_byte(str + offsetof(STRING_DESCRIPTOR, bLength)); + memcpy_P(descriptorBuffer, str, size); + break; + } } return size; } From f16ef6e32184b002b1de0a6f949e77a09e87fa3c Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 11 Jan 2026 16:22:30 +1300 Subject: [PATCH 145/239] mustang neck fixes --- include/config.h | 18 ++ include/hid.h | 1 + include/reports/ps5_reports.h | 241 +++++++++++++++++++++---- include/state_translation/pro_guitar.h | 4 +- src/pico/main.cpp | 22 ++- src/pico/xinput_device.cpp | 3 + src/shared/hid/ps3_wii_switch.h | 83 +++++++++ src/shared/main/mustang_neck.cpp | 24 ++- src/shared/main/shared_main.cpp | 67 +++---- src/shared/usb/descriptors.cpp | 63 ++++++- 10 files changed, 445 insertions(+), 81 deletions(-) diff --git a/include/config.h b/include/config.h index 33a138389..c65597f87 100644 --- a/include/config.h +++ b/include/config.h @@ -42,6 +42,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define PS2_REPORT PS2Gamepad_Data_t #define PS3_REPORT PS3SimpleGamepad_Data_t #define PS4_REPORT PS4Gamepad_Data_t +#define PS5_REPORT PS5Gamepad_Data_t #define XINPUT_FLAGS XINPUT_FLAGS_FORCE_FEEDBACK #define PS3_FLAGS 0x07 #define HID_BUTTON_COUNT 14 @@ -71,6 +72,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define PS2_REPORT PS2Gamepad_Data_t #define PS3_REPORT PS3SimpleGamepad_Data_t #define PS4_REPORT PS4Gamepad_Data_t +#define PS5_REPORT PS5Gamepad_Data_t #define XINPUT_FLAGS XINPUT_FLAGS_FORCE_FEEDBACK #define PS3_FLAGS 0x07 #define HID_BUTTON_COUNT 14 @@ -100,6 +102,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define PS2_REPORT PS2Gamepad_Data_t #define PS3_REPORT PS3SimpleGamepad_Data_t #define PS4_REPORT PS4Gamepad_Data_t +#define PS5_REPORT PS5Gamepad_Data_t #define XINPUT_FLAGS XINPUT_FLAGS_FORCE_FEEDBACK #define PS3_FLAGS 0x07 #define HID_BUTTON_COUNT 14 @@ -129,6 +132,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define PS2_REPORT PS2Gamepad_Data_t #define PS3_REPORT PS3SimpleGamepad_Data_t #define PS4_REPORT PS4Gamepad_Data_t +#define PS5_REPORT PS5Gamepad_Data_t #define XINPUT_FLAGS XINPUT_FLAGS_FORCE_FEEDBACK #define PS3_FLAGS 0x07 #define HID_BUTTON_COUNT 14 @@ -158,6 +162,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define PS2_REPORT PS2Gamepad_Data_t #define PS3_REPORT PS3SimpleGamepad_Data_t #define PS4_REPORT PS4Gamepad_Data_t +#define PS5_REPORT PS5Gamepad_Data_t #define XINPUT_FLAGS XINPUT_FLAGS_FORCE_FEEDBACK #define PS3_FLAGS 0x07 #define HID_BUTTON_COUNT 14 @@ -187,6 +192,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define PS2_REPORT PS2Gamepad_Data_t #define PS3_REPORT PS3SimpleGamepad_Data_t #define PS4_REPORT PS4Gamepad_Data_t +#define PS5_REPORT PS5Gamepad_Data_t #define XINPUT_FLAGS XINPUT_FLAGS_FORCE_FEEDBACK #define PS3_FLAGS 0x07 #define HID_BUTTON_COUNT 14 @@ -220,6 +226,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define PS2_REPORT PS2GuitarHeroGuitar_Data_t #define PS3_REPORT PS3GuitarHeroGuitar_Data_t #define PS4_REPORT PS4RockBandGuitar_Data_t +#define PS5_REPORT PS5RockBandGuitar_Data_t // FFB flag enables support for the tap bar #define XINPUT_FLAGS XINPUT_FLAGS_FORCE_FEEDBACK #define PS3_FLAGS 0x06 @@ -252,6 +259,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define PS2_REPORT PS2GuitarHeroGuitar_Data_t #define PS3_REPORT PS3RockBandGuitar_Data_t #define PS4_REPORT PS4RockBandGuitar_Data_t +#define PS5_REPORT PS5RockBandGuitar_Data_t // FFB flag was set on strats #define XINPUT_FLAGS XINPUT_FLAGS_FORCE_FEEDBACK #define PS3_FLAGS 0x06 @@ -283,6 +291,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define PS2_REPORT PS2Gamepad_Data_t #define PS3_REPORT PS3RockBandProGuitar_Data_t #define PS4_REPORT PS3RockBandProGuitar_Data_t +#define PS5_REPORT PS3RockBandProGuitar_Data_t #define XINPUT_FLAGS XINPUT_FLAGS_NONE #define PS3_FLAGS 0x06 #define HID_BUTTON_COUNT 13 @@ -313,6 +322,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define PS2_REPORT PS2Gamepad_Data_t #define PS3_REPORT PS3RockBandProGuitar_Data_t #define PS4_REPORT PS3RockBandProGuitar_Data_t +#define PS5_REPORT PS3RockBandProGuitar_Data_t #define XINPUT_FLAGS XINPUT_FLAGS_NONE #define PS3_FLAGS 0x06 #define HID_BUTTON_COUNT 13 @@ -343,6 +353,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define PS2_REPORT PS2Gamepad_Data_t #define PS3_REPORT PS3RockBandProKeyboard_Data_t #define PS4_REPORT PS3RockBandProKeyboard_Data_t +#define PS5_REPORT PS3RockBandProKeyboard_Data_t #define XINPUT_FLAGS XINPUT_FLAGS_NONE #define PS3_FLAGS 0x06 #define HID_BUTTON_COUNT 35 @@ -395,6 +406,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define PS2_REPORT PS2Gamepad_Data_t #define PS3_REPORT PS3GHLGuitar_Data_t #define PS4_REPORT PS4GHLGuitar_Data_t +#define PS5_REPORT PS5GHLGuitar_Data_t // GHL guitars set no navigation #define XINPUT_FLAGS XINPUT_FLAGS_NO_NAV #define PS3_FLAGS 0x06 @@ -428,6 +440,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define PS2_REPORT PS2Gamepad_Data_t #define PS3_REPORT PS3GuitarHeroDrums_Data_t #define PS4_REPORT PS4RockBandDrums_Data_t +#define PS5_REPORT PS5RockBandDrums_Data_t #define XINPUT_FLAGS XINPUT_FLAGS_NONE #define PS3_FLAGS 0x07 #define HID_BUTTON_COUNT 13 @@ -459,6 +472,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define PS2_REPORT PS2Gamepad_Data_t #define PS3_REPORT PS3RockBandDrums_Data_t #define PS4_REPORT PS4RockBandDrums_Data_t +#define PS5_REPORT PS5RockBandDrums_Data_t #define XINPUT_FLAGS XINPUT_FLAGS_FORCE_FEEDBACK #define PS3_FLAGS 0x05 #define HID_BUTTON_COUNT 15 @@ -489,6 +503,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define PS2_REPORT PS2Gamepad_Data_t #define PS3_REPORT PS3Turntable_Data_t #define PS4_REPORT PS3Turntable_Data_t +#define PS5_REPORT PS3Turntable_Data_t #define XINPUT_FLAGS XINPUT_FLAGS_NONE #define PS3_FLAGS 0x06 #define HID_BUTTON_COUNT 13 @@ -511,6 +526,9 @@ extern const uint8_t config[CONFIGURATION_LEN]; #ifndef PS4_TYPE #define PS4_TYPE PS4_GAMEPAD #endif +#ifndef PS5_TYPE +#define PS5_TYPE PS4_GAMEPAD +#endif #if DEVICE_TYPE_IS_GAMEPAD #ifndef HID_AXIS_COUNT #error missing HID_AXIS_COUNT and HID_BUTTON_COUNT diff --git a/include/hid.h b/include/hid.h index ecd2d2663..299aa89dd 100644 --- a/include/hid.h +++ b/include/hid.h @@ -79,6 +79,7 @@ extern const uint8_t ps3_descriptor[148]; extern const uint8_t ps3_instrument_descriptor[137]; extern const uint8_t gha_descriptor[83]; extern const uint8_t ps4_descriptor[160]; +extern const uint8_t ps5_descriptor[165]; extern const uint8_t fnf_descriptor[53]; extern long last_strobe; extern uint8_t stage_kit_millis[5]; diff --git a/include/reports/ps5_reports.h b/include/reports/ps5_reports.h index eb8523f21..6aa4aecc7 100644 --- a/include/reports/ps5_reports.h +++ b/include/reports/ps5_reports.h @@ -2,7 +2,29 @@ #include #define PS5_INPUT_REPORT_ID 1 -typedef struct { +typedef struct +{ + uint8_t counter : 7; + uint8_t unpressed : 1; + + // 12 bit X, followed by 12 bit Y + uint8_t data[3]; +} __attribute__((packed)) TouchpadXY; + +typedef struct +{ + TouchpadXY p1; + TouchpadXY p2; +} __attribute__((packed)) TouchpadData; + +typedef struct +{ + int16_t x; + int16_t y; + int16_t z; +} __attribute__((packed)) PSSensor; +typedef struct +{ uint8_t report_id; uint8_t leftStickX; uint8_t leftStickY; @@ -11,38 +33,90 @@ typedef struct { uint8_t leftTrigger : 8; uint8_t rightTrigger : 8; - uint8_t sequence_number; // 6 + uint8_t sequence_number; // 6 uint8_t dpad : 4; - uint8_t x : 1; // square - uint8_t a : 1; // cross - uint8_t b : 1; // circle - uint8_t y : 1; // triangle - - uint8_t leftShoulder : 1; // l1 - uint8_t rightShoulder : 1; // r1 - uint8_t l2 : 1; // l2 - uint8_t r2 : 1; // r2 - - - uint8_t back : 1; // share - uint8_t start : 1; // options - uint8_t leftThumbClick : 1; // l3 - uint8_t rightThumbClick : 1; // r3 + uint8_t x : 1; // square + uint8_t a : 1; // cross + uint8_t b : 1; // circle + uint8_t y : 1; // triangle + + uint8_t leftShoulder : 1; // l1 + uint8_t rightShoulder : 1; // r1 + uint8_t l2 : 1; // l2 + uint8_t r2 : 1; // r2 + + uint8_t back : 1; // share + uint8_t start : 1; // options + uint8_t leftThumbClick : 1; // l3 + uint8_t rightThumbClick : 1; // r3 uint8_t guide : 1; uint8_t touchpad : 1; + uint8_t : 6; + + uint8_t data_11; + + uint32_t auth_seq_number; + + PSSensor gyroscope; + PSSensor accelerometer; + + uint16_t data_28_29; + + uint16_t data_30_31_0x001a; + + TouchpadData touchpad_data; + + uint8_t data_40_55[16]; + + uint8_t hash[8]; + +} __attribute__((packed)) PS5Dpad_Data_t; +typedef struct +{ + uint8_t report_id; + uint8_t leftStickX; + uint8_t leftStickY; + uint8_t rightStickX; + uint8_t rightStickY; + uint8_t leftTrigger : 8; + uint8_t rightTrigger : 8; + + uint8_t sequence_number; // 6 + + uint8_t dpadUp : 1; + uint8_t dpadDown : 1; + uint8_t dpadLeft : 1; + uint8_t dpadRight : 1; + uint8_t x : 1; // square + uint8_t a : 1; // cross + uint8_t b : 1; // circle + uint8_t y : 1; // triangle + + uint8_t leftShoulder : 1; // l1 + uint8_t rightShoulder : 1; // r1 + uint8_t l2 : 1; // l2 + uint8_t r2 : 1; // r2 + + uint8_t back : 1; // share + uint8_t start : 1; // options + uint8_t leftThumbClick : 1; // l3 + uint8_t rightThumbClick : 1; // r3 + + uint8_t guide : 1; + uint8_t capture : 1; uint8_t mic : 1; - uint8_t dummy : 5; // 7-9 + uint8_t dummy : 5; // 7-9 } __attribute__((packed)) PS5Gamepad_Data_t; typedef struct { - uint8_t report_id; - uint8_t joystickX; - uint8_t joystickY; + uint8_t report_id; + uint8_t leftStickX; + uint8_t leftStickY; uint8_t unused1[5]; @@ -51,28 +125,33 @@ typedef struct // 6 8 2 // 5 3 // 4 - uint8_t dpad : 4; - uint8_t x : 1; // blue - uint8_t a : 1; // green - uint8_t b : 1; // red - uint8_t y : 1; // yellow + uint8_t dpadUp : 1; + uint8_t dpadDown : 1; + uint8_t dpadLeft : 1; + uint8_t dpadRight : 1; + uint8_t x : 1; // blue + uint8_t a : 1; // green + uint8_t b : 1; // red + uint8_t y : 1; // yellow - uint8_t leftShoulder : 1; // orange + uint8_t leftShoulder : 1; // orange uint8_t : 3; - uint8_t back : 1; // share - uint8_t start : 1; // options + uint8_t back : 1; // share + uint8_t start : 1; // options uint8_t solo : 1; uint8_t p1 : 1; uint8_t guide : 1; - uint8_t : 7; + uint8_t capture : 1; // touchpad click + uint8_t : 6; uint8_t unused2; uint32_t packetCounter; - uint8_t unused3[25]; + uint8_t unused3[24]; + uint8_t pickup; uint8_t whammy; uint8_t tilt; @@ -96,4 +175,102 @@ typedef struct uint8_t unused4[11]; uint64_t checksum; -} __attribute__((__packed__)) PS5RockBandGuitar_Data_t; \ No newline at end of file +} __attribute__((__packed__)) PS5RockBandGuitar_Data_t; + +typedef struct +{ + + uint8_t report_id; + uint8_t leftStickX; + uint8_t leftStickY; + + uint8_t unused1[5]; + + // 0 + // 7 1 + // 6 8 2 + // 5 3 + // 4 + uint8_t dpadUp : 1; + uint8_t dpadDown : 1; + uint8_t dpadLeft : 1; + uint8_t dpadRight : 1; + uint8_t x : 1; // blue + uint8_t a : 1; // green + uint8_t b : 1; // red + uint8_t y : 1; // yellow + + uint8_t kick1 : 1; // orange + uint8_t kick2 : 1; // orange + uint8_t : 2; + uint8_t back : 1; // share + uint8_t start : 1; // options + uint8_t : 2; + + uint8_t guide : 1; + uint8_t capture : 1; // touchpad click + uint8_t : 6; + + uint8_t unused2; + + uint32_t packetCounter; + + uint8_t unused3[24]; + + uint8_t redVelocity; + uint8_t blueVelocity; + uint8_t yellowVelocity; + uint8_t greenVelocity; + + uint8_t yellowCymbalVelocity; + uint8_t blueCymbalVelocity; + uint8_t greenCymbalVelocity; + uint8_t unused4[9]; + uint64_t checksum; +} __attribute__((__packed__)) PS5RockBandDrums_Data_t; + +typedef struct +{ + + uint8_t report_id; + + uint8_t leftStickX; + uint8_t strumBar; + uint8_t whammy; + uint8_t tilt; + + uint8_t unused1[2]; + + // 0 + // 7 1 + // 6 8 2 + // 5 3 + // 4 + uint8_t dpadUp : 1; + uint8_t dpadDown : 1; + uint8_t dpadLeft : 1; + uint8_t dpadRight : 1; + uint8_t x : 1; // blue + uint8_t a : 1; // green + uint8_t b : 1; // red + uint8_t y : 1; // yellow + + uint8_t leftShoulder : 1; // orange + uint8_t rightShoulder : 1; // orange + uint8_t : 2; + uint8_t back : 1; // share + uint8_t start : 1; // options + uint8_t solo : 1; + uint8_t p1 : 1; + + uint8_t guide : 1; + uint8_t capture : 1; // touchpad click + uint8_t : 6; + + uint8_t unused2; + + uint32_t packetCounter; + + uint8_t unused3[40]; + uint64_t checksum; +} __attribute__((__packed__)) PS5GHLGuitar_Data_t; \ No newline at end of file diff --git a/include/state_translation/pro_guitar.h b/include/state_translation/pro_guitar.h index 4a337ca8e..45a0ebe18 100644 --- a/include/state_translation/pro_guitar.h +++ b/include/state_translation/pro_guitar.h @@ -3,14 +3,13 @@ typedef struct { uint16_t lowEFret : 5; uint16_t aFret : 5; uint16_t dFret : 5; - uint16_t : 1; // always 1 + uint16_t : 1; // always 0 uint16_t gFret : 5; uint16_t bFret : 5; uint16_t highEFret : 5; uint16_t : 1; // always 0 - uint8_t : 1; // always 0 uint8_t green :1; uint8_t red :1; uint8_t yellow :1; @@ -18,6 +17,7 @@ typedef struct { uint8_t orange :1; uint8_t soloFlag : 1; uint8_t : 1; // always 0 + uint8_t : 1; // always 0 } __attribute__((packed)) protarneck_t; #define TRANSLATE_PRO_GUITAR \ diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 29f0931b9..fbab06329 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -54,6 +54,7 @@ static uint32_t __uninitialized_ram(pico_is_sleeping); USB_Device_Type_t xone_dev_addr = {}; USB_Device_Type_t x360_dev_addr = {}; USB_Device_Type_t ps4_dev_addr = {}; +USB_Device_Type_t ps5_dev_addr = {}; uint8_t total_usb_host_devices = 0; typedef struct { @@ -337,6 +338,10 @@ USB_Device_Type_t get_device_address_for(uint8_t deviceType) { return ps4_dev_addr; } + if (deviceType == PS5) + { + return ps5_dev_addr; + } return {0}; } #endif @@ -480,7 +485,6 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ case KEYBOARD: case MOUSE: case STREAM_DECK: - case PS5: case UNKNOWN: case GENERIC: case STEPMANIAX: @@ -539,6 +543,22 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ ps4_controller_connected(dev_addr, host_vid, host_pid); } break; + case PS5: + usb_host_devices[total_usb_host_devices].type = type; + total_usb_host_devices++; + if (!ps5_dev_addr.dev_addr) + { + ps5_dev_addr = type; + + printf("Found PS5 controller\r\n"); + ps4_controller_connected(dev_addr, host_vid, host_pid); + if (consoleType == PS4) { + consoleType = PS5; + reset_usb(); + } + + } + break; } printf("Total devices: %d\r\n", total_usb_host_devices); diff --git a/src/pico/xinput_device.cpp b/src/pico/xinput_device.cpp index 989210e64..eccbe00ca 100644 --- a/src/pico/xinput_device.cpp +++ b/src/pico/xinput_device.cpp @@ -285,6 +285,9 @@ bool xinputd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, } else if (consoleType == ARCADE) { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, 0x40)); + } else if (consoleType == PS5) { + TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, + 0x40)); } else { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, 0x08)); diff --git a/src/shared/hid/ps3_wii_switch.h b/src/shared/hid/ps3_wii_switch.h index 1de50ba61..2cd6c1f6b 100644 --- a/src/shared/hid/ps3_wii_switch.h +++ b/src/shared/hid/ps3_wii_switch.h @@ -482,3 +482,86 @@ const uint8_t PROGMEM ps4_descriptor[] = { 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) 0xC0, // End Collection }; + +const uint8_t PROGMEM ps5_descriptor[] = +{ + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x05, // Usage (Game Pad) + 0xA1, 0x01, // Collection (Application) + 0x85, 0x01, // Report ID (1) + 0x09, 0x30, // Usage (X) + 0x09, 0x31, // Usage (Y) + 0x09, 0x32, // Usage (Z) + 0x09, 0x35, // Usage (Rz) + 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, 0x06, // Report Count (6) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x20, // Usage (0x20) + 0x95, 0x01, // Report Count (1) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x09, 0x39, // Usage (Hat switch) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x07, // Logical Maximum (7) + 0x35, 0x00, // Physical Minimum (0) + 0x46, 0x3B, 0x01, // Physical Maximum (315) + 0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter) + 0x75, 0x04, // Report Size (4) + 0x95, 0x01, // Report Count (1) + 0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State) + 0x65, 0x00, // Unit (None) + 0x05, 0x09, // Usage Page (Button) + 0x19, 0x01, // Usage Minimum (0x01) + 0x29, 0x0E, // Usage Maximum (0x0E) + 0x15, 0x00, // Logical Minimum (0) + 0x25, 0x01, // Logical Maximum (1) + 0x75, 0x01, // Report Size (1) + 0x95, 0x0E, // Report Count (14) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x21, // Usage (0x21) + 0x95, 0x0E, // Report Count (14) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x06, 0x00, 0xFF, // Usage Page (Vendor Defined 0xFF00) + 0x09, 0x22, // Usage (0x22) + 0x15, 0x00, // Logical Minimum (0) + 0x26, 0xFF, 0x00, // Logical Maximum (255) + 0x75, 0x08, // Report Size (8) + 0x95, 0x34, // Report Count (52) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x85, 0x02, // Report ID (2) + 0x09, 0x23, // Usage (0x23) + 0x95, 0x2F, // Report Count (47) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + 0x85, 0x03, // Report ID (3) + 0x0A, 0x21, 0x28, // Usage (0x2821) + 0x95, 0x2F, // Report Count (47) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + 0x06, 0x80, 0xFF, // Usage Page (Vendor Defined 0xFF80) + 0x85, 0xE0, // Report ID (-32) + 0x09, 0x57, // Usage (0x57) + 0x95, 0x02, // Report Count (2) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + 0xC0, // End Collection + 0x06, 0xF0, 0xFF, // Usage Page (Vendor Defined 0xFFF0) + 0x09, 0x40, // Usage (0x40) + 0xA1, 0x01, // Collection (Application) + 0x85, 0xF0, // Report ID (-16) + 0x09, 0x47, // Usage (0x47) + 0x95, 0x3F, // Report Count (63) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + 0x85, 0xF1, // Report ID (-15) + 0x09, 0x48, // Usage (0x48) + 0x95, 0x3F, // Report Count (63) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + 0x85, 0xF2, // Report ID (-14) + 0x09, 0x49, // Usage (0x49) + 0x95, 0x0F, // Report Count (15) + 0xB1, 0x02, // Feature (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile) + 0xC0, // End Collection +}; diff --git a/src/shared/main/mustang_neck.cpp b/src/shared/main/mustang_neck.cpp index 9fd90c985..ff1a7d11c 100644 --- a/src/shared/main/mustang_neck.cpp +++ b/src/shared/main/mustang_neck.cpp @@ -9,20 +9,32 @@ static long lastTick = 0; static int missing = 0; bool mustang_neck_found = false; static protarneck_t neck; -protarneck_t tickMustangNeck() { - if (micros() - lastTick > 500) { +protarneck_t tickMustangNeck() +{ + if (micros() - lastTick > 500) + { lastTick = micros(); MUSTANG_NECK_CS_CLEAR(); uint8_t resp = spi_transfer(MUSTANG_NECK_SPI_PORT, 0x01); - if (resp != 0x00) { + if (resp == 0x00) + { + mustang_neck_found = true; + memset(&neck, 0, sizeof(neck)); + MUSTANG_NECK_CS_SET(); + return neck; + } + if (resp != 0x01) + { mustang_neck_found = false; + memset(&neck, 0, sizeof(neck)); MUSTANG_NECK_CS_SET(); return neck; } mustang_neck_found = true; - uint8_t* buf = (uint8_t*)&neck; - for (int i = 0; i < sizeof(neck); i++) { - *buf++ = spi_transfer(MUSTANG_NECK_SPI_PORT, 0x42); + uint8_t *buf = (uint8_t *)&neck; + for (int i = 0; i < sizeof(neck); i++) + { + buf[i] = spi_transfer(MUSTANG_NECK_SPI_PORT, 0x48); } MUSTANG_NECK_CS_SET(); } diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 2c840c564..f0b5643de 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1790,7 +1790,7 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t } case PS5: { - PS5Gamepad_Data_t *dpad = (PS5Gamepad_Data_t *)data; + PS5Dpad_Data_t *dpad = (PS5Dpad_Data_t *)data; usb_host_data->dpadLeft = dpad->dpad == 6 || dpad->dpad == 5 || dpad->dpad == 7; usb_host_data->dpadRight = dpad->dpad == 3 || dpad->dpad == 2 || dpad->dpad == 1; usb_host_data->dpadUp = dpad->dpad == 0 || dpad->dpad == 1 || dpad->dpad == 7; @@ -3289,37 +3289,37 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->guide = true; } TICK_PS4; - -#if PRO_GUITAR && USB_HOST_STACK - TRANSLATE_TO_PRO_GUITAR(usb_host_data) - report->autoCal_Light = report->tilt; - report->autoCal_Microphone = report->tilt; -#endif -#if PRO_GUITAR && BLUETOOTH_RX - TRANSLATE_TO_PRO_GUITAR(bt_data) - report->autoCal_Light = report->tilt; - report->autoCal_Microphone = report->tilt; -#endif - -#ifdef MUSTANG_NECK_SPI_PORT - report->lowEFret = lastProtar.lowEFret; - report->aFret = lastProtar.aFret; - report->dFret = lastProtar.dFret; - report->gFret = lastProtar.gFret; - report->bFret = lastProtar.bFret; - report->highEFret = lastProtar.highEFret; - report->green = lastProtar.green; - report->red = lastProtar.red; - report->yellow = lastProtar.yellow; - report->blue = lastProtar.blue; - report->orange = lastProtar.orange; - report->soloFlag = lastProtar.soloFlag; -#endif asm volatile("" :: : "memory"); gamepad->dpad = (gamepad->dpad & 0xf) > 0x0a ? 0x08 : dpad_bindings[gamepad->dpad]; report_size = packet_size = sizeof(PS4_REPORT); } + if (output_console_type == PS5) + { + if (millis() > 450000 && !auth_ps4_controller_found) + { + reset_usb(); + } + PS5_REPORT *report = (PS5_REPORT *)report_data; + memset(report, 0, sizeof(PS5_REPORT)); + PS5Dpad_Data_t *gamepad = (PS5Dpad_Data_t *)report; + gamepad->report_id = 0x01; + gamepad->leftStickX = PS3_STICK_CENTER; + gamepad->leftStickY = PS3_STICK_CENTER; + gamepad->rightStickX = PS3_STICK_CENTER; + gamepad->rightStickY = PS3_STICK_CENTER; + gamepad->data_30_31_0x001a = 0x001a; + // PS4 does not start using the controller until it sees a PS button press. + if (!report_requested) + { + report->guide = true; + } + TICK_PS4; + asm volatile("" :: + : "memory"); + gamepad->dpad = (gamepad->dpad & 0xf) > 0x0a ? 0x08 : dpad_bindings[gamepad->dpad]; + report_size = packet_size = sizeof(PS5_REPORT); + } #endif #ifdef TICK_FESTIVAL if (output_console_type == IOS_FESTIVAL) @@ -3678,7 +3678,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } TICK_RESET // Some hosts want packets sent every frame - if (last_report && output_console_type != ARCADE && output_console_type != OG_XBOX && output_console_type != PS4 && output_console_type != IOS_FESTIVAL && output_console_type != PS3 && output_console_type != BLUETOOTH_REPORT && !updateHIDSequence) + if (last_report && output_console_type != ARCADE && output_console_type != OG_XBOX && output_console_type != PS4 && output_console_type != PS5 && output_console_type != IOS_FESTIVAL && output_console_type != PS3 && output_console_type != BLUETOOTH_REPORT && !updateHIDSequence) { uint8_t cmp = memcmp(last_report, report_data, report_size); if (cmp == 0) @@ -3694,6 +3694,11 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu PS4Gamepad_Data_t *gamepad = (PS4Gamepad_Data_t *)report_data; gamepad->reportCounter = ps4_sequence_number++; } + if (output_console_type == PS5) + { + PS5Dpad_Data_t *gamepad = (PS5Dpad_Data_t *)report_data; + gamepad->sequence_number = ps4_sequence_number++; + } #endif #if DEVICE_TYPE_IS_GAMEPAD @@ -3785,11 +3790,6 @@ bool tick_usb(void) // But the PS2 does not. We also end up here on the wii/wiiu if a device does not have an explicit wii mode. set_console_type(PS3); } - // Due to some quirks with how the PS3 detects controllers, we can also end up here for PS3, but in that case, we won't see any requests for controller data - if ((millis() - millis_at_boot) > 2000 && consoleType == PS4 && !seen_ps4) - { - set_console_type(PS3); - } #endif if (!ready) return 0; @@ -3811,6 +3811,7 @@ bool tick_usb(void) return true; } } + // #if DEVICE_TYPE == SKYLANDERS // if (consoleType == XBOX360) { // size = 32; diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 56023b892..9f47040fe 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -814,6 +814,15 @@ AuthPageSizeReport ps4_pagesize_report = { u4 : {0x00, 0x00, 0x00, 0x00} }; +const PROGMEM uint8_t ps5_feature_config[] = { + 0x03, 0x21, 0x28, 0x03, 0xC3, PS4_TYPE, 0x2C, 0x56, + 0x01, 0x00, 0xD0, 0x07, 0x00, 0x80, 0x04, 0x00, + 0x00, 0x80, 0x0D, 0x0D, 0x84, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + uint8_t idle_rate; uint8_t protocol_mode = HID_RPT_PROTOCOL; bool controlRequestValid(const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength) @@ -842,9 +851,6 @@ bool controlRequestValid(const uint8_t requestType, const uint8_t request, const return true; } } - // Doing this actually *breaks* xb360 on pro micros. - // But its necessary on the pico :/ -#if SUPPORTS_PICO switch (request) { case 0x81: @@ -855,7 +861,6 @@ bool controlRequestValid(const uint8_t requestType, const uint8_t request, const case 0x86: return true; } -#endif if (requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) { switch (request) @@ -1150,8 +1155,6 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const if (consoleType == UNIVERSAL && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT && wValue == 0x0303) { seen_ps4 = true; - memcpy_P(requestBuffer, ps4_feature_config, sizeof(ps4_feature_config)); - return sizeof(ps4_feature_config); // PS3 Drums and Guitars get used on both consoles, so we can jump straight to PS3 mode #if DEVICE_TYPE_IS_INSTRUMENT && !SUPPORTS_PS4 consoleType = PS3; @@ -1205,6 +1208,27 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const memcpy_P(requestBuffer, &ps4_pagesize_report, sizeof(ps4_pagesize_report)); return sizeof(ps4_pagesize_report); } +#endif + } + } + if (consoleType == PS5 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT) + { + switch (wValue) + { + case 0x0303: + seen_ps4 = true; + memcpy_P(requestBuffer, ps5_feature_config, sizeof(ps5_feature_config)); + return sizeof(ps5_feature_config); + +#if USB_HOST_STACK + case GET_RESPONSE: + { + return transfer_with_usb_controller(get_device_address_for(PS5).dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); + } + case GET_AUTH_STATUS: + { + return transfer_with_usb_controller(get_device_address_for(PS5).dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); + } #endif } } @@ -1224,12 +1248,20 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const return size; } } - else if (request == HID_REQUEST_SET_REPORT && wValue == SET_CHALLENGE && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) + else if (request == HID_REQUEST_SET_REPORT && consoleType == PS4 && wValue == SET_CHALLENGE && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) { #if USB_HOST_STACK return transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); #else return 0; +#endif + } + else if (request == HID_REQUEST_SET_REPORT && consoleType == PS5 && wValue == SET_CHALLENGE && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) + { +#if USB_HOST_STACK + return transfer_with_usb_controller(get_device_address_for(PS5).dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); +#else + return 0; #endif } else if (request == HID_REQUEST_SET_REPORT && wValue == 0x03F2 && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) @@ -1431,6 +1463,11 @@ uint16_t descriptorRequest(const uint16_t wValue, dev->idVendor = PS4_VID; dev->idProduct = PS4_PID; } + else if (consoleType == PS5) + { + dev->idVendor = 0x3651; + dev->idProduct = 0x1600; + } else if (consoleType == IOS_FESTIVAL) { dev->idVendor = SONY_VID; @@ -1513,6 +1550,13 @@ uint16_t descriptorRequest(const uint16_t wValue, desc->EndpointOutHID.wMaxPacketSize = 64; desc->EndpointInHID.wMaxPacketSize = 64; } + else if (consoleType == PS5) + { + desc->HIDDescriptor.wDescriptorLength = sizeof(ps5_descriptor); + desc->EndpointOutHID.wMaxPacketSize = 64; + desc->EndpointInHID.wMaxPacketSize = 64; + desc->HIDDescriptor.bcdHID = 0x0111; + } else if (consoleType == IOS_FESTIVAL) { desc->HIDDescriptor.wDescriptorLength = sizeof(ps3_descriptor); @@ -1581,6 +1625,11 @@ uint16_t descriptorRequest(const uint16_t wValue, address = ps4_descriptor; size = sizeof(ps4_descriptor); } + else if (consoleType == PS5) + { + address = ps5_descriptor; + size = sizeof(ps5_descriptor); + } else if (consoleType == IOS_FESTIVAL) { address = ps3_descriptor; From 318b4b918a1200287c8dfabd9ad1c69dfbe1980c Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 11 Jan 2026 17:15:48 +1300 Subject: [PATCH 146/239] mustang neck fixes --- src/shared/main/mustang_neck.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/shared/main/mustang_neck.cpp b/src/shared/main/mustang_neck.cpp index ff1a7d11c..ee962b7eb 100644 --- a/src/shared/main/mustang_neck.cpp +++ b/src/shared/main/mustang_neck.cpp @@ -15,7 +15,7 @@ protarneck_t tickMustangNeck() { lastTick = micros(); MUSTANG_NECK_CS_CLEAR(); - uint8_t resp = spi_transfer(MUSTANG_NECK_SPI_PORT, 0x01); + uint8_t resp = spi_transfer(MUSTANG_NECK_SPI_PORT, 0x80); if (resp == 0x00) { mustang_neck_found = true; @@ -23,10 +23,9 @@ protarneck_t tickMustangNeck() MUSTANG_NECK_CS_SET(); return neck; } - if (resp != 0x01) + if (resp != 0x80) { mustang_neck_found = false; - memset(&neck, 0, sizeof(neck)); MUSTANG_NECK_CS_SET(); return neck; } @@ -34,7 +33,7 @@ protarneck_t tickMustangNeck() uint8_t *buf = (uint8_t *)&neck; for (int i = 0; i < sizeof(neck); i++) { - buf[i] = spi_transfer(MUSTANG_NECK_SPI_PORT, 0x48); + buf[i] = spi_transfer(MUSTANG_NECK_SPI_PORT, 0x12); } MUSTANG_NECK_CS_SET(); } From 6d185ba767dd5ad988b4f578563548101283dde7 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 12 Jan 2026 10:03:22 +1300 Subject: [PATCH 147/239] support ps5 auth --- include/reports/ps5_reports.h | 25 +++++------------------- src/pico/main.cpp | 34 +++++++++++++++++++++++++++++++-- src/shared/main/shared_main.cpp | 19 ++++++++---------- src/shared/usb/descriptors.cpp | 4 ++-- 4 files changed, 47 insertions(+), 35 deletions(-) diff --git a/include/reports/ps5_reports.h b/include/reports/ps5_reports.h index 6aa4aecc7..7bdc170e2 100644 --- a/include/reports/ps5_reports.h +++ b/include/reports/ps5_reports.h @@ -30,8 +30,8 @@ typedef struct uint8_t leftStickY; uint8_t rightStickX; uint8_t rightStickY; - uint8_t leftTrigger : 8; - uint8_t rightTrigger : 8; + uint8_t leftTrigger; + uint8_t rightTrigger; uint8_t sequence_number; // 6 @@ -80,8 +80,8 @@ typedef struct uint8_t leftStickY; uint8_t rightStickX; uint8_t rightStickY; - uint8_t leftTrigger : 8; - uint8_t rightTrigger : 8; + uint8_t leftTrigger; + uint8_t rightTrigger; uint8_t sequence_number; // 6 @@ -120,11 +120,6 @@ typedef struct uint8_t unused1[5]; - // 0 - // 7 1 - // 6 8 2 - // 5 3 - // 4 uint8_t dpadUp : 1; uint8_t dpadDown : 1; uint8_t dpadLeft : 1; @@ -136,6 +131,7 @@ typedef struct uint8_t leftShoulder : 1; // orange uint8_t : 3; + uint8_t back : 1; // share uint8_t start : 1; // options uint8_t solo : 1; @@ -176,7 +172,6 @@ typedef struct uint8_t unused4[11]; uint64_t checksum; } __attribute__((__packed__)) PS5RockBandGuitar_Data_t; - typedef struct { @@ -186,11 +181,6 @@ typedef struct uint8_t unused1[5]; - // 0 - // 7 1 - // 6 8 2 - // 5 3 - // 4 uint8_t dpadUp : 1; uint8_t dpadDown : 1; uint8_t dpadLeft : 1; @@ -241,11 +231,6 @@ typedef struct uint8_t unused1[2]; - // 0 - // 7 1 - // 6 8 2 - // 5 3 - // 4 uint8_t dpadUp : 1; uint8_t dpadDown : 1; uint8_t dpadLeft : 1; diff --git a/src/pico/main.cpp b/src/pico/main.cpp index fbab06329..5c9e8421a 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -115,8 +115,31 @@ bool usb_configured() return tud_ready(); } +bool ps5_auth_ready = 0; +uint8_t hash_pending_buffer[64]; +uint8_t hash_finish_buffer[64]; + +uint8_t auth_buffer[64]; +bool dongle_ready = false; +bool hash_pending = false; +bool hash_ready = false; +uint32_t hash_timer; void send_report_to_pc(const void *report, uint8_t len) { + if (consoleType == PS5 && ps5_dev_addr.dev_addr) + { + if (hash_pending) { + return; + } + hash_pending = true; + send_report_to_controller(ps5_dev_addr.dev_addr, ps5_dev_addr.instance, (const uint8_t*)report, len); + return; + // if (tuh_xinput_ready(ps5_dev_addr.dev_addr, ps5_dev_addr.instance)) + // { + // printf("send\r\n"); + // tuh_xinput_send_report(ps5_dev_addr.dev_addr, ps5_dev_addr.instance, (const uint8_t*)report, len); + // } + } tud_xusb_n_report(0, report, len); } bool foundXB = false; @@ -552,11 +575,11 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_typ printf("Found PS5 controller\r\n"); ps4_controller_connected(dev_addr, host_vid, host_pid); - if (consoleType == PS4) { + if (consoleType == PS4) + { consoleType = PS5; reset_usb(); } - } break; } @@ -624,6 +647,13 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c { receive_report_from_controller(report, len); } + // receive report from p5general and forward it to the console + if (dev_addr == ps5_dev_addr.dev_addr && instance == ps5_dev_addr.instance) + { + hash_pending = false; + tud_xusb_n_report(0, report, len); + return; + } // Send player indicator every 10 seconds or so just as a keep alive if (millis() - lastPlayerLed > 10000) { diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index f0b5643de..b992acb6b 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -776,6 +776,9 @@ long lastTick; uint8_t keyboard_report = 0; void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_type, USB_Host_Data_t *usb_host_data) { + if (!len) { + return; + } switch (device_type.console_type) { case STADIA: @@ -3309,12 +3312,12 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu gamepad->rightStickX = PS3_STICK_CENTER; gamepad->rightStickY = PS3_STICK_CENTER; gamepad->data_30_31_0x001a = 0x001a; - // PS4 does not start using the controller until it sees a PS button press. + // PS5 does not start using the controller until it sees a PS button press. + TICK_PS4; if (!report_requested) { - report->guide = true; + gamepad->guide = true; } - TICK_PS4; asm volatile("" :: : "memory"); gamepad->dpad = (gamepad->dpad & 0xf) > 0x0a ? 0x08 : dpad_bindings[gamepad->dpad]; @@ -3509,11 +3512,11 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu TICK_PS3_WITHOUT_CAPTURE; report_size = packet_size = sizeof(PS3Gamepad_Data_t); } - if (output_console_type != OG_XBOX && output_console_type != WINDOWS && output_console_type != XBOX360 && output_console_type != PS3 && output_console_type != BLUETOOTH_REPORT && output_console_type != UNIVERSAL && output_console_type != XBOXONE && output_console_type != PS4) + if (output_console_type != OG_XBOX && output_console_type != WINDOWS && output_console_type != XBOX360 && output_console_type != PS3 && output_console_type != BLUETOOTH_REPORT && output_console_type != UNIVERSAL && output_console_type != XBOXONE && output_console_type != PS4 && output_console_type != PS5) { #else // For instruments, we instead use the below block, as all other console types use the below format - if ((output_console_type != OG_XBOX && output_console_type != ARCADE && output_console_type != WINDOWS && output_console_type != KEYBOARD_MOUSE && output_console_type != IOS_FESTIVAL && output_console_type != FNF && output_console_type != XBOX360 && output_console_type != PS4 && output_console_type != BLUETOOTH_REPORT && output_console_type != UNIVERSAL && output_console_type != XBOXONE) || updateHIDSequence) + if ((output_console_type != OG_XBOX && output_console_type != ARCADE && output_console_type != WINDOWS && output_console_type != KEYBOARD_MOUSE && output_console_type != IOS_FESTIVAL && output_console_type != FNF && output_console_type != XBOX360 && output_console_type != PS4 && output_console_type != PS5 && output_console_type != BLUETOOTH_REPORT && output_console_type != UNIVERSAL && output_console_type != XBOXONE) || updateHIDSequence) { #endif report_size = sizeof(PS3_REPORT); @@ -3694,11 +3697,6 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu PS4Gamepad_Data_t *gamepad = (PS4Gamepad_Data_t *)report_data; gamepad->reportCounter = ps4_sequence_number++; } - if (output_console_type == PS5) - { - PS5Dpad_Data_t *gamepad = (PS5Dpad_Data_t *)report_data; - gamepad->sequence_number = ps4_sequence_number++; - } #endif #if DEVICE_TYPE_IS_GAMEPAD @@ -3811,7 +3809,6 @@ bool tick_usb(void) return true; } } - // #if DEVICE_TYPE == SKYLANDERS // if (consoleType == XBOX360) { // size = 32; diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 9f47040fe..79e927107 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1465,8 +1465,8 @@ uint16_t descriptorRequest(const uint16_t wValue, } else if (consoleType == PS5) { - dev->idVendor = 0x3651; - dev->idProduct = 0x1600; + dev->idVendor = 0x2B81; + dev->idProduct = 0x0101; } else if (consoleType == IOS_FESTIVAL) { From 4d1381b01ae4d1720743521e168c8008d4461e7a Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 12 Jan 2026 16:51:58 +1300 Subject: [PATCH 148/239] disable ps5 logic if usb host is disabled --- src/pico/main.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 5c9e8421a..19ec82b7c 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -126,13 +126,15 @@ bool hash_ready = false; uint32_t hash_timer; void send_report_to_pc(const void *report, uint8_t len) { +#if USB_HOST_STACK if (consoleType == PS5 && ps5_dev_addr.dev_addr) { - if (hash_pending) { + if (hash_pending) + { return; } hash_pending = true; - send_report_to_controller(ps5_dev_addr.dev_addr, ps5_dev_addr.instance, (const uint8_t*)report, len); + send_report_to_controller(ps5_dev_addr.dev_addr, ps5_dev_addr.instance, (const uint8_t *)report, len); return; // if (tuh_xinput_ready(ps5_dev_addr.dev_addr, ps5_dev_addr.instance)) // { @@ -140,6 +142,7 @@ void send_report_to_pc(const void *report, uint8_t len) // tuh_xinput_send_report(ps5_dev_addr.dev_addr, ps5_dev_addr.instance, (const uint8_t*)report, len); // } } +#endif tud_xusb_n_report(0, report, len); } bool foundXB = false; From f7047a44579dadec2f21b3e5162ad95398fb87f0 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 13 Jan 2026 10:13:49 +1300 Subject: [PATCH 149/239] fix issues with velocity parsing with rb drums --- src/pico/xinput_host.cpp | 2 -- src/shared/main/shared_main.cpp | 16 ++++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/pico/xinput_host.cpp b/src/pico/xinput_host.cpp index a6b312013..1738def44 100644 --- a/src/pico/xinput_host.cpp +++ b/src/pico/xinput_host.cpp @@ -198,8 +198,6 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const { return false; } - // Some controllers need a delay here otherwise they don't initialise properly - sleep_ms(1); TU_VERIFY(0x58 == desc_itf->bInterfaceClass || TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass || TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); xinputh_interface_t *p_xinput = NULL; uint8_t i = 0; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index b992acb6b..519c219f9 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1498,10 +1498,14 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t case ROCK_BAND_DRUMS: { PS3RockBandDrums_Data_t *report = (PS3RockBandDrums_Data_t *)data; - uint8_t redVelocity = ~report->redVelocity; - uint8_t greenVelocity = ~report->greenVelocity; - uint8_t yellowVelocity = ~report->yellowVelocity; - uint8_t blueVelocity = ~report->blueVelocity; + uint8_t redVelocity = 255-report->redVelocity; + uint8_t greenVelocity = 255-report->greenVelocity; + uint8_t yellowVelocity = 255-report->yellowVelocity; + uint8_t blueVelocity = 255-report->blueVelocity; + redVelocity = max(redVelocity, 1); + greenVelocity = max(greenVelocity, 1); + yellowVelocity = max(yellowVelocity, 1); + blueVelocity = max(blueVelocity, 1); bool kick1 = report->leftShoulder; bool kick2 = report->rightShoulder; usb_host_data->back |= report->back; @@ -2364,6 +2368,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t uint8_t greenVelocity = xinput_rb_velocity_negative(report->greenVelocity); uint8_t yellowVelocity = xinput_rb_velocity_negative(report->yellowVelocity); uint8_t blueVelocity = xinput_rb_velocity_positive(report->blueVelocity); + redVelocity = max(redVelocity, 1); + greenVelocity = max(greenVelocity, 1); + yellowVelocity = max(yellowVelocity, 1); + blueVelocity = max(blueVelocity, 1); SET_RB_PADS(); From 44304b2e9c81101b637dd6ec63950f228fb8fa39 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 13 Jan 2026 10:24:05 +1300 Subject: [PATCH 150/239] fix issues with velocity parsing with rb drums --- include/state_translation/drums.h | 36 +++++++++++++++---------------- src/pico/main.cpp | 5 ----- src/shared/main/shared_main.cpp | 8 ------- 3 files changed, 18 insertions(+), 31 deletions(-) diff --git a/include/state_translation/drums.h b/include/state_translation/drums.h index 0c3cb0dd6..cb01db500 100644 --- a/include/state_translation/drums.h +++ b/include/state_translation/drums.h @@ -43,18 +43,18 @@ { \ if (up) \ { \ - onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, redVelocity >> 1); \ - onNote(10, RB_MIDI_NOTE_YELLOW, yellowVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, max(redVelocity >> 1, 1)); \ + onNote(10, RB_MIDI_NOTE_YELLOW, max(yellowVelocity >> 1, 1)); \ } \ else if (down) \ { \ - onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, redVelocity >> 1); \ - onNote(10, RB_MIDI_NOTE_BLUE, blueVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, max(redVelocity >> 1, 1)); \ + onNote(10, RB_MIDI_NOTE_BLUE, max(blueVelocity >> 1, 1)); \ } \ else \ { \ - onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, redVelocity >> 1); \ - onNote(10, RB_MIDI_NOTE_GREEN, greenVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, max(redVelocity >> 1, 1)); \ + onNote(10, RB_MIDI_NOTE_GREEN, max(greenVelocity >> 1, 1)); \ } \ pad = false; \ cymbal = false; \ @@ -64,7 +64,7 @@ /* Yellow */ \ if (up) \ { \ - onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, yellowVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, max(yellowVelocity >> 1, 1)); \ yellow = false; \ cymbal = false; \ } \ @@ -72,7 +72,7 @@ /* Blue */ \ if (down) \ { \ - onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, blueVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, max(blueVelocity >> 1, 1)); \ blue = false; \ cymbal = false; \ } \ @@ -80,7 +80,7 @@ /* Green */ \ if (!(up || down)) \ { \ - onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, greenVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, max(greenVelocity >> 1, 1)); \ green = false; \ cymbal = false; \ } \ @@ -90,19 +90,19 @@ { \ if (yellow) \ { \ - onNote(10, RB_MIDI_NOTE_YELLOW, yellowVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_YELLOW, max(yellowVelocity >> 1, 1)); \ } \ if (blue) \ { \ - onNote(10, RB_MIDI_NOTE_BLUE, blueVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_BLUE, max(blueVelocity >> 1, 1)); \ } \ if (red) \ { \ - onNote(10, RB_MIDI_NOTE_RED, redVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_RED, max(redVelocity >> 1, 1)); \ } \ if (green) \ { \ - onNote(10, RB_MIDI_NOTE_GREEN, greenVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_GREEN, max(greenVelocity >> 1, 1)); \ } \ } \ \ @@ -110,28 +110,28 @@ { \ if (blue) \ { \ - onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, blueVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, max(blueVelocity >> 1, 1)); \ } \ if (yellow) \ { \ - onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, yellowVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, max(yellowVelocity >> 1, 1)); \ } \ if (green) \ { \ - onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, greenVelocity >> 1); \ + onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, max(greenVelocity >> 1, 1)); \ } \ } \ if (kick1) \ { \ onNote(10, RB_MIDI_NOTE_KICK, 0x7F); \ - } \ + } \ /*ion kits dont have the second pedal and send out signals like its always on, so ignore that*/ \ if (device_type.drum_type != DRUM_ION) \ { \ if (kick2) \ { \ onNote(10, RB_MIDI_NOTE_KICK2, 0x7F); \ - } \ + } \ } #if DEVICE_TYPE == ROCK_BAND_DRUMS #define SET_GH_PADS() \ diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 19ec82b7c..46c7c783e 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -136,11 +136,6 @@ void send_report_to_pc(const void *report, uint8_t len) hash_pending = true; send_report_to_controller(ps5_dev_addr.dev_addr, ps5_dev_addr.instance, (const uint8_t *)report, len); return; - // if (tuh_xinput_ready(ps5_dev_addr.dev_addr, ps5_dev_addr.instance)) - // { - // printf("send\r\n"); - // tuh_xinput_send_report(ps5_dev_addr.dev_addr, ps5_dev_addr.instance, (const uint8_t*)report, len); - // } } #endif tud_xusb_n_report(0, report, len); diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 519c219f9..1bca087d4 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1502,10 +1502,6 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t uint8_t greenVelocity = 255-report->greenVelocity; uint8_t yellowVelocity = 255-report->yellowVelocity; uint8_t blueVelocity = 255-report->blueVelocity; - redVelocity = max(redVelocity, 1); - greenVelocity = max(greenVelocity, 1); - yellowVelocity = max(yellowVelocity, 1); - blueVelocity = max(blueVelocity, 1); bool kick1 = report->leftShoulder; bool kick2 = report->rightShoulder; usb_host_data->back |= report->back; @@ -2368,10 +2364,6 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t uint8_t greenVelocity = xinput_rb_velocity_negative(report->greenVelocity); uint8_t yellowVelocity = xinput_rb_velocity_negative(report->yellowVelocity); uint8_t blueVelocity = xinput_rb_velocity_positive(report->blueVelocity); - redVelocity = max(redVelocity, 1); - greenVelocity = max(greenVelocity, 1); - yellowVelocity = max(yellowVelocity, 1); - blueVelocity = max(blueVelocity, 1); SET_RB_PADS(); From 71361c7d79a31332e61351893ba38b7b77155e77 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 16 Jan 2026 10:25:43 +1300 Subject: [PATCH 151/239] various ps auth fixes --- include/shared_main.h | 1 + src/pico/main.cpp | 4 ++-- src/pico/xinput_host.cpp | 2 +- src/pico/xinput_host.h | 2 +- src/shared/usb/descriptors.cpp | 25 +++++++++++++++---------- 5 files changed, 20 insertions(+), 14 deletions(-) diff --git a/include/shared_main.h b/include/shared_main.h index dfe23068b..6a5eff042 100644 --- a/include/shared_main.h +++ b/include/shared_main.h @@ -39,6 +39,7 @@ typedef struct { uint8_t sub_type; uint8_t dev_addr; uint8_t instance; + uint8_t interface; uint8_t drum_type; uint8_t pickup; uint8_t whammy; diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 46c7c783e..eca69f6e1 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -416,14 +416,14 @@ uint8_t read_usb_host_devices(uint8_t *buf) return total_usb_host_devices * 2; } -bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t console_type, uint8_t sub_type) +bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t itf_num, uint8_t console_type, uint8_t sub_type) { printf("Detected controller: %d (%d) on %d, %d\r\n", console_type, sub_type, dev_addr, instance); uint16_t host_vid = 0; uint16_t host_pid = 0; tuh_vid_pid_get(dev_addr, &host_vid, &host_pid); printf("VID: %04x, PID: %04x \r\n", host_vid, host_pid); - USB_Device_Type_t type = {console_type, sub_type, dev_addr, instance, DRUM_UNKNOWN}; + USB_Device_Type_t type = {console_type, sub_type, dev_addr, instance, itf_num, DRUM_UNKNOWN}; tuh_descriptor_get_device_sync(dev_addr, buf, sizeof(USB_DEVICE_DESCRIPTOR)); USB_DEVICE_DESCRIPTOR *desc = (USB_DEVICE_DESCRIPTOR *)buf; get_usb_device_type_for(host_vid, host_pid, desc->bcdDevice, &type); diff --git a/src/pico/xinput_host.cpp b/src/pico/xinput_host.cpp index 1738def44..3ee5d0842 100644 --- a/src/pico/xinput_host.cpp +++ b/src/pico/xinput_host.cpp @@ -543,7 +543,7 @@ static void config_driver_mount_complete(uint8_t dev_addr, uint8_t instance) { xinputh_interface_t *hid_itf = get_instance(dev_addr, instance); // enumeration is complete - tuh_xinput_mount_cb(dev_addr, instance, hid_itf->type, hid_itf->subtype); + tuh_xinput_mount_cb(dev_addr, instance, hid_itf->itf_num, hid_itf->type, hid_itf->subtype); // notify usbh that driver enumeration is complete usbh_driver_set_config_complete(dev_addr, hid_itf->itf_num); diff --git a/src/pico/xinput_host.h b/src/pico/xinput_host.h index 695bce2fa..5c85c5aba 100644 --- a/src/pico/xinput_host.h +++ b/src/pico/xinput_host.h @@ -118,7 +118,7 @@ bool tuh_xinput_receive_report(uint8_t dev_addr, uint8_t instance); // can be used to parse common/simple enough descriptor. // Note: if report descriptor length > CFG_TUH_ENUMERATION_BUFSIZE, it will be skipped // therefore report_desc = NULL, desc_len = 0 -bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t type, uint8_t subtype); +bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t itf_num, uint8_t type, uint8_t subtype); bool tuh_xinput_ready(uint8_t dev_addr, uint8_t instance); bool tuh_xinput_send_report(uint8_t dev_addr, uint8_t instance, uint8_t const *report, uint16_t len); diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 79e927107..bcffa7543 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -820,8 +820,7 @@ const PROGMEM uint8_t ps5_feature_config[] = { 0x00, 0x80, 0x0D, 0x0D, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t idle_rate; uint8_t protocol_mode = HID_RPT_PROTOCOL; @@ -1164,7 +1163,9 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const { consoleType = PS4; reset_usb(); - } else { + } + else + { consoleType = PS3; reset_usb(); } @@ -1183,11 +1184,12 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const #if USB_HOST_STACK case GET_RESPONSE: { - return transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); + + return transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, requestType, request, wValue, get_device_address_for(PS4).interface, wLength, requestBuffer, status); } case GET_AUTH_STATUS: { - return transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); + return transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, requestType, request, wValue, get_device_address_for(PS4).interface, wLength, requestBuffer, status); } case GET_AUTH_PAGE_SIZE: { @@ -1197,9 +1199,12 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const return 0; } // Attempt to read the page size from the connected controller - // On a DS4, this will fail but we have the default page size report for that scenario. - transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_GET_REPORT, GET_AUTH_PAGE_SIZE, INTERFACE_ID_Device, sizeof(AuthPageSizeReport), (uint8_t *)&ps4_pagesize_report, NULL); - memcpy_P(requestBuffer, &ps4_pagesize_report, sizeof(ps4_pagesize_report)); + bool auth_read_success = true; + uint32_t len = transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_GET_REPORT, GET_AUTH_PAGE_SIZE, get_device_address_for(PS4).interface, sizeof(AuthPageSizeReport), (uint8_t *)&ps4_pagesize_report, &auth_read_success); + if (!auth_read_success) + { + memcpy_P(requestBuffer, &ps4_pagesize_report, sizeof(ps4_pagesize_report)); + } return sizeof(ps4_pagesize_report); } #else @@ -1223,11 +1228,11 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const #if USB_HOST_STACK case GET_RESPONSE: { - return transfer_with_usb_controller(get_device_address_for(PS5).dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); + return transfer_with_usb_controller(get_device_address_for(PS5).dev_addr, requestType, request, wValue, get_device_address_for(PS5).interface, wLength, requestBuffer, status); } case GET_AUTH_STATUS: { - return transfer_with_usb_controller(get_device_address_for(PS5).dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); + return transfer_with_usb_controller(get_device_address_for(PS5).dev_addr, requestType, request, wValue, get_device_address_for(PS5).interface, wLength, requestBuffer, status); } #endif } From 23c5619d7e3dda481b55733fb6600a821693300b Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 16 Jan 2026 10:26:24 +1300 Subject: [PATCH 152/239] various ps auth fixes --- src/shared/usb/descriptors.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index bcffa7543..9fb20c796 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1203,6 +1203,7 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const uint32_t len = transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_GET_REPORT, GET_AUTH_PAGE_SIZE, get_device_address_for(PS4).interface, sizeof(AuthPageSizeReport), (uint8_t *)&ps4_pagesize_report, &auth_read_success); if (!auth_read_success) { + // On a DS4, this will fail but we have the default page size report for that scenario. memcpy_P(requestBuffer, &ps4_pagesize_report, sizeof(ps4_pagesize_report)); } return sizeof(ps4_pagesize_report); From 16fde71248cf28d8ea6f1616ffd0244ca4cee2bd Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 16 Jan 2026 10:34:15 +1300 Subject: [PATCH 153/239] various ps auth fixes --- src/pico/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index eca69f6e1..366efb73d 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -573,7 +573,8 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t itf_num, ui printf("Found PS5 controller\r\n"); ps4_controller_connected(dev_addr, host_vid, host_pid); - if (consoleType == PS4) + // assume ps5 auth if p5general is plugged in + if (consoleType == PS4 && host_vid == 0x2b81 && host_pid == 0x0101) { consoleType = PS5; reset_usb(); From 09e3de86c0e185bafcc4ccfad1f3aa83e29e31a7 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 16 Jan 2026 10:44:29 +1300 Subject: [PATCH 154/239] various ps auth fixes --- src/pico/main.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 366efb73d..08ae3fde5 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -567,18 +567,18 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t itf_num, ui case PS5: usb_host_devices[total_usb_host_devices].type = type; total_usb_host_devices++; - if (!ps5_dev_addr.dev_addr) + // assume ps5 auth if p5general is plugged in + if (consoleType == PS4 && host_vid == 0x2b81 && host_pid == 0x0101) + { + consoleType = PS5; + reset_usb(); + } + if (consoleType == PS5 && !ps5_dev_addr.dev_addr) { ps5_dev_addr = type; printf("Found PS5 controller\r\n"); ps4_controller_connected(dev_addr, host_vid, host_pid); - // assume ps5 auth if p5general is plugged in - if (consoleType == PS4 && host_vid == 0x2b81 && host_pid == 0x0101) - { - consoleType = PS5; - reset_usb(); - } } break; } From 6e13479cef9ae85c8157353fd99cad97187c22b8 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 16 Jan 2026 10:44:56 +1300 Subject: [PATCH 155/239] various ps auth fixes --- src/pico/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 08ae3fde5..8f3fe8b65 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -556,7 +556,7 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t itf_num, ui case PS4: usb_host_devices[total_usb_host_devices].type = type; total_usb_host_devices++; - if (!ps4_dev_addr.dev_addr) + if (consoleType == PS4 && !ps4_dev_addr.dev_addr) { ps4_dev_addr = type; From 2f3d2b28062666314351c390556bc4da90175426 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 16 Jan 2026 11:32:45 +1300 Subject: [PATCH 156/239] support switch 2 pro con --- include/reports/switch_reports.h | 41 +++++ src/pico/main.cpp | 8 +- src/shared/main/shared_main.cpp | 271 +++++++++++++++++++------------ 3 files changed, 213 insertions(+), 107 deletions(-) diff --git a/include/reports/switch_reports.h b/include/reports/switch_reports.h index 4ee601941..e0f919556 100644 --- a/include/reports/switch_reports.h +++ b/include/reports/switch_reports.h @@ -40,6 +40,47 @@ typedef struct uint8_t c : 1; uint8_t : 3; + uint16_t leftStickX : 12; + uint16_t leftStickY : 12; + uint16_t rightStickX : 12; + uint16_t rightStickY : 12; + uint8_t vibrationCode; + uint8_t leftTrigger; + uint8_t rightTrigger; + uint8_t imuLength; + uint8_t motionBuffer[10]; +} __attribute__((packed)) Switch2ProGamepadGC_Data_t; + +typedef struct +{ + uint8_t reportId; // 0x09 + uint8_t packetId; // counts up for each packet + uint8_t status; // 0x20 + uint8_t b : 1; + uint8_t a : 1; + uint8_t y : 1; + uint8_t x : 1; + uint8_t rightShoulder : 1; + uint8_t r2 : 1; + uint8_t start : 1; + uint8_t rightThumbClick: 1; + + uint8_t dpadDown : 1; + uint8_t dpadRight : 1; + uint8_t dpadLeft : 1; + uint8_t dpadUp : 1; + uint8_t leftShoulder : 1; + uint8_t l2 : 1; + uint8_t back : 1; + uint8_t leftThumbClick: 1; + + uint8_t guide : 1; + uint8_t capture : 1; + uint8_t gl : 1; + uint8_t gr : 1; + uint8_t c : 1; + uint8_t : 3; + uint16_t leftStickX : 12; uint16_t leftStickY : 12; uint16_t rightStickX : 12; diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 8f3fe8b65..c827a7407 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -521,12 +521,14 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t itf_num, ui { printf("Found Switch controller\r\n"); usb_host_devices[total_usb_host_devices].type = type; + usb_host_devices[total_usb_host_devices].switch_sent_timeout = false; total_usb_host_devices++; break; } case SWITCH2: printf("Found Switch 2 controller\r\n"); usb_host_devices[total_usb_host_devices].type = type; + usb_host_devices[total_usb_host_devices].switch_sent_timeout = false; total_usb_host_devices++; if (type.sub_type == NON_CONTROLLER) { @@ -786,6 +788,10 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c { continue; } + if (usb_host_devices[i].type.console_type == SWITCH2 && usb_host_devices[i].type.sub_type == NON_CONTROLLER) + { + continue; + } if (usb_host_devices[i].type.console_type == SWITCH && usb_host_devices[i].type.sub_type == GAMEPAD) { if (report[0] == 0x81 && report[1] == 0x01) @@ -816,7 +822,7 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c } if (usb_host_devices[i].type.console_type == SWITCH2 && usb_host_devices[i].type.sub_type == GAMEPAD) { - if (report[0] != SWITCH_2_GC_FULL_REPORT_ID) + if (report[0] != SWITCH_2_GC_FULL_REPORT_ID && report[0] != SWITCH_2_PRO_CON_FULL_REPORT_ID) { continue; } diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 1bca087d4..9ab3218fc 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -456,7 +456,8 @@ int16_t handle_calibration_xbox(int16_t previous, int32_t orig_val, int16_t min, { val = INT16_MIN; } - if (section == 0) { + if (section == 0) + { if (val < center) { if ((center - val) < deadzone) @@ -479,9 +480,13 @@ int16_t handle_calibration_xbox(int16_t previous, int32_t orig_val, int16_t min, val = map(val, center + deadzone, max, 0, INT16_MAX); } } - } else if (section == 1) { + } + else if (section == 1) + { val = map(val, min, max, INT16_MIN, 0); - } else if (section == 2) { + } + else if (section == 2) + { val = map(val, min, max, 0, INT16_MAX); } if (val > INT16_MAX) @@ -776,7 +781,8 @@ long lastTick; uint8_t keyboard_report = 0; void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_type, USB_Host_Data_t *usb_host_data) { - if (!len) { + if (!len) + { return; } switch (device_type.console_type) @@ -1069,7 +1075,8 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t { usb_host_data->whammy = report->whammy; } - if (report->slider != PS3_STICK_CENTER) { + if (report->slider != PS3_STICK_CENTER) + { usb_host_data->slider = report->slider; } break; @@ -1498,10 +1505,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t case ROCK_BAND_DRUMS: { PS3RockBandDrums_Data_t *report = (PS3RockBandDrums_Data_t *)data; - uint8_t redVelocity = 255-report->redVelocity; - uint8_t greenVelocity = 255-report->greenVelocity; - uint8_t yellowVelocity = 255-report->yellowVelocity; - uint8_t blueVelocity = 255-report->blueVelocity; + uint8_t redVelocity = 255 - report->redVelocity; + uint8_t greenVelocity = 255 - report->greenVelocity; + uint8_t yellowVelocity = 255 - report->yellowVelocity; + uint8_t blueVelocity = 255 - report->blueVelocity; bool kick1 = report->leftShoulder; bool kick2 = report->rightShoulder; usb_host_data->back |= report->back; @@ -1978,51 +1985,103 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t { case GAMEPAD: { - Switch2ProGamepad_Data_t *report = (Switch2ProGamepad_Data_t *)data; - usb_host_data->dpadLeft |= report->dpadLeft; - usb_host_data->dpadRight |= report->dpadRight; - usb_host_data->dpadUp |= report->dpadUp; - usb_host_data->dpadDown |= report->dpadDown; - usb_host_data->green |= report->a; - usb_host_data->red |= report->b; - usb_host_data->yellow |= report->y; - usb_host_data->blue |= report->x; - usb_host_data->orange |= report->leftShoulder; - usb_host_data->a |= report->a; - usb_host_data->b |= report->b; - usb_host_data->x |= report->x; - usb_host_data->y |= report->y; - usb_host_data->leftShoulder |= report->leftShoulder; - usb_host_data->rightShoulder |= report->rightShoulder; - usb_host_data->back |= report->back; - usb_host_data->start |= report->start; - usb_host_data->guide |= report->guide; - usb_host_data->capture |= report->capture; - usb_host_data->leftThumbClick |= report->leftThumbClick; - usb_host_data->rightThumbClick |= report->rightThumbClick; - if (report->leftTrigger) - { - usb_host_data->leftTrigger = report->leftTrigger << 8; - } - if (report->rightTrigger) - { - usb_host_data->rightTrigger = report->rightTrigger << 8; - } - if (report->leftStickX != SWITCH_2_STICK_CENTER) - { - usb_host_data->leftStickX = (report->leftStickX - SWITCH_2_STICK_CENTER) << 4; - } - if (report->leftStickY != SWITCH_2_STICK_CENTER) - { - usb_host_data->leftStickY = ((report->leftStickY - SWITCH_2_STICK_CENTER)) << 4; - } - if (report->rightStickX != SWITCH_2_STICK_CENTER) - { - usb_host_data->rightStickX = (report->rightStickX - SWITCH_2_STICK_CENTER) << 4; + if (data[0] == SWITCH_2_GC_FULL_REPORT_ID) + { + Switch2ProGamepadGC_Data_t *report = (Switch2ProGamepadGC_Data_t *)data; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->capture |= report->capture; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->rightThumbClick |= report->rightThumbClick; + if (report->leftTrigger) + { + usb_host_data->leftTrigger = report->leftTrigger << 8; + } + if (report->rightTrigger) + { + usb_host_data->rightTrigger = report->rightTrigger << 8; + } + if (report->leftStickX != SWITCH_2_STICK_CENTER) + { + usb_host_data->leftStickX = (report->leftStickX - SWITCH_2_STICK_CENTER) << 4; + } + if (report->leftStickY != SWITCH_2_STICK_CENTER) + { + usb_host_data->leftStickY = ((report->leftStickY - SWITCH_2_STICK_CENTER)) << 4; + } + if (report->rightStickX != SWITCH_2_STICK_CENTER) + { + usb_host_data->rightStickX = (report->rightStickX - SWITCH_2_STICK_CENTER) << 4; + } + if (report->rightStickY != SWITCH_2_STICK_CENTER) + { + usb_host_data->rightStickY = ((report->rightStickY - SWITCH_2_STICK_CENTER)) << 4; + } } - if (report->rightStickY != SWITCH_2_STICK_CENTER) + else { - usb_host_data->rightStickY = ((report->rightStickY - SWITCH_2_STICK_CENTER)) << 4; + Switch2ProGamepad_Data_t *report = (Switch2ProGamepad_Data_t *)data; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; + usb_host_data->green |= report->a; + usb_host_data->red |= report->b; + usb_host_data->yellow |= report->y; + usb_host_data->blue |= report->x; + usb_host_data->orange |= report->leftShoulder; + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->capture |= report->capture; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->rightThumbClick |= report->rightThumbClick; + if (report->l2) + { + usb_host_data->leftTrigger = 0xFFFF; + } + if (report->r2) + { + usb_host_data->rightTrigger = 0xFFFF; + } + if (report->leftStickX != SWITCH_2_STICK_CENTER) + { + usb_host_data->leftStickX = (report->leftStickX - SWITCH_2_STICK_CENTER) << 4; + } + if (report->leftStickY != SWITCH_2_STICK_CENTER) + { + usb_host_data->leftStickY = ((report->leftStickY - SWITCH_2_STICK_CENTER)) << 4; + } + if (report->rightStickX != SWITCH_2_STICK_CENTER) + { + usb_host_data->rightStickX = (report->rightStickX - SWITCH_2_STICK_CENTER) << 4; + } + if (report->rightStickY != SWITCH_2_STICK_CENTER) + { + usb_host_data->rightStickY = ((report->rightStickY - SWITCH_2_STICK_CENTER)) << 4; + } } break; } @@ -3151,7 +3210,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu GipPacket_t *packet = (GipPacket_t *)report; report_data = (USB_Report_Data_t *)packet->data; updateSequence = true; - + #if DEVICE_TYPE_IS_LIVE_GUITAR packet_size = sizeof(XboxOneGHLGuitarWithGamepad_Data_t); uint8_t cmp = memcmp(last_report, report_data, report_size); @@ -3191,7 +3250,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->whammy = INT16_MIN; #endif #if DEVICE_TYPE == ROCK_BAND_DRUMS -// rb drums have some weird logic so this is what we need to send when nothing is hit + // rb drums have some weird logic so this is what we need to send when nothing is hit report->redVelocity = -1; report->blueVelocity = -1; report->greenVelocity = 0; @@ -3402,17 +3461,17 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #endif #ifdef MUSTANG_NECK_SPI_PORT - report->lowEFret = lastProtar.lowEFret; - report->aFret = lastProtar.aFret; - report->dFret = lastProtar.dFret; - report->gFret = lastProtar.gFret; - report->bFret = lastProtar.bFret; - report->highEFret = lastProtar.highEFret; - report->green = lastProtar.green; - report->red = lastProtar.red; - report->yellow = lastProtar.yellow; - report->blue = lastProtar.blue; - report->orange = lastProtar.orange; + report->lowEFret = lastProtar.lowEFret; + report->aFret = lastProtar.aFret; + report->dFret = lastProtar.dFret; + report->gFret = lastProtar.gFret; + report->bFret = lastProtar.bFret; + report->highEFret = lastProtar.highEFret; + report->green = lastProtar.green; + report->red = lastProtar.red; + report->yellow = lastProtar.yellow; + report->blue = lastProtar.blue; + report->orange = lastProtar.orange; #endif #if PRO_GUITAR && BLUETOOTH_RX TRANSLATE_TO_PRO_GUITAR(bt_data) @@ -3567,10 +3626,10 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu PS3_REPORT *report = (PS3_REPORT *)report_data; // rb drums have inverted velocity so they start at 0 #if DEVICE_TYPE == ROCK_BAND_DRUMS - report->redVelocity = 0; - report->blueVelocity = 0; - report->greenVelocity = 0; - report->yellowVelocity = 0; + report->redVelocity = 0; + report->blueVelocity = 0; + report->greenVelocity = 0; + report->yellowVelocity = 0; #endif #if DEVICE_TYPE == ROCK_BAND_GUITAR report->whammy = 0; @@ -3584,18 +3643,18 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #endif #ifdef MUSTANG_NECK_SPI_PORT - report->lowEFret = lastProtar.lowEFret; - report->aFret = lastProtar.aFret; - report->dFret = lastProtar.dFret; - report->gFret = lastProtar.gFret; - report->bFret = lastProtar.bFret; - report->highEFret = lastProtar.highEFret; - report->green = lastProtar.green; - report->red = lastProtar.red; - report->yellow = lastProtar.yellow; - report->blue = lastProtar.blue; - report->orange = lastProtar.orange; - report->soloFlag = lastProtar.soloFlag; + report->lowEFret = lastProtar.lowEFret; + report->aFret = lastProtar.aFret; + report->dFret = lastProtar.dFret; + report->gFret = lastProtar.gFret; + report->bFret = lastProtar.bFret; + report->highEFret = lastProtar.highEFret; + report->green = lastProtar.green; + report->red = lastProtar.red; + report->yellow = lastProtar.yellow; + report->blue = lastProtar.blue; + report->orange = lastProtar.orange; + report->soloFlag = lastProtar.soloFlag; #endif #if PRO_GUITAR && BLUETOOTH_RX TRANSLATE_TO_PRO_GUITAR(bt_data) @@ -3681,7 +3740,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } TICK_RESET // Some hosts want packets sent every frame - if (last_report && output_console_type != ARCADE && output_console_type != OG_XBOX && output_console_type != PS4 && output_console_type != PS5 && output_console_type != IOS_FESTIVAL && output_console_type != PS3 && output_console_type != BLUETOOTH_REPORT && !updateHIDSequence) + if (last_report && output_console_type != ARCADE && output_console_type != OG_XBOX && output_console_type != PS4 && output_console_type != PS5 && output_console_type != IOS_FESTIVAL && output_console_type != PS3 && output_console_type != BLUETOOTH_REPORT && !updateHIDSequence) { uint8_t cmp = memcmp(last_report, report_data, report_size); if (cmp == 0) @@ -3809,30 +3868,30 @@ bool tick_usb(void) return true; } } -// #if DEVICE_TYPE == SKYLANDERS -// if (consoleType == XBOX360) { -// size = 32; -// switch (portal_state) { -// case 0: -// memcpy(&combined_report, init_packet_skylanders, sizeof(init_packet_skylanders)); -// break; -// case 1: -// memcpy(&combined_report, version_response_skylanders, sizeof(version_response_skylanders)); -// break; -// } -// } -// if (consoleType == XBOXONE) { -// size = 32; -// switch (portal_state) { -// case 0: -// memcpy(&combined_report, init_packet_skylanders, sizeof(init_packet_skylanders)); -// break; -// case 1: -// memcpy(&combined_report, version_response_skylanders, sizeof(version_response_skylanders)); -// break; -// } -// } -// #endif + // #if DEVICE_TYPE == SKYLANDERS + // if (consoleType == XBOX360) { + // size = 32; + // switch (portal_state) { + // case 0: + // memcpy(&combined_report, init_packet_skylanders, sizeof(init_packet_skylanders)); + // break; + // case 1: + // memcpy(&combined_report, version_response_skylanders, sizeof(version_response_skylanders)); + // break; + // } + // } + // if (consoleType == XBOXONE) { + // size = 32; + // switch (portal_state) { + // case 0: + // memcpy(&combined_report, init_packet_skylanders, sizeof(init_packet_skylanders)); + // break; + // case 1: + // memcpy(&combined_report, version_response_skylanders, sizeof(version_response_skylanders)); + // break; + // } + // } + // #endif if (!size) { size = tick_inputs(&combined_report, &last_report_usb, consoleType); From ce5c24088db4480ac80ccd8591fc574863f9e55b Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 16 Jan 2026 12:02:48 +1300 Subject: [PATCH 157/239] handle usb host transfers better --- include/shared_main.h | 24 ++++++++++++------------ src/pico/main.cpp | 22 +++++++++++++++------- src/shared/hid/hid.cpp | 6 +++--- src/shared/main/inputs/usb_host.h | 4 ++-- src/shared/main/shared_main.cpp | 7 ------- src/shared/usb/descriptors.cpp | 22 +++++++++++----------- 6 files changed, 43 insertions(+), 42 deletions(-) diff --git a/include/shared_main.h b/include/shared_main.h index 6a5eff042..2fbb03677 100644 --- a/include/shared_main.h +++ b/include/shared_main.h @@ -2,6 +2,17 @@ #include "reports/controller_reports.h" #include "config.h" +typedef struct { + uint8_t console_type; + uint8_t sub_type; + uint8_t dev_addr; + uint8_t instance; + uint8_t interface; + uint8_t drum_type; + uint8_t pickup; + uint8_t whammy; + bool xone_guide; +} USB_Device_Type_t; void init_main(void); void device_reset(void); @@ -9,7 +20,7 @@ void tick(void); void tick_wiioutput(); uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t output_console_type); void reset_usb(void); -uint32_t transfer_with_usb_controller(const uint8_t dev_addr, const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, uint8_t *buffer, bool* status); +uint32_t transfer_with_usb_controller(const USB_Device_Type_t dev, const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wLength, uint8_t *buffer, bool *status); void send_report_to_controller(uint8_t dev_addr, uint8_t instance, const uint8_t *report, uint8_t len); void send_report_to_pc(const void *report, uint8_t len); bool ready_for_next_packet(void); @@ -34,17 +45,6 @@ void offNote(uint8_t channel, uint8_t note, uint8_t velocity); void onControlChange(uint8_t channel, uint8_t b1, uint8_t b2); void onPitchBend(uint8_t channel, int pitch); -typedef struct { - uint8_t console_type; - uint8_t sub_type; - uint8_t dev_addr; - uint8_t instance; - uint8_t interface; - uint8_t drum_type; - uint8_t pickup; - uint8_t whammy; - bool xone_guide; -} USB_Device_Type_t; void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_Device_Type_t *type); typedef struct { // If this bit is set, then an led effect (like star power) has overridden the leds diff --git a/src/pico/main.cpp b/src/pico/main.cpp index c827a7407..859e1682b 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -468,8 +468,8 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t itf_num, ui uint8_t data2[] = {0x06, 0x00, 0x00}; for (int i = 0; i < 10; i++) { - transfer_with_usb_controller(dev_addr, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE, HID_REQUEST_SET_REPORT, 0x0300, 1, 3, data2, NULL); - transfer_with_usb_controller(dev_addr, USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE, HID_REQUEST_GET_REPORT, 0x0300, 1, 3, data, NULL); + transfer_with_usb_controller(type, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE, HID_REQUEST_SET_REPORT, 0x0300, sizeof(data2), data2, NULL); + transfer_with_usb_controller(type, USB_SETUP_DEVICE_TO_HOST | USB_SETUP_TYPE_CLASS | USB_SETUP_RECIPIENT_INTERFACE, HID_REQUEST_GET_REPORT, 0x0300, sizeof(data), data, NULL); if (data[0]) { break; @@ -554,6 +554,14 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t itf_num, ui printf("Found PS3 controller\r\n"); printf("Sub type: %d\r\n", type.sub_type); ps3_controller_connected(dev_addr, host_vid, host_pid); + + if (host_vid == SONY_VID && host_pid == SONY_DS3_PID) + { + // Enable PS3 reports + uint8_t hid_command_enable[] = {0x42, 0x0c, 0x00, 0x00}; + transfer_with_usb_controller(type, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x03F4, sizeof(hid_command_enable), hid_command_enable, NULL); + handle_player_leds(0); + } break; case PS4: usb_host_devices[total_usb_host_devices].type = type; @@ -689,7 +697,7 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE9, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - transfer_with_usb_controller(dev_addr, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS, HID_REQUEST_SET_REPORT, 0x0300, 0, sizeof(hid_command_enable), hid_command_enable, NULL); + transfer_with_usb_controller(usb_host_devices[i].type, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS, HID_REQUEST_SET_REPORT, 0x0300, sizeof(hid_command_enable), hid_command_enable, NULL); } } if (usb_host_devices[i].type.console_type == XBOX360_W) @@ -929,9 +937,9 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) return NULL; } -uint32_t transfer_with_usb_controller(const uint8_t dev_addr, const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, uint8_t *buffer, bool *status) +uint32_t transfer_with_usb_controller(const USB_Device_Type_t dev, const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wLength, uint8_t *buffer, bool *status) { - if (!dev_addr) + if (!dev.dev_addr) { // Device is not connected yet! if (status) @@ -944,11 +952,11 @@ uint32_t transfer_with_usb_controller(const uint8_t dev_addr, const uint8_t requ bmRequestType : requestType, bRequest : request, wValue : wValue, - wIndex : wIndex, + wIndex : dev.interface, wLength : wLength }; tuh_xfer_t xfer = {}; - xfer.daddr = dev_addr; + xfer.daddr = dev.dev_addr; xfer.ep_addr = 0; xfer.setup = &setup; xfer.buffer = buffer; diff --git a/src/shared/hid/hid.cpp b/src/shared/hid/hid.cpp index d21023afd..e3f27d222 100644 --- a/src/shared/hid/hid.cpp +++ b/src/shared/hid/hid.cpp @@ -258,7 +258,7 @@ void handle_player_leds(uint8_t player) { if (type.sub_type == GAMEPAD) { ps3_output_report *report = &ps3_output_reports[i]; report->leds_bitmap |= _BV(player); - transfer_with_usb_controller(type.dev_addr, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0201, 0x00, sizeof(ps3_output_report), (uint8_t *)report, NULL); + transfer_with_usb_controller(type, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0201, sizeof(ps3_output_report), (uint8_t *)report, NULL); // send_report_to_controller(type.dev_addr, (uint8_t *)report, sizeof(report)); } return; @@ -270,7 +270,7 @@ void handle_player_leds(uint8_t player) { report->lightbar_red = ps4_colors[player - 1][0]; report->lightbar_green = ps4_colors[player - 1][1]; report->lightbar_blue = ps4_colors[player - 1][2]; - transfer_with_usb_controller(type.dev_addr, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0205, 0x00, sizeof(ps4_output_report), (uint8_t *)report, NULL); + transfer_with_usb_controller(type, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0205, sizeof(ps4_output_report), (uint8_t *)report, NULL); } return; } @@ -372,7 +372,7 @@ void handle_rumble(uint8_t rumble_left, uint8_t rumble_right) { ps3_output_report *report = &ps3_output_reports[i]; report->rumble.left_motor_force = rumble_left; report->rumble.right_motor_on = rumble_right != 0; - transfer_with_usb_controller(i, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0201, 0x00, sizeof(ps3_output_report), (uint8_t *)report, NULL); + transfer_with_usb_controller(type, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0201, sizeof(ps3_output_report), (uint8_t *)report, NULL); return; } case PS4: { diff --git a/src/shared/main/inputs/usb_host.h b/src/shared/main/inputs/usb_host.h index d3519d284..b5cdf695f 100644 --- a/src/shared/main/inputs/usb_host.h +++ b/src/shared/main/inputs/usb_host.h @@ -19,9 +19,9 @@ for (int i = 0; i < device_count; i++) { // Poke any GHL guitars to keep em alive if (poke_ghl && device_type.sub_type == LIVE_GUITAR) { if (device_type.console_type == PS3) { - transfer_with_usb_controller(device_type.dev_addr, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS, HID_REQUEST_SET_REPORT, 0x0201, 0, sizeof(ghl_ps3wiiu_magic_data), ghl_ps3wiiu_magic_data, NULL); + transfer_with_usb_controller(device_type, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS, HID_REQUEST_SET_REPORT, 0x0201, sizeof(ghl_ps3wiiu_magic_data), ghl_ps3wiiu_magic_data, NULL); } else if (device_type.console_type == PS4) { - transfer_with_usb_controller(device_type.dev_addr, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS, HID_REQUEST_SET_REPORT, 0x0201, 0, sizeof(ghl_ps4_magic_data), ghl_ps4_magic_data, NULL); + transfer_with_usb_controller(device_type, USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS, HID_REQUEST_SET_REPORT, 0x0201, sizeof(ghl_ps4_magic_data), ghl_ps4_magic_data, NULL); } else if (device_type.console_type == XBOXONE) { if (ghl_sequence_number_host == 0) { ghl_sequence_number_host = 1; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 9ab3218fc..33d7c4952 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -4235,13 +4235,6 @@ void ps4_controller_connected(uint8_t dev_addr, uint16_t vid, uint16_t pid) void ps3_controller_connected(uint8_t dev_addr, uint16_t vid, uint16_t pid) { - if (vid == SONY_VID && pid == SONY_DS3_PID) - { - // Enable PS3 reports - uint8_t hid_command_enable[] = {0x42, 0x0c, 0x00, 0x00}; - transfer_with_usb_controller(dev_addr, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x03F4, 0x00, sizeof(hid_command_enable), hid_command_enable, NULL); - handle_player_leds(0); - } } void ps4_controller_disconnected(void) diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 9fb20c796..3e9fae8c5 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -806,7 +806,7 @@ const PROGMEM uint8_t ps4_feature_config[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -AuthPageSizeReport ps4_pagesize_report = { +const PROGMEM AuthPageSizeReport ps4_pagesize_report = { type : 0xF3, u1 : 0x00, size_challenge : 0x38, @@ -1185,11 +1185,11 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const case GET_RESPONSE: { - return transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, requestType, request, wValue, get_device_address_for(PS4).interface, wLength, requestBuffer, status); + return transfer_with_usb_controller(get_device_address_for(PS4), requestType, request, wValue, wLength, requestBuffer, status); } case GET_AUTH_STATUS: { - return transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, requestType, request, wValue, get_device_address_for(PS4).interface, wLength, requestBuffer, status); + return transfer_with_usb_controller(get_device_address_for(PS4), requestType, request, wValue, wLength, requestBuffer, status); } case GET_AUTH_PAGE_SIZE: { @@ -1199,14 +1199,14 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const return 0; } // Attempt to read the page size from the connected controller - bool auth_read_success = true; - uint32_t len = transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_GET_REPORT, GET_AUTH_PAGE_SIZE, get_device_address_for(PS4).interface, sizeof(AuthPageSizeReport), (uint8_t *)&ps4_pagesize_report, &auth_read_success); - if (!auth_read_success) + uint32_t len = transfer_with_usb_controller(get_device_address_for(PS4), requestType, request, wValue, wLength, requestBuffer, NULL); + if (!len) { // On a DS4, this will fail but we have the default page size report for that scenario. memcpy_P(requestBuffer, &ps4_pagesize_report, sizeof(ps4_pagesize_report)); + len = sizeof(ps4_pagesize_report); } - return sizeof(ps4_pagesize_report); + return len; } #else case GET_AUTH_PAGE_SIZE: @@ -1229,11 +1229,11 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const #if USB_HOST_STACK case GET_RESPONSE: { - return transfer_with_usb_controller(get_device_address_for(PS5).dev_addr, requestType, request, wValue, get_device_address_for(PS5).interface, wLength, requestBuffer, status); + return transfer_with_usb_controller(get_device_address_for(PS5), requestType, request, wValue, wLength, requestBuffer, status); } case GET_AUTH_STATUS: { - return transfer_with_usb_controller(get_device_address_for(PS5).dev_addr, requestType, request, wValue, get_device_address_for(PS5).interface, wLength, requestBuffer, status); + return transfer_with_usb_controller(get_device_address_for(PS5), requestType, request, wValue, wLength, requestBuffer, status); } #endif } @@ -1257,7 +1257,7 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const else if (request == HID_REQUEST_SET_REPORT && consoleType == PS4 && wValue == SET_CHALLENGE && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) { #if USB_HOST_STACK - return transfer_with_usb_controller(get_device_address_for(PS4).dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); + return transfer_with_usb_controller(get_device_address_for(PS4), requestType, request, wValue, wLength, requestBuffer, status); #else return 0; #endif @@ -1265,7 +1265,7 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const else if (request == HID_REQUEST_SET_REPORT && consoleType == PS5 && wValue == SET_CHALLENGE && requestType == (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS)) { #if USB_HOST_STACK - return transfer_with_usb_controller(get_device_address_for(PS5).dev_addr, requestType, request, wValue, wIndex, wLength, requestBuffer, status); + return transfer_with_usb_controller(get_device_address_for(PS5), requestType, request, wValue, wLength, requestBuffer, status); #else return 0; #endif From f8ba3d292bed42729cce6ffd560b02e0d6a0cce0 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 16 Jan 2026 18:04:49 +1300 Subject: [PATCH 158/239] fix turntables --- src/shared/hid/hid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/hid/hid.cpp b/src/shared/hid/hid.cpp index e3f27d222..262a3911f 100644 --- a/src/shared/hid/hid.cpp +++ b/src/shared/hid/hid.cpp @@ -461,7 +461,7 @@ void handle_rumble(uint8_t rumble_left, uint8_t rumble_right) { enable : rumble_left != 0, padding : {0} }; - transfer_with_usb_controller(i, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0200, 0x00, sizeof(report), (uint8_t *)&report, NULL); + transfer_with_usb_controller(type, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0200, 0x00, sizeof(report), (uint8_t *)&report, NULL); return; } } From 4a839a9b198dedc6e80481f4ec63c7cd3702b65b Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 16 Jan 2026 20:01:32 +1300 Subject: [PATCH 159/239] fix turntables --- src/shared/hid/hid.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/hid/hid.cpp b/src/shared/hid/hid.cpp index 262a3911f..e1adf86b2 100644 --- a/src/shared/hid/hid.cpp +++ b/src/shared/hid/hid.cpp @@ -461,7 +461,7 @@ void handle_rumble(uint8_t rumble_left, uint8_t rumble_right) { enable : rumble_left != 0, padding : {0} }; - transfer_with_usb_controller(type, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0200, 0x00, sizeof(report), (uint8_t *)&report, NULL); + transfer_with_usb_controller(type, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0200, sizeof(report), (uint8_t *)&report, NULL); return; } } From fe96cb29c3c70c857ab111c30a1288cd59c63814 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 17 Jan 2026 10:12:24 +1300 Subject: [PATCH 160/239] procon 1 fixes --- src/pico/main.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 859e1682b..1e014e8f5 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -523,6 +523,8 @@ bool tuh_xinput_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t itf_num, ui usb_host_devices[total_usb_host_devices].type = type; usb_host_devices[total_usb_host_devices].switch_sent_timeout = false; total_usb_host_devices++; + uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x02 /* PROCON_USB_HANDSHAKE */}; + send_report_to_controller(dev_addr, instance, buf, 2); break; } case SWITCH2: @@ -802,26 +804,24 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c } if (usb_host_devices[i].type.console_type == SWITCH && usb_host_devices[i].type.sub_type == GAMEPAD) { - if (report[0] == 0x81 && report[1] == 0x01) - { - uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x02 /* PROCON_USB_HANDSHAKE */}; - send_report_to_controller(dev_addr, instance, buf, 2); - } - else if (!usb_host_devices[i].switch_sent_timeout && report[0] == 0x81 && report[1] == 0x02) + if (!usb_host_devices[i].switch_sent_timeout && report[0] == 0x81 && report[1] == 0x02 /* PROCON_USB_HANDSHAKE */) { usb_host_devices[i].switch_sent_timeout = true; - uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x03 /* PROCON_USB_ENABLE */}; + uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x03 /* HIGH SPEED */}; send_report_to_controller(dev_addr, instance, buf, 2); + continue; } - else if (report[0] == 0x81 && report[1] == 0x03) + else if (report[0] == 0x81 && report[1] == 0x03 /* HIGH SPEED */) { uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x02 /* PROCON_USB_HANDSHAKE */}; send_report_to_controller(dev_addr, instance, buf, 2); + continue; } - else if (report[0] == 0x81 && report[1] == 0x02) + else if (report[0] == 0x81 && report[1] == 0x02 /* PROCON_USB_HANDSHAKE */) { uint8_t buf[2] = {0x80 /* PROCON_REPORT_SEND_USB */, 0x04 /* PROCON_USB_ENABLE */}; send_report_to_controller(dev_addr, instance, buf, 2); + continue; } if (report[0] != SWITCH_PRO_CON_FULL_REPORT_ID) { From f29fa777a5dac42ff9184ec074482ad6c6b30b45 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 20 Jan 2026 12:28:39 +1300 Subject: [PATCH 161/239] add missing leftthumbclick for ps4 ghl --- include/reports/ps5_reports.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/reports/ps5_reports.h b/include/reports/ps5_reports.h index 7bdc170e2..c289cecd8 100644 --- a/include/reports/ps5_reports.h +++ b/include/reports/ps5_reports.h @@ -245,7 +245,7 @@ typedef struct uint8_t : 2; uint8_t back : 1; // share uint8_t start : 1; // options - uint8_t solo : 1; + uint8_t leftThumbClick : 1; uint8_t p1 : 1; uint8_t guide : 1; From 93ffd54a6c145d082cb924a226bff6c6d77c3340 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 2 Mar 2026 12:02:46 +1300 Subject: [PATCH 162/239] fixes for SDL support --- src/shared/usb/descriptors.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 3e9fae8c5..59e88db38 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1062,7 +1062,7 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const { #if DEVICE_TYPE_IS_GAMEPAD // PS3s request this as some form of controller id - if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x0300 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT && wLength == 0x08) + if ((consoleType == PS3 || consoleType == IOS_FESTIVAL) && wValue == 0x0300 && wIndex == INTERFACE_ID_Device && request == HID_REQUEST_GET_REPORT) { // Pro instruments use a different init flow #if DEVICE_TYPE_IS_PRO @@ -1335,11 +1335,13 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const compat->TotalLength = sizeof(OS_COMPATIBLE_ID_DESCRIPTOR); return sizeof(OS_COMPATIBLE_ID_DESCRIPTOR); } + #if DEVICE_TYPE != GUITAR_HERO_GUITAR else if (consoleType == PS3 || consoleType == WII_RB) { memcpy_P(requestBuffer, &DevCompatIDsPS3, sizeof(OS_COMPATIBLE_ID_DESCRIPTOR_SINGLE)); return sizeof(OS_COMPATIBLE_ID_DESCRIPTOR_SINGLE); } + #endif else if (consoleType != UNIVERSAL) { return 0; From 111fc14a888bffa045409c61fb7f9d7c4a41fa03 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 2 Mar 2026 15:06:30 +1300 Subject: [PATCH 163/239] set extended data for ps4/5 --- include/config.h | 7 +++++++ src/shared/usb/descriptors.cpp | 4 ++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/include/config.h b/include/config.h index c65597f87..44353fa96 100644 --- a/include/config.h +++ b/include/config.h @@ -217,6 +217,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define SUB_TYPE XINPUT_GUITAR_ALTERNATE #define PS3_TYPE PS3_GH_GUITAR_PID #define PS4_TYPE PS4_GUITAR +#define PS4_EXTENDED 0x06 #define WII_TYPE WII_RB_GUITAR_PID #define OG_XBOX_REPORT OGXboxGuitarHeroGuitar_Data_t #define XINPUT_REPORT XInputGuitarHeroGuitar_Data_t @@ -250,6 +251,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define SUB_TYPE XINPUT_GUITAR #define PS3_TYPE PS3_RB_GUITAR_PID #define PS4_TYPE PS4_GUITAR +#define PS4_EXTENDED 0x07 #define WII_TYPE WII_RB_GUITAR_PID #define OG_XBOX_REPORT OGXboxRockBandGuitar_Data_t #define XINPUT_REPORT XInputRockBandGuitar_Data_t @@ -431,6 +433,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define SUB_TYPE XINPUT_DRUMS #define PS3_TYPE PS3_GH_DRUM_PID #define PS4_TYPE PS4_DRUMS +#define PS4_EXTENDED 0x1f #define WII_TYPE WII_RB_DRUM_PID #define OG_XBOX_REPORT OGXboxGuitarHeroDrums_Data_t #define XINPUT_REPORT XInputGuitarHeroDrums_Data_t @@ -463,6 +466,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define SUB_TYPE XINPUT_DRUMS #define PS3_TYPE PS3_RB_DRUM_PID #define PS4_TYPE PS4_DRUMS +#define PS4_EXTENDED 0x1f #define WII_TYPE WII_RB_DRUM_PID #define OG_XBOX_REPORT OGXboxRockBandDrums_Data_t #define XINPUT_REPORT XInputRockBandDrums_Data_t @@ -526,6 +530,9 @@ extern const uint8_t config[CONFIGURATION_LEN]; #ifndef PS4_TYPE #define PS4_TYPE PS4_GAMEPAD #endif +#ifndef PS4_EXTENDED +#define PS4_EXTENDED 0 +#endif #ifndef PS5_TYPE #define PS5_TYPE PS4_GAMEPAD #endif diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 59e88db38..85de3fe93 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -801,7 +801,7 @@ const PROGMEM uint8_t ps3_feature_ef[] = { const PROGMEM uint8_t ps4_feature_config[] = { 0x03, 0x21, 0x27, 0x04, 0x91, PS4_TYPE, 0x2c, 0x56, 0xa0, 0x0f, 0x3d, 0x00, 0x00, 0x04, 0x01, 0x00, - 0x00, 0x20, 0x0d, 0x0d, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x0d, 0x0d, 0x00, 0x00, 0x00, PS4_EXTENDED, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; @@ -817,7 +817,7 @@ const PROGMEM AuthPageSizeReport ps4_pagesize_report = { const PROGMEM uint8_t ps5_feature_config[] = { 0x03, 0x21, 0x28, 0x03, 0xC3, PS4_TYPE, 0x2C, 0x56, 0x01, 0x00, 0xD0, 0x07, 0x00, 0x80, 0x04, 0x00, - 0x00, 0x80, 0x0D, 0x0D, 0x84, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x0D, 0x0D, 0x84, 0x00, 0x00, PS4_EXTENDED, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; From a09ec828bcdb6c7ce3eacba83ae8d26e5d6dc783 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 5 Mar 2026 10:58:25 +1300 Subject: [PATCH 164/239] fix extended byte again --- src/shared/usb/descriptors.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 85de3fe93..adbf8a677 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -801,8 +801,8 @@ const PROGMEM uint8_t ps3_feature_ef[] = { const PROGMEM uint8_t ps4_feature_config[] = { 0x03, 0x21, 0x27, 0x04, 0x91, PS4_TYPE, 0x2c, 0x56, 0xa0, 0x0f, 0x3d, 0x00, 0x00, 0x04, 0x01, 0x00, - 0x00, 0x20, 0x0d, 0x0d, 0x00, 0x00, 0x00, PS4_EXTENDED, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x0d, 0x0d, 0x00, 0x00, 0x00, 0x00, + PS4_EXTENDED, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; @@ -817,8 +817,8 @@ const PROGMEM AuthPageSizeReport ps4_pagesize_report = { const PROGMEM uint8_t ps5_feature_config[] = { 0x03, 0x21, 0x28, 0x03, 0xC3, PS4_TYPE, 0x2C, 0x56, 0x01, 0x00, 0xD0, 0x07, 0x00, 0x80, 0x04, 0x00, - 0x00, 0x80, 0x0D, 0x0D, 0x84, 0x00, 0x00, PS4_EXTENDED, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x0D, 0x0D, 0x84, 0x00, 0x00, 0x00, + PS4_EXTENDED, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; @@ -1335,13 +1335,13 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const compat->TotalLength = sizeof(OS_COMPATIBLE_ID_DESCRIPTOR); return sizeof(OS_COMPATIBLE_ID_DESCRIPTOR); } - #if DEVICE_TYPE != GUITAR_HERO_GUITAR +#if DEVICE_TYPE != GUITAR_HERO_GUITAR else if (consoleType == PS3 || consoleType == WII_RB) { memcpy_P(requestBuffer, &DevCompatIDsPS3, sizeof(OS_COMPATIBLE_ID_DESCRIPTOR_SINGLE)); return sizeof(OS_COMPATIBLE_ID_DESCRIPTOR_SINGLE); } - #endif +#endif else if (consoleType != UNIVERSAL) { return 0; From 46813dd78bdbd23a286fc15fd0597d44e16fa69a Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 5 Mar 2026 12:29:38 +1300 Subject: [PATCH 165/239] pad to midi for rb1 kits --- include/state_translation/drums.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/state_translation/drums.h b/include/state_translation/drums.h index cb01db500..234d38664 100644 --- a/include/state_translation/drums.h +++ b/include/state_translation/drums.h @@ -86,7 +86,7 @@ } \ } \ } \ - if (pad) \ + if (pad || device_type.drum_type == DRUM_RB1) \ { \ if (yellow) \ { \ From 502d77f8d103b2bb4bfe5c61b8c35a069ffb5bcb Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 23 Mar 2026 11:43:25 +1300 Subject: [PATCH 166/239] fix velocity handling with rb santroller over usb host --- src/shared/main/shared_main.cpp | 44 +++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 5 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 33d7c4952..715fbfb0d 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1162,13 +1162,47 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->back |= report->back; usb_host_data->start |= report->start; usb_host_data->guide |= report->guide; - uint8_t redVelocity = report->redVelocity; - uint8_t greenVelocity = report->greenVelocity; - uint8_t yellowVelocity = report->yellowVelocity; - uint8_t blueVelocity = report->blueVelocity; bool kick1 = report->leftShoulder; bool kick2 = report->rightShoulder; - SET_RB_PADS(); + if (report->yellowVelocity) + { + onNote(10, RB_MIDI_NOTE_YELLOW, report->yellowVelocity >> 1); + } + if (report->blueVelocity) + { + onNote(10, RB_MIDI_NOTE_BLUE, report->blueVelocity >> 1); + } + + if (report->redVelocity) + { + onNote(10, RB_MIDI_NOTE_RED, report->redVelocity >> 1); + } + + if (report->greenVelocity) + { + onNote(10, RB_MIDI_NOTE_GREEN, report->greenVelocity >> 1); + } + if (report->blueCymbalVelocity) + { + onNote(10, RB_MIDI_NOTE_YELLOW, report->blueCymbalVelocity >> 1); + } + if (report->yellowCymbalVelocity) + { + onNote(10, RB_MIDI_NOTE_BLUE, report->yellowCymbalVelocity >> 1); + } + + if (report->greenCymbalVelocity) + { + onNote(10, RB_MIDI_NOTE_RED, report->greenCymbalVelocity >> 1); + } + if (kick1) + { + onNote(10, RB_MIDI_NOTE_KICK, 0x7F); + } + if (kick2) + { + onNote(10, RB_MIDI_NOTE_KICK2, 0x7F); + } break; } case LIVE_GUITAR: From 7b01e5b7d7c725b3413bb5113b68cd159d399046 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 23 Mar 2026 12:00:11 +1300 Subject: [PATCH 167/239] fix velocity handling with rb santroller over usb host --- src/shared/main/shared_main.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 715fbfb0d..020d7c765 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1184,16 +1184,16 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t } if (report->blueCymbalVelocity) { - onNote(10, RB_MIDI_NOTE_YELLOW, report->blueCymbalVelocity >> 1); + onNote(10, RB_MIDI_NOTE_BLUE_CYMBAL, report->blueCymbalVelocity >> 1); } if (report->yellowCymbalVelocity) { - onNote(10, RB_MIDI_NOTE_BLUE, report->yellowCymbalVelocity >> 1); + onNote(10, RB_MIDI_NOTE_YELLOW_CYMBAL, report->yellowCymbalVelocity >> 1); } if (report->greenCymbalVelocity) { - onNote(10, RB_MIDI_NOTE_RED, report->greenCymbalVelocity >> 1); + onNote(10, RB_MIDI_NOTE_GREEN_CYMBAL, report->greenCymbalVelocity >> 1); } if (kick1) { From 3498f2ff1a966942a0e9c473d23da46e647b634e Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 24 Mar 2026 11:34:46 +1300 Subject: [PATCH 168/239] fix usb hubs --- include/reports/ps5_reports.h | 4 +- include/tusb_config.h | 3 +- platformio.ini | 2 +- src/pico/TUSB-MIDI.hpp | 26 +- src/pico/main.cpp | 23 +- src/pico/midi_host.c | 1289 ++++++++++++++------------------ src/pico/midi_host.h | 192 +++-- src/pico/xinput_device.cpp | 192 +++-- src/pico/xinput_host.cpp | 18 +- src/pico/xinput_host.h | 2 +- src/shared/usb/descriptors.cpp | 2 +- 11 files changed, 855 insertions(+), 898 deletions(-) diff --git a/include/reports/ps5_reports.h b/include/reports/ps5_reports.h index c289cecd8..62acbefb2 100644 --- a/include/reports/ps5_reports.h +++ b/include/reports/ps5_reports.h @@ -190,8 +190,8 @@ typedef struct uint8_t b : 1; // red uint8_t y : 1; // yellow - uint8_t kick1 : 1; // orange - uint8_t kick2 : 1; // orange + uint8_t leftShoulder : 1; // orange + uint8_t rightShoulder : 1; // orange uint8_t : 2; uint8_t back : 1; // share uint8_t start : 1; // options diff --git a/include/tusb_config.h b/include/tusb_config.h index 5142e5ae6..e9445aee7 100644 --- a/include/tusb_config.h +++ b/include/tusb_config.h @@ -19,7 +19,8 @@ #define CFG_TUD_XINPUT 8 #define CFG_TUH_XINPUT 8 #define CFG_TUSB_DEBUG 0 -#define CFG_TUH_MIDI 1 +#define CFG_TUH_MIDI 0 +#define CFG_TUH_MIDI_CUSTOM 1 // HID buffer size Should be sufficient to hold ID (if any) + Data #define CFG_TUH_ENUMERATION_BUFSIZE 512 diff --git a/platformio.ini b/platformio.ini index 935685993..ff9532111 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ board_upload.ardwiino_bootloader_teensy = true board_build.use_usb = 1 platform = https://github.com/maxgerhardt/platform-raspberrypi/archive/39b90392af50585e429941bd2561a91949a2ba46.zip@1.15.0 platform_packages = - framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.4-sanjay/rp2040-4.6.4-sanjay.zip@1.40404.0 + framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.5-sanjay/rp2040-4.6.5-sanjay.zip@1.40404.0 board = pico framework = arduino board_build.core = earlephilhower diff --git a/src/pico/TUSB-MIDI.hpp b/src/pico/TUSB-MIDI.hpp index 3ef11a674..9c94f2652 100644 --- a/src/pico/TUSB-MIDI.hpp +++ b/src/pico/TUSB-MIDI.hpp @@ -30,7 +30,7 @@ namespace usbMidi { }; public: - uint8_t midi_dev_addr = 0; + uint8_t midi_idx = 0; static const bool thruActivated = false; @@ -41,19 +41,19 @@ namespace usbMidi { }; void pollUsb() { - if (!midi_dev_addr || !tuh_midi_configured(midi_dev_addr)) { - return; - } - if (tuh_midih_get_num_rx_cables(midi_dev_addr) < 1) { - return; - } - - tuh_midi_read_poll(midi_dev_addr); // if there is data, then the callback will be called - tuh_midi_stream_flush(midi_dev_addr); + // if (!midi_idx || !tuh_midi_mounted(midi_idx)) { + // return; + // } + // if (tuh_midi_get_tx_cable_count(midi_idx) < 1) { + // return; + // } + + // tuh_midi_read_poll(midi_idx); // if there is data, then the callback will be called + // tuh_midi_stream_flush(midi_idx); } void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets) { - if (midi_dev_addr != dev_addr) return; + if (midi_idx != dev_addr) return; while (num_packets > 0) { --num_packets; @@ -124,7 +124,7 @@ namespace usbMidi { } else if (i == 2) { mPacket.byte3 = byte; if (byte != MidiType::SystemExclusiveEnd) { - tuh_midi_packet_write(midi_dev_addr, (uint8_t*)&mPacket); + tuh_midi_packet_write(midi_idx, (uint8_t*)&mPacket); } } } @@ -132,7 +132,7 @@ namespace usbMidi { }; void endTransmission() { - tuh_midi_packet_write(midi_dev_addr, (uint8_t*)&mPacket); + tuh_midi_packet_write(midi_idx, (uint8_t*)&mPacket); }; byte read() { diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 1e014e8f5..3ddc36486 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -273,7 +273,10 @@ void setup() arcadeSide = 1; } init_main(); - tud_init(TUD_OPT_RHPORT); + const tusb_rhport_init_t rd_init = { + .role = TUSB_ROLE_DEVICE, + .speed = TUD_OPT_HIGH_SPEED ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL}; + tud_rhport_init(TUD_OPT_RHPORT, &rd_init); #if USB_HOST_STACK pio_usb_configuration_t config = { pin_dp : USB_HOST_DP_PIN, @@ -290,7 +293,11 @@ void setup() pinout : PIO_USB_PINOUT_DPDM }; tuh_configure(0, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &config); - tuh_init(TUH_OPT_RHPORT); + const tusb_rhport_init_t rh_init = { + .role = TUSB_ROLE_HOST, + .speed = TUH_OPT_HIGH_SPEED ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL, + }; + tuh_rhport_init(TUH_OPT_RHPORT, &rh_init); #ifdef INPUT_USB_HOST MIDI.begin(0); MIDI.setHandleNoteOn(onNote); @@ -316,14 +323,14 @@ void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets) usbMIDITransport.tuh_midi_rx_cb(dev_addr, num_packets); } -void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t in_ep, uint8_t out_ep, uint8_t num_cables_rx, uint16_t num_cables_tx) +void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t *mount_cb_data) { - printf("MIDI device address = %u, IN endpoint %u has %u cables, OUT endpoint %u has %u cables\r\n", - dev_addr, in_ep & 0xf, num_cables_rx, out_ep & 0xf, num_cables_tx); + printf("MIDI device address = %u, IN endpoint has %u cables, OUT endpoint has %u cables\r\n", + mount_cb_data->daddr, mount_cb_data->rx_cable_count, mount_cb_data->tx_cable_count); - usbMIDITransport.midi_dev_addr = dev_addr; + usbMIDITransport.midi_idx = idx; - USB_Device_Type_t type = {MIDI_ID, 0, dev_addr, 0}; + USB_Device_Type_t type = {MIDI_ID, 0, mount_cb_data->daddr, 0}; usb_host_devices[total_usb_host_devices].type = type; total_usb_host_devices++; } @@ -333,7 +340,7 @@ void tuh_midi_umount_cb(uint8_t dev_addr, uint8_t instance) { printf("MIDI device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); - usbMIDITransport.midi_dev_addr = 0; + usbMIDITransport.midi_idx = 0; // Probably should actulaly work out what was unplugged and all that total_usb_host_devices = 0; } diff --git a/src/pico/midi_host.c b/src/pico/midi_host.c index 9d856e2d3..7ebe56d57 100644 --- a/src/pico/midi_host.c +++ b/src/pico/midi_host.c @@ -26,33 +26,69 @@ #include "tusb_option.h" -#if (TUSB_OPT_HOST_ENABLED && CFG_TUH_MIDI) +#if (CFG_TUH_ENABLED && CFG_TUH_MIDI_CUSTOM) #include "host/usbh.h" #include "host/usbh_pvt.h" + #include "midi_host.h" +#include + +// Level where CFG_TUSB_DEBUG must be at least for this driver is logged +#ifndef CFG_TUH_MIDI_CUSTOM_LOG_LEVEL + #define CFG_TUH_MIDI_CUSTOM_LOG_LEVEL 0 +#endif + +#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_MIDI_CUSTOM_LOG_LEVEL, __VA_ARGS__) + +#define MIDI_CS_ROLAND_HEADER 0xF1 +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t * desc_cb_data) { (void) idx; (void) desc_cb_data; } +TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t* mount_cb_data) { (void) idx; (void) mount_cb_data; } +TU_ATTR_WEAK void tuh_midi_umount_cb(uint8_t idx) { (void) idx; } +TU_ATTR_WEAK void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes) { (void) idx; (void) xferred_bytes; } +TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes) { (void) idx; (void) xferred_bytes; } //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -#ifndef CFG_TUH_MAX_CABLES -#define CFG_TUH_MAX_CABLES 16 -#endif -#define CFG_TUH_MIDI_RX_BUFSIZE 64 -#define CFG_TUH_MIDI_TX_BUFSIZE 64 -#ifndef CFG_TUH_MIDI_EP_BUFSIZE -#define CFG_TUH_MIDI_EP_BUFSIZE 64 -#endif -#define MIDI_CS_ROLAND_HEADER 0xF1 +typedef struct { + uint8_t daddr; + uint8_t bInterfaceNumber; // interface number of MIDI streaming + uint8_t iInterface; + uint8_t itf_count; // number of interfaces including Audio Control + MIDI streaming + + uint8_t rx_cable_count; // IN endpoint CS descriptor bNumEmbMIDIJack value + uint8_t tx_cable_count; // OUT endpoint CS descriptor bNumEmbMIDIJack value + + #if CFG_TUH_MIDI_CUSTOM_STREAM_API + // For Stream read()/write() API + // Messages are always 4 bytes long, queue them for reading and writing so the + // callers can use the Stream interface with single-byte read/write calls. + midi_driver_stream_t stream_write; + midi_driver_stream_t stream_read; + #endif + + // Endpoint stream + struct { + tu_edpt_stream_t tx; + tu_edpt_stream_t rx; + + uint8_t rx_ff_buf[CFG_TUH_MIDI_RX_BUFSIZE]; + uint8_t tx_ff_buf[CFG_TUH_MIDI_TX_BUFSIZE]; + } ep_stream; + + bool mounted; +}midih_interface_t; + +typedef struct { + TUH_EPBUF_DEF(tx, TUH_EPSIZE_BULK_MAX); + TUH_EPBUF_DEF(rx, TUH_EPSIZE_BULK_MAX); +} midih_epbuf_t; -// TODO: refactor to share code with the MIDI Device driver -typedef struct -{ - uint8_t buffer[4]; - uint8_t index; - uint8_t total; -} midi_stream_t; /// MIDI In Jack Descriptor typedef struct TU_ATTR_PACKED { @@ -63,785 +99,594 @@ typedef struct TU_ATTR_PACKED { uint8_t num_cables_rx; /// rx cable count uint8_t num_cables_tx; /// tx cable count } midi_desc_roland_header_t; +static midih_interface_t _midi_host[CFG_TUH_MIDI_CUSTOM]; +CFG_TUH_MEM_SECTION static midih_epbuf_t _midi_epbuf[CFG_TUH_MIDI_CUSTOM]; -typedef struct -{ - uint8_t dev_addr; - uint8_t itf_num; - - uint8_t ep_in; // IN endpoint address - uint8_t ep_out; // OUT endpoint address - uint16_t ep_in_max; // min( CFG_TUH_MIDI_RX_BUFSIZE, wMaxPacketSize of the IN endpoint) - uint16_t ep_out_max; // min( CFG_TUH_MIDI_TX_BUFSIZE, wMaxPacketSize of the OUT endpoint) - - uint8_t num_cables_rx; // IN endpoint CS descriptor bNumEmbMIDIJack value - uint8_t num_cables_tx; // OUT endpoint CS descriptor bNumEmbMIDIJack value - - // For Stream read()/write() API - // Messages are always 4 bytes long, queue them for reading and writing so the - // callers can use the Stream interface with single-byte read/write calls. - midi_stream_t stream_write; - midi_stream_t stream_read; - - /*------------- From this point, data is not cleared by bus reset -------------*/ - // Endpoint FIFOs - tu_fifo_t rx_ff; - tu_fifo_t tx_ff; - - uint8_t rx_ff_buf[CFG_TUH_MIDI_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUH_MIDI_TX_BUFSIZE]; - -#if CFG_FIFO_MUTEX - osal_mutex_def_t rx_ff_mutex; - osal_mutex_def_t tx_ff_mutex; -#endif - - // Endpoint Transfer buffer - CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUH_MIDI_EP_BUFSIZE]; - CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUH_MIDI_EP_BUFSIZE]; - - bool configured; - -#if CFG_MIDI_HOST_DEVSTRINGS -#define MAX_STRING_INDICES 32 - uint8_t all_string_indices[MAX_STRING_INDICES]; - uint8_t num_string_indices; -#define MAX_IN_JACKS 8 -#define MAX_OUT_JACKS 8 - struct { - uint8_t jack_id; - uint8_t jack_type; - uint8_t string_index; - } in_jack_info[MAX_IN_JACKS]; - uint8_t next_in_jack; - struct { - uint8_t jack_id; - uint8_t jack_type; - uint8_t num_source_ids; - uint8_t source_ids[MAX_IN_JACKS / 4]; - uint8_t string_index; - } out_jack_info[MAX_OUT_JACKS]; - uint8_t next_out_jack; - uint8_t ep_in_associated_jacks[MAX_OUT_JACKS / 2]; - uint8_t ep_out_associated_jacks[MAX_IN_JACKS / 2]; -#endif -} midih_interface_t; - -static midih_interface_t _midi_host[CFG_TUH_DEVICE_MAX]; - -static midih_interface_t *get_midi_host(uint8_t dev_addr) { - TU_VERIFY(dev_addr > 0 && dev_addr <= CFG_TUH_DEVICE_MAX); - return (_midi_host + dev_addr - 1); +//--------------------------------------------------------------------+ +// Helper +//--------------------------------------------------------------------+ +TU_ATTR_ALWAYS_INLINE static inline uint8_t find_new_midi_index(void) { + for (uint8_t idx = 0; idx < CFG_TUH_MIDI_CUSTOM; idx++) { + if (_midi_host[idx].daddr == 0) { + return idx; + } + } + return TUSB_INDEX_INVALID_8; } -//------------- Internal prototypes -------------// -static uint32_t write_flush(uint8_t dev_addr, midih_interface_t *midi); +static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) { + for (uint8_t idx = 0; idx < CFG_TUH_MIDI_CUSTOM; idx++) { + const midih_interface_t *p_midi = &_midi_host[idx]; + if ((p_midi->daddr == daddr) && + (ep_addr == p_midi->ep_stream.rx.ep_addr || ep_addr == p_midi->ep_stream.tx.ep_addr)) { + return idx; + } + } + return TUSB_INDEX_INVALID_8; +} //--------------------------------------------------------------------+ // USBH API //--------------------------------------------------------------------+ bool midih_init(void) { - tu_memclr(&_midi_host, sizeof(_midi_host)); - // config fifos - for (int inst = 0; inst < CFG_TUH_DEVICE_MAX; inst++) { - midih_interface_t *p_midi_host = &_midi_host[inst]; - tu_fifo_config(&p_midi_host->rx_ff, p_midi_host->rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, 1, false); // true, true - tu_fifo_config(&p_midi_host->tx_ff, p_midi_host->tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, 1, false); // OBVS. - -#if CFG_FIFO_MUTEX - tu_fifo_config_mutex(&p_midi_host->rx_ff, NULL, osal_mutex_create(&p_midi_host->rx_ff_mutex)); - tu_fifo_config_mutex(&p_midi_host->tx_ff, osal_mutex_create(&p_midi_host->tx_ff_mutex), NULL); + tu_memclr(&_midi_host, sizeof(_midi_host)); + for (int inst = 0; inst < CFG_TUH_MIDI_CUSTOM; inst++) { + midih_interface_t *p_midi_host = &_midi_host[inst]; + tu_edpt_stream_init(&p_midi_host->ep_stream.rx, true, false, false, + p_midi_host->ep_stream.rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, _midi_epbuf[inst].rx); + tu_edpt_stream_init(&p_midi_host->ep_stream.tx, true, true, false, + p_midi_host->ep_stream.tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, _midi_epbuf[inst].tx); + } + return true; +} + +bool midih_deinit(void) { + for (size_t i = 0; i < CFG_TUH_MIDI_CUSTOM; i++) { + midih_interface_t* p_midi = &_midi_host[i]; + tu_edpt_stream_deinit(&p_midi->ep_stream.rx); + tu_edpt_stream_deinit(&p_midi->ep_stream.tx); + } + return true; +} + +void midih_close(uint8_t daddr) { + for (uint8_t idx = 0; idx < CFG_TUH_MIDI_CUSTOM; idx++) { + midih_interface_t* p_midi = &_midi_host[idx]; + if (p_midi->daddr == daddr) { + TU_LOG_DRV(" MIDI close addr = %u index = %u\r\n", daddr, idx); + tuh_midi_umount_cb(idx); + + p_midi->bInterfaceNumber = 0; + p_midi->rx_cable_count = 0; + p_midi->tx_cable_count = 0; + p_midi->daddr = 0; + p_midi->mounted = false; +#if CFG_TUH_MIDI_CUSTOM_STREAM_API + tu_memclr(&p_midi->stream_read, sizeof(p_midi->stream_read)); + tu_memclr(&p_midi->stream_write, sizeof(p_midi->stream_write)); #endif + tu_edpt_stream_close(&p_midi->ep_stream.rx); + tu_edpt_stream_close(&p_midi->ep_stream.tx); } - return true; + } } bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { - (void)result; - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); - if (ep_addr == p_midi_host->ep_in) { - if (0 == xferred_bytes) { - return true; // No data to handle - } - - // receive new data if available - uint32_t packets_queued = 0; - if (xferred_bytes) { - // put in the RX FIFO only non-zero MIDI IN 4-byte packets - uint8_t *buf = p_midi_host->epin_buf; - uint32_t npackets = xferred_bytes / 4; - uint32_t packet_num; - for (packet_num = 0; packet_num < npackets; packet_num++) { - // some devices send back all zero packets even if there is no data ready - uint32_t packet = (uint32_t)((*buf) << 24) | ((uint32_t)(*(buf + 1)) << 16) | ((uint32_t)(*(buf + 2)) << 8) | ((uint32_t)(*(buf + 3))); - if (packet != 0) { - tu_fifo_write_n(&p_midi_host->rx_ff, buf, 4); - ++packets_queued; - TU_LOG3("MIDI RX=%08x\r\n", packet); - } - buf += 4; - } - } - // invoke receive callback if available - if (tuh_midi_rx_cb) { - tuh_midi_rx_cb(dev_addr, packets_queued); - } - } else if (ep_addr == p_midi_host->ep_out) { - if (0 == write_flush(dev_addr, p_midi_host)) { - // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - if (!tu_fifo_count(&p_midi_host->tx_ff) && xferred_bytes && (0 == (xferred_bytes % p_midi_host->ep_out_max))) { - if (usbh_edpt_claim(dev_addr, p_midi_host->ep_out)) { - TU_ASSERT(usbh_edpt_xfer(dev_addr, p_midi_host->ep_out, XFER_RESULT_SUCCESS, 0)); - } - } - } - if (tuh_midi_tx_cb) { - tuh_midi_tx_cb(dev_addr); - } + (void) result; + const uint8_t idx = get_idx_by_ep_addr(dev_addr, ep_addr); + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); + midih_interface_t *p_midi = &_midi_host[idx]; + tu_edpt_stream_t *ep_str_rx = &p_midi->ep_stream.rx; + tu_edpt_stream_t *ep_str_tx = &p_midi->ep_stream.tx; + + if (ep_addr == ep_str_rx->ep_addr) { + // receive new data, put it into FIFO and invoke callback if available + // Note: some devices send back all zero packets even if there is no data ready + if (xferred_bytes && !tu_mem_is_zero(ep_str_rx->ep_buf, xferred_bytes)) { + tu_edpt_stream_read_xfer_complete(ep_str_rx, xferred_bytes); + tuh_midi_rx_cb(idx, xferred_bytes); } - return true; -} + tu_edpt_stream_read_xfer(ep_str_rx); // prepare for next transfer + } else if (ep_addr == ep_str_tx->ep_addr) { + tuh_midi_tx_cb(idx, xferred_bytes); + + if (0 == tu_edpt_stream_write_xfer(ep_str_tx)) { + // If there is no data left, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + tu_edpt_stream_write_zlp_if_needed(ep_str_tx, xferred_bytes); + } + } -void midih_close(uint8_t dev_addr) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - if (p_midi_host == NULL) - return; - if (tuh_midi_umount_cb) - tuh_midi_umount_cb(dev_addr, 0); - tu_fifo_clear(&p_midi_host->rx_ff); - tu_fifo_clear(&p_midi_host->tx_ff); - p_midi_host->ep_in = 0; - p_midi_host->ep_in_max = 0; - p_midi_host->ep_out = 0; - p_midi_host->ep_out_max = 0; - p_midi_host->itf_num = 0; - p_midi_host->num_cables_rx = 0; - p_midi_host->num_cables_tx = 0; - p_midi_host->dev_addr = 255; // invalid - p_midi_host->configured = false; - tu_memclr(&p_midi_host->stream_read, sizeof(p_midi_host->stream_read)); - tu_memclr(&p_midi_host->stream_write, sizeof(p_midi_host->stream_write)); + return true; } //--------------------------------------------------------------------+ // Enumeration //--------------------------------------------------------------------+ -bool midih_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { - (void)rhport; - - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - - TU_VERIFY(p_midi_host != NULL); -#if CFG_MIDI_HOST_DEVSTRINGS - p_midi_host->num_string_indices = 0; -#endif - // Some roland devices use vendor specific and have their own header - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass || TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass); - // There can be just a MIDI interface or an audio and a MIDI interface. Only open the MIDI interface - uint8_t const *p_desc = (uint8_t const *)desc_itf; - uint16_t len_parsed = 0; - if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) { -#if CFG_MIDI_HOST_DEVSTRINGS - // Keep track of any string descriptor that might be here - if (desc_itf->iInterface != 0) - p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = desc_itf->iInterface; -#endif - // This driver does not support audio streaming. However, if this is the audio control interface - // there might be a MIDI interface following it. Search through every descriptor until a MIDI - // interface is found or the end of the descriptor is found - while (len_parsed < max_len && (desc_itf->bInterfaceClass != TUSB_CLASS_AUDIO || desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING)) { - len_parsed += desc_itf->bLength; - p_desc = tu_desc_next(p_desc); - desc_itf = (tusb_desc_interface_t const *)p_desc; - } +uint16_t midih_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *desc_itf, uint16_t max_len) { + (void) rhport; + // Some roland devices use vendor specific and have their own header + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass || TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0); + bool roland = TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass; + const uint8_t *desc_start = (const uint8_t *)desc_itf; + const uint8_t *p_desc = desc_start; + const uint8_t *desc_end = desc_start + max_len; + + const uint8_t idx = find_new_midi_index(); + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM, 0); + midih_interface_t *p_midi = &_midi_host[idx]; + p_midi->itf_count = 0; + + tuh_midi_descriptor_cb_t desc_cb = { 0 }; + desc_cb.jack_num = 0; + + // There can be just a MIDI or an Audio + MIDI interface + // - If there is Audio Control Interface + Audio Header descriptor, then skip it. + // - If there is an Audio Control Interface + Audio Streaming Interface, then ignore the Audio Streaming Interface. + // Future: + // Note that if this driver is used with an USB Audio Streaming host driver, + // then call that driver first. If the MIDI interface comes before the + // audio streaming interface, then the audio driver will have to call this + // driver after parsing the audio control interface and then resume parsing + // the streaming audio interface. + if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) { + TU_VERIFY(max_len > 2 * sizeof(tusb_desc_interface_t) + sizeof(midi10_desc_cs_ac_interface_t), 0); + p_desc = tu_desc_next(p_desc); + TU_VERIFY(tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && + tu_desc_subtype(p_desc) == AUDIO10_CS_AC_INTERFACE_HEADER, + 0); + desc_cb.desc_audio_control = desc_itf; - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass); + p_desc = tu_desc_next(p_desc); + desc_itf = (const tusb_desc_interface_t *)p_desc; + p_midi->itf_count = 1; + // skip non-interface and non-midi streaming descriptors + while (tu_desc_in_bounds(p_desc, desc_end) && (desc_itf->bDescriptorType != TUSB_DESC_INTERFACE || + (desc_itf->bInterfaceClass == TUSB_CLASS_AUDIO && + desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING))) { + if (desc_itf->bDescriptorType == TUSB_DESC_INTERFACE && desc_itf->bAlternateSetting == 0) { + p_midi->itf_count++; + } + p_desc = tu_desc_next(p_desc); + desc_itf = (const tusb_desc_interface_t *)p_desc; } - TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass); - len_parsed += desc_itf->bLength; -#if CFG_MIDI_HOST_DEVSTRINGS - // Keep track of any string descriptor that might be here - if (desc_itf->iInterface != 0) - p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = desc_itf->iInterface; -#endif + TU_VERIFY(p_desc < desc_end, 0); + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass, 0); + } + TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass, 0); + + TU_LOG_DRV("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); + p_midi->bInterfaceNumber = desc_itf->bInterfaceNumber; + p_midi->iInterface = desc_itf->iInterface; + p_midi->itf_count++; + desc_cb.desc_midi = desc_itf; + + bool found_new_interface = false; + do { p_desc = tu_desc_next(p_desc); - TU_LOG1("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); - // Find out if getting the MIDI class specific interface header or an endpoint descriptor - // or a class-specific endpoint descriptor - // Jack descriptors or element descriptors must follow the cs interface header, - // but this driver does not support devices that contain element descriptors - - // assume it is an interface header - midi_desc_header_t const *p_mdh = (midi_desc_header_t const *)p_desc; - TU_VERIFY((p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE && p_mdh->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) || - (p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE && p_mdh->bDescriptorSubType == MIDI_CS_ROLAND_HEADER) || - (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || - p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); - - uint8_t prev_ep_addr = 0; // the CS endpoint descriptor is associated with the previous endpoint descrptor - p_midi_host->itf_num = desc_itf->bInterfaceNumber; - tusb_desc_endpoint_t const *in_desc = NULL; - tusb_desc_endpoint_t const *out_desc = NULL; - while (len_parsed < max_len) { - TU_VERIFY((p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE) || - (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT && p_mdh->bDescriptorSubType == MIDI_CS_ENDPOINT_GENERAL) || - p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT); - - if (p_mdh->bDescriptorType == TUSB_DESC_CS_INTERFACE) { - // The USB host doesn't really need this information unless it uses - // the string descriptor for a jack or Element - - // assume it is an input jack - midi_desc_in_jack_t const *p_mdij = (midi_desc_in_jack_t const *)p_desc; - if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_HEADER) { - TU_LOG2("Found MIDI Interface Header\r\n"); - } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_IN_JACK) { - // Then it is an in jack. - TU_LOG2("Found in jack\r\n"); -#if CFG_MIDI_HOST_DEVSTRINGS - if (p_midi_host->next_in_jack < MAX_IN_JACKS) { - p_midi_host->in_jack_info[p_midi_host->next_in_jack].jack_id = p_mdij->bJackID; - p_midi_host->in_jack_info[p_midi_host->next_in_jack].jack_type = p_mdij->bJackType; - p_midi_host->in_jack_info[p_midi_host->next_in_jack].string_index = p_mdij->iJack; - ++p_midi_host->next_in_jack; - // Keep track of any string descriptor that might be here - if (p_mdij->iJack != 0) - p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = p_mdij->iJack; - } -#endif - } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_OUT_JACK) { - // then it is an out jack - TU_LOG2("Found out jack\r\n"); -#if CFG_MIDI_HOST_DEVSTRINGS - if (p_midi_host->next_out_jack < MAX_OUT_JACKS) { - midi_desc_out_jack_t const *p_mdoj = (midi_desc_out_jack_t const *)p_desc; - p_midi_host->out_jack_info[p_midi_host->next_out_jack].jack_id = p_mdoj->bJackID; - p_midi_host->out_jack_info[p_midi_host->next_out_jack].jack_type = p_mdoj->bJackType; - p_midi_host->out_jack_info[p_midi_host->next_out_jack].num_source_ids = p_mdoj->bNrInputPins; - const struct associated_jack_s { - uint8_t id; - uint8_t pin; - } *associated_jack = (const struct associated_jack_s *)(p_desc + 6); - int jack; - for (jack = 0; jack < p_mdoj->bNrInputPins; jack++) { - p_midi_host->out_jack_info[p_midi_host->next_out_jack].source_ids[jack] = associated_jack->id; - } - p_midi_host->out_jack_info[p_midi_host->next_out_jack].string_index = *(p_desc + 6 + p_mdoj->bNrInputPins * 2); - ++p_midi_host->next_out_jack; - if (p_mdoj->iJack != 0) - p_midi_host->all_string_indices[p_midi_host->num_string_indices++] = p_mdoj->iJack; - } -#endif - } else if (p_mdij->bDescriptorSubType == MIDI_CS_INTERFACE_ELEMENT) { - // the it is an element; -#if CFG_MIDI_HOST_DEVSTRINGS - TU_LOG1("Found element; strings not supported\r\n"); -#else - TU_LOG2("Found element\r\n"); -#endif - } else if (p_mdij->bDescriptorSubType == MIDI_CS_ROLAND_HEADER) { - midi_desc_roland_header_t const *p_rl = (midi_desc_roland_header_t const *)p_desc; - TU_LOG2("Found Roland Header %02x %02x %02x %02x\r\n", p_rl->bLength, p_rl->always_2, p_rl->num_cables_rx, p_rl->num_cables_tx); - if (p_rl->bLength >= sizeof(midi_desc_roland_header_t) && p_rl->always_2 == 0x02) { - TU_VERIFY(p_rl->num_cables_rx < 0x10 && p_rl->num_cables_tx < 0x10); - TU_LOG2("Found Roland Header\r\n"); - p_midi_host->num_cables_rx = (1 << p_rl->num_cables_rx) - 1; - p_midi_host->num_cables_tx = (1 << p_rl->num_cables_tx) - 1; - - } else { - TU_LOG2("Unknown CS Interface sub-type %u\r\n", p_mdij->bDescriptorSubType); - TU_VERIFY(false); // unknown CS Interface sub-type - } - len_parsed += p_mdij->bLength; - } else { - TU_LOG2("Unknown CS Interface sub-type %u\r\n", p_mdij->bDescriptorSubType); - TU_VERIFY(false); // unknown CS Interface sub-type - } - len_parsed += p_mdij->bLength; - } else if (p_mdh->bDescriptorType == TUSB_DESC_CS_ENDPOINT) { - TU_LOG2("found CS_ENDPOINT Descriptor for %u\r\n", prev_ep_addr); - TU_VERIFY(prev_ep_addr != 0); - // parse out the mapping between the device's embedded jacks and the endpoints - // Each embedded IN jack is assocated with an OUT endpoint - midi_cs_desc_endpoint_t const *p_csep = (midi_cs_desc_endpoint_t const *)p_mdh; - if (tu_edpt_dir(prev_ep_addr) == TUSB_DIR_OUT) { - TU_VERIFY(p_midi_host->ep_out == prev_ep_addr); - TU_VERIFY(p_midi_host->num_cables_tx == 0); - p_midi_host->num_cables_tx = p_csep->bNumEmbMIDIJack; -#if CFG_MIDI_HOST_DEVSTRINGS - uint8_t jack; - uint8_t max_jack = p_midi_host->num_cables_tx; - if (max_jack > sizeof(p_midi_host->ep_out_associated_jacks)) { - max_jack = sizeof(p_midi_host->ep_out_associated_jacks); - } - for (jack = 0; jack < max_jack; jack++) { - p_midi_host->ep_out_associated_jacks[jack] = p_csep->baAssocJackID[jack]; - } -#endif - } else { - TU_VERIFY(p_midi_host->ep_in == prev_ep_addr); - TU_VERIFY(p_midi_host->num_cables_rx == 0); - p_midi_host->num_cables_rx = p_csep->bNumEmbMIDIJack; -#if CFG_MIDI_HOST_DEVSTRINGS - uint8_t jack; - uint8_t max_jack = p_midi_host->num_cables_rx; - if (max_jack > sizeof(p_midi_host->ep_in_associated_jacks)) { - max_jack = sizeof(p_midi_host->ep_in_associated_jacks); - } - for (jack = 0; jack < max_jack; jack++) { - p_midi_host->ep_in_associated_jacks[jack] = p_csep->baAssocJackID[jack]; - } -#endif - } - len_parsed += p_csep->bLength; - prev_ep_addr = 0; - } else if (p_mdh->bDescriptorType == TUSB_DESC_ENDPOINT) { - // parse out the bulk endpoint info - tusb_desc_endpoint_t const *p_ep = (tusb_desc_endpoint_t const *)p_mdh; - TU_LOG2("found ENDPOINT Descriptor for %u\r\n", p_ep->bEndpointAddress); - if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) { - TU_VERIFY(p_midi_host->ep_out == 0); - TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass || p_midi_host->num_cables_tx == 0); - p_midi_host->ep_out = p_ep->bEndpointAddress; - p_midi_host->ep_out_max = p_ep->wMaxPacketSize; - if (p_midi_host->ep_out_max > CFG_TUH_MIDI_TX_BUFSIZE) - p_midi_host->ep_out_max = CFG_TUH_MIDI_TX_BUFSIZE; - prev_ep_addr = p_midi_host->ep_out; - out_desc = p_ep; - } else { - TU_VERIFY(p_midi_host->ep_in == 0); - TU_VERIFY(TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass || p_midi_host->num_cables_rx == 0); - p_midi_host->ep_in = p_ep->bEndpointAddress; - p_midi_host->ep_in_max = p_ep->wMaxPacketSize; - if (p_midi_host->ep_in_max > CFG_TUH_MIDI_RX_BUFSIZE) - p_midi_host->ep_in_max = CFG_TUH_MIDI_RX_BUFSIZE; - prev_ep_addr = p_midi_host->ep_in; - in_desc = p_ep; + if (!tu_desc_in_bounds(p_desc, desc_end)) { + break; + } + switch (tu_desc_type(p_desc)) { + case TUSB_DESC_INTERFACE: + found_new_interface = true; + break; + + case TUSB_DESC_CS_INTERFACE: + switch (tu_desc_subtype(p_desc)) { + case MIDI_CS_INTERFACE_HEADER: + TU_LOG_DRV(" Interface Header descriptor\r\n"); + desc_cb.desc_header = p_desc; + break; + + case MIDI_CS_INTERFACE_IN_JACK: + case MIDI_CS_INTERFACE_OUT_JACK: { + TU_LOG_DRV(" Jack %s %s descriptor \r\n", + tu_desc_subtype(p_desc) == MIDI_CS_INTERFACE_IN_JACK ? "IN" : "OUT", + p_desc[3] == MIDI_JACK_EXTERNAL ? "External" : "Embedded"); + if (desc_cb.jack_num < TU_ARRAY_SIZE(desc_cb.desc_jack)) { + desc_cb.desc_jack[desc_cb.jack_num++] = p_desc; } - len_parsed += p_mdh->bLength; - } - if (TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass && (p_midi_host->ep_out != 0 && p_midi_host->num_cables_tx != 0) && (p_midi_host->ep_in != 0 && p_midi_host->num_cables_rx != 0)) { + break; + } + + case MIDI_CS_INTERFACE_ELEMENT: + TU_LOG_DRV(" Element descriptor\r\n"); + desc_cb.desc_element = p_desc; + break; + + case MIDI_CS_ROLAND_HEADER: + midi_desc_roland_header_t const *p_rl = (midi_desc_roland_header_t const *)p_desc; + TU_LOG2("Found Roland Header %02x %02x %02x %02x\r\n", p_rl->bLength, p_rl->always_2, p_rl->num_cables_rx, p_rl->num_cables_tx); + if (p_rl->bLength >= sizeof(midi_desc_roland_header_t) && p_rl->always_2 == 0x02) { + TU_VERIFY(p_rl->num_cables_rx < 0x10 && p_rl->num_cables_tx < 0x10); + TU_LOG2("Found Roland Header\r\n"); + p_midi->rx_cable_count = (1 << p_rl->num_cables_rx) - 1; + p_midi->tx_cable_count = (1 << p_rl->num_cables_tx) - 1; + break; + } + TU_LOG_DRV(" Unknown CS Interface sub-type %u\r\n", tu_desc_subtype(p_desc)); + break; + default: + TU_LOG_DRV(" Unknown CS Interface sub-type %u\r\n", tu_desc_subtype(p_desc)); break; } - p_desc = tu_desc_next(p_desc); - p_mdh = (midi_desc_header_t const *)p_desc; - } - TU_VERIFY((p_midi_host->ep_out != 0 && p_midi_host->num_cables_tx != 0) || - (p_midi_host->ep_in != 0 && p_midi_host->num_cables_rx != 0)); - TU_LOG1("MIDI descriptor parsed successfully\r\n"); - -#if CFG_MIDI_HOST_DEVSTRINGS - // remove duplicate string indices - for (int idx = 0; idx < p_midi_host->num_string_indices; idx++) { - for (int jdx = idx + 1; jdx < p_midi_host->num_string_indices; jdx++) { - while (jdx < p_midi_host->num_string_indices && p_midi_host->all_string_indices[idx] == p_midi_host->all_string_indices[jdx]) { - // delete the duplicate by overwriting it with the last entry and reducing the number of entries by 1 - p_midi_host->all_string_indices[jdx] = p_midi_host->all_string_indices[p_midi_host->num_string_indices - 1]; - --p_midi_host->num_string_indices; - } + break; + + case TUSB_DESC_ENDPOINT: { + const tusb_desc_endpoint_t *p_ep = (const tusb_desc_endpoint_t *) p_desc; + + p_desc = tu_desc_next(p_desc); // next to CS endpoint + TU_VERIFY(tu_desc_in_bounds(p_desc, desc_end), 0); + tu_edpt_stream_t *ep_stream; + if (roland) { + if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) { + desc_cb.desc_epout = p_ep; + ep_stream = &p_midi->ep_stream.tx; + } else { + desc_cb.desc_epin = p_ep; + ep_stream = &p_midi->ep_stream.rx; + } + } else { + const midi_desc_cs_endpoint_t *p_csep = (const midi_desc_cs_endpoint_t *) p_desc; + + TU_LOG_DRV(" Endpoint and CS_Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress); + if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) { + p_midi->tx_cable_count = p_csep->bNumEmbMIDIJack; + desc_cb.desc_epout = p_ep; + ep_stream = &p_midi->ep_stream.tx; + } else { + p_midi->rx_cable_count = p_csep->bNumEmbMIDIJack; + desc_cb.desc_epin = p_ep; + ep_stream = &p_midi->ep_stream.rx; + } } - } -#endif - if (in_desc) { - TU_ASSERT(tuh_edpt_open(dev_addr, in_desc)); - // Some devices always return exactly the request length so transfers won't complete - // unless you assume every transfer is the last one. - // TODO usbh_edpt_force_last_buffer(dev_addr, p_midi_host->ep_in, true); - } - if (out_desc) { - TU_ASSERT(tuh_edpt_open(dev_addr, out_desc)); - } - p_midi_host->dev_addr = dev_addr; + TU_ASSERT(tuh_edpt_open(dev_addr, p_ep), 0); + tu_edpt_stream_open(ep_stream, dev_addr, p_ep, tu_edpt_packet_size(p_ep)); + tu_edpt_stream_clear(ep_stream); + + break; + } - if (tuh_midi_mount_cb) { - tuh_midi_mount_cb(dev_addr, p_midi_host->ep_in, p_midi_host->ep_out, p_midi_host->num_cables_rx, p_midi_host->num_cables_tx); + default: break; // skip unknown descriptor } - return true; -} + } while (!found_new_interface); + + desc_cb.desc_midi_total_len = (uint16_t)((uintptr_t)p_desc - (uintptr_t)desc_start); -bool tuh_midi_configured(uint8_t dev_addr) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); - return p_midi_host->configured; + p_midi->daddr = dev_addr; + tuh_midi_descriptor_cb(idx, &desc_cb); + + return desc_cb.desc_midi_total_len; } bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) { - (void)itf_num; - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); - p_midi_host->configured = true; - - // TODO I don't think there are any special config things to do for MIDI - usbh_driver_set_config_complete(dev_addr, p_midi_host->itf_num); - return true; + uint8_t idx = tuh_midi_itf_get_index(dev_addr, itf_num); + TU_ASSERT(idx < CFG_TUH_MIDI_CUSTOM); + midih_interface_t *p_midi = &_midi_host[idx]; + p_midi->mounted = true; + + const tuh_midi_mount_cb_t mount_cb_data = { + .daddr = dev_addr, + .bInterfaceNumber = p_midi->bInterfaceNumber, + .rx_cable_count = p_midi->rx_cable_count, + .tx_cable_count = p_midi->tx_cable_count, + }; + tuh_midi_mount_cb(idx, &mount_cb_data); + + tu_edpt_stream_read_xfer(&p_midi->ep_stream.rx); // prepare for incoming data + + // No special config things to do for MIDI + usbh_driver_set_config_complete(dev_addr, p_midi->bInterfaceNumber); + return true; } //--------------------------------------------------------------------+ -// Stream API +// API //--------------------------------------------------------------------+ -static uint32_t write_flush(uint8_t dev_addr, midih_interface_t *midi) { - // No data to send - if (!tu_fifo_count(&midi->tx_ff)) return 0; - - // skip if previous transfer not complete - TU_VERIFY(usbh_edpt_claim(dev_addr, midi->ep_out)); - - uint16_t count = tu_fifo_read_n(&midi->tx_ff, midi->epout_buf, midi->ep_out_max); - - if (count) { - TU_ASSERT(usbh_edpt_xfer(dev_addr, midi->ep_out, midi->epout_buf, count), 0); - return count; - } else { - // Release endpoint since we don't make any transfer - usbh_edpt_release(dev_addr, midi->ep_out); - return 0; - } +bool tuh_midi_mounted(uint8_t idx) { + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); + midih_interface_t *p_midi = &_midi_host[idx]; + return p_midi->mounted; } -bool tuh_midi_read_poll(uint8_t dev_addr) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); - bool result = false; - - bool in_edpt_not_busy = !usbh_edpt_busy(dev_addr, p_midi_host->ep_in); - if (in_edpt_not_busy) { - TU_LOG2("Requesting poll IN endpoint %d\r\n", p_midi_host->ep_in); - TU_ASSERT(usbh_edpt_xfer(p_midi_host->dev_addr, p_midi_host->ep_in, p_midi_host->epin_buf, p_midi_host->ep_in_max), 0); - result = true; - } else { - // Maybe the IN endpoint is only busy because the RP2040 host hardware - // is retrying a NAK'd IN transfer forever. Try aborting the NAK'd - // transfer to allow other transfers to happen on the one shared - // epx endpoint. - // TODO for RP2040 USB shared endpoint: usbh_edpt_clear_in_on_nak(p_midi_host->dev_addr, p_midi_host->ep_in); +uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num) { + for (uint8_t idx = 0; idx < CFG_TUH_MIDI_CUSTOM; idx++) { + const midih_interface_t *p_midi = &_midi_host[idx]; + if (p_midi->daddr == daddr && + (p_midi->bInterfaceNumber == itf_num || + p_midi->bInterfaceNumber == (uint8_t) (itf_num + p_midi->itf_count - 1))) { + return idx; } - return result; + } + return TUSB_INDEX_INVALID_8; } -uint32_t tuh_midi_stream_write(uint8_t dev_addr, uint8_t cable_num, uint8_t const *buffer, uint32_t bufsize) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); - TU_VERIFY(cable_num < p_midi_host->num_cables_tx); - midi_stream_t *stream = &p_midi_host->stream_write; - - uint32_t i = 0; - while ((i < bufsize) && (tu_fifo_remaining(&p_midi_host->tx_ff) >= 4)) { - uint8_t const data = buffer[i]; - i++; - if (data >= MIDI_STATUS_SYSREAL_TIMING_CLOCK) { - // real-time messages need to be sent right away - midi_stream_t streamrt; - streamrt.buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - streamrt.buffer[1] = data; - streamrt.index = 2; - streamrt.total = 2; - uint16_t const count = tu_fifo_write_n(&p_midi_host->tx_ff, streamrt.buffer, 4); - // FIFO overflown, since we already check fifo remaining. It is probably race condition - TU_ASSERT(count == 4, i); - } else if (stream->index == 0) { - //------------- New event packet -------------// - - uint8_t const msg = data >> 4; - - stream->index = 2; - stream->buffer[1] = data; - - // Check to see if we're still in a SysEx transmit. - if (stream->buffer[0] == MIDI_CIN_SYSEX_START) { - if (data == MIDI_STATUS_SYSEX_END) { - stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - stream->total = 2; - } else { - stream->total = 4; - } - } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) { - // Channel Voice Messages - stream->buffer[0] = (uint8_t)((cable_num << 4) | msg); - stream->total = 4; - } else if (msg == 0xC || msg == 0xD) { - // Channel Voice Messages, two-byte variants (Program Change and Channel Pressure) - stream->buffer[0] = (uint8_t)((cable_num << 4) | msg); - stream->total = 3; - } else if (msg == 0xf) { - // System message - if (data == MIDI_STATUS_SYSEX_START) { - stream->buffer[0] = MIDI_CIN_SYSEX_START; - stream->total = 4; - } else if (data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT) { - stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE; - stream->total = 3; - } else if (data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER) { - stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE; - stream->total = 4; - } else { - stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - stream->total = 2; - } - } else { - // Pack individual bytes if we don't support packing them into words. - stream->buffer[0] = (uint8_t)(cable_num << 4 | 0xf); - stream->buffer[2] = 0; - stream->buffer[3] = 0; - stream->index = 2; - stream->total = 2; - } - } else { - //------------- On-going (buffering) packet -------------// - - TU_ASSERT(stream->index < 4, i); - stream->buffer[stream->index] = data; - stream->index++; - // See if this byte ends a SysEx. - if (stream->buffer[0] == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END) { - stream->buffer[0] = MIDI_CIN_SYSEX_START + (stream->index - 1); - stream->total = stream->index; - } - } - - // Send out packet - if (stream->index >= 2 && stream->index == stream->total) { - // zeroes unused bytes - for (uint8_t idx = stream->total; idx < 4; idx++) stream->buffer[idx] = 0; - TU_LOG3_MEM(stream->buffer, 4, 2); - - uint16_t const count = tu_fifo_write_n(&p_midi_host->tx_ff, stream->buffer, 4); - - // complete current event packet, reset stream - stream->index = 0; - stream->total = 0; - - // FIFO overflown, since we already check fifo remaining. It is probably race condition - TU_ASSERT(count == 4, i); - } - } - return i; +bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) { + midih_interface_t* p_midi = &_midi_host[idx]; + TU_VERIFY(p_midi && info); + + info->daddr = p_midi->daddr; + + // re-construct descriptor + tusb_desc_interface_t* desc = &info->desc; + desc->bLength = sizeof(tusb_desc_interface_t); + desc->bDescriptorType = TUSB_DESC_INTERFACE; + + desc->bInterfaceNumber = p_midi->bInterfaceNumber; + desc->bAlternateSetting = 0; + desc->bNumEndpoints = 0; + if (tu_edpt_stream_is_opened(&p_midi->ep_stream.tx)) { + desc->bNumEndpoints++; + } + if (tu_edpt_stream_is_opened(&p_midi->ep_stream.rx)) { + desc->bNumEndpoints++; + } + desc->bInterfaceClass = TUSB_CLASS_AUDIO; + desc->bInterfaceSubClass = AUDIO_SUBCLASS_MIDI_STREAMING; + desc->bInterfaceProtocol = 0; + desc->iInterface = p_midi->iInterface; + + return true; } -bool tuh_midi_packet_write(uint8_t dev_addr, uint8_t const packet[4]) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); - - if (tu_fifo_remaining(&p_midi_host->tx_ff) < 4) { - return false; - } - - tu_fifo_write_n(&p_midi_host->tx_ff, packet, 4); +uint8_t tuh_midi_get_tx_cable_count (uint8_t idx) { + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); + midih_interface_t *p_midi = &_midi_host[idx]; + TU_VERIFY(p_midi->ep_stream.tx.ep_addr != 0, 0); + return p_midi->tx_cable_count; +} - return true; +uint8_t tuh_midi_get_rx_cable_count (uint8_t idx) { + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); + midih_interface_t *p_midi = &_midi_host[idx]; + TU_VERIFY(p_midi->ep_stream.rx.ep_addr != 0, 0); + return p_midi->rx_cable_count; } -uint32_t tuh_midi_stream_flush(uint8_t dev_addr) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); +uint32_t tuh_midi_read_available(uint8_t idx) { + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); + midih_interface_t *p_midi = &_midi_host[idx]; + return tu_edpt_stream_read_available(&p_midi->ep_stream.rx); +} - uint32_t bytes_flushed = 0; - if (!usbh_edpt_busy(p_midi_host->dev_addr, p_midi_host->ep_out)) { - bytes_flushed = write_flush(dev_addr, p_midi_host); - } - return bytes_flushed; +uint32_t tuh_midi_write_flush(uint8_t idx) { + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); + midih_interface_t *p_midi = &_midi_host[idx]; + return tu_edpt_stream_write_xfer(&p_midi->ep_stream.tx); } + //--------------------------------------------------------------------+ -// Helper +// Packet API //--------------------------------------------------------------------+ -uint8_t tuh_midih_get_num_tx_cables(uint8_t dev_addr) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); - TU_VERIFY(p_midi_host->ep_out != 0); // returns 0 if fails - return p_midi_host->num_cables_tx; +uint32_t tuh_midi_packet_read_n(uint8_t idx, uint8_t* buffer, uint32_t bufsize) { + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM && buffer && bufsize > 0, 0); + midih_interface_t *p_midi = &_midi_host[idx]; + + uint32_t count4 = tu_min32(bufsize, tu_edpt_stream_read_available(&p_midi->ep_stream.rx)); + count4 = tu_align4(count4); // round down to multiple of 4 + TU_VERIFY(count4 > 0, 0); + return tu_edpt_stream_read(&p_midi->ep_stream.rx, buffer, count4); } -uint8_t tuh_midih_get_num_rx_cables(uint8_t dev_addr) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); - TU_VERIFY(p_midi_host->ep_in != 0); // returns 0 if fails - return p_midi_host->num_cables_rx; -} +uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t* buffer, uint32_t bufsize) { + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM && buffer && bufsize > 0, 0); + midih_interface_t *p_midi = &_midi_host[idx]; -bool tuh_midi_packet_read(uint8_t dev_addr, uint8_t packet[4]) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); - TU_VERIFY(tu_fifo_count(&p_midi_host->rx_ff) >= 4); - return tu_fifo_read_n(&p_midi_host->rx_ff, packet, 4) == 4; + const uint32_t bufsize4 = tu_align4(bufsize); + TU_VERIFY(bufsize4 > 0, 0); + return tu_edpt_stream_write(&p_midi->ep_stream.tx, buffer, bufsize4); } -uint32_t tuh_midi_stream_read(uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); - uint32_t bytes_buffered = 0; - TU_ASSERT(p_cable_num); - TU_ASSERT(p_buffer); - TU_ASSERT(bufsize); - uint8_t one_byte; - if (!tu_fifo_peek(&p_midi_host->rx_ff, &one_byte)) { - return 0; - } - *p_cable_num = (one_byte >> 4) & 0xf; - uint32_t nread = tu_fifo_read_n(&p_midi_host->rx_ff, p_midi_host->stream_read.buffer, 4); - static uint16_t cable_sysex_in_progress; // bit i is set if received MIDI_STATUS_SYSEX_START but not MIDI_STATUS_SYSEX_END - while (nread == 4 && bytes_buffered < bufsize) { - *p_cable_num = (p_midi_host->stream_read.buffer[0] >> 4) & 0x0f; - uint8_t bytes_to_add_to_stream = 0; - if (*p_cable_num < p_midi_host->num_cables_rx) { - // ignore the CIN field; too many devices out there encode this wrong - uint8_t status = p_midi_host->stream_read.buffer[1]; - uint16_t cable_mask = (uint16_t)(1 << *p_cable_num); - if (status <= MIDI_MAX_DATA_VAL || status == MIDI_STATUS_SYSEX_START) { - if (status == MIDI_STATUS_SYSEX_START) { - cable_sysex_in_progress |= cable_mask; - } - // only add the packet if a sysex message is in progress - if (cable_sysex_in_progress & cable_mask) { - ++bytes_to_add_to_stream; - uint8_t idx; - for (idx = 2; idx < 4; idx++) { - if (p_midi_host->stream_read.buffer[idx] <= MIDI_MAX_DATA_VAL) { - ++bytes_to_add_to_stream; - } else if (p_midi_host->stream_read.buffer[idx] == MIDI_STATUS_SYSEX_END) { - ++bytes_to_add_to_stream; - cable_sysex_in_progress &= (uint16_t)~cable_mask; - idx = 4; // force the loop to exit; I hate break statements in loops - } - } - } - } else if (status < MIDI_STATUS_SYSEX_START) { - // then it is a channel message either three bytes or two - uint8_t fake_cin = (status & 0xf0) >> 4; - switch (fake_cin) { - case MIDI_CIN_NOTE_OFF: - case MIDI_CIN_NOTE_ON: - case MIDI_CIN_POLY_KEYPRESS: - case MIDI_CIN_CONTROL_CHANGE: - case MIDI_CIN_PITCH_BEND_CHANGE: - bytes_to_add_to_stream = 3; - break; - case MIDI_CIN_PROGRAM_CHANGE: - case MIDI_CIN_CHANNEL_PRESSURE: - bytes_to_add_to_stream = 2; - break; - default: - break; // Should not get this - } - cable_sysex_in_progress &= (uint16_t)~cable_mask; - } else if (status < MIDI_STATUS_SYSREAL_TIMING_CLOCK) { - switch (status) { - case MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME: - case MIDI_STATUS_SYSCOM_SONG_SELECT: - bytes_to_add_to_stream = 2; - break; - case MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER: - bytes_to_add_to_stream = 3; - break; - case MIDI_STATUS_SYSCOM_TUNE_REQUEST: - case MIDI_STATUS_SYSEX_END: - bytes_to_add_to_stream = 1; - break; - default: - break; - cable_sysex_in_progress &= (uint16_t)~cable_mask; - } - } else { - // Real-time message: can be inserted into a sysex message, - // so do don't clear cable_sysex_in_progress bit - bytes_to_add_to_stream = 1; - } - } - uint8_t idx; - for (idx = 1; idx <= bytes_to_add_to_stream; idx++) { - *p_buffer++ = p_midi_host->stream_read.buffer[idx]; +//--------------------------------------------------------------------+ +// Stream API +//--------------------------------------------------------------------+ +#if CFG_TUH_MIDI_CUSTOM_STREAM_API +uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *buffer, uint32_t bufsize) { + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM && buffer && bufsize > 0); + midih_interface_t *p_midi = &_midi_host[idx]; + TU_VERIFY(cable_num < p_midi->tx_cable_count); + midi_driver_stream_t *stream = &p_midi->stream_write; + + uint32_t byte_count = 0; + while ((byte_count < bufsize) && (tu_edpt_stream_write_available(&p_midi->ep_stream.tx) >= 4)) { + const uint8_t data = buffer[byte_count]; + byte_count++; + if (data >= MIDI_STATUS_SYSREAL_TIMING_CLOCK) { + // real-time messages need to be sent right away + midi_driver_stream_t streamrt; + streamrt.buffer[0] = (uint8_t)((cable_num << 4) | MIDI_CIN_SYSEX_END_1BYTE); + streamrt.buffer[1] = data; + streamrt.index = 2; + streamrt.total = 2; + const uint32_t count = tu_edpt_stream_write(&p_midi->ep_stream.tx, streamrt.buffer, 4); + TU_ASSERT(count == 4, byte_count); // Check FIFO overflown, since we already check fifo remaining. It is probably race condition + } else if (stream->index == 0) { + //------------- New event packet -------------// + + uint8_t const msg = data >> 4; + + stream->index = 2; + stream->buffer[1] = data; + + // Check to see if we're still in a SysEx transmit. + if ((stream->buffer[0] & 0xF) == MIDI_CIN_SYSEX_START) { + if (data == MIDI_STATUS_SYSEX_END) { + stream->buffer[0] = (uint8_t)((cable_num << 4) | MIDI_CIN_SYSEX_END_1BYTE); + stream->total = 2; + } else { + stream->total = 4; } - bytes_buffered += bytes_to_add_to_stream; - nread = 0; - if (tu_fifo_peek(&p_midi_host->rx_ff, &one_byte)) { - uint8_t new_cable = (one_byte >> 4) & 0xf; - if (new_cable == *p_cable_num) { - // still on the same cable. Continue reading the stream - nread = tu_fifo_read_n(&p_midi_host->rx_ff, p_midi_host->stream_read.buffer, 4); - } + } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) { + // Channel Voice Messages + stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); + stream->total = 4; + } else if (msg == 0xC || msg == 0xD) { + // Channel Voice Messages, two-byte variants (Program Change and Channel Pressure) + stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); + stream->total = 3; + } else if (msg == 0xf) { + // System message + if (data == MIDI_STATUS_SYSEX_START) { + stream->buffer[0] = MIDI_CIN_SYSEX_START; + stream->total = 4; + } else if (data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT) { + stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE; + stream->total = 3; + } else if (data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER) { + stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE; + stream->total = 4; + } else { + stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; + stream->total = 2; } + stream->buffer[0] |= (uint8_t)(cable_num << 4); + } else { + // Pack individual bytes if we don't support packing them into words. + stream->buffer[0] = (uint8_t) (cable_num << 4 | 0xf); + stream->buffer[2] = 0; + stream->buffer[3] = 0; + stream->index = 2; + stream->total = 2; + } + } else { + //------------- On-going (buffering) packet -------------// + TU_ASSERT(stream->index < 4, byte_count); + stream->buffer[stream->index] = data; + stream->index++; + // See if this byte ends a SysEx. + if ((stream->buffer[0] & 0xF) == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END) { + stream->buffer[0] = (uint8_t)((cable_num << 4) | (MIDI_CIN_SYSEX_START + (stream->index - 1))); + stream->total = stream->index; + } } - return bytes_buffered; -} + // Send out packet + if (stream->index >= 2 && stream->index == stream->total) { + // zeroes unused bytes + for (uint8_t i = stream->total; i < 4; i++) { + stream->buffer[i] = 0; + } + TU_LOG3_MEM(stream->buffer, 4, 2); -uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); - uint8_t num_cables = 0; - if (p_midi_host) { - num_cables = p_midi_host->num_cables_rx; - } - return num_cables; -} + const uint32_t count = tu_edpt_stream_write(&p_midi->ep_stream.tx, stream->buffer, 4); + + // complete current event packet, reset stream + stream->index = 0; + stream->total = 0; -uint8_t tuh_midi_get_num_tx_cables(uint8_t dev_addr) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); - uint8_t num_cables = 0; - if (p_midi_host) { - num_cables = p_midi_host->num_cables_tx; + // FIFO overflown, since we already check fifo remaining. It is probably race condition + TU_ASSERT(count == 4, byte_count); } - return num_cables; + } + return byte_count; } -#if CFG_MIDI_HOST_DEVSTRINGS -static uint8_t find_string_index(midih_interface_t *ptr, uint8_t jack_id) { - uint8_t index = 0; - uint8_t assoc; - for (assoc = 0; index == 0 && assoc < ptr->next_in_jack; assoc++) { - if (jack_id == ptr->in_jack_info[assoc].jack_id) { - index = ptr->in_jack_info[assoc].string_index; +uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize) { + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM && p_cable_num && p_buffer && bufsize > 0); + midih_interface_t *p_midi = &_midi_host[idx]; + uint32_t bytes_buffered = 0; + uint8_t one_byte; + if (!tu_edpt_stream_peek(&p_midi->ep_stream.rx, &one_byte)) { + return 0; + } + *p_cable_num = (one_byte >> 4) & 0xf; + uint32_t nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); + static uint16_t cable_sysex_in_progress;// bit i is set if received MIDI_STATUS_SYSEX_START but not MIDI_STATUS_SYSEX_END + while (nread == 4 && bytes_buffered < bufsize) { + *p_cable_num = (p_midi->stream_read.buffer[0] >> 4) & 0x0f; + uint8_t bytes_to_add_to_stream = 0; + if (*p_cable_num < p_midi->rx_cable_count) { + // ignore the CIN field; too many devices out there encode this wrong + uint8_t status = p_midi->stream_read.buffer[1]; + uint16_t cable_mask = (uint16_t) (1 << *p_cable_num); + if (status <= MIDI_MAX_DATA_VAL || status == MIDI_STATUS_SYSEX_START) { + if (status == MIDI_STATUS_SYSEX_START) { + cable_sysex_in_progress |= cable_mask; } - } - for (assoc = 0; index == 0 && assoc < ptr->next_out_jack; assoc++) { - if (jack_id == ptr->out_jack_info[assoc].jack_id) { - index = ptr->out_jack_info[assoc].string_index; + // only add the packet if a sysex message is in progress + if (cable_sysex_in_progress & cable_mask) { + ++bytes_to_add_to_stream; + for (uint8_t i = 2; i < 4; i++) { + if (p_midi->stream_read.buffer[i] <= MIDI_MAX_DATA_VAL) { + ++bytes_to_add_to_stream; + } else if (p_midi->stream_read.buffer[i] == MIDI_STATUS_SYSEX_END) { + ++bytes_to_add_to_stream; + cable_sysex_in_progress &= (uint16_t) ~cable_mask; + i = 4;// force the loop to exit; I hate break statements in loops + } + } } + else { + // bad packet discard + nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); + continue; + } + } else if (status < MIDI_STATUS_SYSEX_START) { + // then it is a channel message either three bytes or two + uint8_t fake_cin = (status & 0xf0) >> 4; + switch (fake_cin) { + case MIDI_CIN_NOTE_OFF: + case MIDI_CIN_NOTE_ON: + case MIDI_CIN_POLY_KEYPRESS: + case MIDI_CIN_CONTROL_CHANGE: + case MIDI_CIN_PITCH_BEND_CHANGE: + bytes_to_add_to_stream = 3; + break; + case MIDI_CIN_PROGRAM_CHANGE: + case MIDI_CIN_CHANNEL_PRESSURE: + bytes_to_add_to_stream = 2; + break; + default: + break;// Should not get this + } + cable_sysex_in_progress &= (uint16_t) ~cable_mask; + } else if (status < MIDI_STATUS_SYSREAL_TIMING_CLOCK) { + switch (status) { + case MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME: + case MIDI_STATUS_SYSCOM_SONG_SELECT: + bytes_to_add_to_stream = 2; + break; + case MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER: + bytes_to_add_to_stream = 3; + break; + case MIDI_STATUS_SYSCOM_TUNE_REQUEST: + case MIDI_STATUS_SYSEX_END: + bytes_to_add_to_stream = 1; + break; + default: + break; + } + cable_sysex_in_progress &= (uint16_t) ~cable_mask; + } else { + // Real-time message: can be inserted into a sysex message, + // so do don't clear cable_sysex_in_progress bit + bytes_to_add_to_stream = 1; + } } - return index; -} -uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t *istrings, uint8_t max_istrings) { - uint8_t nstrings = 0; - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); - nstrings = p_midi_host->num_cables_rx; - if (nstrings > max_istrings) { - nstrings = max_istrings; - } - uint8_t jack; - for (jack = 0; jack < nstrings; jack++) { - uint8_t jack_id = p_midi_host->ep_in_associated_jacks[jack]; - istrings[jack] = find_string_index(p_midi_host, jack_id); + else { + // bad packet discard + nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); + continue; } - return nstrings; -} -uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t *istrings, uint8_t max_istrings) { - uint8_t nstrings = 0; - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); - nstrings = p_midi_host->num_cables_tx; - if (nstrings > max_istrings) { - nstrings = max_istrings; + for (uint8_t i = 1; i <= bytes_to_add_to_stream; i++) { + *p_buffer++ = p_midi->stream_read.buffer[i]; } - uint8_t jack; - for (jack = 0; jack < nstrings; jack++) { - uint8_t jack_id = p_midi_host->ep_out_associated_jacks[jack]; - istrings[jack] = find_string_index(p_midi_host, jack_id); + bytes_buffered += bytes_to_add_to_stream; + nread = 0; + if (tu_edpt_stream_peek(&p_midi->ep_stream.rx, &one_byte)) { + uint8_t new_cable = (one_byte >> 4) & 0xf; + if (new_cable == *p_cable_num) { + // still on the same cable. Continue reading the stream + nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); + } } - return nstrings; -} + } -uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t **istrings) { - midih_interface_t *p_midi_host = get_midi_host(dev_addr); - TU_VERIFY(p_midi_host != NULL); - uint8_t nstrings = p_midi_host->num_string_indices; - if (nstrings) - *istrings = p_midi_host->all_string_indices; - return nstrings; + return bytes_buffered; } #endif -#endif +#endif \ No newline at end of file diff --git a/src/pico/midi_host.h b/src/pico/midi_host.h index b5eac9591..9694f367e 100644 --- a/src/pico/midi_host.h +++ b/src/pico/midi_host.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -24,77 +24,124 @@ * This file is part of the TinyUSB stack. */ -#ifndef _TUSB_MIDI_HOST_H_ -#define _TUSB_MIDI_HOST_H_ +#ifndef TUSB_MIDI_HOST_H_ +#define TUSB_MIDI_HOST_H_ #include "class/audio/audio.h" - #include "class/midi/midi.h" #ifdef __cplusplus - extern "C" { +extern "C" { #endif //--------------------------------------------------------------------+ // Class Driver Configuration //--------------------------------------------------------------------+ +#ifndef CFG_TUH_MIDI_RX_BUFSIZE + #define CFG_TUH_MIDI_RX_BUFSIZE TUH_EPSIZE_BULK_MAX +#endif -// TODO Highspeed bulk transfer can be up to 512 bytes -#ifndef CFG_TUH_HID_EPIN_BUFSIZE -#define CFG_TUH_HID_EPIN_BUFSIZE 64 +#ifndef CFG_TUH_MIDI_TX_BUFSIZE + #define CFG_TUH_MIDI_TX_BUFSIZE TUH_EPSIZE_BULK_MAX #endif -#ifndef CFG_TUH_HID_EPOUT_BUFSIZE -#define CFG_TUH_HID_EPOUT_BUFSIZE 64 +#ifndef CFG_TUH_MIDI_EP_BUFSIZE + #define CFG_TUH_MIDI_EP_BUFSIZE TUH_EPSIZE_BULK_MAX #endif -typedef struct -{ - uint8_t bLength ; ///< Size of this descriptor in bytes (4+bNumEmbMIDIJack) - uint8_t bDescriptorType ; ///< Descriptor Type, must be CS_ENDPOINT - uint8_t bDescriptorSubType ; ///< Descriptor SubType, must be MS_GENERAL - uint8_t bNumEmbMIDIJack; ; ///< Number of embedded MIDI jacks associated with this endpoint - uint8_t baAssocJackID[]; ; ///< A list of associated jacks -} midi_cs_desc_endpoint_t; -enum -{ - MIDI_MAX_DATA_VAL = 0x7F, -}; +// Enable the MIDI stream read/write API. Some library can work with raw USB MIDI packet +// Disable this can save driver footprint. +#ifndef CFG_TUH_MIDI_STREAM_API + #define CFG_TUH_MIDI_STREAM_API 1 +#endif //--------------------------------------------------------------------+ -// Application API (Single Interface) +// Application Types //--------------------------------------------------------------------+ -bool tuh_midi_configured (uint8_t dev_addr); +typedef struct { + const tusb_desc_interface_t *desc_audio_control; + const tusb_desc_interface_t *desc_midi; // start of whole midi interface descriptor + uint16_t desc_midi_total_len; + + const uint8_t *desc_header; + const uint8_t *desc_element; + const tusb_desc_endpoint_t *desc_epin; // endpoint IN descriptor, CS_ENDPOINT is right after + const tusb_desc_endpoint_t *desc_epout; // endpoint OUT descriptor, CS_ENDPOINT is right after + + uint8_t jack_num; + const uint8_t *desc_jack[32]; // list of jack descriptors (embedded + external) +} tuh_midi_descriptor_cb_t; + +typedef struct { + uint8_t daddr; + uint8_t bInterfaceNumber; // interface number of MIDI streaming + uint8_t rx_cable_count; + uint8_t tx_cable_count; +} tuh_midi_mount_cb_t; -// return the number of virtual midi cables on the device's OUT endpoint -uint8_t tuh_midih_get_num_tx_cables (uint8_t dev_addr); +//--------------------------------------------------------------------+ +// Application API +//--------------------------------------------------------------------+ + +// Check if MIDI interface is mounted +bool tuh_midi_mounted(uint8_t idx); + +// Get Interface index from device address + interface number +// return TUSB_INDEX_INVALID_8 (0xFF) if not found +uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num); + +// Get Interface information +// return true if index is correct and interface is currently mounted +bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t *info); // return the number of virtual midi cables on the device's IN endpoint -uint8_t tuh_midih_get_num_rx_cables (uint8_t dev_addr); - -// request available data from the device. tuh_midi_message_received_cb() will -// be called if the device has any data to send. Otherwise, the device will -// respond NAK. This function blocks until the transfer completes or the -// devices sends NAK. -// This function will return false if the hardware is busy. -bool tuh_midi_read_poll( uint8_t dev_addr ); - -// Queue a packet to the device. The application -// must call tuh_midi_stream_flush to actually have the -// data go out. It is up to the application to properly -// format this packet; this function does not check. -// Returns true if the packet was successfully queued. -bool tuh_midi_packet_write (uint8_t dev_addr, uint8_t const packet[4]); +uint8_t tuh_midi_get_rx_cable_count(uint8_t idx); -// Queue a message to the device. The application -// must call tuh_midi_stream_flush to actually have the -// data go out. -uint32_t tuh_midi_stream_write (uint8_t dev_addr, uint8_t cable_num, uint8_t const* p_buffer, uint32_t bufsize); +// return the number of virtual midi cables on the device's OUT endpoint +uint8_t tuh_midi_get_tx_cable_count(uint8_t idx); + +// return the raw number of bytes available. +// Note: this is related but not the same as number of stream bytes available. +uint32_t tuh_midi_read_available(uint8_t idx); // Send any queued packets to the device if the host hardware is able to do it // Returns the number of bytes flushed to the host hardware or 0 if // the host hardware is busy or there is nothing in queue to send. -uint32_t tuh_midi_stream_flush( uint8_t dev_addr); +uint32_t tuh_midi_write_flush(uint8_t idx); + +//--------------------------------------------------------------------+ +// Packet API +//--------------------------------------------------------------------+ + +// Read all available MIDI packets from the connected device +// Return number of bytes read (always multiple of 4) +uint32_t tuh_midi_packet_read_n(uint8_t idx, uint8_t *buffer, uint32_t bufsize); + +// Read a raw MIDI packet from the connected device +// Return true if a packet was returned +TU_ATTR_ALWAYS_INLINE static inline bool tuh_midi_packet_read(uint8_t idx, uint8_t packet[4]) { + return 4 == tuh_midi_packet_read_n(idx, packet, 4); +} + +// Write all 4-byte packets, data is locally buffered and only transferred when buffered bytes +// reach the endpoint packet size or tuh_midi_write_flush() is called +uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t *buffer, uint32_t bufsize); + +// Write a 4-bytes packet to the device. +// Returns true if the packet was successfully queued. +TU_ATTR_ALWAYS_INLINE static inline bool tuh_midi_packet_write(uint8_t idx, const uint8_t packet[4]) { + return 4 == tuh_midi_packet_write_n(idx, packet, 4); +} + +//--------------------------------------------------------------------+ +// Stream API +//--------------------------------------------------------------------+ +#if CFG_TUH_MIDI_STREAM_API + +// Queue a message to the device using stream API. data is locally buffered and only transferred when buffered bytes +// reach the endpoint packet size or tuh_midi_write_flush() is called +// Returns number of bytes was successfully queued. +uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, const uint8_t *p_buffer, uint32_t bufsize); // Get the MIDI stream from the device. Set the value pointed // to by p_cable_num to the MIDI cable number intended to receive it. @@ -103,47 +150,42 @@ uint32_t tuh_midi_stream_flush( uint8_t dev_addr); // Note that this function ignores the CIN field of the MIDI packet // because a number of commercial devices out there do not encode // it properly. -uint32_t tuh_midi_stream_read (uint8_t dev_addr, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize); +uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize); -// Read a raw MIDI packet from the connected device -// This function does not parse the packet format -// Return true if a packet was returned -bool tuh_midi_packet_read (uint8_t dev_addr, uint8_t packet[4]); - -uint8_t tuh_midi_get_num_rx_cables(uint8_t dev_addr); -uint8_t tuh_midi_get_num_tx_cables(uint8_t dev_addr); -#if CFG_MIDI_HOST_DEVSTRINGS -uint8_t tuh_midi_get_rx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings); -uint8_t tuh_midi_get_tx_cable_istrings(uint8_t dev_addr, uint8_t* istrings, uint8_t max_istrings); -uint8_t tuh_midi_get_all_istrings(uint8_t dev_addr, const uint8_t** istrings); #endif -//--------------------------------------------------------------------+ -// Internal Class Driver API -//--------------------------------------------------------------------+ -bool midih_init (void); -bool midih_open (uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len); -bool midih_set_config (uint8_t dev_addr, uint8_t itf_num); -bool midih_xfer_cb (uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); -void midih_close (uint8_t dev_addr); //--------------------------------------------------------------------+ // Callbacks (Weak is optional) //--------------------------------------------------------------------+ +// Invoked when MIDI interface is detected in enumeration. Application can copy/parse descriptor if needed. +// Note: may be fired before tuh_midi_mount_cb(), therefore midi interface is not mounted/ready. +void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t *desc_cb_data); + // Invoked when device with MIDI interface is mounted. -// If the MIDI host application requires MIDI IN, it should requst an -// IN transfer here. The device will likely NAK this transfer. How the driver -// handles the NAK is hardware dependent. -TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t dev_addr, uint8_t in_ep, uint8_t out_ep, uint8_t num_cables_rx, uint16_t num_cables_tx); +void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t *mount_cb_data); // Invoked when device with MIDI interface is un-mounted -// For now, the instance parameter is always 0 and can be ignored -TU_ATTR_WEAK void tuh_midi_umount_cb(uint8_t dev_addr, uint8_t instance); +void tuh_midi_umount_cb(uint8_t idx); + +// Invoked when received new data +void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes); + +// Invoked when a TX is complete and therefore space becomes available in TX buffer +void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes); + +//--------------------------------------------------------------------+ +// Internal Class Driver API +//--------------------------------------------------------------------+ +bool midih_init(void); +bool midih_deinit(void); +uint16_t midih_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *desc_itf, uint16_t max_len); +bool midih_set_config(uint8_t dev_addr, uint8_t itf_num); +bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); +void midih_close(uint8_t daddr); -TU_ATTR_WEAK void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets); -TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t dev_addr); #ifdef __cplusplus } #endif -#endif /* _TUSB_MIDI_HOST_H_ */ +#endif \ No newline at end of file diff --git a/src/pico/xinput_device.cpp b/src/pico/xinput_device.cpp index eccbe00ca..4a0cd3a25 100644 --- a/src/pico/xinput_device.cpp +++ b/src/pico/xinput_device.cpp @@ -16,12 +16,13 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -typedef struct { +typedef struct +{ uint8_t itf_num; uint8_t ep_in; - uint8_t ep_out; // optional Out endpoint - uint8_t boot_protocol; // Boot mouse or keyboard - bool boot_mode; // default = false (Report) + uint8_t ep_out; // optional Out endpoint + uint8_t boot_protocol; // Boot mouse or keyboard + bool boot_mode; // default = false (Report) CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_XINPUT_TX_BUFSIZE]; CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_XINPUT_RX_BUFSIZE]; @@ -30,9 +31,12 @@ typedef struct { CFG_TUSB_MEM_SECTION static xinputd_interface_t _xinputd_itf[CFG_TUD_XINPUT]; static volatile bool sending = false; /*------------- Helpers -------------*/ -static inline uint8_t get_index_by_itfnum(uint8_t itf_num) { - for (uint8_t i = 0; i < CFG_TUD_XINPUT; i++) { - if (itf_num == _xinputd_itf[i].itf_num) return i; +static inline uint8_t get_index_by_itfnum(uint8_t itf_num) +{ + for (uint8_t i = 0; i < CFG_TUD_XINPUT; i++) + { + if (itf_num == _xinputd_itf[i].itf_num) + return i; } return 0xFF; @@ -41,16 +45,19 @@ static inline uint8_t get_index_by_itfnum(uint8_t itf_num) { //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ -bool tud_xinput_n_ready(uint8_t itf) { +bool tud_xinput_n_ready(uint8_t itf) +{ uint8_t const ep_in = _xinputd_itf[itf].ep_in; return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); } -bool tud_ready_for_packet(void) { +bool tud_ready_for_packet(void) +{ return !sending; } -bool tud_xusb_n_report(uint8_t itf, void const *report, uint8_t len) { +bool tud_xusb_n_report(uint8_t itf, void const *report, uint8_t len) +{ uint8_t const rhport = 0; xinputd_interface_t *p_xinput = &_xinputd_itf[itf]; @@ -59,11 +66,12 @@ bool tud_xusb_n_report(uint8_t itf, void const *report, uint8_t len) { memcpy(p_xinput->epin_buf, report, len); sending = true; - return usbd_edpt_xfer(TUD_OPT_RHPORT, p_xinput->ep_in, p_xinput->epin_buf, len); + return usbd_edpt_xfer(TUD_OPT_RHPORT, p_xinput->ep_in, p_xinput->epin_buf, len, false); } bool tud_xinput_n_report(uint8_t itf, uint8_t report_id, void const *report, - uint8_t len) { + uint8_t len) +{ uint8_t const rhport = 0; xinputd_interface_t *p_xinput = &_xinputd_itf[itf]; @@ -71,20 +79,23 @@ bool tud_xinput_n_report(uint8_t itf, uint8_t report_id, void const *report, TU_VERIFY(usbd_edpt_claim(rhport, p_xinput->ep_in)); // prepare data - if (report_id) { + if (report_id) + { len = tu_min8(len, CFG_TUD_XINPUT_TX_BUFSIZE - 1); p_xinput->epin_buf[0] = report_id; memcpy(p_xinput->epin_buf + 1, report, len); len++; - } else { + } + else + { // If report id = 0, skip ID field len = tu_min8(len, CFG_TUD_XINPUT_TX_BUFSIZE); memcpy(p_xinput->epin_buf, report, len); } sending = true; return usbd_edpt_xfer(TUD_OPT_RHPORT, p_xinput->ep_in, p_xinput->epin_buf, - len); + len, false); } bool tud_xinput_n_boot_mode(uint8_t itf) { return _xinputd_itf[itf].boot_mode; } @@ -92,20 +103,24 @@ bool tud_xinput_n_boot_mode(uint8_t itf) { return _xinputd_itf[itf].boot_mode; } //--------------------------------------------------------------------+ // USBD-CLASS API //--------------------------------------------------------------------+ -void xinputd_init(void) { +void xinputd_init(void) +{ xinputd_reset(TUD_OPT_RHPORT); } -void xinputd_reset(uint8_t rhport) { +void xinputd_reset(uint8_t rhport) +{ (void)rhport; tu_memclr(_xinputd_itf, sizeof(_xinputd_itf)); sending = false; } uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, - uint16_t max_len) { + uint16_t max_len) +{ uint16_t drv_len; - if (TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) { + if (TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) + { drv_len = sizeof(tusb_desc_interface_t) + (itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); @@ -113,16 +128,19 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, // Find available interface xinputd_interface_t *p_xinput = NULL; - for (uint8_t i = 0; i < CFG_TUD_XINPUT; i++) { - if (_xinputd_itf[i].ep_in == 0 && _xinputd_itf[i].ep_out == 0) { + for (uint8_t i = 0; i < CFG_TUD_XINPUT; i++) + { + if (_xinputd_itf[i].ep_in == 0 && _xinputd_itf[i].ep_out == 0) + { p_xinput = &_xinputd_itf[i]; break; } } TU_VERIFY(p_xinput, 0); uint8_t const *p_desc = (uint8_t const *)itf_desc; - - if (itf_desc->bInterfaceSubClass == 0x01 && itf_desc->bInterfaceProtocol == 0xFF) { + + if (itf_desc->bInterfaceSubClass == 0x01 && itf_desc->bInterfaceProtocol == 0xFF) + { p_desc = tu_desc_next(p_desc); printf("Opened: %d\r\n", itf_desc->bNumEndpoints); TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, itf_desc->bNumEndpoints, @@ -130,17 +148,21 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, &p_xinput->ep_in), 0); printf("Opened: %02x %02x\r\n", p_xinput->ep_out, p_xinput->ep_in); - if (p_xinput->ep_out) { - if (!usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, sizeof(p_xinput->epout_buf))) { + if (p_xinput->ep_out) + { + if (!usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, sizeof(p_xinput->epout_buf), false)) + { TU_LOG_FAILED(); TU_BREAKPOINT(); } } return drv_len; - } else if (itf_desc->bInterfaceSubClass == 0x5D && - (itf_desc->bInterfaceProtocol == 0x01 || - itf_desc->bInterfaceProtocol == 0x03 || - itf_desc->bInterfaceProtocol == 0x02)) { + } + else if (itf_desc->bInterfaceSubClass == 0x5D && + (itf_desc->bInterfaceProtocol == 0x01 || + itf_desc->bInterfaceProtocol == 0x03 || + itf_desc->bInterfaceProtocol == 0x02)) + { // Xinput reserved endpoint //-------------- Xinput Descriptor --------------// p_desc = tu_desc_next(p_desc); @@ -155,14 +177,19 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, 0); p_xinput->itf_num = itf_desc->bInterfaceNumber; - if (p_xinput->ep_out) { - if (!usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, sizeof(p_xinput->epout_buf))) { + if (p_xinput->ep_out) + { + if (!usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, sizeof(p_xinput->epout_buf), false)) + { TU_LOG_FAILED(); TU_BREAKPOINT(); } } - } else if (itf_desc->bInterfaceSubClass == 0xfD && - itf_desc->bInterfaceProtocol == 0x13) { + return drv_len; + } + else if (itf_desc->bInterfaceSubClass == 0xfD && + itf_desc->bInterfaceProtocol == 0x13) + { // Xinput reserved endpoint //-------------- Xinput Descriptor --------------// p_desc = tu_desc_next(p_desc); @@ -171,22 +198,30 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, TU_ASSERT(XINPUT_SECURITY_DESC_TYPE_RESERVED == x_desc->bDescriptorType, 0); drv_len += x_desc->bLength; p_desc = tu_desc_next(p_desc); - } else if (itf_desc->bInterfaceSubClass == 0x47 && - itf_desc->bInterfaceProtocol == 0xD0) { + return drv_len; + } + else if (itf_desc->bInterfaceSubClass == 0x47 && + itf_desc->bInterfaceProtocol == 0xD0) + { p_desc = tu_desc_next(p_desc); TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, itf_desc->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_xinput->ep_out, &p_xinput->ep_in), 0); p_xinput->itf_num = itf_desc->bInterfaceNumber; // Prepare for output endpoint - if (p_xinput->ep_out) { - if (!usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, sizeof(p_xinput->epout_buf))) { + if (p_xinput->ep_out) + { + if (!usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, sizeof(p_xinput->epout_buf), false)) + { TU_LOG_FAILED(); TU_BREAKPOINT(); } } + return drv_len; } - } else if (0x58 == itf_desc->bInterfaceClass) { + } + else if (0x58 == itf_desc->bInterfaceClass) + { // len = interface + n*endpoints drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t); TU_ASSERT(max_len >= drv_len, 0); @@ -194,8 +229,10 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, // Find available interface xinputd_interface_t *p_hid = NULL; uint8_t hid_id; - for (hid_id = 0; hid_id < CFG_TUD_XINPUT; hid_id++) { - if (_xinputd_itf[hid_id].ep_in == 0) { + for (hid_id = 0; hid_id < CFG_TUD_XINPUT; hid_id++) + { + if (_xinputd_itf[hid_id].ep_in == 0) + { p_hid = &_xinputd_itf[hid_id]; break; } @@ -211,13 +248,18 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, p_hid->itf_num = itf_desc->bInterfaceNumber; // Prepare for output endpoint - if (p_hid->ep_out) { - if (!usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))) { + if (p_hid->ep_out) + { + if (!usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf), false)) + { TU_LOG_FAILED(); TU_BREAKPOINT(); } } - } else { + return drv_len; + } + else + { TU_VERIFY(TUSB_CLASS_HID == itf_desc->bInterfaceClass, 0); // len = interface + hid + n*endpoints @@ -227,8 +269,10 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, // Find available interface xinputd_interface_t *p_hid = NULL; uint8_t hid_id; - for (hid_id = 0; hid_id < CFG_TUD_XINPUT; hid_id++) { - if (_xinputd_itf[hid_id].ep_in == 0) { + for (hid_id = 0; hid_id < CFG_TUD_XINPUT; hid_id++) + { + if (_xinputd_itf[hid_id].ep_in == 0) + { p_hid = &_xinputd_itf[hid_id]; break; } @@ -248,52 +292,70 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, p_hid->itf_num = itf_desc->bInterfaceNumber; // Prepare for output endpoint - if (p_hid->ep_out) { - if (!usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf))) { + if (p_hid->ep_out) + { + if (!usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf), false)) + { TU_LOG_FAILED(); TU_BREAKPOINT(); } } + return drv_len; } //------------- Endpoint Descriptor -------------// // Config endpoint - return drv_len; + return 0; } bool xinputd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, - uint32_t xferred_bytes) { + uint32_t xferred_bytes) +{ (void)result; uint8_t itf = 0; xinputd_interface_t *p_xinput = _xinputd_itf; - for (;; itf++, p_xinput++) { - if (itf >= TU_ARRAY_SIZE(_xinputd_itf)) return false; + for (;; itf++, p_xinput++) + { + if (itf >= TU_ARRAY_SIZE(_xinputd_itf)) + return false; - if (ep_addr == p_xinput->ep_out || ep_addr == p_xinput->ep_in) break; + if (ep_addr == p_xinput->ep_out || ep_addr == p_xinput->ep_in) + break; } - if (ep_addr == p_xinput->ep_out) { + if (ep_addr == p_xinput->ep_out) + { hid_set_report(p_xinput->epout_buf, xferred_bytes, 0x00, INTERRUPT_ID); - if (consoleType == XBOX360 || consoleType == WINDOWS || consoleType == OG_XBOX) { + if (consoleType == XBOX360 || consoleType == WINDOWS || consoleType == OG_XBOX) + { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, - 0x20)); - } else if (consoleType == XBOXONE) { + 0x20, false)); + } + else if (consoleType == XBOXONE) + { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, - 0x40)); - } else if (consoleType == ARCADE) { + 0x40, false)); + } + else if (consoleType == ARCADE) + { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, - 0x40)); - } else if (consoleType == PS5) { + 0x40, false)); + } + else if (consoleType == PS5) + { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, - 0x40)); - } else { + 0x40, false)); + } + else + { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, - 0x08)); + 0x08, false)); } - - } else if (ep_addr == p_xinput->ep_in) { + } + else if (ep_addr == p_xinput->ep_in) + { sending = false; } return true; diff --git a/src/pico/xinput_host.cpp b/src/pico/xinput_host.cpp index 3ee5d0842..8b95007a6 100644 --- a/src/pico/xinput_host.cpp +++ b/src/pico/xinput_host.cpp @@ -190,7 +190,7 @@ void xinputh_close(uint8_t dev_addr) // Enumeration //--------------------------------------------------------------------+ extern uint8_t transfer_with_usb_controller(const uint8_t dev_addr, const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, uint8_t *buffer, bool *status); -bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) +uint16_t xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *desc_itf, uint16_t max_len) { (void)rhport; (void)max_len; @@ -294,7 +294,7 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const _xinputh_dev->inst_count++; tuh_xinput_receive_report(dev_addr, i); p_xinput->subtype = GAMEPAD; - return true; + return drv_len; } uint8_t const *p_desc = (uint8_t const *)desc_itf; if (0xFF == desc_itf->bInterfaceClass && desc_itf->bInterfaceSubClass == 0x00 && @@ -325,7 +325,7 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_xinput->type = SWITCH2; p_xinput->subtype = NON_CONTROLLER; - return true; + return drv_len; } if (desc_itf->bInterfaceSubClass == 0x5D && @@ -357,7 +357,7 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_xinput->type = XBOX360_BB; p_xinput->subtype = GAMEPAD; - return true; + return drv_len; } else if (desc_itf->bInterfaceSubClass == 0x5D && (desc_itf->bInterfaceProtocol == 0x01 || @@ -404,7 +404,7 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_xinput->type = NON_CONTROLLER; } _xinputh_dev->inst_count++; - return true; + return drv_len; } else if (desc_itf->bInterfaceSubClass == 0xfD && desc_itf->bInterfaceProtocol == 0x13) @@ -421,7 +421,7 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_xinput->subtype = GAMEPAD; p_xinput->itf_num = desc_itf->bInterfaceNumber; _xinputh_dev->inst_count++; - return true; + return drv_len; } else if (desc_itf->bInterfaceSubClass == 0x47 && desc_itf->bInterfaceProtocol == 0xD0 && desc_itf->bNumEndpoints) @@ -451,7 +451,7 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_xinput->subtype = GAMEPAD; _xinputh_dev->inst_count++; usbh_edpt_xfer(dev_addr, p_xinput->ep_in, p_xinput->epin_buf, p_xinput->epin_size); - return true; + return drv_len; } else if (desc_itf->bInterfaceSubClass == 0x5D && desc_itf->bInterfaceProtocol == 0x81) @@ -483,7 +483,7 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_xinput->subtype = UNKNOWN; _xinputh_dev->inst_count++; usbh_edpt_xfer(dev_addr, p_xinput->ep_in, p_xinput->epin_buf, p_xinput->epin_size); - return true; + return drv_len; } else if (desc_itf->bInterfaceClass == 0x58) { @@ -512,7 +512,7 @@ bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const p_xinput->type = OG_XBOX; p_xinput->subtype = GAMEPAD; - return true; + return drv_len; } return false; } diff --git a/src/pico/xinput_host.h b/src/pico/xinput_host.h index 5c85c5aba..00d68ac09 100644 --- a/src/pico/xinput_host.h +++ b/src/pico/xinput_host.h @@ -143,7 +143,7 @@ TU_ATTR_WEAK void tuh_xinput_set_protocol_complete_cb(uint8_t dev_addr, uint8_t // Internal Class Driver API //--------------------------------------------------------------------+ bool xinputh_init(void); -bool xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* desc_itf, uint16_t max_len); +uint16_t xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const* desc_itf, uint16_t max_len); bool xinputh_set_config(uint8_t dev_addr, uint8_t itf_num); bool xinputh_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes); void xinputh_close(uint8_t dev_addr); diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index adbf8a677..b1c9bd61b 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -935,7 +935,7 @@ bool cleared_input = false; bool cleared_output = false; uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wIndex, const uint16_t wLength, uint8_t *requestBuffer, bool *status) { - printf("%02x %04x %04x %04x %04x\r\n", requestType, request, wValue, wIndex, wLength); + // printf("%02x %04x %04x %04x %04x\r\n", requestType, request, wValue, wIndex, wLength); #if DEVICE_TYPE_IS_GAMEPAD if (requestType == (USB_SETUP_DEVICE_TO_HOST | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_VENDOR) && (consoleType == UNIVERSAL || consoleType == OG_XBOX)) { From 864fa049a091dc8b5d3d653413de79bc1a751938 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 24 Mar 2026 11:36:14 +1300 Subject: [PATCH 169/239] fix usb hubs --- src/pico/xinput_device.cpp | 178 ++++++++++++------------------------- 1 file changed, 58 insertions(+), 120 deletions(-) diff --git a/src/pico/xinput_device.cpp b/src/pico/xinput_device.cpp index 4a0cd3a25..d4b9ebe5e 100644 --- a/src/pico/xinput_device.cpp +++ b/src/pico/xinput_device.cpp @@ -16,13 +16,12 @@ //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ -typedef struct -{ +typedef struct { uint8_t itf_num; uint8_t ep_in; - uint8_t ep_out; // optional Out endpoint - uint8_t boot_protocol; // Boot mouse or keyboard - bool boot_mode; // default = false (Report) + uint8_t ep_out; // optional Out endpoint + uint8_t boot_protocol; // Boot mouse or keyboard + bool boot_mode; // default = false (Report) CFG_TUSB_MEM_ALIGN uint8_t epin_buf[CFG_TUD_XINPUT_TX_BUFSIZE]; CFG_TUSB_MEM_ALIGN uint8_t epout_buf[CFG_TUD_XINPUT_RX_BUFSIZE]; @@ -31,12 +30,9 @@ typedef struct CFG_TUSB_MEM_SECTION static xinputd_interface_t _xinputd_itf[CFG_TUD_XINPUT]; static volatile bool sending = false; /*------------- Helpers -------------*/ -static inline uint8_t get_index_by_itfnum(uint8_t itf_num) -{ - for (uint8_t i = 0; i < CFG_TUD_XINPUT; i++) - { - if (itf_num == _xinputd_itf[i].itf_num) - return i; +static inline uint8_t get_index_by_itfnum(uint8_t itf_num) { + for (uint8_t i = 0; i < CFG_TUD_XINPUT; i++) { + if (itf_num == _xinputd_itf[i].itf_num) return i; } return 0xFF; @@ -45,19 +41,16 @@ static inline uint8_t get_index_by_itfnum(uint8_t itf_num) //--------------------------------------------------------------------+ // APPLICATION API //--------------------------------------------------------------------+ -bool tud_xinput_n_ready(uint8_t itf) -{ +bool tud_xinput_n_ready(uint8_t itf) { uint8_t const ep_in = _xinputd_itf[itf].ep_in; return tud_ready() && (ep_in != 0) && !usbd_edpt_busy(TUD_OPT_RHPORT, ep_in); } -bool tud_ready_for_packet(void) -{ +bool tud_ready_for_packet(void) { return !sending; } -bool tud_xusb_n_report(uint8_t itf, void const *report, uint8_t len) -{ +bool tud_xusb_n_report(uint8_t itf, void const *report, uint8_t len) { uint8_t const rhport = 0; xinputd_interface_t *p_xinput = &_xinputd_itf[itf]; @@ -70,8 +63,7 @@ bool tud_xusb_n_report(uint8_t itf, void const *report, uint8_t len) } bool tud_xinput_n_report(uint8_t itf, uint8_t report_id, void const *report, - uint8_t len) -{ + uint8_t len) { uint8_t const rhport = 0; xinputd_interface_t *p_xinput = &_xinputd_itf[itf]; @@ -79,16 +71,13 @@ bool tud_xinput_n_report(uint8_t itf, uint8_t report_id, void const *report, TU_VERIFY(usbd_edpt_claim(rhport, p_xinput->ep_in)); // prepare data - if (report_id) - { + if (report_id) { len = tu_min8(len, CFG_TUD_XINPUT_TX_BUFSIZE - 1); p_xinput->epin_buf[0] = report_id; memcpy(p_xinput->epin_buf + 1, report, len); len++; - } - else - { + } else { // If report id = 0, skip ID field len = tu_min8(len, CFG_TUD_XINPUT_TX_BUFSIZE); memcpy(p_xinput->epin_buf, report, len); @@ -103,24 +92,20 @@ bool tud_xinput_n_boot_mode(uint8_t itf) { return _xinputd_itf[itf].boot_mode; } //--------------------------------------------------------------------+ // USBD-CLASS API //--------------------------------------------------------------------+ -void xinputd_init(void) -{ +void xinputd_init(void) { xinputd_reset(TUD_OPT_RHPORT); } -void xinputd_reset(uint8_t rhport) -{ +void xinputd_reset(uint8_t rhport) { (void)rhport; tu_memclr(_xinputd_itf, sizeof(_xinputd_itf)); sending = false; } uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, - uint16_t max_len) -{ + uint16_t max_len) { uint16_t drv_len; - if (TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) - { + if (TUSB_CLASS_VENDOR_SPECIFIC == itf_desc->bInterfaceClass) { drv_len = sizeof(tusb_desc_interface_t) + (itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t)); @@ -128,19 +113,16 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, // Find available interface xinputd_interface_t *p_xinput = NULL; - for (uint8_t i = 0; i < CFG_TUD_XINPUT; i++) - { - if (_xinputd_itf[i].ep_in == 0 && _xinputd_itf[i].ep_out == 0) - { + for (uint8_t i = 0; i < CFG_TUD_XINPUT; i++) { + if (_xinputd_itf[i].ep_in == 0 && _xinputd_itf[i].ep_out == 0) { p_xinput = &_xinputd_itf[i]; break; } } TU_VERIFY(p_xinput, 0); uint8_t const *p_desc = (uint8_t const *)itf_desc; - - if (itf_desc->bInterfaceSubClass == 0x01 && itf_desc->bInterfaceProtocol == 0xFF) - { + + if (itf_desc->bInterfaceSubClass == 0x01 && itf_desc->bInterfaceProtocol == 0xFF) { p_desc = tu_desc_next(p_desc); printf("Opened: %d\r\n", itf_desc->bNumEndpoints); TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, itf_desc->bNumEndpoints, @@ -148,21 +130,17 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, &p_xinput->ep_in), 0); printf("Opened: %02x %02x\r\n", p_xinput->ep_out, p_xinput->ep_in); - if (p_xinput->ep_out) - { - if (!usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, sizeof(p_xinput->epout_buf), false)) - { + if (p_xinput->ep_out) { + if (!usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, sizeof(p_xinput->epout_buf), false)) { TU_LOG_FAILED(); TU_BREAKPOINT(); } } return drv_len; - } - else if (itf_desc->bInterfaceSubClass == 0x5D && - (itf_desc->bInterfaceProtocol == 0x01 || - itf_desc->bInterfaceProtocol == 0x03 || - itf_desc->bInterfaceProtocol == 0x02)) - { + } else if (itf_desc->bInterfaceSubClass == 0x5D && + (itf_desc->bInterfaceProtocol == 0x01 || + itf_desc->bInterfaceProtocol == 0x03 || + itf_desc->bInterfaceProtocol == 0x02)) { // Xinput reserved endpoint //-------------- Xinput Descriptor --------------// p_desc = tu_desc_next(p_desc); @@ -177,19 +155,14 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, 0); p_xinput->itf_num = itf_desc->bInterfaceNumber; - if (p_xinput->ep_out) - { - if (!usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, sizeof(p_xinput->epout_buf), false)) - { + if (p_xinput->ep_out) { + if (!usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, sizeof(p_xinput->epout_buf), false)) { TU_LOG_FAILED(); TU_BREAKPOINT(); } } - return drv_len; - } - else if (itf_desc->bInterfaceSubClass == 0xfD && - itf_desc->bInterfaceProtocol == 0x13) - { + } else if (itf_desc->bInterfaceSubClass == 0xfD && + itf_desc->bInterfaceProtocol == 0x13) { // Xinput reserved endpoint //-------------- Xinput Descriptor --------------// p_desc = tu_desc_next(p_desc); @@ -198,30 +171,22 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, TU_ASSERT(XINPUT_SECURITY_DESC_TYPE_RESERVED == x_desc->bDescriptorType, 0); drv_len += x_desc->bLength; p_desc = tu_desc_next(p_desc); - return drv_len; - } - else if (itf_desc->bInterfaceSubClass == 0x47 && - itf_desc->bInterfaceProtocol == 0xD0) - { + } else if (itf_desc->bInterfaceSubClass == 0x47 && + itf_desc->bInterfaceProtocol == 0xD0) { p_desc = tu_desc_next(p_desc); TU_ASSERT(usbd_open_edpt_pair(rhport, p_desc, itf_desc->bNumEndpoints, TUSB_XFER_INTERRUPT, &p_xinput->ep_out, &p_xinput->ep_in), 0); p_xinput->itf_num = itf_desc->bInterfaceNumber; // Prepare for output endpoint - if (p_xinput->ep_out) - { - if (!usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, sizeof(p_xinput->epout_buf), false)) - { + if (p_xinput->ep_out) { + if (!usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, sizeof(p_xinput->epout_buf), false)) { TU_LOG_FAILED(); TU_BREAKPOINT(); } } - return drv_len; } - } - else if (0x58 == itf_desc->bInterfaceClass) - { + } else if (0x58 == itf_desc->bInterfaceClass) { // len = interface + n*endpoints drv_len = sizeof(tusb_desc_interface_t) + itf_desc->bNumEndpoints * sizeof(tusb_desc_endpoint_t); TU_ASSERT(max_len >= drv_len, 0); @@ -229,10 +194,8 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, // Find available interface xinputd_interface_t *p_hid = NULL; uint8_t hid_id; - for (hid_id = 0; hid_id < CFG_TUD_XINPUT; hid_id++) - { - if (_xinputd_itf[hid_id].ep_in == 0) - { + for (hid_id = 0; hid_id < CFG_TUD_XINPUT; hid_id++) { + if (_xinputd_itf[hid_id].ep_in == 0) { p_hid = &_xinputd_itf[hid_id]; break; } @@ -248,18 +211,13 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, p_hid->itf_num = itf_desc->bInterfaceNumber; // Prepare for output endpoint - if (p_hid->ep_out) - { - if (!usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf), false)) - { + if (p_hid->ep_out) { + if (!usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf), false)) { TU_LOG_FAILED(); TU_BREAKPOINT(); } } - return drv_len; - } - else - { + } else { TU_VERIFY(TUSB_CLASS_HID == itf_desc->bInterfaceClass, 0); // len = interface + hid + n*endpoints @@ -269,10 +227,8 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, // Find available interface xinputd_interface_t *p_hid = NULL; uint8_t hid_id; - for (hid_id = 0; hid_id < CFG_TUD_XINPUT; hid_id++) - { - if (_xinputd_itf[hid_id].ep_in == 0) - { + for (hid_id = 0; hid_id < CFG_TUD_XINPUT; hid_id++) { + if (_xinputd_itf[hid_id].ep_in == 0) { p_hid = &_xinputd_itf[hid_id]; break; } @@ -292,70 +248,52 @@ uint16_t xinputd_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, p_hid->itf_num = itf_desc->bInterfaceNumber; // Prepare for output endpoint - if (p_hid->ep_out) - { - if (!usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf), false)) - { + if (p_hid->ep_out) { + if (!usbd_edpt_xfer(rhport, p_hid->ep_out, p_hid->epout_buf, sizeof(p_hid->epout_buf), false)) { TU_LOG_FAILED(); TU_BREAKPOINT(); } } - return drv_len; } //------------- Endpoint Descriptor -------------// // Config endpoint - return 0; + return drv_len; } bool xinputd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, - uint32_t xferred_bytes) -{ + uint32_t xferred_bytes) { (void)result; uint8_t itf = 0; xinputd_interface_t *p_xinput = _xinputd_itf; - for (;; itf++, p_xinput++) - { - if (itf >= TU_ARRAY_SIZE(_xinputd_itf)) - return false; + for (;; itf++, p_xinput++) { + if (itf >= TU_ARRAY_SIZE(_xinputd_itf)) return false; - if (ep_addr == p_xinput->ep_out || ep_addr == p_xinput->ep_in) - break; + if (ep_addr == p_xinput->ep_out || ep_addr == p_xinput->ep_in) break; } - if (ep_addr == p_xinput->ep_out) - { + if (ep_addr == p_xinput->ep_out) { hid_set_report(p_xinput->epout_buf, xferred_bytes, 0x00, INTERRUPT_ID); - if (consoleType == XBOX360 || consoleType == WINDOWS || consoleType == OG_XBOX) - { + if (consoleType == XBOX360 || consoleType == WINDOWS || consoleType == OG_XBOX) { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, 0x20, false)); - } - else if (consoleType == XBOXONE) - { + } else if (consoleType == XBOXONE) { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, 0x40, false)); - } - else if (consoleType == ARCADE) - { + } else if (consoleType == ARCADE) { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, 0x40, false)); - } - else if (consoleType == PS5) - { + } else if (consoleType == PS5) { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, 0x40, false)); - } - else - { + } else { TU_ASSERT(usbd_edpt_xfer(rhport, p_xinput->ep_out, p_xinput->epout_buf, 0x08, false)); } - } - else if (ep_addr == p_xinput->ep_in) - { + + } else if (ep_addr == p_xinput->ep_in) { sending = false; } return true; From 1a3a115c0f7f7f18a358cf828cb68bf1fa570c4c Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 26 Mar 2026 09:29:56 +1300 Subject: [PATCH 170/239] handle ps4 and xb1 tilt better --- include/config.h | 4 ++-- include/defines.h | 4 ++++ src/shared/main/shared_main.cpp | 11 +++++++++++ 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/include/config.h b/include/config.h index 44353fa96..c732f7ae4 100644 --- a/include/config.h +++ b/include/config.h @@ -217,7 +217,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define SUB_TYPE XINPUT_GUITAR_ALTERNATE #define PS3_TYPE PS3_GH_GUITAR_PID #define PS4_TYPE PS4_GUITAR -#define PS4_EXTENDED 0x06 +#define PS4_EXTENDED PS4_FLAG_GUITAR_TILT | PS4_FLAG_GUITAR_WHAMMY #define WII_TYPE WII_RB_GUITAR_PID #define OG_XBOX_REPORT OGXboxGuitarHeroGuitar_Data_t #define XINPUT_REPORT XInputGuitarHeroGuitar_Data_t @@ -251,7 +251,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define SUB_TYPE XINPUT_GUITAR #define PS3_TYPE PS3_RB_GUITAR_PID #define PS4_TYPE PS4_GUITAR -#define PS4_EXTENDED 0x07 +#define PS4_EXTENDED PS4_FLAG_GUITAR_TILT | PS4_FLAG_GUITAR_WHAMMY | PS4_FLAG_GUITAR_EFFECTS #define WII_TYPE WII_RB_GUITAR_PID #define OG_XBOX_REPORT OGXboxRockBandGuitar_Data_t #define XINPUT_REPORT XInputRockBandGuitar_Data_t diff --git a/include/defines.h b/include/defines.h index 0ba5bb65c..e708e410e 100644 --- a/include/defines.h +++ b/include/defines.h @@ -13,6 +13,10 @@ #define XINPUT_FLAGS_NONE 0x0000 #define XINPUT_FLAGS_FORCE_FEEDBACK 0x000D +#define PS4_FLAG_GUITAR_EFFECTS 1 +#define PS4_FLAG_GUITAR_TILT 2 +#define PS4_FLAG_GUITAR_WHAMMY 4 + // https://docs.microsoft.com/en-us/windows/win32/xinput/xinput-and-controller-subtypes // http://forum.gimx.fr/viewtopic.php?f=11&t=2897&start=10 #define XINPUT_GAMEPAD 1 diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 020d7c765..293ebc20a 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -613,6 +613,17 @@ uint8_t handle_calibration_ps3(uint8_t previous, int32_t orig_val, int16_t min, int8_t ret = handle_calibration_xbox((previous - PS3_STICK_CENTER) << 8, orig_val, min, max, center, deadzone, section) >> 8; return (uint8_t)(ret + PS3_STICK_CENTER); } +uint8_t handle_calibration_ps4_xb1_tilt(uint8_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, int16_t deadzone) +{ + int16_t ret = abs(handle_calibration_xbox(previous << 7, orig_val, min, max, center, deadzone, 0)) >> 7; + if (ret > 255) { + ret = 255; + } + if (ret < 0) { + ret = 0; + } + return (uint8_t)(ret); +} int8_t handle_calibration_mouse(int8_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, int16_t deadzone) { From 9bfe0c0df57c25d0cd2e4f9dea4439301d7d80a8 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 27 Mar 2026 11:35:20 +1300 Subject: [PATCH 171/239] add hang prevention --- include/defines.h | 1 + include/endpoints.h | 3 + include/reports/ps3_reports.h | 53 ++++++++ include/reports/xinput_reports.h | 210 +++++++++++++++++++------------ platformio.ini | 2 +- 5 files changed, 188 insertions(+), 81 deletions(-) diff --git a/include/defines.h b/include/defines.h index e708e410e..306ada54f 100644 --- a/include/defines.h +++ b/include/defines.h @@ -34,6 +34,7 @@ #define XINPUT_TURNTABLE 23 #define XINPUT_PRO_GUITAR 25 #define XINPUT_DISNEY_INFINITY_AND_LEGO_DIMENSIONS 33 +#define XINPUT_UDRAW 35 #define XINPUT_SKYLANDERS 36 // Next few arent real, but its easier for us to match this way #define XINPUT_GUITAR_HERO_LIVE 24 diff --git a/include/endpoints.h b/include/endpoints.h index 66650aed6..3ab03e13f 100644 --- a/include/endpoints.h +++ b/include/endpoints.h @@ -124,6 +124,9 @@ enum endpoints_t { #define STADIA_VID 0x18d1 #define STADIA_PID 0x9400 +#define PS3_UDRAW_VID 0x20D6 +#define PS3_UDRAW_PID 0xCB17 + #define SIMULTANEOUS_KEYS 6 diff --git a/include/reports/ps3_reports.h b/include/reports/ps3_reports.h index a9d35f49d..8e4773c86 100644 --- a/include/reports/ps3_reports.h +++ b/include/reports/ps3_reports.h @@ -816,3 +816,56 @@ typedef struct uint16_t unused4[3]; } __attribute__((packed)) PS3GHLGuitar_Data_t; + + +typedef struct +{ + uint8_t x : 1; // square, white1 + uint8_t a : 1; // cross, black1 + uint8_t b : 1; // circle, black2 + uint8_t y : 1; // triangle, black3 + + uint8_t leftShoulder : 1; // white2, l1 + uint8_t rightShoulder : 1; // white3, r1 + uint8_t : 1; + uint8_t : 1; + + uint8_t back : 1; // back, heroPower + uint8_t start : 1; // start, pause + uint8_t leftThumbClick : 1; // leftThumbClick, ghtv + uint8_t : 1; + + uint8_t guide : 1; // ps + uint8_t capture : 1; // switch capture button + uint8_t : 2; + + // To make things easier, we use bitfields here, and then we map to a proper hat later + uint8_t dpadUp : 1; + uint8_t dpadDown : 1; + uint8_t dpadLeft : 1; + uint8_t dpadRight : 1; + uint8_t : 4; + + uint8_t leftStickX; // leftStickX + uint8_t leftStickY; // leftStickY + uint8_t rightStickX; // rightStickX + uint8_t rightStickY; // rightStickY + + uint8_t unused3[4]; + uint8_t status; // 0x40 = pen touch, 0x80 = single finger, anything else = multi touch + uint8_t distance; // distance between fingers for multitouch (0x74 -> 0xff) + uint8_t pressure; // 0x74 -> 0xff, 0x60 if not pressed + uint8_t unused4; + uint8_t penXHigh; + uint8_t penYHigh; + uint8_t penXLow; + uint8_t penYLow; + + // Reminder that this value is 10-bit in range + // Each of the following are 10 bits in accuracy + // Centered/neutral state is nominally 0x0200, actual values may vary + uint16_t accelX; // Left/right acceleration (roll) + uint16_t accelZ; // Forward/back acceleration (pitch) + uint16_t accelY; // Up/down acceleration (gravity) + uint16_t gyro; // Left/right instantaneous rotation (yaw) +} __attribute__((packed)) PS3UDraw_Data_t; diff --git a/include/reports/xinput_reports.h b/include/reports/xinput_reports.h index e9460d532..a37e66b3f 100644 --- a/include/reports/xinput_reports.h +++ b/include/reports/xinput_reports.h @@ -26,13 +26,15 @@ #define BB_BLUE 0 #define BB_YELLOW 0 -typedef struct { +typedef struct +{ uint8_t rid; uint8_t rsize; uint8_t led; } __attribute__((packed)) XInputLEDReport_t; -typedef struct { +typedef struct +{ uint8_t rid; uint8_t rsize; uint8_t unused; @@ -41,7 +43,8 @@ typedef struct { uint8_t unused2[3]; } __attribute__((packed)) XInputRumbleReport_t; -typedef struct { +typedef struct +{ uint8_t rid; uint8_t rsize; uint8_t padding; @@ -50,7 +53,8 @@ typedef struct { uint8_t padding_2[3]; } __attribute__((packed)) XInputVibrationCapabilities_t; -typedef struct { +typedef struct +{ uint8_t rid; uint8_t rsize; uint16_t buttons; @@ -64,11 +68,13 @@ typedef struct { uint16_t flags; } __attribute__((packed)) XInputInputCapabilities_t; -typedef struct { +typedef struct +{ uint32_t serial; } __attribute__((packed)) XInputSerialNumber_t; -typedef struct { +typedef struct +{ uint8_t rid; uint8_t rsize; uint8_t controllerNumber; @@ -94,7 +100,8 @@ typedef struct { uint8_t reserved; } __attribute__((packed)) XInputBigButton_Data_t; -typedef struct { +typedef struct +{ uint8_t rid; uint8_t rsize; uint8_t dpadUp : 1; @@ -124,9 +131,11 @@ typedef struct { int16_t rightStickX; int16_t rightStickY; uint8_t reserved_1[6]; + } __attribute__((packed)) XInputGamepad_Data_t; -typedef struct { +typedef struct +{ uint8_t rid; uint16_t leftStickX; uint16_t leftStickY; @@ -152,7 +161,8 @@ typedef struct { uint8_t : 6; } __attribute__((packed)) XInputCompatGamepad_Data_t; -typedef struct { +typedef struct +{ uint8_t rid; uint8_t guide : 1; uint8_t : 7; @@ -168,24 +178,24 @@ typedef struct uint8_t start : 1; uint8_t back : 1; - uint8_t leftThumbClick : 1; // pedal2 - uint8_t padFlag : 1; // right thumb click + uint8_t leftThumbClick : 1; // pedal2 + uint8_t padFlag : 1; // right thumb click - uint8_t leftShoulder : 1; // pedal1 - uint8_t cymbalFlag : 1; // right shoulder click + uint8_t leftShoulder : 1; // pedal1 + uint8_t cymbalFlag : 1; // right shoulder click uint8_t guide : 1; uint8_t : 1; - uint8_t a : 1; // green - uint8_t b : 1; // red - uint8_t x : 1; // blue - uint8_t y : 1; // yellow + uint8_t a : 1; // green + uint8_t b : 1; // red + uint8_t x : 1; // blue + uint8_t y : 1; // yellow - uint8_t unused[2]; // trigger - int16_t redVelocity; // lx + uint8_t unused[2]; // trigger + int16_t redVelocity; // lx int16_t yellowVelocity; // ly - int16_t blueVelocity; // rx - int16_t greenVelocity; // ry + int16_t blueVelocity; // rx + int16_t greenVelocity; // ry uint8_t reserved_1[6]; } __attribute__((packed)) XInputRockBandDrums_Data_t; @@ -200,36 +210,36 @@ typedef struct uint8_t start : 1; uint8_t back : 1; - uint8_t leftThumbClick : 1; // isGuitarHero + uint8_t leftThumbClick : 1; // isGuitarHero uint8_t : 1; - uint8_t leftShoulder : 1; // kick - uint8_t rightShoulder : 1; // orange + uint8_t leftShoulder : 1; // kick + uint8_t rightShoulder : 1; // orange uint8_t guide : 1; uint8_t : 1; - uint8_t a : 1; // green - uint8_t b : 1; // red - uint8_t x : 1; // blue - uint8_t y : 1; // yellow + uint8_t a : 1; // green + uint8_t b : 1; // red + uint8_t x : 1; // blue + uint8_t y : 1; // yellow uint8_t unused1[2]; int16_t unused2; uint8_t greenVelocity; - uint8_t redVelocity; // redVelocity stores the velocity for the cymbal if both cymbal and pad of the same colour get hit simultaneously + uint8_t redVelocity; // redVelocity stores the velocity for the cymbal if both cymbal and pad of the same colour get hit simultaneously uint8_t yellowVelocity; uint8_t blueVelocity; uint8_t orangeVelocity; uint8_t kickVelocity; - uint8_t midiPacket[6]; // 0x99 note, velocity, xxxx + uint8_t midiPacket[6]; // 0x99 note, velocity, xxxx } __attribute__((packed)) XInputGuitarHeroDrums_Data_t; typedef struct { uint8_t rid; uint8_t rsize; - uint8_t dpadUp : 1; // dpadStrumUp - uint8_t dpadDown : 1; // dpadStrumDown + uint8_t dpadUp : 1; // dpadStrumUp + uint8_t dpadDown : 1; // dpadStrumDown uint8_t dpadLeft : 1; uint8_t dpadRight : 1; @@ -238,15 +248,15 @@ typedef struct uint8_t : 1; uint8_t : 1; - uint8_t leftShoulder : 1; // orange - uint8_t rightShoulder : 1; // pedal + uint8_t leftShoulder : 1; // orange + uint8_t rightShoulder : 1; // pedal uint8_t guide : 1; uint8_t : 1; - uint8_t a : 1; // green - uint8_t b : 1; // red - uint8_t x : 1; // blue - uint8_t y : 1; // yellow + uint8_t a : 1; // green + uint8_t b : 1; // red + uint8_t x : 1; // blue + uint8_t y : 1; // yellow uint8_t accelZ; uint8_t accelX; @@ -261,25 +271,25 @@ typedef struct { uint8_t rid; uint8_t rsize; - uint8_t dpadUp : 1; // dpadStrumUp - uint8_t dpadDown : 1; // dpadStrumDown + uint8_t dpadUp : 1; // dpadStrumUp + uint8_t dpadDown : 1; // dpadStrumDown uint8_t dpadLeft : 1; uint8_t dpadRight : 1; uint8_t start : 1; uint8_t back : 1; - uint8_t solo : 1; // leftThumbClick + uint8_t solo : 1; // leftThumbClick uint8_t : 1; - uint8_t leftShoulder : 1; // orange + uint8_t leftShoulder : 1; // orange uint8_t : 1; uint8_t guide : 1; uint8_t : 1; - uint8_t a : 1; // green - uint8_t b : 1; // red - uint8_t x : 1; // blue - uint8_t y : 1; // yellow + uint8_t a : 1; // green + uint8_t b : 1; // red + uint8_t x : 1; // blue + uint8_t y : 1; // yellow uint8_t pickup; uint8_t unused1; @@ -294,25 +304,25 @@ typedef struct { uint8_t rid; uint8_t rsize; - uint8_t dpadUp : 1; // dpadStrumUp - uint8_t dpadDown : 1; // dpadStrumDown + uint8_t dpadUp : 1; // dpadStrumUp + uint8_t dpadDown : 1; // dpadStrumDown uint8_t dpadLeft : 1; uint8_t dpadRight : 1; uint8_t start : 1; uint8_t back : 1; - uint8_t solo : 1; // leftThumbClick + uint8_t solo : 1; // leftThumbClick uint8_t : 1; - uint8_t leftShoulder : 1; // orange + uint8_t leftShoulder : 1; // orange uint8_t : 1; uint8_t guide : 1; uint8_t : 1; - uint8_t a : 1; // green - uint8_t b : 1; // red - uint8_t x : 1; // blue - uint8_t y : 1; // yellow + uint8_t a : 1; // green + uint8_t b : 1; // red + uint8_t x : 1; // blue + uint8_t y : 1; // yellow uint16_t lowEFret : 5; uint16_t aFret : 5; @@ -336,8 +346,8 @@ typedef struct uint16_t highEFretVelocity : 7; uint16_t : 1; - uint8_t autoCal_Microphone; // When the sensor isn't activated, this - uint8_t autoCal_Light; // and this just duplicate the tilt axis + uint8_t autoCal_Microphone; // When the sensor isn't activated, this + uint8_t autoCal_Light; // and this just duplicate the tilt axis uint8_t tilt; uint8_t : 7; @@ -353,27 +363,29 @@ typedef struct { uint8_t rid; uint8_t rsize; - uint8_t dpadUp : 1; // dpadStrumUp - uint8_t dpadDown : 1; // dpadStrumDown + uint8_t dpadUp : 1; // dpadStrumUp + uint8_t dpadDown : 1; // dpadStrumDown uint8_t dpadLeft : 1; uint8_t dpadRight : 1; uint8_t start : 1; uint8_t back : 1; - uint8_t solo : 1; // leftThumbClick + uint8_t solo : 1; // leftThumbClick uint8_t : 1; - uint8_t leftShoulder : 1; // orange + uint8_t leftShoulder : 1; // orange uint8_t : 1; uint8_t guide : 1; uint8_t : 1; - uint8_t a : 1; // green - uint8_t b : 1; // red - uint8_t x : 1; // blue - uint8_t y : 1; // yellow - union { - struct { + uint8_t a : 1; // green + uint8_t b : 1; // red + uint8_t x : 1; // blue + uint8_t y : 1; // yellow + union + { + struct + { uint8_t key8 : 1; uint8_t key7 : 1; uint8_t key6 : 1; @@ -402,8 +414,10 @@ typedef struct uint8_t keys[3]; }; - union { - struct { + union + { + struct + { uint8_t velocity1 : 7; uint8_t key25 : 1; uint8_t velocity2 : 7; @@ -429,7 +443,7 @@ typedef struct uint8_t unused2[4]; - uint8_t pedalConnection : 1; // If this matches PS3 MPA behavior, always 0 with the MIDI Pro Adapter + uint8_t pedalConnection : 1; // If this matches PS3 MPA behavior, always 0 with the MIDI Pro Adapter uint8_t : 7; } __attribute__((packed)) XInputRockBandKeyboard_Data_t; @@ -442,20 +456,20 @@ typedef struct uint8_t dpadLeft : 1; uint8_t dpadRight : 1; - uint8_t start : 1; // start, pause - uint8_t back : 1; // back, heroPower - uint8_t leftThumbClick : 1; // leftThumbClick, ghtv + uint8_t start : 1; // start, pause + uint8_t back : 1; // back, heroPower + uint8_t leftThumbClick : 1; // leftThumbClick, ghtv uint8_t : 1; - uint8_t leftShoulder : 1; // white2 leftShoulder - uint8_t rightShoulder : 1; // white3 rightShoulder + uint8_t leftShoulder : 1; // white2 leftShoulder + uint8_t rightShoulder : 1; // white3 rightShoulder uint8_t guide : 1; uint8_t : 1; - uint8_t a : 1; // black1 a - uint8_t b : 1; // black2 b - uint8_t x : 1; // white1 x - uint8_t y : 1; // black3 y + uint8_t a : 1; // black1 a + uint8_t b : 1; // black2 b + uint8_t x : 1; // white1 x + uint8_t y : 1; // black3 y uint8_t unused1[2]; @@ -489,7 +503,7 @@ typedef struct uint8_t a : 1; uint8_t b : 1; uint8_t x : 1; - uint8_t y : 1; // euphoria + uint8_t y : 1; // euphoria uint8_t leftGreen : 1; uint8_t leftRed : 1; @@ -504,7 +518,43 @@ typedef struct int16_t leftTableVelocity; int16_t rightTableVelocity; - int16_t effectsKnob; // Whether or not this is signed doesn't really matter, as either way it's gonna loop over when it reaches min/max + int16_t effectsKnob; // Whether or not this is signed doesn't really matter, as either way it's gonna loop over when it reaches min/max int16_t crossfader; uint8_t reserved_1[6]; } __attribute__((packed)) XInputTurntable_Data_t; + +typedef struct +{ + uint8_t rid; + uint8_t rsize; + uint8_t dpadUp : 1; + uint8_t dpadDown : 1; + uint8_t dpadLeft : 1; + uint8_t dpadRight : 1; + + uint8_t start : 1; + uint8_t back : 1; + uint8_t leftThumbClick : 1; + uint8_t rightThumbClick : 1; + + uint8_t leftShoulder : 1; + uint8_t rightShoulder : 1; + uint8_t guide : 1; + uint8_t : 1; + + uint8_t a : 1; + uint8_t b : 1; + uint8_t x : 1; + uint8_t y : 1; + + uint8_t penPressure; // starts at 0x72, goes up to 0xff + uint8_t accelZ; // 0x0a to 0x35 + uint8_t penX; // + uint8_t penY; + uint8_t status; // 0x40 = pen touch, 0x80 = single finger, anything else = multi touch + uint8_t distance; // distance between fingers for multitouch + uint8_t accelX; // 0x0a to 0x35 + uint8_t accelY; // 0x0a to 0x35 + uint8_t reserved_1[6]; + +} __attribute__((packed)) XInputUDraw_Data_t; diff --git a/platformio.ini b/platformio.ini index ff9532111..de50914ea 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ board_upload.ardwiino_bootloader_teensy = true board_build.use_usb = 1 platform = https://github.com/maxgerhardt/platform-raspberrypi/archive/39b90392af50585e429941bd2561a91949a2ba46.zip@1.15.0 platform_packages = - framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.5-sanjay/rp2040-4.6.5-sanjay.zip@1.40404.0 + framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.7-sanjay/rp2040-4.6.7-sanjay.zip@1.40404.0 board = pico framework = arduino board_build.core = earlephilhower From 87eb22985a1cfbda496defa8c8a07c23af62e2ad Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 27 Mar 2026 14:39:25 +1300 Subject: [PATCH 172/239] add hang prevention --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index de50914ea..402c7f507 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ board_upload.ardwiino_bootloader_teensy = true board_build.use_usb = 1 platform = https://github.com/maxgerhardt/platform-raspberrypi/archive/39b90392af50585e429941bd2561a91949a2ba46.zip@1.15.0 platform_packages = - framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.7-sanjay/rp2040-4.6.7-sanjay.zip@1.40404.0 + framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.8-sanjay/rp2040-4.6.8-sanjay.zip@1.40404.0 board = pico framework = arduino board_build.core = earlephilhower From 51979ba30633589407562fc3ea2377e9b2a7f4de Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 28 Mar 2026 07:43:03 +1300 Subject: [PATCH 173/239] when ticking usb, data not being available doesnt mean not ready --- src/shared/main/shared_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 293ebc20a..20a802e7c 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3947,7 +3947,7 @@ bool tick_usb(void) send_report_to_pc(&combined_report, size); } report_requested = true; - return size; + return ready; } #if BLUETOOTH_RX int tick_bluetooth_inputs(const void *data, uint8_t len, USB_Device_Type_t device_type) From f0ef44455bb71678fa3c6dad528adeeda99d801e Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 30 Mar 2026 05:55:08 +1300 Subject: [PATCH 174/239] fix 360 wireles receivers --- src/pico/xinput_host.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pico/xinput_host.cpp b/src/pico/xinput_host.cpp index 8b95007a6..ad1862692 100644 --- a/src/pico/xinput_host.cpp +++ b/src/pico/xinput_host.cpp @@ -458,6 +458,9 @@ uint16_t xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t co { // Skip over 0x22 descriptor p_desc = tu_desc_next(p_desc); + XBOX_ID_DESCRIPTOR *x_desc = + (XBOX_ID_DESCRIPTOR *)p_desc; + drv_len += x_desc->bLength; uint8_t endpoints = desc_itf->bNumEndpoints; while (endpoints--) { From 727995c776e10b6daf66d12c043863607aaa4121 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 15 Apr 2026 09:47:20 +1200 Subject: [PATCH 175/239] use PDP drum vid+pid as thats what festival will support --- src/shared/config/config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/config/config.c b/src/shared/config/config.c index 6794eebe6..01f544344 100644 --- a/src/shared/config/config.c +++ b/src/shared/config/config.c @@ -19,7 +19,7 @@ const uint8_t announce[] = {0x02, 0x20, 0x01, 0x1c, 0x7e, 0xed, 0x81, TEMP, TEMP const uint8_t xb1_descriptor[] = {0x04, 0xf0, 0x01, 0x3a, 0xf5, 0x01, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00, 0xb6, 0x00, 0x16, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x23, 0x00, 0x29, 0x00, 0x75, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x06, 0x07, 0x05, 0x01, 0x04, 0x05, 0x06, 0x0a, 0x02, 0x04, 0xa0, 0x01, 0xba, 0x00, 0x3a, 0x20, 0x00, 0x4d, 0x61, 0x64, 0x43, 0x61, 0x74, 0x7a, 0x2e, 0x58, 0x62, 0x6f, 0x78, 0x2e, 0x47, 0x75, 0x69, 0x74, 0x61, 0x72, 0x2e, 0x53, 0x74, 0x72, 0x61, 0x74, 0x6f, 0x63, 0x61, 0x73, 0x74, 0x65, 0x72, 0x27, 0x00, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2e, 0x58, 0x62, 0x6f, 0x78, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x2e, 0x4e, 0x61, 0x76, 0x04, 0xa0, 0x01, 0xba, 0x00, 0x74, 0x69, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x04, 0x38, 0xe4, 0x2a, 0x0d, 0x7d, 0x7f, 0x33, 0x49, 0x86, 0x93, 0x30, 0xfc, 0x55, 0x01, 0x8e, 0x77, 0xe7, 0x1f, 0xf3, 0xb8, 0x86, 0x73, 0xe9, 0x40, 0xa9, 0xf8, 0x2f, 0x21, 0x26, 0x3a, 0xcf, 0xb7, 0x56, 0xff, 0x76, 0x97, 0xfd, 0x9b, 0x81, 0x45, 0x04, 0xa0, 0x01, 0x3a, 0xae, 0x01, 0xad, 0x45, 0xb6, 0x45, 0xbb, 0xa5, 0x26, 0xd6, 0x77, 0xce, 0x34, 0x7a, 0xe2, 0x7d, 0xc6, 0x45, 0x8c, 0xa4, 0x00, 0x42, 0xc0, 0x8b, 0xd9, 0x4a, 0x02, 0x17, 0x00, 0x20, 0x20, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x21, 0x05, 0x00, 0x01, 0x00, 0x0c, 0x00, 0x00, 0x04, 0xb0, 0x01, 0x0d, 0xe8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const uint8_t xb1_descriptor_end[] = {0x04, 0xa0, 0x01, 0x00, 0xf5, 0x01}; #elif DEVICE_TYPE_IS_DRUM -const uint8_t announce[] = {0x02, 0x20, 0x01, 0x1c, 0x7e, 0xed, 0x81, TEMP, TEMP, TEMP, 0x00, 0x00, 0x38, 0x07, 0x62, 0x42, 0x01, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}; +const uint8_t announce[] = {0x02, 0x20, 0x01, 0x1c, 0x7e, 0xed, 0x81, TEMP, TEMP, TEMP, 0x00, 0x00, 0x6f, 0x0e, 0x71, 0x01, 0x01, 0x00, 0x00, 0x00, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}; const uint8_t xb1_descriptor[] = {0x04, 0xf0, 0x01, 0x3a, 0xd5, 0x01, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, 0x00, 0xad, 0x00, 0x16, 0x00, 0x1b, 0x00, 0x1c, 0x00, 0x23, 0x00, 0x29, 0x00, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x02, 0x03, 0x04, 0x06, 0x07, 0x05, 0x01, 0x04, 0x05, 0x06, 0x0a, 0x02, 0x04, 0xa0, 0x01, 0xba, 0x00, 0x3a, 0x17, 0x00, 0x4d, 0x61, 0x64, 0x43, 0x61, 0x74, 0x7a, 0x2e, 0x58, 0x62, 0x6f, 0x78, 0x2e, 0x44, 0x72, 0x75, 0x6d, 0x73, 0x2e, 0x47, 0x6c, 0x61, 0x6d, 0x27, 0x00, 0x57, 0x69, 0x6e, 0x64, 0x6f, 0x77, 0x73, 0x2e, 0x58, 0x62, 0x6f, 0x78, 0x2e, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x2e, 0x4e, 0x61, 0x76, 0x69, 0x67, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x04, 0xa0, 0x01, 0xba, 0x00, 0x74, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x04, 0x93, 0x28, 0x18, 0x06, 0xe0, 0xcc, 0x85, 0x4b, 0x92, 0x71, 0x0a, 0x10, 0xdb, 0xab, 0x7e, 0x07, 0xe7, 0x1f, 0xf3, 0xb8, 0x86, 0x73, 0xe9, 0x40, 0xa9, 0xf8, 0x2f, 0x21, 0x26, 0x3a, 0xcf, 0xb7, 0x56, 0xff, 0x76, 0x97, 0xfd, 0x9b, 0x81, 0x45, 0xad, 0x45, 0xb6, 0x45, 0xbb, 0xa5, 0x26, 0xd6, 0x77, 0x04, 0xb0, 0x01, 0x27, 0xae, 0x01, 0xce, 0x34, 0x7a, 0xe2, 0x7d, 0xc6, 0x45, 0x8c, 0xa4, 0x00, 0x42, 0xc0, 0x8b, 0xd9, 0x4a, 0x01, 0x17, 0x00, 0x20, 0x0a, 0x00, 0x01, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; const uint8_t xb1_descriptor_end[] = {0x04, 0xa0, 0x01, 0x00, 0xd5, 0x01}; #elif DEVICE_TYPE_IS_LIVE_GUITAR From 79db20f42efb10c689a3c414baabc4a717331608 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 18 Apr 2026 07:55:51 +1200 Subject: [PATCH 176/239] actually provide a hid report descriptor --- src/shared/usb/descriptors.cpp | 53 ++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index b1c9bd61b..c5faf1e7f 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1615,6 +1615,59 @@ uint16_t descriptorRequest(const uint16_t wValue, #endif break; } + case HID_DESCRIPTOR_HID: + { + size = sizeof(UNIVERSAL_CONFIGURATION_DESCRIPTOR); + memcpy_P(descriptorBuffer, &UniversalConfigurationDescriptor, size); + USB_HID_DESCRIPTOR *desc = (USB_HID_DESCRIPTOR *)descriptorBuffer; + + if (consoleType == PS4) + { + desc->wDescriptorLength = sizeof(ps4_descriptor); + } + else if (consoleType == PS5) + { + desc->wDescriptorLength = sizeof(ps5_descriptor); + desc->bcdHID = 0x0111; + } + else if (consoleType == IOS_FESTIVAL) + { + desc->wDescriptorLength = sizeof(ps3_descriptor); +#if DEVICE_TYPE_IS_INSTRUMENT +#if defined(TICK_NKRO) || defined(TICK_SIXKRO) + } + else if (consoleType == KEYBOARD_MOUSE) + { + desc->wDescriptorLength = sizeof(keyboard_mouse_descriptor); +#endif +#if DEVICE_TYPE == ROCK_BAND_GUITAR || DEVICE_TYPE == GUITAR_HERO_GUITAR + } + else if (consoleType == FNF) + { + desc->wDescriptorLength = sizeof(fnf_descriptor); +#endif + } + else + { + desc->wDescriptorLength = sizeof(ps3_instrument_descriptor); + } +#else + } + else if (consoleType == PS3) + { + desc->wDescriptorLength = sizeof(ps3_descriptor); + } + else + { + desc->wDescriptorLength = sizeof(ps3_instrument_descriptor); + } +#endif + if (consoleType == UNIVERSAL) + { + desc->wDescriptorLength = sizeof(pc_descriptor); + } + break; + } case HID_DESCRIPTOR_REPORT: { const void *address; From 1c57d3f065f7a672a58d387ad22a1dc121c26fb0 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 18 Apr 2026 08:09:17 +1200 Subject: [PATCH 177/239] fix usb host overwriting dpad instead of merging --- src/shared/main/shared_main.cpp | 136 ++++++++++++++++---------------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 20a802e7c..80fec966d 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -1720,10 +1720,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t case PS4: { PS4Dpad_Data_t *dpad = (PS4Dpad_Data_t *)data; - usb_host_data->dpadLeft = dpad->dpad == 6 || dpad->dpad == 5 || dpad->dpad == 7; - usb_host_data->dpadRight = dpad->dpad == 3 || dpad->dpad == 2 || dpad->dpad == 1; - usb_host_data->dpadUp = dpad->dpad == 0 || dpad->dpad == 1 || dpad->dpad == 7; - usb_host_data->dpadDown = dpad->dpad == 5 || dpad->dpad == 4 || dpad->dpad == 3; + usb_host_data->dpadLeft |= dpad->dpad == 6 || dpad->dpad == 5 || dpad->dpad == 7; + usb_host_data->dpadRight |= dpad->dpad == 3 || dpad->dpad == 2 || dpad->dpad == 1; + usb_host_data->dpadUp |= dpad->dpad == 0 || dpad->dpad == 1 || dpad->dpad == 7; + usb_host_data->dpadDown |= dpad->dpad == 5 || dpad->dpad == 4 || dpad->dpad == 3; switch (device_type.sub_type) { case GAMEPAD: @@ -1846,10 +1846,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t case PS5: { PS5Dpad_Data_t *dpad = (PS5Dpad_Data_t *)data; - usb_host_data->dpadLeft = dpad->dpad == 6 || dpad->dpad == 5 || dpad->dpad == 7; - usb_host_data->dpadRight = dpad->dpad == 3 || dpad->dpad == 2 || dpad->dpad == 1; - usb_host_data->dpadUp = dpad->dpad == 0 || dpad->dpad == 1 || dpad->dpad == 7; - usb_host_data->dpadDown = dpad->dpad == 5 || dpad->dpad == 4 || dpad->dpad == 3; + usb_host_data->dpadLeft |= dpad->dpad == 6 || dpad->dpad == 5 || dpad->dpad == 7; + usb_host_data->dpadRight |= dpad->dpad == 3 || dpad->dpad == 2 || dpad->dpad == 1; + usb_host_data->dpadUp |= dpad->dpad == 0 || dpad->dpad == 1 || dpad->dpad == 7; + usb_host_data->dpadDown |= dpad->dpad == 5 || dpad->dpad == 4 || dpad->dpad == 3; switch (device_type.sub_type) { case GAMEPAD: @@ -1941,10 +1941,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t case GAMEPAD: { SwitchProGamepad_Data_t *report = (SwitchProGamepad_Data_t *)data; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; usb_host_data->green |= report->a; usb_host_data->red |= report->b; usb_host_data->yellow |= report->y; @@ -2007,10 +2007,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->guide |= report->guide; usb_host_data->leftThumbClick |= report->leftThumbClick; usb_host_data->rightThumbClick |= report->rightThumbClick; - usb_host_data->dpadLeft = report->dpad == 6 || report->dpad == 5 || report->dpad == 7; - usb_host_data->dpadRight = report->dpad == 3 || report->dpad == 2 || report->dpad == 1; - usb_host_data->dpadUp = report->dpad == 0 || report->dpad == 1 || report->dpad == 7; - usb_host_data->dpadDown = report->dpad == 5 || report->dpad == 4 || report->dpad == 3; + usb_host_data->dpadLeft |= report->dpad == 6 || report->dpad == 5 || report->dpad == 7; + usb_host_data->dpadRight |= report->dpad == 3 || report->dpad == 2 || report->dpad == 1; + usb_host_data->dpadUp |= report->dpad == 0 || report->dpad == 1 || report->dpad == 7; + usb_host_data->dpadDown |= report->dpad == 5 || report->dpad == 4 || report->dpad == 3; if (report->l2) { usb_host_data->leftTrigger = UINT16_MAX; @@ -2146,10 +2146,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->start |= report->start; usb_host_data->leftThumbClick |= report->leftThumbClick; usb_host_data->rightThumbClick |= report->rightThumbClick; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; if (report->leftTrigger) { usb_host_data->leftTrigger = report->leftTrigger << 8; @@ -2219,10 +2219,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->guide |= report->guide; usb_host_data->leftThumbClick |= report->leftThumbClick; usb_host_data->rightThumbClick |= report->rightThumbClick; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; break; } @@ -2237,10 +2237,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t if (report->rid == 1) { uint8_t dpad = report->dpad - 1; - usb_host_data->dpadLeft = dpad == 6 || dpad == 5 || dpad == 7; - usb_host_data->dpadRight = dpad == 3 || dpad == 2 || dpad == 1; - usb_host_data->dpadUp = dpad == 0 || dpad == 1 || dpad == 7; - usb_host_data->dpadDown = dpad == 5 || dpad == 4 || dpad == 3; + usb_host_data->dpadLeft |= dpad == 6 || dpad == 5 || dpad == 7; + usb_host_data->dpadRight |= dpad == 3 || dpad == 2 || dpad == 1; + usb_host_data->dpadUp |= dpad == 0 || dpad == 1 || dpad == 7; + usb_host_data->dpadDown |= dpad == 5 || dpad == 4 || dpad == 3; // Festival pro mode mappings usb_host_data->green |= dpad == 6 || dpad == 5 || dpad == 7; usb_host_data->red |= dpad == 0 || dpad == 1 || dpad == 7; @@ -2319,10 +2319,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->back |= report->back; usb_host_data->start |= report->start; usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; if (report->tilt) { usb_host_data->tilt = INT16_MAX; @@ -2362,10 +2362,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->back |= report->back; usb_host_data->start |= report->start; usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; if (report->tilt) { usb_host_data->tilt = report->tilt; @@ -2439,10 +2439,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->back |= report->back; usb_host_data->start |= report->start; usb_host_data->guide |= report->guide; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; SET_GH_PADS(); // Forward any midi data we get if ((report->midiPacket[0] & 0xF0) == 0x90) @@ -2477,10 +2477,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->b |= report->b; usb_host_data->x |= report->x; usb_host_data->y |= report->y; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; } usb_host_data->back |= report->back; usb_host_data->start |= report->start; @@ -2502,10 +2502,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->yellow |= report->y; usb_host_data->blue |= report->x; usb_host_data->orange |= report->leftShoulder; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; usb_host_data->leftThumbClick |= report->leftThumbClick; usb_host_data->back |= report->back; usb_host_data->start |= report->start; @@ -2527,10 +2527,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->b |= report->b; usb_host_data->x |= report->x; usb_host_data->y |= report->y; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; usb_host_data->back |= report->back; usb_host_data->start |= report->start; usb_host_data->guide |= report->guide; @@ -2615,10 +2615,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->guide |= report->guide; usb_host_data->leftThumbClick |= report->leftThumbClick; usb_host_data->rightThumbClick |= report->rightThumbClick; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; if (report->leftTrigger) { usb_host_data->leftTrigger = report->leftTrigger << 8; @@ -2671,10 +2671,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->start |= report->start; usb_host_data->leftThumbClick |= report->leftThumbClick; usb_host_data->rightThumbClick |= report->rightThumbClick; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; // XB1 reports range from 0 - 1024 if (report->leftTrigger) { @@ -2722,10 +2722,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->soloYellow |= report->soloYellow; usb_host_data->soloBlue |= report->soloBlue; usb_host_data->soloOrange |= report->soloOrange; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; if (report->tilt) { usb_host_data->tilt = report->tilt << 7; @@ -2749,10 +2749,10 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->y |= report->y; usb_host_data->back |= report->back; usb_host_data->start |= report->start; - usb_host_data->dpadLeft = report->dpadLeft; - usb_host_data->dpadRight = report->dpadRight; - usb_host_data->dpadUp = report->dpadUp; - usb_host_data->dpadDown = report->dpadDown; + usb_host_data->dpadLeft |= report->dpadLeft; + usb_host_data->dpadRight |= report->dpadRight; + usb_host_data->dpadUp |= report->dpadUp; + usb_host_data->dpadDown |= report->dpadDown; if (report->greenVelocity) { onNote(10, RB_MIDI_NOTE_GREEN, report->greenVelocity << 3); From 9b20f45fb9401c2f6e58ea303a4d4b954ec7b5a3 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 18 Apr 2026 11:32:54 +1200 Subject: [PATCH 178/239] mappings for switch --- include/config.h | 2 +- include/reports/pc_reports.h | 31 +++++----- include/reports/ps3_reports.h | 103 +++++++++++++++++++++++++++++++ include/reports/switch_reports.h | 36 +++++++++++ src/shared/main/shared_main.cpp | 53 +++++++++++++++- 5 files changed, 205 insertions(+), 20 deletions(-) diff --git a/include/config.h b/include/config.h index c732f7ae4..53562d7f1 100644 --- a/include/config.h +++ b/include/config.h @@ -471,7 +471,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define OG_XBOX_REPORT OGXboxRockBandDrums_Data_t #define XINPUT_REPORT XInputRockBandDrums_Data_t #define XBOX_ONE_REPORT XboxOneRockBandDrums_Data_t -#define PC_FESTIVAL_REPORT FestivalProGuitarLayerRB_Data_t +#define PC_FESTIVAL_REPORT FestivalProDrumsLayerRB_Data_t #define PC_REPORT PCRockBandDrums_Data_t #define PS2_REPORT PS2Gamepad_Data_t #define PS3_REPORT PS3RockBandDrums_Data_t diff --git a/include/reports/pc_reports.h b/include/reports/pc_reports.h index 727b5734b..4e91db2b1 100644 --- a/include/reports/pc_reports.h +++ b/include/reports/pc_reports.h @@ -251,15 +251,15 @@ typedef struct typedef struct { uint8_t reportId; - uint8_t rightShoulder : 1; // a, cross, green - uint8_t leftShoulder : 1; // b, circle, red - uint8_t x : 1; // y, triangle, yellow - uint8_t y : 1; // x, square, blue - - uint8_t dpadUp : 1; // leftShoulder, orange, l1 - uint8_t dpadDown : 1; // rightShoulder - uint8_t whammy : 1; // l2 - uint8_t tilt : 1; // r2 + uint8_t greenCymbal : 1; // a, cross, green + uint8_t green : 1; // b, circle, red + uint8_t blueCymbal : 1; // y, triangle, yellow + uint8_t blue : 1; // x, square, blue + + uint8_t kick2 : 1; // leftShoulder, orange, l1 + uint8_t kick : 1; // rightShoulder + uint8_t l2 : 1; // l2 + uint8_t r2 : 1; // r2 uint8_t : 2; uint8_t back : 1; // back, select uint8_t start : 1; // start @@ -270,18 +270,15 @@ typedef struct // To make things easier, we use bitfields here, and then we map to a proper hat later union { struct { - uint8_t b : 1; // dpadUp - uint8_t dpadRight : 1; // dpadDown - uint8_t a : 1; // dpadLeft - uint8_t dpadLeft : 1; // dpadRight + uint8_t yellowCymbal : 1; // dpadUp + uint8_t yellow : 1; // dpadDown + uint8_t red : 1; // dpadLeft + uint8_t dpadRight : 1; // dpadRight uint8_t : 4; }; uint8_t dpad; }; - - uint8_t unused[2]; - uint8_t slider; -} __attribute__((packed)) FestivalProGuitarLayerRB_Data_t; +} __attribute__((packed)) FestivalProDrumsLayerRB_Data_t; typedef struct { diff --git a/include/reports/ps3_reports.h b/include/reports/ps3_reports.h index 8e4773c86..1c3a87bfe 100644 --- a/include/reports/ps3_reports.h +++ b/include/reports/ps3_reports.h @@ -149,6 +149,58 @@ typedef struct { uint16_t accelZ; uint16_t gyro; } __attribute__((packed)) PS3Gamepad_Data_t; +typedef struct { + uint8_t reportId; + uint8_t : 8; + uint8_t back : 1; // select + uint8_t padFlag : 1; // left stick click, l3 + uint8_t cymbalFlag : 1; // right stick click, r3 + uint8_t start : 1; + + uint8_t dpadUp : 1; + uint8_t dpadRight : 1; + uint8_t dpadDown : 1; + uint8_t dpadLeft : 1; + + uint8_t l2 : 1; // l1 + uint8_t r2 : 1; // r1 + uint8_t leftShoulder : 1; // l1 + uint8_t rightShoulder : 1; // r1 + + uint8_t y : 1; // triangle + uint8_t b : 1; // circle + uint8_t a : 1; // cross + uint8_t x : 1; // square + + uint8_t guide : 1; + uint8_t : 7; + uint8_t : 8; + uint8_t leftStickX; + uint8_t leftStickY; + uint8_t rightStickX; + uint8_t rightStickY; + uint8_t padding_3[4]; + uint8_t pressureDpadUp; + uint8_t pressureDpadRight; + uint8_t pressureDpadDown; + uint8_t pressureDpadLeft; + uint8_t leftTrigger; // pressure_l2 + uint8_t rightTrigger; // pressure_r2 + uint8_t yellowVelocity; + uint8_t redVelocity; // If you hit two cymbals at once, it puts the velocity for the cymbal here + uint8_t greenVelocity; + uint8_t blueVelocity; + uint8_t blueCymbalVelocity; + uint8_t yellowCymbalVelocity; + uint8_t greenCymbalVelocity; + uint8_t padding_4[14]; + // Each of the following are 10 bits in accuracy + // Centered/neutral state is nominally 0x0200, actual values may vary + uint16_t accelX; // Left/right acceleration (roll) + uint16_t accelZ; // Forward/back acceleration (pitch) + uint16_t accelY; // Up/down acceleration (gravity) + uint16_t gyro; // Left/right instantaneous rotation (yaw) +} __attribute__((packed)) PS3GamepadDrum_Data_t; typedef struct { uint8_t reportId; uint8_t : 8; @@ -253,6 +305,57 @@ typedef struct { uint16_t gyro; // Left/right instantaneous rotation (yaw) } __attribute__((packed)) PS3FestivalProGuitarLayer_Data_t; +typedef struct { + uint8_t reportId; + uint8_t : 8; + uint8_t back : 1; // select + uint8_t leftThumbClick : 1; // l3 + uint8_t rightThumbClick : 1; // r3 + uint8_t start : 1; + + uint8_t yellowCymbal : 1; // dpadUp + uint8_t dpadRight : 1; + uint8_t yellow : 1; + uint8_t red : 1; // dpadLeft + + uint8_t l2 : 1; // l2 - whammy + uint8_t r2 : 1; // r2 - overdrive + uint8_t kick2 : 1; // l1 (leftShoulder) - strum up + uint8_t kick : 1; // r1 (rightShoulder) - strum down + + uint8_t blue : 1; // triangle (y) - blue + uint8_t green : 1; // circle (b) - orange + uint8_t greenCymbal : 1; // cross (a) + uint8_t blueCymbal : 1; // square (x) - yellow + + uint8_t guide : 1; + uint8_t : 7; + uint8_t : 8; + uint8_t leftStickX; + uint8_t leftStickY; + uint8_t rightStickX; + uint8_t rightStickY; + uint8_t padding_3[4]; + uint8_t pressureDpadUp; + uint8_t pressureDpadRight; + uint8_t pressureDpadDown; + uint8_t pressureDpadLeft; + uint8_t leftTrigger; // pressure_l2 + uint8_t rightTrigger; // pressure_r2 + uint8_t pressureL1; + uint8_t pressureR1; + uint8_t pressureTriangle; + uint8_t pressureCircle; + uint8_t pressureCross; + uint8_t pressureSquare; + uint8_t padding_4[15]; + // Each of the following are 10 bits in accuracy + // Centered/neutral state is nominally 0x0200, actual values may vary + uint16_t accelX; // Left/right acceleration (roll) + uint16_t accelZ; // Forward/back acceleration (pitch) + uint16_t accelY; // Up/down acceleration (gravity) + uint16_t gyro; // Left/right instantaneous rotation (yaw) +} __attribute__((packed)) PS3FestivalProDrumLayer_Data_t; typedef struct { // Button bits uint8_t x : 1; // square diff --git a/include/reports/switch_reports.h b/include/reports/switch_reports.h index e0f919556..8bb955729 100644 --- a/include/reports/switch_reports.h +++ b/include/reports/switch_reports.h @@ -211,6 +211,42 @@ typedef struct uint8_t slider; } __attribute__((packed)) SwitchFestivalProGuitarLayer_Data_t; +// Festivals default mappings suck, so its easiest to set up custom mappings for that here +typedef struct +{ + uint8_t blue : 1; // y, triangle, yellow + uint8_t green : 1; // b, circle, red + uint8_t greenCymbal : 1; // a, cross, green + uint8_t blueCymbal : 1; // x, square, blue + + uint8_t kick2 : 1; // leftShoulder, orange, l1 + uint8_t kick : 1; // rightShoulder, spPedal, r1 + uint8_t l2 : 1; // l2 + uint8_t r2 : 1; // r2 + + uint8_t back : 1; // back, select + uint8_t start : 1; // start + uint8_t : 2; + + uint8_t guide : 1; // ps + uint8_t : 2; + + + // To make things easier, we use bitfields here, and then we map to a proper hat later + union + { + struct + { + uint8_t yellowCymbal : 1; // dpadUp + uint8_t yellow : 1; // dpadDown + uint8_t red : 1; // dpadLeft + uint8_t dpadRight : 1; // dpadRight + uint8_t : 4; + }; + uint8_t dpad; + }; +} __attribute__((packed)) SwitchFestivalProDrumsLayer_Data_t; + typedef struct { uint8_t y : 1; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 80fec966d..c883853ad 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -616,10 +616,12 @@ uint8_t handle_calibration_ps3(uint8_t previous, int32_t orig_val, int16_t min, uint8_t handle_calibration_ps4_xb1_tilt(uint8_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, int16_t deadzone) { int16_t ret = abs(handle_calibration_xbox(previous << 7, orig_val, min, max, center, deadzone, 0)) >> 7; - if (ret > 255) { + if (ret > 255) + { ret = 255; } - if (ret < 0) { + if (ret < 0) + { ret = 0; } return (uint8_t)(ret); @@ -3433,6 +3435,21 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu { if (!festival_gameplay_mode) { +#if DEVICE_TYPE_IS_DRUM + PS3GamepadDrum_Data_t *report = (PS3GamepadDrum_Data_t *)report_data; + memset(report, 0, sizeof(PS3GamepadDrum_Data_t)); + report->reportId = 1; + report->accelX = PS3_ACCEL_CENTER; + report->accelY = PS3_ACCEL_CENTER; + report->accelZ = PS3_ACCEL_CENTER; + report->gyro = PS3_ACCEL_CENTER; + report->leftStickX = PS3_STICK_CENTER; + report->leftStickY = PS3_STICK_CENTER; + report->rightStickX = PS3_STICK_CENTER; + report->rightStickY = PS3_STICK_CENTER; + TICK_PS3_WITHOUT_CAPTURE; + report_size = packet_size = sizeof(PS3GamepadDrum_Data_t); +#else PS3GamepadGuitar_Data_t *report = (PS3GamepadGuitar_Data_t *)report_data; memset(report, 0, sizeof(PS3GamepadGuitar_Data_t)); report->reportId = 1; @@ -3446,9 +3463,22 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->rightStickY = PS3_STICK_CENTER; TICK_PS3_WITHOUT_CAPTURE; report_size = packet_size = sizeof(PS3GamepadGuitar_Data_t); +#endif } else { + +#if DEVICE_TYPE_IS_DRUM + PS3FestivalProDrumLayer_Data_t *report = (PS3FestivalProDrumLayer_Data_t *)report_data; + memset(report, 0, sizeof(PS3FestivalProDrumLayer_Data_t)); + report->reportId = 0x01; + report->leftStickX = PS3_STICK_CENTER; + report->leftStickY = PS3_STICK_CENTER; + report->rightStickX = PS3_STICK_CENTER; + report->rightStickY = PS3_STICK_CENTER; + TICK_FESTIVAL; + report_size = packet_size = sizeof(PS3FestivalProDrumLayer_Data_t); +#else PS3FestivalProGuitarLayer_Data_t *report = (PS3FestivalProGuitarLayer_Data_t *)report_data; memset(report, 0, sizeof(PS3FestivalProGuitarLayer_Data_t)); report->reportId = 0x01; @@ -3458,6 +3488,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->rightStickY = PS3_STICK_CENTER; TICK_FESTIVAL; report_size = packet_size = sizeof(PS3FestivalProGuitarLayer_Data_t); +#endif } } #endif @@ -3528,6 +3559,18 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } else { +#if DEVICE_TYPE_IS_DRUM + + PC_FESTIVAL_REPORT *report = (PC_FESTIVAL_REPORT *)report_data; + report_size = packet_size = sizeof(PC_FESTIVAL_REPORT); + memset(report, 0, sizeof(PC_FESTIVAL_REPORT)); + report->reportId = 1; + TICK_FESTIVAL; + + asm volatile("" :: + : "memory"); + report->dpad = (report->dpad & 0xf) > 0x0a ? 0x08 : dpad_bindings[report->dpad]; +#else PC_FESTIVAL_REPORT *report = (PC_FESTIVAL_REPORT *)report_data; report_size = packet_size = sizeof(PC_FESTIVAL_REPORT); memset(report, 0, sizeof(PC_FESTIVAL_REPORT)); @@ -3540,6 +3583,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu asm volatile("" :: : "memory"); report->dpad = (report->dpad & 0xf) > 0x0a ? 0x08 : dpad_bindings[report->dpad]; +#endif } #endif } @@ -3770,8 +3814,13 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } else { +#if DEVICE_TYPE_IS_DRUM + SwitchFestivalProDrumsLayer_Data_t *report = (SwitchFestivalProDrumsLayer_Data_t *)report_data; + TICK_FESTIVAL; +#else SwitchFestivalProGuitarLayer_Data_t *report = (SwitchFestivalProGuitarLayer_Data_t *)report_data; TICK_FESTIVAL; +#endif asm volatile("" :: : "memory"); From edbbbef0cc57fe05997fb23fda5d73062bed9b73 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 18 Apr 2026 18:04:25 +1200 Subject: [PATCH 179/239] oops --- include/reports/pc_reports.h | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/include/reports/pc_reports.h b/include/reports/pc_reports.h index 4e91db2b1..0d8642415 100644 --- a/include/reports/pc_reports.h +++ b/include/reports/pc_reports.h @@ -248,6 +248,41 @@ typedef struct uint8_t slider; } __attribute__((packed)) FestivalProGuitarLayerGH_Data_t; +typedef struct +{ + uint8_t reportId; + uint8_t rightShoulder : 1; // a, cross, green + uint8_t leftShoulder : 1; // b, circle, red + uint8_t x : 1; // y, triangle, yellow + uint8_t y : 1; // x, square, blue + + uint8_t dpadUp : 1; // leftShoulder, orange, l1 + uint8_t dpadDown : 1; // rightShoulder + uint8_t whammy : 1; // l2 + uint8_t tilt : 1; // r2 + uint8_t : 2; + uint8_t back : 1; // back, select + uint8_t start : 1; // start + + uint8_t guide : 1; // ps + uint8_t : 2; + + // To make things easier, we use bitfields here, and then we map to a proper hat later + union { + struct { + uint8_t b : 1; // dpadUp + uint8_t dpadRight : 1; // dpadDown + uint8_t a : 1; // dpadLeft + uint8_t dpadLeft : 1; // dpadRight + uint8_t : 4; + }; + uint8_t dpad; + }; + + uint8_t unused[2]; + uint8_t slider; +} __attribute__((packed)) FestivalProGuitarLayerRB_Data_t; + typedef struct { uint8_t reportId; From 61a1eaf8dbbe3258589b8738d2bd27f1c1b38c2e Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 8 May 2026 12:47:22 +1200 Subject: [PATCH 180/239] support lis3dsh, sca7a20 --- include/accel.h | 3 ++ include/defines.h | 2 + src/shared/main/accel.cpp | 86 ++++++++++++++++++++++++++++----------- 3 files changed, 67 insertions(+), 24 deletions(-) diff --git a/include/accel.h b/include/accel.h index 2bb07227d..16b28d03a 100644 --- a/include/accel.h +++ b/include/accel.h @@ -13,6 +13,7 @@ extern "C" { #define LIS3DH_ADDRESS_2 0x19 #define LIS3DH_REG_CTRL1 0x20 #define LIS3DH_REG_CTRL4 0x23 +#define LIS3DH_REG_CTRL5 0x24 #define LIS3DH_REG_WHOAMI 0x0F #define LIS3DH_REG_OUT 0x28 | 0x80 // Set auto increment #define LIS3DH_REG_OUTADC1_L 0x08 | 0x80 @@ -22,6 +23,8 @@ extern "C" { #define LIS3DH_REG_OUTADC3_L 0x0C | 0x80 #define LIS3DH_REG_OUTADC3_H 0x0D | 0x80 #define LIS3DH_ID 0x33 +#define LIS3DSH_ID 0x3F +#define SC7A20_ID 0x11 #define LIS3DH_REG_TEMPCFG 0x1F #define MPU6050_ADDRESS 0x68 #define MPU6050_REG_ACCEL_OUT 0x3B diff --git a/include/defines.h b/include/defines.h index 306ada54f..d623458b8 100644 --- a/include/defines.h +++ b/include/defines.h @@ -8,6 +8,8 @@ #define ADXL345 1 #define LIS3DH 2 #define MPU6050 3 +#define SC7A20 4 +#define LIS3DSH 5 #define XINPUT_FLAGS_NO_NAV 0xFFFF #define XINPUT_FLAGS_NONE 0x0000 diff --git a/src/shared/main/accel.cpp b/src/shared/main/accel.cpp index eb9df5514..5c66af844 100644 --- a/src/shared/main/accel.cpp +++ b/src/shared/main/accel.cpp @@ -10,27 +10,46 @@ bool accel_found = false; uint8_t lis3dh_address = LIS3DH_ADDRESS; uint8_t type = NONE; #ifdef ACCEL_TWI_PORT -void init_lis3dh() { +void init_lis3dh() +{ uint8_t id = 0; lis3dh_address = LIS3DH_ADDRESS; twi_readFromPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_WHOAMI, 1, &id); - if (id != LIS3DH_ID) { + if (id != LIS3DH_ID && id != SC7A20_ID && id != LIS3DSH_ID) + { lis3dh_address = LIS3DH_ADDRESS_2; twi_readFromPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_WHOAMI, 1, &id); - if (id != LIS3DH_ID) { + if (id != LIS3DH_ID && id != SC7A20_ID && id != LIS3DSH_ID) + { return; } } - type = LIS3DH; accel_found = true; - twi_writeSingleToPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_CTRL1, 0b01110111); // enable all axis, set data rate to 4000hz - twi_writeSingleToPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_CTRL4, 0x88); // High res & BDU enabled - twi_writeSingleToPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_TEMPCFG, 0x80); // enable adc + if (id == SC7A20_ID) + { + type = SC7A20; + twi_writeSingleToPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_CTRL1, 0b01110111); // enable all axis, set data rate to 4000hz + twi_writeSingleToPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_CTRL4, 0x88); // High res & BDU enabled + } + else if (id == LIS3DSH_ID) + { + type = LIS3DSH; + twi_writeSingleToPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_CTRL1, 0b01111111); // enable all axis, BDU, set data rate to 4000hz + } + else + { + type = LIS3DH; + twi_writeSingleToPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_CTRL1, 0b01110111); // enable all axis, set data rate to 4000hz + twi_writeSingleToPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_CTRL4, 0x88); // High res & BDU enabled + twi_writeSingleToPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_TEMPCFG, 0x80); // enable adc + } } -void init_adxl() { +void init_adxl() +{ uint8_t id = 0; twi_readFromPointer(ACCEL_TWI_PORT, ADXL345_ADDRESS, ADXL345_REG_DEVID, 1, &id); - if (id != ADXL345_ID) { + if (id != ADXL345_ID) + { return; } type = ADXL345; @@ -38,10 +57,12 @@ void init_adxl() { twi_writeSingleToPointer(ACCEL_TWI_PORT, ADXL345_ADDRESS, ADXL345_POWER_CTL, 0x08); twi_writeSingleToPointer(ACCEL_TWI_PORT, ADXL345_ADDRESS, ADXL345_DATA_FORMAT, 0x0B); } -void init_mpu6050() { +void init_mpu6050() +{ uint8_t id = 0; twi_readFromPointer(ACCEL_TWI_PORT, MPU6050_ADDRESS, MPU6050_REG_WHO_AM_I, 1, &id); - if (id != MPU6050_ID && id != MPU6050_ID2) { + if (id != MPU6050_ID && id != MPU6050_ID2) + { return; } type = MPU6050; @@ -51,33 +72,50 @@ void init_mpu6050() { id &= ~(1 << 6); twi_writeSingleToPointer(ACCEL_TWI_PORT, MPU6050_ADDRESS, MPU6050_REG_PWR_MGMT_1, id); } -void init_accel() { +void init_accel() +{ init_mpu6050(); init_lis3dh(); init_adxl(); } -void tick_accel() { - if (!accel_found) { +void tick_accel() +{ + if (!accel_found) + { init_accel(); return; } int16_t raw[3]; - if (type == LIS3DH) { - accel_found = twi_readFromPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_OUT, 6, (uint8_t*)raw); - accel_found = twi_readFromPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_OUTADC1_L, sizeof(accel_adc), (uint8_t*)accel_adc); - for (int i = 0; i < 3; i++) { + if (type == LIS3DH) + { + accel_found = twi_readFromPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_OUT, 6, (uint8_t *)raw); + accel_found = twi_readFromPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_OUTADC1_L, sizeof(accel_adc), (uint8_t *)accel_adc); + for (int i = 0; i < 3; i++) + { + filtered[i] = (raw[i]) * currentLowPassAlpha + (filtered[i] * (1.0 - currentLowPassAlpha)); + } + } + if (type == SC7A20 || type == LIS3DSH) + { + accel_found = twi_readFromPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_OUT, 6, (uint8_t *)raw); + for (int i = 0; i < 3; i++) + { filtered[i] = (raw[i]) * currentLowPassAlpha + (filtered[i] * (1.0 - currentLowPassAlpha)); } } - if (type == ADXL345) { - accel_found = twi_readFromPointer(ACCEL_TWI_PORT, ADXL345_ADDRESS, ADXL345_DATAX0, 6, (uint8_t*)raw); - for (int i = 0; i < 3; i++) { + if (type == ADXL345) + { + accel_found = twi_readFromPointer(ACCEL_TWI_PORT, ADXL345_ADDRESS, ADXL345_DATAX0, 6, (uint8_t *)raw); + for (int i = 0; i < 3; i++) + { filtered[i] = (raw[i] * 64) * currentLowPassAlpha + (filtered[i] * (1.0 - currentLowPassAlpha)); } } - if (type == MPU6050) { - accel_found = twi_readFromPointer(ACCEL_TWI_PORT, MPU6050_ADDRESS, MPU6050_REG_ACCEL_OUT, 6, (uint8_t*)raw); - for (int i = 0; i < 3; i++) { + if (type == MPU6050) + { + accel_found = twi_readFromPointer(ACCEL_TWI_PORT, MPU6050_ADDRESS, MPU6050_REG_ACCEL_OUT, 6, (uint8_t *)raw); + for (int i = 0; i < 3; i++) + { filtered[i] = (raw[i]) * currentLowPassAlpha + (filtered[i] * (1.0 - currentLowPassAlpha)); } } From 2eb1ae8723ba631d42de2871afe6286c0a9bdd11 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 14 May 2026 08:20:28 +1200 Subject: [PATCH 181/239] fix gh + fest --- include/config.h | 2 +- include/reports/pc_reports.h | 31 +++++++++++++++++++++++++++++++ include/reports/ps3_reports.h | 4 +++- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/include/config.h b/include/config.h index 53562d7f1..edeeeadbf 100644 --- a/include/config.h +++ b/include/config.h @@ -439,7 +439,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define XINPUT_REPORT XInputGuitarHeroDrums_Data_t #define XBOX_ONE_REPORT XboxOneRockBandDrums_Data_t #define PC_REPORT PCGuitarHeroDrums_Data_t -#define PC_FESTIVAL_REPORT FestivalProGuitarLayerGH_Data_t +#define PC_FESTIVAL_REPORT FestivalProDrumsLayerGH_Data_t #define PS2_REPORT PS2Gamepad_Data_t #define PS3_REPORT PS3GuitarHeroDrums_Data_t #define PS4_REPORT PS4RockBandDrums_Data_t diff --git a/include/reports/pc_reports.h b/include/reports/pc_reports.h index 0d8642415..95e3b9fc6 100644 --- a/include/reports/pc_reports.h +++ b/include/reports/pc_reports.h @@ -315,6 +315,37 @@ typedef struct }; } __attribute__((packed)) FestivalProDrumsLayerRB_Data_t; +typedef struct +{ + uint8_t reportId; + uint8_t greenCymbal : 1; // a, cross, green + uint8_t green : 1; // b, circle, red + uint8_t blueCymbal : 1; // y, triangle, yellow + uint8_t blue : 1; // x, square, blue + + uint8_t kick2 : 1; // leftShoulder, orange, l1 + uint8_t kick : 1; // rightShoulder + uint8_t l2 : 1; // l2 + uint8_t r2 : 1; // r2 + uint8_t : 2; + uint8_t back : 1; // back, select + uint8_t start : 1; // start + + uint8_t guide : 1; // ps + uint8_t : 2; + + // To make things easier, we use bitfields here, and then we map to a proper hat later + union { + struct { + uint8_t yellowCymbal : 1; // dpadUp + uint8_t yellow : 1; // dpadDown + uint8_t red : 1; // dpadLeft + uint8_t dpadRight : 1; // dpadRight + uint8_t : 4; + }; + uint8_t dpad; + }; +} __attribute__((packed)) FestivalProDrumsLayerGH_Data_t; typedef struct { uint8_t reportId; diff --git a/include/reports/ps3_reports.h b/include/reports/ps3_reports.h index 1c3a87bfe..f17f05c9c 100644 --- a/include/reports/ps3_reports.h +++ b/include/reports/ps3_reports.h @@ -193,7 +193,9 @@ typedef struct { uint8_t blueCymbalVelocity; uint8_t yellowCymbalVelocity; uint8_t greenCymbalVelocity; - uint8_t padding_4[14]; + uint8_t orangeVelocity; + uint8_t kickVelocity; + uint8_t padding_4[12]; // Each of the following are 10 bits in accuracy // Centered/neutral state is nominally 0x0200, actual values may vary uint16_t accelX; // Left/right acceleration (roll) From f28cb983227dedcb949f303cad7faffd045fc55e Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 14 May 2026 16:14:25 +1200 Subject: [PATCH 182/239] ignore alternate interface --- src/pico/xinput_host.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pico/xinput_host.cpp b/src/pico/xinput_host.cpp index ad1862692..0c5dadd54 100644 --- a/src/pico/xinput_host.cpp +++ b/src/pico/xinput_host.cpp @@ -199,6 +199,7 @@ uint16_t xinputh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t co return false; } TU_VERIFY(0x58 == desc_itf->bInterfaceClass || TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass || TUSB_CLASS_HID == desc_itf->bInterfaceClass, 0); + TU_VERIFY(desc_itf->bAlternateSetting == 0, 0); xinputh_interface_t *p_xinput = NULL; uint8_t i = 0; for (; i < CFG_TUH_XINPUT; i++) From 13a7c6df04ce6f922eb31c5332994e40c4a6ab06 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 15 May 2026 11:01:25 +1200 Subject: [PATCH 183/239] only send player led changes to connected controllers --- src/shared/hid/hid.cpp | 1271 +++++++++++++++++++++++----------------- 1 file changed, 733 insertions(+), 538 deletions(-) diff --git a/src/shared/hid/hid.cpp b/src/shared/hid/hid.cpp index e1adf86b2..b474de498 100644 --- a/src/shared/hid/hid.cpp +++ b/src/shared/hid/hid.cpp @@ -22,20 +22,20 @@ const PROGMEM char board[] = ARDWIINO_BOARD; const PROGMEM char f_cpu_descriptor_str[] = STR(F_CPU); uint8_t xbox_players[] = { - 0, // 0x00 All off - 0, // 0x01 All blinking - 1, // 0x02 1 flashes, then on - 2, // 0x03 2 flashes, then on - 3, // 0x04 3 flashes, then on - 4, // 0x05 4 flashes, then on - 1, // 0x06 1 on - 2, // 0x07 2 on - 3, // 0x08 3 on - 4, // 0x09 4 on - 0, // 0x0A Rotating (e.g. 1-2-4-3) - 0, // 0x0B Blinking* - 0, // 0x0C Slow blinking* - 0, // 0x0D Alternating (e.g. 1+4-2+3), then back to previous* + 0, // 0x00 All off + 0, // 0x01 All blinking + 1, // 0x02 1 flashes, then on + 2, // 0x03 2 flashes, then on + 3, // 0x04 3 flashes, then on + 4, // 0x05 4 flashes, then on + 1, // 0x06 1 on + 2, // 0x07 2 on + 3, // 0x08 3 on + 4, // 0x09 4 on + 0, // 0x0A Rotating (e.g. 1-2-4-3) + 0, // 0x0B Blinking* + 0, // 0x0C Slow blinking* + 0, // 0x0D Alternating (e.g. 1+4-2+3), then back to previous* }; static const int ps4_colors[4][3] = { @@ -46,10 +46,10 @@ static const int ps4_colors[4][3] = { }; uint8_t stage_kit_millis[] = { 0, - 75, // Fastest - 100, // Fast - 125, // Medium - 150, // Slow + 75, // Fastest + 100, // Fast + 125, // Medium + 150, // Slow }; uint8_t current_player = 0xFF; uint8_t strobe_delay = 0; @@ -234,129 +234,166 @@ ps3_output_report ps3_output_reports[8] = { }}; #endif -void handle_auth_led(void) { +void handle_auth_led(void) +{ authentication_successful(); HANDLE_AUTH_LED; } -void handle_player_leds(uint8_t player) { - if (player == current_player) return; - if (player == 0) { +void handle_player_leds(uint8_t player) +{ + if (player == current_player) + return; + if (player == 0) + { player = current_player; } - if (player == 0xFF) { + if (player == 0xFF) + { player = 1; } current_player = player; HANDLE_PLAYER_LED; #ifdef INPUT_USB_HOST USB_Device_Type_t type; - for (uint8_t i = 0; i < get_usb_host_device_count(); i++) { + for (uint8_t i = 0; i < get_usb_host_device_count(); i++) + { type = get_usb_host_device_type(i); - switch (type.console_type) { - case PS3: { - // Only actual ds3s support this - if (type.sub_type == GAMEPAD) { - ps3_output_report *report = &ps3_output_reports[i]; - report->leds_bitmap |= _BV(player); - transfer_with_usb_controller(type, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0201, sizeof(ps3_output_report), (uint8_t *)report, NULL); - // send_report_to_controller(type.dev_addr, (uint8_t *)report, sizeof(report)); - } - return; - } - case PS4: { - // Only actual ds4s support the lightbar - if (type.sub_type == GAMEPAD) { - ps4_output_report *report = &ps4_output_reports[i]; - report->lightbar_red = ps4_colors[player - 1][0]; - report->lightbar_green = ps4_colors[player - 1][1]; - report->lightbar_blue = ps4_colors[player - 1][2]; - transfer_with_usb_controller(type, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0205, sizeof(ps4_output_report), (uint8_t *)report, NULL); - } - return; + switch (type.console_type) + { + case PS3: + { + // Only actual ds3s support this + if (type.sub_type == GAMEPAD) + { + ps3_output_report *report = &ps3_output_reports[i]; + report->leds_bitmap |= _BV(player); + transfer_with_usb_controller(type, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0201, sizeof(ps3_output_report), (uint8_t *)report, NULL); } - case XBOX360: { - XInputLEDReport_t report = { - rid : XBOX_LED_ID, - rsize : sizeof(XInputLEDReport_t), - led : (uint8_t)(player + LED_ONE - 1) - }; - send_report_to_controller(type.dev_addr, type.instance, (uint8_t *)&report, sizeof(report)); - return; + continue; + } + case PS4: + { + // Only actual ds4s support the lightbar + if (type.sub_type == GAMEPAD) + { + ps4_output_report *report = &ps4_output_reports[i]; + report->lightbar_red = ps4_colors[player - 1][0]; + report->lightbar_green = ps4_colors[player - 1][1]; + report->lightbar_blue = ps4_colors[player - 1][2]; + transfer_with_usb_controller(type, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0205, sizeof(ps4_output_report), (uint8_t *)report, NULL); } - case XBOX360_W: { + continue; + } + case XBOX360: + { + XInputLEDReport_t report = { + rid : XBOX_LED_ID, + rsize : sizeof(XInputLEDReport_t), + led : (uint8_t)(player + LED_ONE - 1) + }; + send_report_to_controller(type.dev_addr, type.instance, (uint8_t *)&report, sizeof(report)); + continue; + } + case XBOX360_W: + { + // Don't send anything if the controller isnt connected + if (type.sub_type != UNKNOWN) + { uint8_t report[] = {0x00, 0x00, 0x08, (uint8_t)(0x40 | (player + LED_ONE - 1)), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; send_report_to_controller(type.dev_addr, type.instance, report, sizeof(report)); - return; } + continue; + } } } #endif } // PS3 controllers and other controllers use different LED bitmasks #if DEVICE_TYPE == GAMEPAD -void handle_player_leds_ps3(uint8_t player_mask) { - if (player_mask == 2) { +void handle_player_leds_ps3(uint8_t player_mask) +{ + if (player_mask == 2) + { handle_player_leds(1); } - if (player_mask == 4) { + if (player_mask == 4) + { handle_player_leds(2); } - if (player_mask == 8) { + if (player_mask == 8) + { handle_player_leds(3); } - if (player_mask == 16) { + if (player_mask == 16) + { handle_player_leds(4); } - if (player_mask == 18) { + if (player_mask == 18) + { handle_player_leds(5); } - if (player_mask == 20) { + if (player_mask == 20) + { handle_player_leds(6); } - if (player_mask == 24) { + if (player_mask == 24) + { handle_player_leds(7); } } #else -void handle_player_leds_ps3(uint8_t player_mask) { - if (player_mask == 1) { +void handle_player_leds_ps3(uint8_t player_mask) +{ + if (player_mask == 1) + { handle_player_leds(1); } - if (player_mask == 2) { + if (player_mask == 2) + { handle_player_leds(2); } - if (player_mask == 4) { + if (player_mask == 4) + { handle_player_leds(3); } - if (player_mask == 8) { + if (player_mask == 8) + { handle_player_leds(4); } - if (player_mask == 9) { + if (player_mask == 9) + { handle_player_leds(5); } - if (player_mask == 10) { + if (player_mask == 10) + { handle_player_leds(6); } - if (player_mask == 12) { + if (player_mask == 12) + { handle_player_leds(7); } } #endif -void handle_lightbar_leds(uint8_t red, uint8_t green, uint8_t blue) { +void handle_lightbar_leds(uint8_t red, uint8_t green, uint8_t blue) +{ HANDLE_LIGHTBAR_LED; // We know the default lightbar colours that sony uses so we can extract a player number from that. - for (int i = 0; i < 4; i++) { - if (red == ps4_colors[i][0] && green == ps4_colors[i][1] && blue == ps4_colors[i][2]) { + for (int i = 0; i < 4; i++) + { + if (red == ps4_colors[i][0] && green == ps4_colors[i][1] && blue == ps4_colors[i][2]) + { handle_player_leds(i + 1); } } } -void handle_rumble(uint8_t rumble_left, uint8_t rumble_right) { +void handle_rumble(uint8_t rumble_left, uint8_t rumble_right) +{ // printf("Rumble: %d %d\r\n", rumble_left, rumble_right); HANDLE_RUMBLE; #ifdef HANDLE_LED_RUMBLE_OFF - if (rumble_left == 0x00 && rumble_right == 0xFF) { + if (rumble_left == 0x00 && rumble_right == 0xFF) + { last_strobe = 0; HANDLE_LED_RUMBLE_OFF; } @@ -364,64 +401,76 @@ void handle_rumble(uint8_t rumble_left, uint8_t rumble_right) { #if defined(INPUT_USB_HOST) && DEVICE_TYPE == GAMEPAD USB_Device_Type_t type; - for (uint8_t i = 0; i < get_usb_host_device_count(); i++) { + for (uint8_t i = 0; i < get_usb_host_device_count(); i++) + { type = get_usb_host_device_type(i); - if (type.sub_type != GAMEPAD && type.sub_type != XINPUT_WHEEL) continue; - switch (type.console_type) { - case PS3: { - ps3_output_report *report = &ps3_output_reports[i]; - report->rumble.left_motor_force = rumble_left; - report->rumble.right_motor_on = rumble_right != 0; - transfer_with_usb_controller(type, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0201, sizeof(ps3_output_report), (uint8_t *)report, NULL); - return; - } - case PS4: { - ps4_output_report *report = &ps4_output_reports[i]; - report->motor_left = rumble_left; - report->motor_right = rumble_right != 0; - send_report_to_controller(type.dev_addr, type.instance, (uint8_t *)report, sizeof(ps4_output_report)); - return; - } - case OG_XBOX: { - uint8_t rumble_packet[] = {0x00, 0x06, 0x00, rumble_left, 0x00, rumble_right}; - send_report_to_controller(type.dev_addr, type.instance, rumble_packet, sizeof(rumble_packet)); - return; - } - case XBOX360: { - XInputRumbleReport_t report = { - rid : XBOX_RUMBLE_ID, - rsize : sizeof(XInputRumbleReport_t), - leftRumble : rumble_left, - rightRumble : rumble_right - }; - send_report_to_controller(type.dev_addr, type.instance, (uint8_t *)&report, sizeof(report)); - return; - } - case XBOX360_W: { - uint8_t rumble_packet[] = {0x00, 0x01, 0x0f, 0xc0, 0x00, rumble_left, rumble_right, 0x00, 0x00, 0x00, 0x00, 0x00}; - send_report_to_controller(type.dev_addr, type.instance, rumble_packet, sizeof(rumble_packet)); - return; - } - case XBOXONE: { - GipRumble_t report; - GipRumble_t *packet = &report; - GIP_HEADER(packet, GIP_CMD_RUMBLE, true, xone_sequences[i]++); - report.leftMotor = rumble_left; - report.rightMotor = rumble_right; - if (xone_sequences[i] == 0) { - xone_sequences[i] = 1; - } - send_report_to_controller(type.dev_addr, type.instance, (uint8_t *)&report, sizeof(report)); + if (type.sub_type != GAMEPAD && type.sub_type != XINPUT_WHEEL) + continue; + switch (type.console_type) + { + case PS3: + { + ps3_output_report *report = &ps3_output_reports[i]; + report->rumble.left_motor_force = rumble_left; + report->rumble.right_motor_on = rumble_right != 0; + transfer_with_usb_controller(type, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0201, sizeof(ps3_output_report), (uint8_t *)report, NULL); + return; + } + case PS4: + { + ps4_output_report *report = &ps4_output_reports[i]; + report->motor_left = rumble_left; + report->motor_right = rumble_right != 0; + send_report_to_controller(type.dev_addr, type.instance, (uint8_t *)report, sizeof(ps4_output_report)); + return; + } + case OG_XBOX: + { + uint8_t rumble_packet[] = {0x00, 0x06, 0x00, rumble_left, 0x00, rumble_right}; + send_report_to_controller(type.dev_addr, type.instance, rumble_packet, sizeof(rumble_packet)); + return; + } + case XBOX360: + { + XInputRumbleReport_t report = { + rid : XBOX_RUMBLE_ID, + rsize : sizeof(XInputRumbleReport_t), + leftRumble : rumble_left, + rightRumble : rumble_right + }; + send_report_to_controller(type.dev_addr, type.instance, (uint8_t *)&report, sizeof(report)); + return; + } + case XBOX360_W: + { + uint8_t rumble_packet[] = {0x00, 0x01, 0x0f, 0xc0, 0x00, rumble_left, rumble_right, 0x00, 0x00, 0x00, 0x00, 0x00}; + send_report_to_controller(type.dev_addr, type.instance, rumble_packet, sizeof(rumble_packet)); + return; + } + case XBOXONE: + { + GipRumble_t report; + GipRumble_t *packet = &report; + GIP_HEADER(packet, GIP_CMD_RUMBLE, true, xone_sequences[i]++); + report.leftMotor = rumble_left; + report.rightMotor = rumble_right; + if (xone_sequences[i] == 0) + { + xone_sequences[i] = 1; } + send_report_to_controller(type.dev_addr, type.instance, (uint8_t *)&report, sizeof(report)); + } } } #endif #if defined(INPUT_USB_HOST) && DEVICE_TYPE == STAGE_KIT USB_Device_Type_t type; // Only xinput has stage kit - for (uint8_t i = 0; i < get_usb_host_device_count(); i++) { + for (uint8_t i = 0; i < get_usb_host_device_count(); i++) + { type = get_usb_host_device_type(i); - if (type.sub_type != STAGE_KIT) continue; + if (type.sub_type != STAGE_KIT) + continue; XInputRumbleReport_t report = { rid : XBOX_RUMBLE_ID, rsize : sizeof(XInputRumbleReport_t), @@ -433,114 +482,124 @@ void handle_rumble(uint8_t rumble_left, uint8_t rumble_right) { } #endif #if DEVICE_TYPE == DJ_HERO_TURNTABLE - if (rumble_right == RUMBLE_SANTROLLER_EUPHORIA_LED) { + if (rumble_right == RUMBLE_SANTROLLER_EUPHORIA_LED) + { lastEuphoriaLed = rumble_left != 0; } #endif #if defined(INPUT_USB_HOST) && DEVICE_TYPE == DJ_HERO_TURNTABLE USB_Device_Type_t type; // Only ps3 and xinput have dj turntables - for (uint8_t i = 0; i < get_usb_host_device_count(); i++) { + for (uint8_t i = 0; i < get_usb_host_device_count(); i++) + { type = get_usb_host_device_type(i); - if (type.sub_type != DJ_HERO_TURNTABLE) continue; - switch (type.console_type) { - case XBOX360: { - XInputRumbleReport_t report = { - rid : XBOX_RUMBLE_ID, - rsize : sizeof(XInputRumbleReport_t), - leftRumble : rumble_left, - rightRumble : rumble_right - }; - send_report_to_controller(type.dev_addr, type.instance, (uint8_t *)&report, sizeof(report)); - return; - } - case PS3: { - ps3_turntable_output_report_t report = { - outputType : DJ_LED_ID, - unknown1 : 0x01, - enable : rumble_left != 0, - padding : {0} - }; - transfer_with_usb_controller(type, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0200, sizeof(report), (uint8_t *)&report, NULL); - return; - } + if (type.sub_type != DJ_HERO_TURNTABLE) + continue; + switch (type.console_type) + { + case XBOX360: + { + XInputRumbleReport_t report = { + rid : XBOX_RUMBLE_ID, + rsize : sizeof(XInputRumbleReport_t), + leftRumble : rumble_left, + rightRumble : rumble_right + }; + send_report_to_controller(type.dev_addr, type.instance, (uint8_t *)&report, sizeof(report)); + return; + } + case PS3: + { + ps3_turntable_output_report_t report = { + outputType : DJ_LED_ID, + unknown1 : 0x01, + enable : rumble_left != 0, + padding : {0} + }; + transfer_with_usb_controller(type, (USB_SETUP_HOST_TO_DEVICE | USB_SETUP_RECIPIENT_INTERFACE | USB_SETUP_TYPE_CLASS), HID_REQUEST_SET_REPORT, 0x0200, sizeof(report), (uint8_t *)&report, NULL); + return; + } } } #endif } -void handle_rumble(PCStageKitOutputWithoutReportId_Data_t *report) { +void handle_rumble(PCStageKitOutputWithoutReportId_Data_t *report) +{ HANDLE_RUMBLE_EXPANDED; } -void handle_keyboard_leds(uint8_t leds) { +void handle_keyboard_leds(uint8_t leds) +{ HANDLE_KEYBOARD_LED; } #if BLUETOOTH_RX -void handle_bt_rumble(uint8_t rumble_left, uint8_t rumble_right) { - switch (rumble_right) { - case RUMBLE_STAGEKIT_FOG_ON: - stage_kit_report.report.stageKitFog = true; - break; - case RUMBLE_STAGEKIT_FOG_OFF: - stage_kit_report.report.stageKitFog = false; - break; - case RUMBLE_STAGEKIT_SLOW_STROBE: - stage_kit_report.report.stageKitStrobe = 1; - break; - case RUMBLE_STAGEKIT_MEDIUM_STROBE: - stage_kit_report.report.stageKitStrobe = 2; - break; - case RUMBLE_STAGEKIT_FAST_STROBE: - stage_kit_report.report.stageKitStrobe = 3; - break; - case RUMBLE_STAGEKIT_FASTEST_STROBE: - stage_kit_report.report.stageKitStrobe = 4; - break; - case RUMBLE_STAGEKIT_NO_STROBE: - stage_kit_report.report.stageKitStrobe = 0; - break; - case RUMBLE_STAGEKIT_ALLOFF: - stage_kit_report.report.stageKitFog = false; - stage_kit_report.report.stageKitStrobe = 0; - stage_kit_report.report.stageKitBlue = 0; - stage_kit_report.report.stageKitGreen = 0; - stage_kit_report.report.stageKitYellow = 0; - stage_kit_report.report.stageKitRed = 0; - break; - case RUMBLE_STAGEKIT_BLUE: - stage_kit_report.report.stageKitBlue = rumble_left; - break; - case RUMBLE_STAGEKIT_GREEN: - stage_kit_report.report.stageKitGreen = rumble_left; - break; - case RUMBLE_STAGEKIT_YELLOW: - stage_kit_report.report.stageKitYellow = rumble_left; - break; - case RUMBLE_STAGEKIT_RED: - stage_kit_report.report.stageKitRed = rumble_left; - break; - case RUMBLE_SANTROLLER_NOTE_MISS: - stage_kit_report.report.noteMiss = rumble_left; - break; - case RUMBLE_SANTROLLER_MULTIPLIER: - stage_kit_report.report.multiplier = rumble_left; - break; - case RUMBLE_SANTROLLER_SOLO: - stage_kit_report.report.soloActive = rumble_left; - break; - case RUMBLE_SANTROLLER_STAR_POWER_ACTIVE: - stage_kit_report.report.starPowerActive = rumble_left; - break; - case RUMBLE_SANTROLLER_STAR_POWER_FILL: - stage_kit_report.report.starPowerState = rumble_left; - break; - case RUMBLE_SANTROLLER_NOTE_HIT: - stage_kit_report.report.noteHitRaw = rumble_left; - break; +void handle_bt_rumble(uint8_t rumble_left, uint8_t rumble_right) +{ + switch (rumble_right) + { + case RUMBLE_STAGEKIT_FOG_ON: + stage_kit_report.report.stageKitFog = true; + break; + case RUMBLE_STAGEKIT_FOG_OFF: + stage_kit_report.report.stageKitFog = false; + break; + case RUMBLE_STAGEKIT_SLOW_STROBE: + stage_kit_report.report.stageKitStrobe = 1; + break; + case RUMBLE_STAGEKIT_MEDIUM_STROBE: + stage_kit_report.report.stageKitStrobe = 2; + break; + case RUMBLE_STAGEKIT_FAST_STROBE: + stage_kit_report.report.stageKitStrobe = 3; + break; + case RUMBLE_STAGEKIT_FASTEST_STROBE: + stage_kit_report.report.stageKitStrobe = 4; + break; + case RUMBLE_STAGEKIT_NO_STROBE: + stage_kit_report.report.stageKitStrobe = 0; + break; + case RUMBLE_STAGEKIT_ALLOFF: + stage_kit_report.report.stageKitFog = false; + stage_kit_report.report.stageKitStrobe = 0; + stage_kit_report.report.stageKitBlue = 0; + stage_kit_report.report.stageKitGreen = 0; + stage_kit_report.report.stageKitYellow = 0; + stage_kit_report.report.stageKitRed = 0; + break; + case RUMBLE_STAGEKIT_BLUE: + stage_kit_report.report.stageKitBlue = rumble_left; + break; + case RUMBLE_STAGEKIT_GREEN: + stage_kit_report.report.stageKitGreen = rumble_left; + break; + case RUMBLE_STAGEKIT_YELLOW: + stage_kit_report.report.stageKitYellow = rumble_left; + break; + case RUMBLE_STAGEKIT_RED: + stage_kit_report.report.stageKitRed = rumble_left; + break; + case RUMBLE_SANTROLLER_NOTE_MISS: + stage_kit_report.report.noteMiss = rumble_left; + break; + case RUMBLE_SANTROLLER_MULTIPLIER: + stage_kit_report.report.multiplier = rumble_left; + break; + case RUMBLE_SANTROLLER_SOLO: + stage_kit_report.report.soloActive = rumble_left; + break; + case RUMBLE_SANTROLLER_STAR_POWER_ACTIVE: + stage_kit_report.report.starPowerActive = rumble_left; + break; + case RUMBLE_SANTROLLER_STAR_POWER_FILL: + stage_kit_report.report.starPowerState = rumble_left; + break; + case RUMBLE_SANTROLLER_NOTE_HIT: + stage_kit_report.report.noteHitRaw = rumble_left; + break; #if DEVICE_TYPE == DJ_HERO_TURNTABLE - case RUMBLE_SANTROLLER_EUPHORIA_LED: - stage_kit_report.report.euphoriaBrightness = rumble_left; - break; + case RUMBLE_SANTROLLER_EUPHORIA_LED: + stage_kit_report.report.euphoriaBrightness = rumble_left; + break; #endif } stage_kit_report.reportId = PS3_RUMBLE_ID; @@ -549,7 +608,8 @@ void handle_bt_rumble(uint8_t rumble_left, uint8_t rumble_right) { } #endif -void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_t report_id) { +void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_t report_id) +{ // for (int i = 0; i < len; i++) { // printf("%02x, ", data[i]); // } @@ -559,8 +619,10 @@ void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_ // portal_state = 1; // } // } - if (consoleType == ARCADE) { - if (data[0] == 0x03) { + if (consoleType == ARCADE) + { + if (data[0] == 0x03) + { // packet sends 0 for left and 1 for right, hid report uses 1 for left and 2 for right setArcadeSide(data[1] + 1); } @@ -571,37 +633,48 @@ void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_ #endif uint8_t id = data[0]; #if defined(INPUT_USB_HOST) - for (uint8_t i = 0; i < get_usb_host_device_count(); i++) { + for (uint8_t i = 0; i < get_usb_host_device_count(); i++) + { USB_Device_Type_t type = get_usb_host_device_type(i); - if (type.console_type != SANTROLLER) continue; + if (type.console_type != SANTROLLER) + continue; // Convert xinput payloads to their hid counterparts and send - if ((consoleType == XBOX360 || consoleType == WINDOWS) && report_id != BLUETOOTH_REPORT) { + if ((consoleType == XBOX360 || consoleType == WINDOWS) && report_id != BLUETOOTH_REPORT) + { uint8_t data_hid[8] = {0}; data_hid[0] = PS3_REPORT_ID; - if (id == XBOX_LED_ID) { + if (id == XBOX_LED_ID) + { uint8_t led = data[2]; uint8_t player = xbox_players[led]; - if (player) { + if (player) + { data_hid[1] = PS3_LED_ID; data_hid[3] = 1 << player; send_report_to_controller(type.dev_addr, type.instance, (uint8_t *)&data_hid, sizeof(data_hid)); } - - } else if (id == XBOX_RUMBLE_ID) { + } + else if (id == XBOX_RUMBLE_ID) + { data_hid[1] = SANTROLLER_LED_ID; data_hid[2] = data[3]; data_hid[3] = data[4]; send_report_to_controller(type.dev_addr, type.instance, (uint8_t *)&data_hid, sizeof(data_hid)); } - } else if ((consoleType == XBOXONE) && report_id != BLUETOOTH_REPORT) { - if (xbox_one_state == Ready) { + } + else if ((consoleType == XBOXONE) && report_id != BLUETOOTH_REPORT) + { + if (xbox_one_state == Ready) + { uint8_t data_hid[8] = {0}; data_hid[0] = PS3_REPORT_ID; // Live guitar is a bit special, so handle it here #if DEVICE_TYPE == LIVE_GUITAR - if (id == GHL_HID_OUTPUT) { + if (id == GHL_HID_OUTPUT) + { uint8_t sub_id = data[1]; - if (sub_id == PS3_RUMBLE_ID) { + if (sub_id == PS3_RUMBLE_ID) + { uint8_t player = (data[3] & 0x0F); data_hid[1] = PS3_RUMBLE_ID; data_hid[3] = 1 << player; @@ -609,7 +682,8 @@ void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_ } } #endif - if (id == GIP_CMD_RUMBLE) { + if (id == GIP_CMD_RUMBLE) + { GipRumble_t *rumble = (GipRumble_t *)data; data_hid[1] = SANTROLLER_LED_ID; data_hid[2] = rumble->leftMotor; @@ -617,7 +691,9 @@ void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_ send_report_to_controller(type.dev_addr, type.instance, (uint8_t *)&data_hid, sizeof(data_hid)); } } - } else { + } + else + { // Already a hid payload, send it as is send_report_to_controller(type.dev_addr, type.instance, data, len); } @@ -625,20 +701,24 @@ void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_ #endif #if BLUETOOTH_RX // BT uses HID, so convert XInput based reports to HID before sending them over BT - if (consoleType == XBOX360 || consoleType == WINDOWS) { + if (consoleType == XBOX360 || consoleType == WINDOWS) + { uint8_t data_hid[8] = {0}; data_hid[0] = PS3_REPORT_ID; - if (id == XBOX_LED_ID) { + if (id == XBOX_LED_ID) + { uint8_t led = data[2]; uint8_t player = xbox_players[led]; - if (player) { + if (player) + { handle_player_leds(player); data_hid[1] = PS3_RUMBLE_ID; data_hid[3] = 1 << player; bt_set_report(data_hid, 8, reportType, report_id); } - - } else if (id == XBOX_RUMBLE_ID) { + } + else if (id == XBOX_RUMBLE_ID) + { #if DEVICE_TYPE == GAMEPAD data_hid[1] = SANTROLLER_LED_ID; data_hid[2] = data[3]; @@ -648,17 +728,24 @@ void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_ handle_bt_rumble(data[3], data[4]); #endif } - } else { + } + else + { #if DEVICE_TYPE == GAMEPAD bt_set_report(data, len, reportType, report_id); #else // Convert rumble based reports to combined reports - if (id == SANTROLLER_LED_ID) { + if (id == SANTROLLER_LED_ID) + { handle_bt_rumble(data[1], data[2]); - } else if (id == PS3_REPORT_ID && data[1] == SANTROLLER_LED_ID) { + } + else if (id == PS3_REPORT_ID && data[1] == SANTROLLER_LED_ID) + { handle_bt_rumble(data[2], data[3]); // Pass combined reports directly over bt - } else if (id == SANTROLLER_LED_EXPANDED_ID || (id == PS3_REPORT_ID && data[1] == SANTROLLER_LED_EXPANDED_ID)) { + } + else if (id == SANTROLLER_LED_EXPANDED_ID || (id == PS3_REPORT_ID && data[1] == SANTROLLER_LED_EXPANDED_ID)) + { bt_set_report(data, len, reportType, report_id); } #endif @@ -667,451 +754,559 @@ void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_ #endif // Handle Xbox 360 LEDs and rumble // Handle XBOX One Auth - if ((consoleType == XBOXONE) && report_id != BLUETOOTH_REPORT) { - if (xbox_one_state == WaitingDesc1) { + if ((consoleType == XBOXONE) && report_id != BLUETOOTH_REPORT) + { + if (xbox_one_state == WaitingDesc1) + { xbox_one_state = IdentDesc1; - } else if (xbox_one_state == WaitingDesc) { + } + else if (xbox_one_state == WaitingDesc) + { xbox_one_state = IdentDesc; - } else if (xbox_one_state == WaitingDescEnd) { + } + else if (xbox_one_state == WaitingDescEnd) + { xbox_one_state = IdentDescEnd; - } else if (xbox_one_state == Auth) { + } + else if (xbox_one_state == Auth) + { delay(1); - if (data[0] == GIP_AUTHENTICATION && len == 6 && data[3] == 2 && data[4] == 1 && data[5] == 0) { + if (data[0] == GIP_AUTHENTICATION && len == 6 && data[3] == 2 && data[4] == 1 && data[5] == 0) + { handle_auth_led(); printf("Ready!\r\n"); xbox_one_state = Ready; data_from_console_size = len; memcpy(data_from_console, data, len); - } else if (data[0] != GIP_POWER_MODE_DEVICE_CONFIG && data[0] != 2 && data[0] != 4) { + } + else if (data[0] != GIP_POWER_MODE_DEVICE_CONFIG && data[0] != 2 && data[0] != 4) + { data_from_console_size = len; memcpy(data_from_console, data, len); } - } else if (xbox_one_state == Ready) { + } + else if (xbox_one_state == Ready) + { // Live guitar is a bit special, so handle it here #if DEVICE_TYPE == LIVE_GUITAR - if (id == GHL_HID_OUTPUT) { + if (id == GHL_HID_OUTPUT) + { uint8_t sub_id = data[1]; - if (sub_id == PS3_RUMBLE_ID) { + if (sub_id == PS3_RUMBLE_ID) + { uint8_t player = (data[3] & 0x0F); handle_player_leds(player + 1); } } #endif - if (id == GIP_CMD_RUMBLE) { + if (id == GIP_CMD_RUMBLE) + { GipRumble_t *rumble = (GipRumble_t *)data; handle_rumble(rumble->leftMotor, rumble->rightMotor); } } - } else + } + else // Bt reports are ALWAYS hid even if USB is in xinput mode - if ((consoleType == XBOX360 || consoleType == WINDOWS) && report_id != BLUETOOTH_REPORT) { - if (id == XBOX_LED_ID) { + if ((consoleType == XBOX360 || consoleType == WINDOWS) && report_id != BLUETOOTH_REPORT) + { + if (id == XBOX_LED_ID) + { uint8_t led = data[2]; uint8_t player = xbox_players[led]; - if (player) { + if (player) + { handle_player_leds(player); } - - } else if (id == XBOX_RUMBLE_ID) { + } + else if (id == XBOX_RUMBLE_ID) + { uint8_t rumble_left = data[3]; uint8_t rumble_right = data[4]; // Turntable commands will conflict as the actual game sends rumble out on both motors at the same time // To solve this problem, we stay in a turntable compatibility mode until we receive a valid santroller command #if DEVICE_TYPE == DJ_HERO_TURNTABLE - if ((rumble_right >= RUMBLE_SANTROLLER_STAR_POWER_FILL && rumble_right <= RUMBLE_SANTROLLER_NOTE_MISS) || rumble_right == RUMBLE_SANTROLLER_NOTE_HIT) { - if (rumble_left != rumble_right) { + if ((rumble_right >= RUMBLE_SANTROLLER_STAR_POWER_FILL && rumble_right <= RUMBLE_SANTROLLER_NOTE_MISS) || rumble_right == RUMBLE_SANTROLLER_NOTE_HIT) + { + if (rumble_left != rumble_right) + { received_valid_command = true; } } // Turntable led emulation mode - if (!received_valid_command && rumble_left == rumble_right) { + if (!received_valid_command && rumble_left == rumble_right) + { rumble_right = RUMBLE_SANTROLLER_EUPHORIA_LED; } #endif handle_rumble(rumble_left, rumble_right); } - } else { - if (id == PS4_LED_RUMBLE_ID) { + } + else + { + if (id == PS4_LED_RUMBLE_ID) + { ps4_output_report *report = (ps4_output_report *)data; handle_lightbar_leds(report->lightbar_red, report->lightbar_green, report->lightbar_blue); handle_rumble(report->motor_left, report->motor_right); #if defined(INPUT_USB_HOST) && DEVICE_TYPE == GAMEPAD USB_Device_Type_t type; - for (uint8_t i = 0; i < get_usb_host_device_count(); i++) { + for (uint8_t i = 0; i < get_usb_host_device_count(); i++) + { type = get_usb_host_device_type(i); - if (type.sub_type != GAMEPAD || type.console_type != PS4) continue; + if (type.sub_type != GAMEPAD || type.console_type != PS4) + continue; send_report_to_controller(type.dev_addr, type.instance, (uint8_t *)report, sizeof(ps4_output_report)); return; } #endif } #if DEVICE_TYPE_IS_INSTRUMENT - else if (id == PS3_REPORT_ID && data[1] == SANTROLLER_LED_ID) { + else if (id == PS3_REPORT_ID && data[1] == SANTROLLER_LED_ID) + { handle_rumble(data[2], data[3]); - } else if (id == PS3_REPORT_ID && data[1] == SANTROLLER_LED_EXPANDED_ID) { + } + else if (id == PS3_REPORT_ID && data[1] == SANTROLLER_LED_EXPANDED_ID) + { PCStageKitOutput_Data_t *output = (PCStageKitOutput_Data_t *)data; handle_rumble(&output->report); - } else if (id == PS3_REPORT_ID && data[1] == PS3_RUMBLE_ID) { + } + else if (id == PS3_REPORT_ID && data[1] == PS3_RUMBLE_ID) + { uint8_t player = data[3]; handle_player_leds_ps3(player); - } else if (id == PS3_RUMBLE_ID) { + } + else if (id == PS3_RUMBLE_ID) + { uint8_t player = data[2]; handle_player_leds_ps3(player); - } else if (id == SANTROLLER_LED_ID) { + } + else if (id == SANTROLLER_LED_ID) + { handle_rumble(data[1], data[2]); - } else if (id == SANTROLLER_LED_EXPANDED_ID) { + } + else if (id == SANTROLLER_LED_EXPANDED_ID) + { PCStageKitOutputWithoutReportId_Data_t *output = (PCStageKitOutputWithoutReportId_Data_t *)data; handle_rumble(output); } #if DEVICE_TYPE == DJ_HERO_TURNTABLE - else if (id == DJ_LED_ID) { + else if (id == DJ_LED_ID) + { uint8_t euphoria_on = data[2] * 0xFF; // Use the santroller euphoria rumble command so that rumble is correctly mapped handle_rumble(euphoria_on, RUMBLE_SANTROLLER_EUPHORIA_LED); } #endif #else - else if (id == PS3_LED_ID) { - handle_player_leds_ps3(data[9]); - handle_rumble(data[0x04], data[0x02] ? 0xff : 0); - } else if (id == PS3_RUMBLE_ID) { - handle_rumble(data[0x05], data[0x03] ? 0xff : 0); - } + else if (id == PS3_LED_ID) + { + handle_player_leds_ps3(data[9]); + handle_rumble(data[0x04], data[0x02] ? 0xff : 0); + } + else if (id == PS3_RUMBLE_ID) + { + handle_rumble(data[0x05], data[0x03] ? 0xff : 0); + } #endif } } long millis_since_command = 0; -uint8_t handle_serial_command(uint8_t request, uint16_t wValue, uint8_t *response_buffer, bool *success) { - switch (request) { - case COMMAND_READ_CONFIG: { - if (wValue > CONFIGURATION_LEN) { - return 0; - } - uint16_t size = CONFIGURATION_LEN - wValue; - if (size > 64) size = 64; - memcpy_P(response_buffer, config + wValue, size); - return size; +uint8_t handle_serial_command(uint8_t request, uint16_t wValue, uint8_t *response_buffer, bool *success) +{ + switch (request) + { + case COMMAND_READ_CONFIG: + { + if (wValue > CONFIGURATION_LEN) + { + return 0; } - case COMMAND_READ_SERIAL: - read_serial(response_buffer, 20); - return 20; - case COMMAND_READ_BOARD: - memcpy_P(response_buffer, board, sizeof(board)); - return sizeof(board); - case COMMAND_READ_F_CPU: - memcpy_P(response_buffer, f_cpu_descriptor_str, sizeof(f_cpu_descriptor_str)); - return sizeof(f_cpu_descriptor_str); + uint16_t size = CONFIGURATION_LEN - wValue; + if (size > 64) + size = 64; + memcpy_P(response_buffer, config + wValue, size); + return size; + } + case COMMAND_READ_SERIAL: + read_serial(response_buffer, 20); + return 20; + case COMMAND_READ_BOARD: + memcpy_P(response_buffer, board, sizeof(board)); + return sizeof(board); + case COMMAND_READ_F_CPU: + memcpy_P(response_buffer, f_cpu_descriptor_str, sizeof(f_cpu_descriptor_str)); + return sizeof(f_cpu_descriptor_str); - case COMMAND_GET_EXTENSION_WII: - if (!lastWiiWasSuccessful) { - return 0; - } - memcpy(response_buffer, &wiiControllerType, sizeof(wiiControllerType)); - return sizeof(wiiControllerType); - case COMMAND_GET_EXTENSION_PS2: - if (!lastPS2WasSuccessful) { - return 0; - } - memcpy(response_buffer, &ps2ControllerType, sizeof(ps2ControllerType)); - return sizeof(ps2ControllerType); - case COMMAND_READ_WII: - if (!lastWiiWasSuccessful) { - return 0; - } - memcpy(response_buffer, &lastSuccessfulWiiPacket, wiiBytes); - return wiiBytes; - case COMMAND_READ_PS2: - if (!lastPS2WasSuccessful) { - return 0; - } - memcpy(response_buffer, &lastSuccessfulPS2Packet, sizeof(lastSuccessfulPS2Packet)); - return sizeof(lastSuccessfulPS2Packet); - case COMMAND_READ_DJ_LEFT: - if (!lastTurntableWasSuccessfulLeft) { - return 0; - } - memcpy(response_buffer, &lastSuccessfulTurntablePacketLeft, sizeof(lastSuccessfulTurntablePacketLeft)); - return sizeof(lastSuccessfulTurntablePacketLeft); - case COMMAND_READ_DJ_RIGHT: - if (!lastTurntableWasSuccessfulRight) { - return 0; - } - memcpy(response_buffer, &lastSuccessfulTurntablePacketRight, sizeof(lastSuccessfulTurntablePacketRight)); - return sizeof(lastSuccessfulTurntablePacketRight); - case COMMAND_READ_GH5: - if (!lastGH5WasSuccessful) { - return 0; - } - memcpy(response_buffer, &lastSuccessfulGH5Packet, sizeof(lastSuccessfulGH5Packet)); - return sizeof(lastSuccessfulGH5Packet); - case COMMAND_READ_CLONE: - if (!lastCloneWasSuccessful) { - return 0; - } - memcpy(response_buffer, &lastSuccessfulClonePacket, sizeof(lastSuccessfulClonePacket)); - return sizeof(lastSuccessfulClonePacket); - case COMMAND_READ_CRKD: - if (!lastCrkdWasSuccessful) { - return 0; - } - memcpy(response_buffer, &lastCrkd, sizeof(lastCrkd)); - return sizeof(lastCrkd); -#ifdef INPUT_WT_NECK - case COMMAND_READ_GHWT: { - volatile uint8_t *data = (volatile uint8_t *)lastWt; - for (int i = 0; i < sizeof(lastWt); i++) { - response_buffer[i] = data[i]; - } - return sizeof(lastWt); - } -#endif - case COMMAND_READ_ANALOG: { - uint8_t pin = wValue & 0xff; - uint8_t mask = (wValue >> 8); - uint16_t response = adc_read(pin, mask); - memcpy(response_buffer, &response, sizeof(response)); - return sizeof(response); - } - case COMMAND_READ_ACCEL: { - memcpy(response_buffer, &filtered, sizeof(filtered)); - memcpy(response_buffer + sizeof(filtered), &accel_adc, sizeof(accel_adc)); - return sizeof(filtered) + sizeof(accel_adc); + case COMMAND_GET_EXTENSION_WII: + if (!lastWiiWasSuccessful) + { + return 0; } - case COMMAND_ACCEL_VALID: { - response_buffer[0] = accel_found; - return 1; + memcpy(response_buffer, &wiiControllerType, sizeof(wiiControllerType)); + return sizeof(wiiControllerType); + case COMMAND_GET_EXTENSION_PS2: + if (!lastPS2WasSuccessful) + { + return 0; } - case COMMAND_SET_ACCEL_FILTER: { - memcpy(¤tLowPassAlpha, response_buffer, sizeof(currentLowPassAlpha)); + memcpy(response_buffer, &ps2ControllerType, sizeof(ps2ControllerType)); + return sizeof(ps2ControllerType); + case COMMAND_READ_WII: + if (!lastWiiWasSuccessful) + { return 0; } - case COMMAND_READ_DIGITAL: { - uint8_t port = wValue & 0xff; - uint8_t mask = (wValue >> 8); - uint8_t response = digital_read(port, mask); - memcpy(response_buffer, &response, sizeof(response)); - return sizeof(response); + memcpy(response_buffer, &lastSuccessfulWiiPacket, wiiBytes); + return wiiBytes; + case COMMAND_READ_PS2: + if (!lastPS2WasSuccessful) + { + return 0; } - case COMMAND_WRITE_ANALOG: { - uint8_t port = response_buffer[0]; - uint8_t value = response_buffer[1]; - analogWrite(port, value); + memcpy(response_buffer, &lastSuccessfulPS2Packet, sizeof(lastSuccessfulPS2Packet)); + return sizeof(lastSuccessfulPS2Packet); + case COMMAND_READ_DJ_LEFT: + if (!lastTurntableWasSuccessfulLeft) + { return 0; } - case COMMAND_WRITE_DIGITAL: { - uint8_t port = response_buffer[0]; - uint8_t mask = response_buffer[1]; - uint8_t activeMask = response_buffer[2]; - digital_write(port, mask, activeMask); + memcpy(response_buffer, &lastSuccessfulTurntablePacketLeft, sizeof(lastSuccessfulTurntablePacketLeft)); + return sizeof(lastSuccessfulTurntablePacketLeft); + case COMMAND_READ_DJ_RIGHT: + if (!lastTurntableWasSuccessfulRight) + { return 0; } - case COMMAND_LED_BRIGHTNESS: { - brightness = response_buffer[0]; + memcpy(response_buffer, &lastSuccessfulTurntablePacketRight, sizeof(lastSuccessfulTurntablePacketRight)); + return sizeof(lastSuccessfulTurntablePacketRight); + case COMMAND_READ_GH5: + if (!lastGH5WasSuccessful) + { return 0; } - case COMMAND_DISABLE_MULTIPLEXER: { - disable_multiplexer = response_buffer[0]; + memcpy(response_buffer, &lastSuccessfulGH5Packet, sizeof(lastSuccessfulGH5Packet)); + return sizeof(lastSuccessfulGH5Packet); + case COMMAND_READ_CLONE: + if (!lastCloneWasSuccessful) + { return 0; } - - case COMMAND_READ_MATRIX: { - uint8_t outPin = wValue & 0xff; - uint8_t pin = (wValue >> 8); - response_buffer[0] = matrix_read(pin, outPin); - return 1; + memcpy(response_buffer, &lastSuccessfulClonePacket, sizeof(lastSuccessfulClonePacket)); + return sizeof(lastSuccessfulClonePacket); + case COMMAND_READ_CRKD: + if (!lastCrkdWasSuccessful) + { + return 0; } - case COMMAND_READ_MIDI: { - memcpy(response_buffer, &midiData.midiVelocities, (sizeof(Midi_Data_t) - offsetof(Midi_Data_t, midiVelocities))); - return (sizeof(Midi_Data_t) - offsetof(Midi_Data_t, midiVelocities)); + memcpy(response_buffer, &lastCrkd, sizeof(lastCrkd)); + return sizeof(lastCrkd); +#ifdef INPUT_WT_NECK + case COMMAND_READ_GHWT: + { + volatile uint8_t *data = (volatile uint8_t *)lastWt; + for (int i = 0; i < sizeof(lastWt); i++) + { + response_buffer[i] = data[i]; } + return sizeof(lastWt); + } +#endif + case COMMAND_READ_ANALOG: + { + uint8_t pin = wValue & 0xff; + uint8_t mask = (wValue >> 8); + uint16_t response = adc_read(pin, mask); + memcpy(response_buffer, &response, sizeof(response)); + return sizeof(response); + } + case COMMAND_READ_ACCEL: + { + memcpy(response_buffer, &filtered, sizeof(filtered)); + memcpy(response_buffer + sizeof(filtered), &accel_adc, sizeof(accel_adc)); + return sizeof(filtered) + sizeof(accel_adc); + } + case COMMAND_ACCEL_VALID: + { + response_buffer[0] = accel_found; + return 1; + } + case COMMAND_SET_ACCEL_FILTER: + { + memcpy(¤tLowPassAlpha, response_buffer, sizeof(currentLowPassAlpha)); + return 0; + } + case COMMAND_READ_DIGITAL: + { + uint8_t port = wValue & 0xff; + uint8_t mask = (wValue >> 8); + uint8_t response = digital_read(port, mask); + memcpy(response_buffer, &response, sizeof(response)); + return sizeof(response); + } + case COMMAND_WRITE_ANALOG: + { + uint8_t port = response_buffer[0]; + uint8_t value = response_buffer[1]; + analogWrite(port, value); + return 0; + } + case COMMAND_WRITE_DIGITAL: + { + uint8_t port = response_buffer[0]; + uint8_t mask = response_buffer[1]; + uint8_t activeMask = response_buffer[2]; + digital_write(port, mask, activeMask); + return 0; + } + case COMMAND_LED_BRIGHTNESS: + { + brightness = response_buffer[0]; + return 0; + } + case COMMAND_DISABLE_MULTIPLEXER: + { + disable_multiplexer = response_buffer[0]; + return 0; + } + + case COMMAND_READ_MATRIX: + { + uint8_t outPin = wValue & 0xff; + uint8_t pin = (wValue >> 8); + response_buffer[0] = matrix_read(pin, outPin); + return 1; + } + case COMMAND_READ_MIDI: + { + memcpy(response_buffer, &midiData.midiVelocities, (sizeof(Midi_Data_t) - offsetof(Midi_Data_t, midiVelocities))); + return (sizeof(Midi_Data_t) - offsetof(Midi_Data_t, midiVelocities)); + } #ifdef WT_DRUM_SPI_PORT - case COMMAND_WT_DRUM_VALID: - response_buffer[0] = wt_drum_found; - return 1; + case COMMAND_WT_DRUM_VALID: + response_buffer[0] = wt_drum_found; + return 1; #endif #ifdef MUSTANG_NECK_SPI_PORT - case COMMAND_MUSTANG_NECK_VALID: - response_buffer[0] = mustang_neck_found; - return 1; + case COMMAND_MUSTANG_NECK_VALID: + response_buffer[0] = mustang_neck_found; + return 1; #endif #ifdef BH_DRUM_TWI_PORT - case COMMAND_BH_DRUM_VALID: - response_buffer[0] = bh_drum_found; - return 1; + case COMMAND_BH_DRUM_VALID: + response_buffer[0] = bh_drum_found; + return 1; #endif #ifdef MAX1704X_TWI_PORT - case COMMAND_READ_MAX170X_VALID: - response_buffer[0] = max170x_init; - return 1; - case COMMAND_READ_MAX170X: - memcpy(response_buffer, &lastBattery, sizeof(lastBattery)); - return sizeof(lastBattery); + case COMMAND_READ_MAX170X_VALID: + response_buffer[0] = max170x_init; + return 1; + case COMMAND_READ_MAX170X: + memcpy(response_buffer, &lastBattery, sizeof(lastBattery)); + return sizeof(lastBattery); #endif #ifdef MPR121_TWI_PORT - case COMMAND_READ_MPR121_VALID: - response_buffer[0] = mpr121_init; - return 1; - case COMMAND_READ_MPR121: - memcpy(response_buffer, &lastMpr121, sizeof(lastMpr121)); - return sizeof(lastMpr121); + case COMMAND_READ_MPR121_VALID: + response_buffer[0] = mpr121_init; + return 1; + case COMMAND_READ_MPR121: + memcpy(response_buffer, &lastMpr121, sizeof(lastMpr121)); + return sizeof(lastMpr121); #endif #ifdef SLAVE_TWI_PORT #ifdef INPUT_WT_SLAVE_NECK - case COMMAND_READ_PERIPHERAL_GHWT: - return slaveReadWtRaw(response_buffer); + case COMMAND_READ_PERIPHERAL_GHWT: + return slaveReadWtRaw(response_buffer); #endif - case COMMAND_READ_PERIPHERAL_VALID: - response_buffer[0] = slave_initted; - return 1; - case COMMAND_READ_PERIPHERAL_DIGITAL: { - uint8_t port = wValue & 0xff; - uint8_t mask = (wValue >> 8); - uint8_t response = slaveReadDigital(port, mask); - memcpy(response_buffer, &response, sizeof(response)); - return sizeof(response); - } + case COMMAND_READ_PERIPHERAL_VALID: + response_buffer[0] = slave_initted; + return 1; + case COMMAND_READ_PERIPHERAL_DIGITAL: + { + uint8_t port = wValue & 0xff; + uint8_t mask = (wValue >> 8); + uint8_t response = slaveReadDigital(port, mask); + memcpy(response_buffer, &response, sizeof(response)); + return sizeof(response); + } #endif #if LED_COUNT_WS2812 - case COMMAND_SET_LEDS: { - uint8_t led = response_buffer[0]; - if (led >= LED_COUNT_WS2812) return 0; - if (response_buffer[1] == 0 && response_buffer[2] == 0 && response_buffer[3] == 0) { - ledState[led].select = 0; - return 0; - } - memcpy(&ledState[led], response_buffer, sizeof(Led_WS2812_t)); - ledState[led].select = 1; + case COMMAND_SET_LEDS: + { + uint8_t led = response_buffer[0]; + if (led >= LED_COUNT_WS2812) + return 0; + if (response_buffer[1] == 0 && response_buffer[2] == 0 && response_buffer[3] == 0) + { + ledState[led].select = 0; return 0; } + memcpy(&ledState[led], response_buffer, sizeof(Led_WS2812_t)); + ledState[led].select = 1; + return 0; + } #endif #if LED_COUNT_PERIPHERAL_WS2812 - case COMMAND_SET_LEDS_PERIPHERAL: { - uint8_t led = response_buffer[0]; - if (led >= LED_COUNT_PERIPHERAL_WS2812) return 0; - if (response_buffer[1] == 0 && response_buffer[2] == 0 && response_buffer[3] == 0) { - ledStatePeripheral[led].select = 0; - return 0; - } - memcpy(&ledStatePeripheral[led], response_buffer, sizeof(Led_WS2812_t)); - ledStatePeripheral[led].select = 1; + case COMMAND_SET_LEDS_PERIPHERAL: + { + uint8_t led = response_buffer[0]; + if (led >= LED_COUNT_PERIPHERAL_WS2812) + return 0; + if (response_buffer[1] == 0 && response_buffer[2] == 0 && response_buffer[3] == 0) + { + ledStatePeripheral[led].select = 0; return 0; } + memcpy(&ledStatePeripheral[led], response_buffer, sizeof(Led_WS2812_t)); + ledStatePeripheral[led].select = 1; + return 0; + } #endif #if LED_COUNT - case COMMAND_SET_LEDS: { - uint8_t led = response_buffer[0]; - if (led >= LED_COUNT) return 0; - if (response_buffer[2] == 0 && response_buffer[3] == 0 && response_buffer[4] == 0) { - ledState[led].select = 0; - return 0; - } - ledState[led].select = 1; - ledState[led].brightness = response_buffer[1]; - ledState[led].r = response_buffer[2]; - ledState[led].g = response_buffer[3]; - ledState[led].b = response_buffer[4]; + case COMMAND_SET_LEDS: + { + uint8_t led = response_buffer[0]; + if (led >= LED_COUNT) + return 0; + if (response_buffer[2] == 0 && response_buffer[3] == 0 && response_buffer[4] == 0) + { + ledState[led].select = 0; return 0; } + ledState[led].select = 1; + ledState[led].brightness = response_buffer[1]; + ledState[led].r = response_buffer[2]; + ledState[led].g = response_buffer[3]; + ledState[led].b = response_buffer[4]; + return 0; + } #endif #if LED_COUNT_PERIPHERAL - case COMMAND_SET_LEDS_PERIPHERAL: { - uint8_t led = response_buffer[0]; - if (led >= LED_COUNT_PERIPHERAL) return 0; - if (response_buffer[2] == 0 && response_buffer[3] == 0 && response_buffer[4] == 0) { - ledStatePeripheral[led].select = 0; - return 0; - } - ledStatePeripheral[led].select = 1; - ledStatePeripheral[led].brightness = response_buffer[1]; - ledStatePeripheral[led].r = response_buffer[2]; - ledStatePeripheral[led].g = response_buffer[3]; - ledStatePeripheral[led].b = response_buffer[4]; + case COMMAND_SET_LEDS_PERIPHERAL: + { + uint8_t led = response_buffer[0]; + if (led >= LED_COUNT_PERIPHERAL) + return 0; + if (response_buffer[2] == 0 && response_buffer[3] == 0 && response_buffer[4] == 0) + { + ledStatePeripheral[led].select = 0; return 0; } + ledStatePeripheral[led].select = 1; + ledStatePeripheral[led].brightness = response_buffer[1]; + ledStatePeripheral[led].r = response_buffer[2]; + ledStatePeripheral[led].g = response_buffer[3]; + ledStatePeripheral[led].b = response_buffer[4]; + return 0; + } #endif #if LED_COUNT_MPR121 - case COMMAND_SET_LEDS_MPR121: { - uint8_t led = response_buffer[0]; - if (led >= LED_COUNT_MPR121) return 0; - if (response_buffer[1]) { - bit_set(ledStateMpr121, led % 8); - bit_set(ledStateMpr121Select, led % 8); - } else { - bit_clear(ledStateMpr121, led % 8); - bit_clear(ledStateMpr121Select, led % 8); - } + case COMMAND_SET_LEDS_MPR121: + { + uint8_t led = response_buffer[0]; + if (led >= LED_COUNT_MPR121) return 0; + if (response_buffer[1]) + { + bit_set(ledStateMpr121, led % 8); + bit_set(ledStateMpr121Select, led % 8); } + else + { + bit_clear(ledStateMpr121, led % 8); + bit_clear(ledStateMpr121Select, led % 8); + } + return 0; + } #endif #if LED_COUNT_STP - case COMMAND_SET_LEDS: { - uint8_t led = response_buffer[0]; - if (led >= LED_COUNT_STP) return 0; - if (response_buffer[1]) { - bit_set(ledState[led >> 3], led % 8); - bit_set(ledStateSelect[led >> 3], led % 8); - } else { - bit_clear(ledState[led >> 3], led % 8); - bit_clear(ledStateSelect[led >> 3], led % 8); - } + case COMMAND_SET_LEDS: + { + uint8_t led = response_buffer[0]; + if (led >= LED_COUNT_STP) return 0; + if (response_buffer[1]) + { + bit_set(ledState[led >> 3], led % 8); + bit_set(ledStateSelect[led >> 3], led % 8); + } + else + { + bit_clear(ledState[led >> 3], led % 8); + bit_clear(ledStateSelect[led >> 3], led % 8); } + return 0; + } #endif #if LED_COUNT_PERIPHERAL_STP - case COMMAND_SET_LEDS_PERIPHERAL: { - uint8_t led = response_buffer[0]; - if (led >= LED_COUNT_PERIPHERAL_STP) return 0; - if (response_buffer[1]) { - bit_set(ledStatePeripheral[led >> 3], led % 8); - bit_set(ledStatePeripheralSelect[led >> 3], led % 8); - } else { - bit_clear(ledStatePeripheral[led >> 3], led % 8); - bit_clear(ledStatePeripheralSelect[led >> 3], led % 8); - } + case COMMAND_SET_LEDS_PERIPHERAL: + { + uint8_t led = response_buffer[0]; + if (led >= LED_COUNT_PERIPHERAL_STP) return 0; + if (response_buffer[1]) + { + bit_set(ledStatePeripheral[led >> 3], led % 8); + bit_set(ledStatePeripheralSelect[led >> 3], led % 8); + } + else + { + bit_clear(ledStatePeripheral[led >> 3], led % 8); + bit_clear(ledStatePeripheralSelect[led >> 3], led % 8); } + return 0; + } #endif #ifdef INPUT_USB_HOST - case COMMAND_READ_USB_HOST: { - return read_usb_host_devices(response_buffer); - } - case COMMAND_READ_USB_HOST_INPUTS: { - memcpy(response_buffer, &last_usb_host_data, sizeof(last_usb_host_data)); - return sizeof(last_usb_host_data); - } + case COMMAND_READ_USB_HOST: + { + return read_usb_host_devices(response_buffer); + } + case COMMAND_READ_USB_HOST_INPUTS: + { + memcpy(response_buffer, &last_usb_host_data, sizeof(last_usb_host_data)); + return sizeof(last_usb_host_data); + } #endif #if BLUETOOTH_RX - case COMMAND_START_BT_SCAN: { - bt_start_scan(); - return 0; - } - case COMMAND_STOP_BT_SCAN: { - bt_stop_scan(); - return 0; - } - case COMMAND_GET_BT_DEVICES: { - return bt_get_scan_results(response_buffer); - } - case COMMAND_READ_BLUETOOTH_INPUTS: { - memcpy(response_buffer, &bt_data, sizeof(bt_data)); - return sizeof(bt_data); - } + case COMMAND_START_BT_SCAN: + { + bt_start_scan(); + return 0; + } + case COMMAND_STOP_BT_SCAN: + { + bt_stop_scan(); + return 0; + } + case COMMAND_GET_BT_DEVICES: + { + return bt_get_scan_results(response_buffer); + } + case COMMAND_READ_BLUETOOTH_INPUTS: + { + memcpy(response_buffer, &bt_data, sizeof(bt_data)); + return sizeof(bt_data); + } #endif #if BLUETOOTH - case COMMAND_GET_BT_STATE: { - response_buffer[0] = check_bluetooth_ready(); - return 1; - } - case COMMAND_GET_BT_ADDRESS: { - return get_bt_address(response_buffer); - } + case COMMAND_GET_BT_STATE: + { + response_buffer[0] = check_bluetooth_ready(); + return 1; + } + case COMMAND_GET_BT_ADDRESS: + { + return get_bt_address(response_buffer); + } #endif } *success = false; return 0; } -uint8_t hid_get_report(uint8_t *data, uint8_t reqlen, uint8_t reportType, uint8_t report_id) { +uint8_t hid_get_report(uint8_t *data, uint8_t reqlen, uint8_t reportType, uint8_t report_id) +{ return 0; } \ No newline at end of file From 57e55f9ff16e64dfbf3d28d7ee6a2aefd9f60026 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 17 May 2026 09:46:27 +1200 Subject: [PATCH 184/239] update libs again --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 402c7f507..c3a965cc3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ board_upload.ardwiino_bootloader_teensy = true board_build.use_usb = 1 platform = https://github.com/maxgerhardt/platform-raspberrypi/archive/39b90392af50585e429941bd2561a91949a2ba46.zip@1.15.0 platform_packages = - framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.8-sanjay/rp2040-4.6.8-sanjay.zip@1.40404.0 + framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.9-sanjay/rp2040-4.6.9-sanjay.zip@1.40404.0 board = pico framework = arduino board_build.core = earlephilhower From 73ab0da685f0a7ec677ce35553692b1751a8be65 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 17 May 2026 09:57:14 +1200 Subject: [PATCH 185/239] update libs again --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index c3a965cc3..f6a306420 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ board_upload.ardwiino_bootloader_teensy = true board_build.use_usb = 1 platform = https://github.com/maxgerhardt/platform-raspberrypi/archive/39b90392af50585e429941bd2561a91949a2ba46.zip@1.15.0 platform_packages = - framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.9-sanjay/rp2040-4.6.9-sanjay.zip@1.40404.0 + framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.11-sanjay/rp2040-4.6.11-sanjay.zip@1.50404.0 board = pico framework = arduino board_build.core = earlephilhower From d948a2c8ced7ac86ee4cc00451e27d38d17a1e30 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 17 May 2026 10:12:01 +1200 Subject: [PATCH 186/239] update libs again --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index f6a306420..dcc468804 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ board_upload.ardwiino_bootloader_teensy = true board_build.use_usb = 1 platform = https://github.com/maxgerhardt/platform-raspberrypi/archive/39b90392af50585e429941bd2561a91949a2ba46.zip@1.15.0 platform_packages = - framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.11-sanjay/rp2040-4.6.11-sanjay.zip@1.50404.0 + framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.12-sanjay/rp2040-4.6.12-sanjay.zip@1.50404.0 board = pico framework = arduino board_build.core = earlephilhower From a6b10add03727e9fd6ba3625eb5ca7997bc5e437 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 17 May 2026 13:35:59 +1200 Subject: [PATCH 187/239] update gha descriptor --- include/hid.h | 2 +- src/shared/hid/ps3_wii_switch.h | 37 ++++++++++++++++----------------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/include/hid.h b/include/hid.h index 299aa89dd..435fc4a63 100644 --- a/include/hid.h +++ b/include/hid.h @@ -77,7 +77,7 @@ extern const uint8_t keyboard_mouse_descriptor[NKRO_SIZE + SIXKRO_SIZE + CONSUMER_SIZE + MOUSE_SIZE]; extern const uint8_t ps3_descriptor[148]; extern const uint8_t ps3_instrument_descriptor[137]; -extern const uint8_t gha_descriptor[83]; +extern const uint8_t gha_descriptor[81]; extern const uint8_t ps4_descriptor[160]; extern const uint8_t ps5_descriptor[165]; extern const uint8_t fnf_descriptor[53]; diff --git a/src/shared/hid/ps3_wii_switch.h b/src/shared/hid/ps3_wii_switch.h index 2cd6c1f6b..3fd9ed435 100644 --- a/src/shared/hid/ps3_wii_switch.h +++ b/src/shared/hid/ps3_wii_switch.h @@ -4,27 +4,26 @@ #include "progmem.h" const uint8_t PROGMEM gha_descriptor[] = { 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) + 0x15, 0x00, // Logical Minimum (0) 0x09, 0x04, // Usage (Joystick) 0xA1, 0x01, // Collection (Application) + 0x05, 0x02, // Usage Page (Simulation Controls) + 0x09, 0xBB, // Usage (Throttle) + 0x15, 0x81, // Logical Minimum (-127) + 0x25, 0x7f, // Logical Maximum (127) + 0x75, 0x08, // Report Size (8) + 0x95, 0x00, // Report Cout (0) + 0x81, 0x02, // Input (Data,Var,Abs) + 0x05, 0x01, // Usage Page (Generic Desktop Controls) 0x09, 0x01, // Usage (Pointer) 0xA1, 0x00, // Collection (Physical) 0x09, 0x30, // Usage (X) - 0x25, 0x7F, // Logical Maximum (127) - 0x35, 0x00, // Physical Minimum (0) - 0x45, 0x00, // Physical Maximum (0) - 0x65, 0x00, // Unit (None) - 0x55, 0x00, // Unit Exponent (0) - 0x75, 0x08, // Report Size (8) - 0x95, 0x01, // Report Count (1) - 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x09, 0x31, // Usage (Y) - 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x09, 0x32, // Usage (Z) - 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x09, 0x33, // Usage (Rx) - 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x09, 0x34, // Usage (Ry) - 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x95, 0x05, // Report Count (5) + 0x81, 0x02, // Input (Data,Var,Abs) 0xC0, // End Collection 0x09, 0x39, // Usage (Hat switch) 0x15, 0x00, // Logical Minimum (0) @@ -32,18 +31,18 @@ const uint8_t PROGMEM gha_descriptor[] = { 0x46, 0x0E, 0x01, // Physical Maximum (270) 0x65, 0x14, // Unit (System: English Rotation, Length: Centimeter) 0x75, 0x04, // Report Size (4) - 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x95, 0x01, // Report Count (5) + 0x81, 0x02, // Input (Data,Var,Abs) 0x05, 0x09, // Usage Page (Button) 0x19, 0x01, // Usage Minimum (0x01) 0x29, 0x0A, // Usage Maximum (0x0A) + 0x15, 0x01, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) - 0x45, 0x01, // Physical Maximum (1) - 0x65, 0x00, // Unit (None) 0x75, 0x01, // Report Size (1) - 0x95, 0x0A, // Report Count (10) - 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) - 0x95, 0x02, // Report Count (2) - 0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) + 0x95, 0x0C, // Report Count (12) + 0x55, 0x00, // Unit Exponent (-16) + 0x65, 0x00, // Unit Exponent (0x00) + 0x81, 0x02, // Input (Data,Var,Abs) 0xC0, // End Collection }; const uint8_t PROGMEM ps3_instrument_descriptor[] = { From 1f4759a9c6b1f83e3e8d68caddd65d97093f9669 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 17 May 2026 13:56:52 +1200 Subject: [PATCH 188/239] fix gha tilt --- src/shared/main/shared_main.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index c883853ad..ad3b33aeb 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3616,6 +3616,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu memset(report, 0, sizeof(ArcadeGuitarHeroGuitar_Data_t)); report->always_1d = 0x1d; report->always_ff = 0xff; + report->tilt = PS3_STICK_CENTER; report->side = arcadeSide; TICK_ARCADE; asm volatile("" :: From 09bf0ae0d50d3d4edec03f4c461f320d26bd275a Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 17 May 2026 14:41:16 +1200 Subject: [PATCH 189/239] fix gha tilt --- src/shared/main/shared_main.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index ad3b33aeb..a5f2814cd 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -648,10 +648,11 @@ uint16_t handle_calibration_ps3_accel(uint16_t previous, int32_t orig_val, int16 #endif return PS3_ACCEL_CENTER + ret; } + uint8_t handle_calibration_arcade_accel(uint16_t previous, int32_t orig_val, int16_t min, int16_t max, int16_t center, uint16_t deadzone) { - int8_t ret = handle_calibration_xbox((previous - 65) << 9, orig_val, min, max, center, deadzone, 0) >> 9; - return (uint8_t)(ret + 65); + int8_t ret = handle_calibration_xbox((previous) << 8, orig_val, min, max, center, deadzone, 0) >> 8; + return (uint8_t)(ret); } long last_zero = 0; uint8_t handle_calibration_ps3_whammy(uint8_t previous, uint16_t orig_val, uint32_t min, int16_t multiplier, uint16_t deadzone) @@ -3616,7 +3617,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu memset(report, 0, sizeof(ArcadeGuitarHeroGuitar_Data_t)); report->always_1d = 0x1d; report->always_ff = 0xff; - report->tilt = PS3_STICK_CENTER; + report->tilt = 0; report->side = arcadeSide; TICK_ARCADE; asm volatile("" :: From e6d01d020f3b239e24b1ff7b61ce0c92651a3985 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 17 May 2026 14:58:58 +1200 Subject: [PATCH 190/239] fix gha string --- src/shared/usb/string_descriptors.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/usb/string_descriptors.c b/src/shared/usb/string_descriptors.c index 0a43c725e..d14276451 100644 --- a/src/shared/usb/string_descriptors.c +++ b/src/shared/usb/string_descriptors.c @@ -34,7 +34,7 @@ const PROGMEM STRING_DESCRIPTOR xboxString = USB_DESCRIPTOR_STRING_UTF("Xbox Sec const PROGMEM STRING_DESCRIPTOR rtString = USB_DESCRIPTOR_STRING_UTF("RT GH CONTROLLER "); -const PROGMEM STRING_DESCRIPTOR rtStringLED = USB_DESCRIPTOR_STRING_UTF("RT-GH LED "); +const PROGMEM STRING_DESCRIPTOR rtStringLED = USB_DESCRIPTOR_STRING_UTF("RT-GH LED "); const PROGMEM STRING_DESCRIPTOR rtStringInput = USB_DESCRIPTOR_STRING_UTF("RT-GH INPUT "); const PROGMEM STRING_DESCRIPTOR *const descriptorStrings[3] = { From 7ca3852cba04be4277f45bf83610ee314a4fb53f Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 6 Jul 2026 15:49:51 +1200 Subject: [PATCH 191/239] xb1 controllers pair via bt now --- include/btstack_config.h | 49 +++- platformio.ini | 2 +- src/pico/bt_rx.cpp | 609 ++++++++++++++++++++++++--------------- 3 files changed, 410 insertions(+), 250 deletions(-) diff --git a/include/btstack_config.h b/include/btstack_config.h index 3d1ee3576..fa6a3c113 100644 --- a/include/btstack_config.h +++ b/include/btstack_config.h @@ -1,19 +1,37 @@ -#pragma once +#ifndef _PICO_BTSTACK_BTSTACK_CONFIG_H +#define _PICO_BTSTACK_BTSTACK_CONFIG_H + +// Copy & paste from, with some custom changes: +// https://github.com/raspberrypi/pico-examples/blob/master/pico_w/bt/config/btstack_config.h // BTstack features that can be enabled #define ENABLE_LOG_INFO #define ENABLE_LOG_ERROR +#define ENABLE_LOG_DEBUG #define ENABLE_PRINTF_HEXDUMP #define ENABLE_SCO_OVER_HCI +#ifdef ENABLE_BLE +#define ENABLE_GATT_CLIENT_PAIRING +#define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE +#define ENABLE_LE_CENTRAL +#define ENABLE_LE_DATA_LENGTH_EXTENSION +#define ENABLE_LE_PERIPHERAL +#define ENABLE_LE_PRIVACY_ADDRESS_RESOLUTION +#define ENABLE_LE_SECURE_CONNECTIONS +#else +#error "BP32: ENABLE_BLE should be defined" +#endif + #ifdef ENABLE_CLASSIC #define ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE +#define ENABLE_GOEP_L2CAP +#else +#error "BP32: ENABLE_CLASSIC should be defined" #endif -#ifdef ENABLE_BLE -#define ENABLE_L2CAP_LE_CREDIT_BASED_FLOW_CONTROL_MODE -#define ENABLE_LE_PERIPHERAL -#define ENABLE_LE_CENTRAL +#if defined(ENABLE_CLASSIC) && defined(ENABLE_BLE) +#define ENABLE_CROSS_TRANSPORT_KEY_DERIVATION #endif // BTstack configuration. buffers, sizes, ... @@ -25,14 +43,14 @@ #define MAX_NR_AVRCP_CONNECTIONS 2 #define MAX_NR_BNEP_CHANNELS 1 #define MAX_NR_BNEP_SERVICES 1 -#define MAX_NR_BTSTACK_LINK_KEY_DB_MEMORY_ENTRIES 2 -#define MAX_NR_GATT_CLIENTS 1 -#define MAX_NR_HCI_CONNECTIONS 2 -#define MAX_NR_HID_HOST_CONNECTIONS 1 -#define MAX_NR_HIDS_CLIENTS 1 +#define MAX_NR_BTSTACK_LINK_KEY_DB_MEMORY_ENTRIES 2 +#define MAX_NR_GATT_CLIENTS 4 +#define MAX_NR_HCI_CONNECTIONS 4 +#define MAX_NR_HID_HOST_CONNECTIONS 4 +#define MAX_NR_HIDS_HOSTS 4 #define MAX_NR_HFP_CONNECTIONS 1 -#define MAX_NR_L2CAP_CHANNELS 4 -#define MAX_NR_L2CAP_SERVICES 3 +#define MAX_NR_L2CAP_CHANNELS 6 +#define MAX_NR_L2CAP_SERVICES 5 #define MAX_NR_RFCOMM_CHANNELS 1 #define MAX_NR_RFCOMM_MULTIPLEXERS 1 #define MAX_NR_RFCOMM_SERVICES 1 @@ -71,4 +89,9 @@ #define ENABLE_SOFTWARE_AES128 #define ENABLE_MICRO_ECC_FOR_LE_SECURE_CONNECTIONS -#undef HAVE_BTSTACK_STDIN +#define HAVE_BTSTACK_STDIN + +// To get the audio demos working even with HCI dump at 115200, this truncates long ACL packets +// #define HCI_DUMP_STDOUT_MAX_SIZE_ACL 100 + +#endif // _PICO_BTSTACK_BTSTACK_CONFIG_H \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index dcc468804..caa0beb04 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ board_upload.ardwiino_bootloader_teensy = true board_build.use_usb = 1 platform = https://github.com/maxgerhardt/platform-raspberrypi/archive/39b90392af50585e429941bd2561a91949a2ba46.zip@1.15.0 platform_packages = - framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.12-sanjay/rp2040-4.6.12-sanjay.zip@1.50404.0 + framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.13-sanjay/rp2040-4.6.13-sanjay.zip@1.50404.0 board = pico framework = arduino board_build.core = earlephilhower diff --git a/src/pico/bt_rx.cpp b/src/pico/bt_rx.cpp index 8ba97bbd1..31ac39245 100644 --- a/src/pico/bt_rx.cpp +++ b/src/pico/bt_rx.cpp @@ -20,11 +20,13 @@ #include "hid.h" #include "hidparser.h" #include "shared_main.h" +#include "hci_dump_embedded_stdout.h" // TAG to store remote device address and type in TLV #define TLV_TAG_HOGD ((((uint32_t)'H') << 24) | (((uint32_t)'O') << 16) | (((uint32_t)'G') << 8) | 'D') -typedef struct { +typedef struct +{ bd_addr_t addr; bd_addr_type_t addr_type; } le_device_addr_t; @@ -84,13 +86,15 @@ static void hog_connect(void); * @param size * @returns true if it does */ -static bool adv_event_contains_hid_service(const uint8_t *packet) { +static bool adv_event_contains_hid_service(const uint8_t *packet) +{ const uint8_t *ad_data = gap_event_advertising_report_get_data(packet); uint8_t ad_len = gap_event_advertising_report_get_data_length(packet); return ad_data_contains_uuid16(ad_len, ad_data, ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE); } -typedef struct { +typedef struct +{ char addr[SIZE_OF_BD_ADDRESS]; char name_buffer[100]; } scan_data_t; @@ -99,28 +103,33 @@ static scan_data_t devices[MAX_DEVICES_TO_SCAN]; static uint16_t buffer_size; static uint8_t devices_found; -int get_bt_address(uint8_t *addr) { +int get_bt_address(uint8_t *addr) +{ bd_addr_t local_addr; gap_local_bd_addr(local_addr); memcpy(addr, bd_addr_to_str(local_addr), SIZE_OF_BD_ADDRESS); return SIZE_OF_BD_ADDRESS; } -void bt_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_t report_id) { - hids_client_send_write_report(hids_cid, 1, HID_REPORT_TYPE_OUTPUT, send_report_buf, send_report_len); +void bt_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_t report_id) +{ + hids_host_send_write_report(hids_cid, 1, HID_REPORT_TYPE_OUTPUT, send_report_buf, send_report_len); memcpy(send_report_buf, data, len); send_report_len = len; } -bool check_bluetooth_ready() { +bool check_bluetooth_ready() +{ return app_state == READY; } -void bt_stop_scan() { +void bt_stop_scan() +{ gap_stop_scan(); } -static void bt_stop_scan_timer(btstack_timer_source_t *ts) { +static void bt_stop_scan_timer(btstack_timer_source_t *ts) +{ UNUSED(ts); printf("stop scan\r\n"); gap_stop_scan(); @@ -128,17 +137,19 @@ static void bt_stop_scan_timer(btstack_timer_source_t *ts) { /** * Start scanning */ -void bt_start_scan() { +void bt_start_scan() +{ printf("Scanning for LE HID devices...\r\n"); devices_found = 0; #ifdef BT_ADDR - if (has_address) { + if (has_address) + { strcpy(devices[0].name_buffer, bt_addr); devices_found = 1; } #endif // Passive scanning, 100% (scan interval = scan window) - gap_set_scan_parameters(0, 48, 48); + gap_set_scan_parameters(1, 48, 48); gap_start_scan(); // Auto stop scanning after 10 seconds btstack_run_loop_set_timer(&scan_timer, 10000); @@ -146,9 +157,11 @@ void bt_start_scan() { btstack_run_loop_add_timer(&scan_timer); } -int bt_get_scan_results(uint8_t *buf) { +int bt_get_scan_results(uint8_t *buf) +{ int size = 0; - for (int i = 0; i < devices_found; i++) { + for (int i = 0; i < devices_found; i++) + { int len = strnlen(devices[i].name_buffer, sizeof(devices[i].name_buffer)); memcpy(buf + size, devices[i].name_buffer, len); size += len; @@ -162,7 +175,8 @@ int bt_get_scan_results(uint8_t *buf) { * Handle timer event to trigger reconnect * @param ts */ -static void hog_reconnect_timeout(btstack_timer_source_t *ts) { +static void hog_reconnect_timeout(btstack_timer_source_t *ts) +{ UNUSED(ts); hog_connect(); } @@ -170,7 +184,8 @@ static void hog_reconnect_timeout(btstack_timer_source_t *ts) { * Handle timeout for outgoing connection * @param ts */ -static void hog_connection_timeout(btstack_timer_source_t *ts) { +static void hog_connection_timeout(btstack_timer_source_t *ts) +{ UNUSED(ts); printf("Timeout - abort connection\r\n"); gap_connect_cancel(); @@ -183,7 +198,8 @@ static void hog_connection_timeout(btstack_timer_source_t *ts) { /** * Connect to remote device but set timer for timeout */ -static void hog_connect(void) { +static void hog_connect(void) +{ // set timer btstack_run_loop_set_timer(&connection_timer, 10000); btstack_run_loop_set_timer_handler(&connection_timer, &hog_connection_timeout); @@ -192,7 +208,8 @@ static void hog_connect(void) { gap_connect(remote_device.addr, remote_device.addr_type); } -static void hog_start_reconnect_timer() { +static void hog_start_reconnect_timer() +{ btstack_run_loop_set_timer(&connection_timer, 100); btstack_run_loop_set_timer_handler(&connection_timer, &hog_reconnect_timeout); btstack_run_loop_add_timer(&connection_timer); @@ -201,8 +218,10 @@ static void hog_start_reconnect_timer() { /** * Start connecting after boot up: connect to last used device if possible, start scan otherwise */ -static void hog_start_connect(void) { - if (has_address) { +static void hog_start_connect(void) +{ + if (has_address) + { } // Only try to connect if we have "paired" a device #ifdef BT_ADDR @@ -213,7 +232,8 @@ static void hog_start_connect(void) { /** * In case of error, disconnect and start scanning again */ -static void handle_outgoing_connection_error(void) { +static void handle_outgoing_connection_error(void) +{ printf("Error occurred, disconnect and start over\r\n"); gap_disconnect(connection_handle); hog_start_reconnect_timer(); @@ -226,206 +246,312 @@ static void handle_outgoing_connection_error(void) { * @param packet * @param size */ -static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { +static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ UNUSED(packet_type); UNUSED(channel); UNUSED(size); uint8_t status; - if (hci_event_packet_get_type(packet) != HCI_EVENT_GATTSERVICE_META) { + if (hci_event_packet_get_type(packet) != HCI_EVENT_GATTSERVICE_META) + { return; } - switch (hci_event_gattservice_meta_get_subevent_code(packet)) { - case GATTSERVICE_SUBEVENT_HID_SERVICE_CONNECTED: - status = gattservice_subevent_hid_service_connected_get_status(packet); - switch (status) { - case ERROR_CODE_SUCCESS: - printf("HID service client connected, found %d services\r\n", - gattservice_subevent_hid_service_connected_get_num_instances(packet)); - - // store device as bonded - if (btstack_tlv_singleton_impl) { - btstack_tlv_singleton_impl->store_tag(btstack_tlv_singleton_context, TLV_TAG_HOGD, (const uint8_t *)&remote_device, sizeof(remote_device)); - } - - hids_client_get_hid_information(hids_cid, 0); - // done - printf("Ready - receiving data\r\n"); - app_state = READY; - bluetooth_connected(); - break; - default: - printf("HID service client connection failed, err 0x%02x.\r\n", status); - handle_outgoing_connection_error(); - break; + switch (hci_event_gattservice_meta_get_subevent_code(packet)) + { + case GATTSERVICE_SUBEVENT_HID_SERVICE_CONNECTED: + status = gattservice_subevent_hid_service_connected_get_status(packet); + switch (status) + { + case ERROR_CODE_SUCCESS: + printf("HID service client connected, found %d services\r\n", + gattservice_subevent_hid_service_connected_get_num_instances(packet)); + + // store device as bonded + if (btstack_tlv_singleton_impl) + { + btstack_tlv_singleton_impl->store_tag(btstack_tlv_singleton_context, TLV_TAG_HOGD, (const uint8_t *)&remote_device, sizeof(remote_device)); } + + hids_host_get_hid_information(hids_cid, 0); + // done + printf("Ready - receiving data\r\n"); + app_state = READY; + bluetooth_connected(); break; - case GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_PNP_ID: - status = gattservice_subevent_device_information_pnp_id_get_att_status(packet); - if (status != ATT_ERROR_SUCCESS) { - printf("PNP ID read failed, ATT Error 0x%02x\n", status); - } else { - vid = gattservice_subevent_device_information_pnp_id_get_vendor_id(packet); - pid = gattservice_subevent_device_information_pnp_id_get_product_id(packet); - version = gattservice_subevent_device_information_pnp_id_get_product_version(packet); - type.console_type = GENERIC; - get_usb_device_type_for(vid, pid, version, &type); - printf("Vendor Source ID: 0x%02x\r\n", gattservice_subevent_device_information_pnp_id_get_vendor_source_id(packet)); - printf("Vendor ID: 0x%04x\r\n", gattservice_subevent_device_information_pnp_id_get_vendor_id(packet)); - printf("Product ID: 0x%04x\r\n", gattservice_subevent_device_information_pnp_id_get_product_id(packet)); - printf("Product Version: 0x%04x\r\n", gattservice_subevent_device_information_pnp_id_get_product_version(packet)); - } + default: + printf("HID service client connection failed, err 0x%02x.\r\n", status); + handle_outgoing_connection_error(); break; - case GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_DONE: - printf("info done\r\n"); - // TODO: do other controllers work okay with this? - if (type.console_type == SANTROLLER) { - gap_update_connection_parameters(connection_handle, 6, 6, 0, 100); + } + break; + case GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_PNP_ID: + status = gattservice_subevent_device_information_pnp_id_get_att_status(packet); + if (status != ATT_ERROR_SUCCESS) + { + printf("PNP ID read failed, ATT Error 0x%02x\n", status); + } + else + { + vid = gattservice_subevent_device_information_pnp_id_get_vendor_id(packet); + pid = gattservice_subevent_device_information_pnp_id_get_product_id(packet); + version = gattservice_subevent_device_information_pnp_id_get_product_version(packet); + type.console_type = GENERIC; + get_usb_device_type_for(vid, pid, version, &type); + printf("Vendor Source ID: 0x%02x\r\n", gattservice_subevent_device_information_pnp_id_get_vendor_source_id(packet)); + printf("Vendor ID: 0x%04x\r\n", gattservice_subevent_device_information_pnp_id_get_vendor_id(packet)); + printf("Product ID: 0x%04x\r\n", gattservice_subevent_device_information_pnp_id_get_product_id(packet)); + printf("Product Version: 0x%04x\r\n", gattservice_subevent_device_information_pnp_id_get_product_version(packet)); + } + break; + case GATTSERVICE_SUBEVENT_DEVICE_INFORMATION_DONE: + printf("info done\r\n"); + // TODO: do other controllers work okay with this? + if (type.console_type == SANTROLLER) + { + gap_update_connection_parameters(connection_handle, 6, 6, 0, 100); + } + hids_host_connect(connection_handle, handle_gatt_client_event, protocol_mode, &hids_cid); + break; + case GATTSERVICE_SUBEVENT_HID_INFORMATION: + { + uint16_t cid = gattservice_subevent_hid_information_get_hids_cid(packet); + if (type.console_type == GENERIC) + { + foundPS3 = false; + foundPS4 = false; + foundPS5 = false; + USB_ProcessHIDReport(hids_host_descriptor_storage_get_descriptor_data(cid, 0), hids_host_descriptor_storage_get_descriptor_len(cid, 0), &info); + + if (foundPS5) + { + type.console_type = PS5; } - hids_client_connect(connection_handle, handle_gatt_client_event, protocol_mode, &hids_cid); - break; - case GATTSERVICE_SUBEVENT_HID_INFORMATION: { - uint16_t cid = gattservice_subevent_hid_information_get_hids_cid(packet); - if (type.console_type == GENERIC) { - foundPS3 = false; - foundPS4 = false; - foundPS5 = false; - USB_ProcessHIDReport(hids_client_descriptor_storage_get_descriptor_data(cid, 0), hids_client_descriptor_storage_get_descriptor_len(cid, 0), &info); - - if (foundPS5) { - type.console_type = PS5; - } - if (foundPS4) { - type.console_type = PS4; - } - if (foundPS3) { - type.console_type = PS3; - } + if (foundPS4) + { + type.console_type = PS4; } - break; - } - case GATTSERVICE_SUBEVENT_HID_REPORT: { - if (type.console_type == GENERIC) { - fill_generic_report(info, gattservice_subevent_hid_report_get_report(packet), &bt_data); - break; + if (foundPS3) + { + type.console_type = PS3; } - tick_bluetooth(gattservice_subevent_hid_report_get_report(packet), gattservice_subevent_hid_report_get_report_len(packet), type); + } + break; + } + case GATTSERVICE_SUBEVENT_HID_REPORT: + { + if (type.console_type == GENERIC) + { + fill_generic_report(info, gattservice_subevent_hid_report_get_report(packet), &bt_data); break; } + tick_bluetooth(gattservice_subevent_hid_report_get_report(packet), gattservice_subevent_hid_report_get_report_len(packet), type); + break; + } - default: - break; + default: + break; } } - /* LISTING_START(packetHandler): Packet Handler */ -static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { +static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ /* LISTING_PAUSE */ UNUSED(channel); UNUSED(size); uint8_t event; /* LISTING_RESUME */ - switch (packet_type) { - case HCI_EVENT_PACKET: - event = hci_event_packet_get_type(packet); - switch (event) { - case BTSTACK_EVENT_STATE: - if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) break; - btstack_assert(app_state == W4_WORKING); - - hog_start_connect(); - break; - case GAP_EVENT_ADVERTISING_REPORT: { - if (adv_event_contains_hid_service(packet) == false) break; - // store remote device address and type - bd_addr_t address; - gap_event_advertising_report_get_address(packet, address); - const uint8_t *adv_data = gap_event_advertising_report_get_data(packet); - uint8_t adv_size = gap_event_advertising_report_get_data_length(packet); - ad_context_t context; - for (ad_iterator_init(&context, adv_size, adv_data); ad_iterator_has_more(&context); ad_iterator_next(&context)) { - uint8_t data_type = ad_iterator_get_data_type(&context); - if (data_type != BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME) { - continue; + switch (packet_type) + { + case HCI_EVENT_PACKET: + event = hci_event_packet_get_type(packet); + switch (event) + { + case BTSTACK_EVENT_STATE: + if (btstack_event_state_get_state(packet) != HCI_STATE_WORKING) + break; + btstack_assert(app_state == W4_WORKING); + + hog_start_connect(); + break; + case GAP_EVENT_ADVERTISING_REPORT: + { + // store remote device address and type + bd_addr_t address; + bool has_name = false; + gap_event_advertising_report_get_address(packet, address); + const uint8_t *adv_data = gap_event_advertising_report_get_data(packet); + uint8_t adv_size = gap_event_advertising_report_get_data_length(packet); + ad_context_t context; + + char *address_string = bd_addr_to_str(address); + bool found = false; + int current_device = devices_found; + for (int i = 0; i < devices_found; i++) + { + if (memcmp(address_string, devices[i].addr, SIZE_OF_BD_ADDRESS) == 0) + { + found = true; + current_device = i; + } + } + for (ad_iterator_init(&context, adv_size, adv_data); ad_iterator_has_more(&context); ad_iterator_next(&context)) + { + uint8_t data_type = ad_iterator_get_data_type(&context); + uint8_t data_len = ad_iterator_get_data_len(&context); + const uint8_t *data = ad_iterator_get_data(&context); + + uint8_t i; + uint8_t ad_uuid128[16], uuid128_bt[16]; + switch (data_type) + { + case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS: + case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_16_BIT_SERVICE_CLASS_UUIDS: + for (i = 0u; (i + 2u) <= data_len; i += 2u) + { + uint16_t uuid = (uint16_t)little_endian_read_16(data, (int)i); + if (uuid == ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE) + { + if (!found) + { + memcpy(devices[devices_found].addr, address_string, SIZE_OF_BD_ADDRESS); + devices[devices_found].name_buffer[0] = ' '; + devices[devices_found].name_buffer[0 + 1] = '('; + memcpy(devices[devices_found].name_buffer + 0 + 2, address_string, SIZE_OF_BD_ADDRESS); + devices[devices_found].name_buffer[0 + SIZE_OF_BD_ADDRESS + 1] = ')'; + devices[devices_found].name_buffer[0 + SIZE_OF_BD_ADDRESS + 2] = 0; + found = true; + devices_found++; + printf("found device: %s\n", devices[devices_found - 1].name_buffer); + } + break; } - uint8_t size = ad_iterator_get_data_len(&context); - const uint8_t *data = ad_iterator_get_data(&context); - char *address_string = bd_addr_to_str(address); - bool found = false; - int current_device = devices_found; - for (int i = 0; i < devices_found; i++) { - if (memcmp(address_string, devices[i].addr, SIZE_OF_BD_ADDRESS) == 0) { + } + continue; + case BLUETOOTH_DATA_TYPE_INCOMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS: + case BLUETOOTH_DATA_TYPE_COMPLETE_LIST_OF_128_BIT_SERVICE_CLASS_UUIDS: + uuid_add_bluetooth_prefix(ad_uuid128, ORG_BLUETOOTH_SERVICE_HUMAN_INTERFACE_DEVICE); + reverse_128(ad_uuid128, uuid128_bt); + for (i = 0u; (i + 16u) <= data_len; i += 16u) + { + if (memcmp(uuid128_bt, &data[i], 16) == 0) + { + if (!found) + { + memcpy(devices[devices_found].addr, address_string, SIZE_OF_BD_ADDRESS); + devices[devices_found].name_buffer[0] = ' '; + devices[devices_found].name_buffer[0 + 1] = '('; + memcpy(devices[devices_found].name_buffer + 0 + 2, address_string, SIZE_OF_BD_ADDRESS); + devices[devices_found].name_buffer[0 + SIZE_OF_BD_ADDRESS + 1] = ')'; + devices[devices_found].name_buffer[0 + SIZE_OF_BD_ADDRESS + 2] = 0; found = true; + devices_found++; + printf("found device: %s\n", devices[devices_found - 1].name_buffer); } + break; } - if (!found) { + } + continue; + case BLUETOOTH_DATA_TYPE_APPEARANCE: + if (little_endian_read_16(data, 0) == 0x03C4) + { + if (!found) + { memcpy(devices[devices_found].addr, address_string, SIZE_OF_BD_ADDRESS); - memcpy(devices[devices_found].name_buffer, data, size); - devices[devices_found].name_buffer[size] = ' '; - devices[devices_found].name_buffer[size + 1] = '('; - memcpy(devices[devices_found].name_buffer + size + 2, address_string, SIZE_OF_BD_ADDRESS); - devices[devices_found].name_buffer[size + SIZE_OF_BD_ADDRESS + 1] = ')'; - devices[devices_found].name_buffer[size + SIZE_OF_BD_ADDRESS + 2] = 0; - printf("Found device '%s'\r\n", devices[devices_found].name_buffer); + devices[devices_found].name_buffer[0] = ' '; + devices[devices_found].name_buffer[0 + 1] = '('; + memcpy(devices[devices_found].name_buffer + 0 + 2, address_string, SIZE_OF_BD_ADDRESS); + devices[devices_found].name_buffer[0 + SIZE_OF_BD_ADDRESS + 1] = ')'; + devices[devices_found].name_buffer[0 + SIZE_OF_BD_ADDRESS + 2] = 0; + found = true; devices_found++; + printf("found device name: %s\n", devices[devices_found - 1].name_buffer); } } - break; - } - case HCI_EVENT_DISCONNECTION_COMPLETE: - if (app_state != READY) break; - hids_client_disconnect(hids_cid); - connection_handle = HCI_CON_HANDLE_INVALID; - switch (app_state) { - case READY: - printf("\r\nDisconnected, try to reconnect...\r\n"); - app_state = W4_TIMEOUT_THEN_RECONNECT; - break; - default: - printf("\r\nDisconnected, start over...\r\n"); - app_state = W4_TIMEOUT_THEN_SCAN; - break; + continue; + case BLUETOOTH_DATA_TYPE_COMPLETE_LOCAL_NAME: + if (found) + { + memcpy(devices[current_device].name_buffer, data, data_len); + devices[current_device].name_buffer[data_len] = ' '; + devices[current_device].name_buffer[data_len + 1] = '('; + memcpy(devices[current_device].name_buffer + data_len + 2, address_string, SIZE_OF_BD_ADDRESS); + devices[current_device].name_buffer[data_len + SIZE_OF_BD_ADDRESS + 1] = ')'; + devices[current_device].name_buffer[data_len + SIZE_OF_BD_ADDRESS + 2] = 0; + has_name = true; + printf("has name '%s'\r\n", devices[current_device].name_buffer); } - hog_start_reconnect_timer(); - break; - - case HCI_EVENT_LE_META: - switch (hci_event_le_meta_get_subevent_code(packet)) { - case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: { - // print connection parameters (without using float operations) - uint16_t conn_interval = hci_subevent_le_connection_complete_get_conn_interval(packet); - printf("LE Connection Complete:\r\n"); - printf("- Connection Interval: %u.%02u ms\r\n", conn_interval * 125 / 100, 25 * (conn_interval & 3)); - printf("- Connection Latency: %u\r\n", hci_subevent_le_connection_complete_get_conn_latency(packet)); - break; - } - case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: { - // print connection parameters (without using float operations) - uint16_t conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet); - printf("LE Connection Update:\r\n"); - printf("- Connection Interval: %u.%02u ms\r\n", conn_interval * 125 / 100, 25 * (conn_interval & 3)); - printf("- Connection Latency: %u\r\n", hci_subevent_le_connection_update_complete_get_conn_latency(packet)); - break; - } - default: - break; - } - // wait for connection complete - if (hci_event_le_meta_get_subevent_code(packet) != HCI_SUBEVENT_LE_CONNECTION_COMPLETE) break; - if (app_state != W4_CONNECTED) return; - btstack_run_loop_remove_timer(&connection_timer); - connection_handle = hci_subevent_le_connection_complete_get_connection_handle(packet); - // request security - app_state = W4_ENCRYPTED; - sm_request_pairing(connection_handle); - break; - default: - break; + continue; + } + } + break; + } + case HCI_EVENT_DISCONNECTION_COMPLETE: + if (app_state != READY) + break; + hids_host_disconnect(hids_cid); + connection_handle = HCI_CON_HANDLE_INVALID; + switch (app_state) + { + case READY: + printf("\r\nDisconnected, try to reconnect...\r\n"); + app_state = W4_TIMEOUT_THEN_RECONNECT; + break; + default: + printf("\r\nDisconnected, start over...\r\n"); + app_state = W4_TIMEOUT_THEN_SCAN; + break; + } + hog_start_reconnect_timer(); + break; + case HCI_EVENT_META_GAP: + // wait for connection complete + if (hci_event_gap_meta_get_subevent_code(packet) != GAP_SUBEVENT_LE_CONNECTION_COMPLETE) break; + if (app_state != W4_CONNECTED) return; + btstack_run_loop_remove_timer(&connection_timer); + connection_handle = gap_subevent_le_connection_complete_get_connection_handle(packet); + // request security + app_state = W4_ENCRYPTED; + sm_request_pairing(connection_handle); + break; + case HCI_EVENT_LE_META: + printf("hci evt le: %02x\r\n", hci_event_le_meta_get_subevent_code(packet)); + switch (hci_event_le_meta_get_subevent_code(packet)) + { + case HCI_SUBEVENT_LE_CONNECTION_COMPLETE: + { + // print connection parameters (without using float operations) + uint16_t conn_interval = hci_subevent_le_connection_complete_get_conn_interval(packet); + printf("LE Connection Complete:\r\n"); + printf("- Connection Interval: %u.%02u ms\r\n", conn_interval * 125 / 100, 25 * (conn_interval & 3)); + printf("- Connection Latency: %u\r\n", hci_subevent_le_connection_complete_get_conn_latency(packet)); + break; + } + case HCI_SUBEVENT_LE_DATA_LENGTH_CHANGE: + connection_handle = hci_subevent_le_data_length_change_get_connection_handle(packet); + printf("- LE Connection 0x%04x: data length change - max %u bytes per packet\n", connection_handle, + hci_subevent_le_data_length_change_get_max_tx_octets(packet)); + break; + case HCI_SUBEVENT_LE_CONNECTION_UPDATE_COMPLETE: + { + // print connection parameters (without using float operations) + uint16_t conn_interval = hci_subevent_le_connection_update_complete_get_conn_interval(packet); + printf("LE Connection Update:\r\n"); + printf("- Connection Interval: %u.%02u ms\r\n", conn_interval * 125 / 100, 25 * (conn_interval & 3)); + printf("- Connection Latency: %u\r\n", hci_subevent_le_connection_update_complete_get_conn_latency(packet)); + break; + } + default: + break; } break; default: break; + } + break; + default: + break; } } /* LISTING_END */ @@ -439,64 +565,69 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe /* LISTING_START(SMPacketHandler): Scanning and receiving advertisements */ -static void sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) { +static void sm_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size) +{ UNUSED(channel); UNUSED(size); - if (packet_type != HCI_EVENT_PACKET) return; - - switch (hci_event_packet_get_type(packet)) { - case SM_EVENT_JUST_WORKS_REQUEST: - printf("Just works requested\r\n"); - sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); - break; - case SM_EVENT_NUMERIC_COMPARISON_REQUEST: - printf("Confirming numeric comparison: %" PRIu32 "\r\n", sm_event_numeric_comparison_request_get_passkey(packet)); - sm_numeric_comparison_confirm(sm_event_passkey_display_number_get_handle(packet)); + if (packet_type != HCI_EVENT_PACKET) + return; + printf("hci evt: %02x\r\n", hci_event_packet_get_type(packet)); + switch (hci_event_packet_get_type(packet)) + { + case SM_EVENT_JUST_WORKS_REQUEST: + printf("Just works requested\r\n"); + sm_just_works_confirm(sm_event_just_works_request_get_handle(packet)); + break; + case SM_EVENT_NUMERIC_COMPARISON_REQUEST: + printf("Confirming numeric comparison: %" PRIu32 "\r\n", sm_event_numeric_comparison_request_get_passkey(packet)); + sm_numeric_comparison_confirm(sm_event_passkey_display_number_get_handle(packet)); + break; + case SM_EVENT_PASSKEY_DISPLAY_NUMBER: + printf("Display Passkey: %" PRIu32 "\r\n", sm_event_passkey_display_number_get_passkey(packet)); + break; + case SM_EVENT_PAIRING_COMPLETE: + switch (sm_event_pairing_complete_get_status(packet)) + { + case ERROR_CODE_SUCCESS: + printf("Pairing complete, success\r\n"); + + // continue - query primary services + printf("Search for HID service.\r\n"); + app_state = W4_HID_CLIENT_CONNECTED; + // TODO: figure out why device_information_service isnt working anymore + device_information_service_client_query(connection_handle, handle_gatt_client_event); + // hids_host_connect(connection_handle, handle_gatt_client_event, protocol_mode, &hids_cid); break; - case SM_EVENT_PASSKEY_DISPLAY_NUMBER: - printf("Display Passkey: %" PRIu32 "\r\n", sm_event_passkey_display_number_get_passkey(packet)); + case ERROR_CODE_CONNECTION_TIMEOUT: + printf("Pairing failed, timeout\r\n"); + hog_start_reconnect_timer(); break; - case SM_EVENT_PAIRING_COMPLETE: - switch (sm_event_pairing_complete_get_status(packet)) { - case ERROR_CODE_SUCCESS: - printf("Pairing complete, success\r\n"); - - // continue - query primary services - printf("Search for HID service.\r\n"); - app_state = W4_HID_CLIENT_CONNECTED; - // TODO: figure out why device_information_service isnt working anymore - device_information_service_client_query(connection_handle, handle_gatt_client_event); - // hids_client_connect(connection_handle, handle_gatt_client_event, protocol_mode, &hids_cid); - break; - case ERROR_CODE_CONNECTION_TIMEOUT: - printf("Pairing failed, timeout\r\n"); - hog_start_reconnect_timer(); - break; - case ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION: - printf("Pairing failed, disconnected\r\n"); - hog_start_reconnect_timer(); - break; - case ERROR_CODE_AUTHENTICATION_FAILURE: - printf("Pairing failed, reason = %u\r\n", sm_event_pairing_complete_get_reason(packet)); - hog_start_reconnect_timer(); - break; - default: - break; - } + case ERROR_CODE_REMOTE_USER_TERMINATED_CONNECTION: + printf("Pairing failed, disconnected\r\n"); + hog_start_reconnect_timer(); break; - case SM_EVENT_REENCRYPTION_COMPLETE: - printf("Re-encryption complete, success\n"); - app_state = W4_HID_CLIENT_CONNECTED; - device_information_service_client_query(connection_handle, handle_gatt_client_event); + case ERROR_CODE_AUTHENTICATION_FAILURE: + printf("Pairing failed, reason = %u\r\n", sm_event_pairing_complete_get_reason(packet)); + hog_start_reconnect_timer(); break; default: break; + } + break; + case SM_EVENT_REENCRYPTION_COMPLETE: + printf("Re-encryption complete, success\n"); + app_state = W4_HID_CLIENT_CONNECTED; + device_information_service_client_query(connection_handle, handle_gatt_client_event); + break; + default: + break; } } /* LISTING_END */ -int btstack_main(void) { +int btstack_main(void) +{ printf("Bt init\r\n"); #ifdef BT_ADDR #ifdef CONFIGURABLE_BLOBS @@ -504,13 +635,25 @@ int btstack_main(void) { #else has_address = true; #endif - if (has_address) { + if (has_address) + { sscanf_bd_addr(bt_addr, remote_device.addr); remote_device.addr_type = BD_ADDR_TYPE_LE_PUBLIC; } #endif + /* LISTING_START(HogBootHostSetup): HID-over-GATT Host Setup */ + // hci_dump_init(hci_dump_embedded_stdout_get_instance()); + + // + l2cap_init(); + sm_init(); + sm_set_io_capabilities(IO_CAPABILITY_DISPLAY_ONLY); + sm_set_authentication_requirements(SM_AUTHREQ_SECURE_CONNECTION | SM_AUTHREQ_BONDING); + gatt_client_init(); + hids_host_init(hid_descriptor_storage, sizeof(hid_descriptor_storage)); + device_information_service_client_init(); // register for events from HCI hci_event_callback_registration.callback = &packet_handler; hci_add_event_handler(&hci_event_callback_registration); @@ -518,14 +661,8 @@ int btstack_main(void) { // register for events from Security Manager sm_event_callback_registration.callback = &sm_packet_handler; sm_add_event_handler(&sm_event_callback_registration); + sm_set_authentication_requirements( SM_AUTHREQ_BONDING); - // - l2cap_init(); - sm_init(); - gatt_client_init(); - - hids_client_init(hid_descriptor_storage, sizeof(hid_descriptor_storage)); - device_information_service_client_init(); app_state = W4_WORKING; // Turn on the device From b15efee43857e72464c92dbf18a92be34db0d4e3 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 7 Jul 2026 13:00:25 +1200 Subject: [PATCH 192/239] add pid for xb series controller --- src/shared/main/shared_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index a5f2814cd..26b0e80a6 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -4664,7 +4664,7 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D } break; case XBOX_ONE_CONTROLLER_VID: - if (pid >= 0x02e0 && pid <= 0x02eF && type->console_type != XBOXONE) + if ((pid >= 0x02e0 && pid <= 0x02eF || pid == 0x0b13) && type->console_type != XBOXONE) { type->console_type = XINPUTCOMPAT; type->sub_type = GAMEPAD; From 0654f5cad0c7c97734e2aaefd6a096c8dada6aba Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 7 Jul 2026 13:38:23 +1200 Subject: [PATCH 193/239] only use festival mappings for guitar mode --- src/shared/main/shared_main.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 26b0e80a6..9f41ceff3 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2244,12 +2244,15 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t usb_host_data->dpadRight |= dpad == 3 || dpad == 2 || dpad == 1; usb_host_data->dpadUp |= dpad == 0 || dpad == 1 || dpad == 7; usb_host_data->dpadDown |= dpad == 5 || dpad == 4 || dpad == 3; + +#if DEVICE_TYPE_IS_GUITAR // Festival pro mode mappings usb_host_data->green |= dpad == 6 || dpad == 5 || dpad == 7; usb_host_data->red |= dpad == 0 || dpad == 1 || dpad == 7; usb_host_data->yellow |= report->x; usb_host_data->blue |= report->y; usb_host_data->orange |= report->b; +#endif // Festival expert mappings // usb_host_data->green |= dpad == 6 || dpad == 5 || dpad == 7; // usb_host_data->red |= dpad == 3 || dpad == 2 || dpad == 1; From 8860094994ef4ff24e0f81897de29022edee7e99 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 7 Jul 2026 14:30:46 +1200 Subject: [PATCH 194/239] fix xbox one pad mappings for bt --- include/defines.h | 1 + include/reports/xinput_reports.h | 55 ++++++++++++++++++++++++++++---- src/shared/main/shared_main.cpp | 54 +++++++++++++++++++++++++++++-- 3 files changed, 101 insertions(+), 9 deletions(-) diff --git a/include/defines.h b/include/defines.h index d623458b8..a562b13aa 100644 --- a/include/defines.h +++ b/include/defines.h @@ -105,6 +105,7 @@ #define STADIA 30 #define XINPUTCOMPAT 31 #define SWITCH2 32 +#define XINPUTCOMPAT_NEO_S 33 #define NON_CONTROLLER 0xFE #define UNKNOWN 0xFF diff --git a/include/reports/xinput_reports.h b/include/reports/xinput_reports.h index a37e66b3f..d1ac8a19a 100644 --- a/include/reports/xinput_reports.h +++ b/include/reports/xinput_reports.h @@ -133,7 +133,48 @@ typedef struct uint8_t reserved_1[6]; } __attribute__((packed)) XInputGamepad_Data_t; +// 0x01 +// 0x02 +// 0x08 +// 0x10 +// 0x40 +// 0x80 +typedef struct +{ + uint8_t rid; + uint16_t leftStickX; + uint16_t leftStickY; + uint16_t rightStickX; + uint16_t rightStickY; + uint16_t leftTrigger; + uint16_t rightTrigger; + + uint8_t dpad : 4; + uint8_t : 4; + + uint8_t a : 1; + uint8_t b : 1; + uint8_t : 1; + uint8_t x : 1; + + uint8_t y : 1; + uint8_t :1; + uint8_t leftShoulder : 1; + uint8_t rightShoulder : 1; + uint8_t :1; + uint8_t :1; + uint8_t back : 1; + uint8_t start : 1; + + uint8_t guide:1; + uint8_t leftThumbClick : 1; + uint8_t rightThumbClick : 1; + uint8_t : 1; + + uint8_t capture : 1; + uint8_t : 3; +} __attribute__((packed)) XInputCompatGamepad_Data_t; typedef struct { uint8_t rid; @@ -159,7 +200,7 @@ typedef struct uint8_t leftThumbClick : 1; uint8_t rightThumbClick : 1; uint8_t : 6; -} __attribute__((packed)) XInputCompatGamepad_Data_t; +} __attribute__((packed)) XInputCompatGamepad2_Data_t; typedef struct { @@ -548,13 +589,13 @@ typedef struct uint8_t y : 1; uint8_t penPressure; // starts at 0x72, goes up to 0xff - uint8_t accelZ; // 0x0a to 0x35 - uint8_t penX; // - uint8_t penY; - uint8_t status; // 0x40 = pen touch, 0x80 = single finger, anything else = multi touch + uint8_t accelZ; // 0x0a to 0x35 + uint8_t penX; // + uint8_t penY; + uint8_t status; // 0x40 = pen touch, 0x80 = single finger, anything else = multi touch uint8_t distance; // distance between fingers for multitouch - uint8_t accelX; // 0x0a to 0x35 - uint8_t accelY; // 0x0a to 0x35 + uint8_t accelX; // 0x0a to 0x35 + uint8_t accelY; // 0x0a to 0x35 uint8_t reserved_1[6]; } __attribute__((packed)) XInputUDraw_Data_t; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 9f41ceff3..63ab6c010 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -2229,9 +2229,9 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t break; } - case XINPUTCOMPAT: + case XINPUTCOMPAT_NEO_S: { - XInputCompatGamepad_Data_t *report = (XInputCompatGamepad_Data_t *)data; + XInputCompatGamepad2_Data_t *report = (XInputCompatGamepad2_Data_t *)data; if (report->rid == 2) { usb_host_data->guide = data[1]; @@ -2303,6 +2303,56 @@ void convert_report(const uint8_t *data, uint8_t len, USB_Device_Type_t device_t } break; } + case XINPUTCOMPAT: + { + XInputCompatGamepad_Data_t *report = (XInputCompatGamepad_Data_t *)data; + if (report->rid == 1) + { + uint8_t dpad = report->dpad - 1; + usb_host_data->dpadLeft |= dpad == 6 || dpad == 5 || dpad == 7; + usb_host_data->dpadRight |= dpad == 3 || dpad == 2 || dpad == 1; + usb_host_data->dpadUp |= dpad == 0 || dpad == 1 || dpad == 7; + usb_host_data->dpadDown |= dpad == 5 || dpad == 4 || dpad == 3; + + usb_host_data->a |= report->a; + usb_host_data->b |= report->b; + usb_host_data->x |= report->x; + usb_host_data->y |= report->y; + usb_host_data->leftShoulder |= report->leftShoulder; + usb_host_data->rightShoulder |= report->rightShoulder; + usb_host_data->back |= report->back; + usb_host_data->start |= report->start; + usb_host_data->guide |= report->guide; + usb_host_data->capture |= report->capture; + usb_host_data->leftThumbClick |= report->leftThumbClick; + usb_host_data->rightThumbClick |= report->rightThumbClick; + if (report->leftTrigger) + { + usb_host_data->leftTrigger = report->leftTrigger << 6; + } + if (report->rightTrigger) + { + usb_host_data->rightTrigger = report->rightTrigger << 6; + } + if (report->leftStickX != 0x8000) + { + usb_host_data->leftStickX = report->leftStickX - 0x8000; + } + if (report->leftStickY != 0x8000) + { + usb_host_data->leftStickY = ((UINT16_MAX - report->leftStickY) - 0x8000); + } + if (report->rightStickX != 0x8000) + { + usb_host_data->rightStickX = report->rightStickX - 0x8000; + } + if (report->rightStickY != 0x8000) + { + usb_host_data->rightStickY = ((UINT16_MAX - report->rightStickY) - 0x8000); + } + } + break; + } case XBOX360_W: case XBOX360: { From 86279c5302e4f86639f71cf2c298783fb48a7c96 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 7 Jul 2026 14:57:14 +1200 Subject: [PATCH 195/239] add pid for ds edge --- include/endpoints.h | 3 ++- src/shared/main/shared_main.cpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/endpoints.h b/include/endpoints.h index 3ab03e13f..880ab38d5 100644 --- a/include/endpoints.h +++ b/include/endpoints.h @@ -51,7 +51,8 @@ enum endpoints_t { #define PS4_RIFFMASTER_PID 0x024A #define PS4_MADCATZ_DRUM_PID 0x8262 #define XBOX_ONE_RIFFMASTER_PID 0x0248 -#define PS5_DS_PID 0x0ce6 +#define PS5_DS_PID 0x0CE6 +#define PS5_DS_EDGE_PID 0x0DF2 #define PS5_RIFFMASTER_PID 0x0249 #define PS3_GH_GUITAR_PID 0x0100 #define PS3_GH_DRUM_PID 0x0120 diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 63ab6c010..0ac10431d 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -4531,6 +4531,7 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D type->sub_type = GAMEPAD; break; case PS5_DS_PID: + case PS5_DS_EDGE_PID: type->console_type = PS5; type->sub_type = GAMEPAD; break; From b20e2b275b07788d1ee4ef48f5bafad2c65e0565 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 10 Jul 2026 16:47:26 +1200 Subject: [PATCH 196/239] bump arduino-pico --- platformio.ini | 2 +- src/pico/main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index caa0beb04..92f72707a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ board_upload.ardwiino_bootloader_teensy = true board_build.use_usb = 1 platform = https://github.com/maxgerhardt/platform-raspberrypi/archive/39b90392af50585e429941bd2561a91949a2ba46.zip@1.15.0 platform_packages = - framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.13-sanjay/rp2040-4.6.13-sanjay.zip@1.50404.0 + framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.14-sanjay/rp2040-4.6.14-sanjay.zip@1.50404.0 board = pico framework = arduino board_build.core = earlephilhower diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 3ddc36486..c4cb1f3bd 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -292,7 +292,7 @@ void setup() skip_alarm_pool : false, pinout : PIO_USB_PINOUT_DPDM }; - tuh_configure(0, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &config); + tuh_configure(TUH_OPT_RHPORT, TUH_CFGID_RPI_PIO_USB_CONFIGURATION, &config); const tusb_rhport_init_t rh_init = { .role = TUSB_ROLE_HOST, .speed = TUH_OPT_HIGH_SPEED ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL, From 542a862dcdc263df17b9a4dcae094dd039419755 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 15 Jul 2026 12:20:43 +1200 Subject: [PATCH 197/239] port over midi logic from s2 --- include/Usb.h | 235 +++++++++++ include/hid.h | 2 +- include/midi.hpp | 47 +++ include/midi_descriptors.h | 32 ++ include/shared_main.h | 3 + include/usbhid.h | 115 ++++++ platformio.ini | 2 - src/pico/TUSB-MIDI.hpp | 198 --------- src/pico/TUSB-MIDI_defs.hpp | 36 -- src/pico/main.cpp | 79 ++-- src/pico/midi.cpp | 272 +++++++++++++ src/pico/midi_host.c | 692 -------------------------------- src/pico/midi_host.cpp | 541 +++++++++++++++++++++++++ src/pico/xinput_device.cpp | 1 + src/shared/hid/hid.cpp | 3 +- src/shared/main/shared_main.cpp | 217 +++++----- src/shared/usb/descriptors.cpp | 5 +- 17 files changed, 1377 insertions(+), 1103 deletions(-) create mode 100644 include/Usb.h create mode 100644 include/midi.hpp create mode 100644 include/usbhid.h delete mode 100644 src/pico/TUSB-MIDI.hpp delete mode 100644 src/pico/TUSB-MIDI_defs.hpp create mode 100644 src/pico/midi.cpp delete mode 100644 src/pico/midi_host.c create mode 100644 src/pico/midi_host.cpp diff --git a/include/Usb.h b/include/Usb.h new file mode 100644 index 000000000..39aab0d8b --- /dev/null +++ b/include/Usb.h @@ -0,0 +1,235 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#pragma once +#include "stdint.h" +#include "usbhid.h" +/* USB chapter 9 structures */ +#define _ch9_h_ + +// USB Device Classes +#define USB_CLASS_USE_CLASS_INFO 0x00 // Use Class Info in the Interface Descriptors +#define USB_CLASS_AUDIO 0x01 // Audio +#define USB_CLASS_COM_AND_CDC_CTRL 0x02 // Communications and CDC Control +#define USB_CLASS_HID 0x03 // HID +#define USB_CLASS_PHYSICAL 0x05 // Physical +#define USB_CLASS_IMAGE 0x06 // Image +#define USB_CLASS_PRINTER 0x07 // Printer +#define USB_CLASS_MASS_STORAGE 0x08 // Mass Storage +#define USB_CLASS_HUB 0x09 // Hub +#define USB_CLASS_CDC_DATA 0x0a // CDC-Data +#define USB_CLASS_SMART_CARD 0x0b // Smart-Card +#define USB_CLASS_CONTENT_SECURITY 0x0d // Content Security +#define USB_CLASS_VIDEO 0x0e // Video +#define USB_CLASS_PERSONAL_HEALTH 0x0f // Personal Healthcare +#define USB_CLASS_DIAGNOSTIC_DEVICE 0xdc // Diagnostic Device +#define USB_CLASS_WIRELESS_CTRL 0xe0 // Wireless Controller +#define USB_CLASS_MISC 0xef // Miscellaneous +#define USB_CLASS_APP_SPECIFIC 0xfe // Application Specific +#define USB_CLASS_VENDOR_SPECIFIC 0xff // Vendor Specific + +// Additional Error Codes +#define USB_DEV_CONFIG_ERROR_DEVICE_NOT_SUPPORTED 0xD1 +#define USB_DEV_CONFIG_ERROR_DEVICE_INIT_INCOMPLETE 0xD2 +#define USB_ERROR_UNABLE_TO_REGISTER_DEVICE_CLASS 0xD3 +#define USB_ERROR_OUT_OF_ADDRESS_SPACE_IN_POOL 0xD4 +#define USB_ERROR_HUB_ADDRESS_OVERFLOW 0xD5 +#define USB_ERROR_ADDRESS_NOT_FOUND_IN_POOL 0xD6 +#define USB_ERROR_EPINFO_IS_NULL 0xD7 +#define USB_ERROR_INVALID_ARGUMENT 0xD8 +#define USB_ERROR_CLASS_INSTANCE_ALREADY_IN_USE 0xD9 +#define USB_ERROR_INVALID_MAX_PKT_SIZE 0xDA +#define USB_ERROR_EP_NOT_FOUND_IN_TBL 0xDB +#define USB_ERROR_CONFIG_REQUIRES_ADDITIONAL_RESET 0xE0 +#define USB_ERROR_FailGetDevDescr 0xE1 +#define USB_ERROR_FailSetDevTblEntry 0xE2 +#define USB_ERROR_FailGetConfDescr 0xE3 +#define USB_ERROR_TRANSFER_TIMEOUT 0xFF + +#define USB_XFER_TIMEOUT 5000 // (5000) USB transfer timeout in milliseconds, per section 9.2.6.1 of USB 2.0 spec +//#define USB_NAK_LIMIT 32000 // NAK limit for a transfer. 0 means NAKs are not counted +#define USB_RETRY_LIMIT 3 // 3 retry limit for a transfer +#define USB_SETTLE_DELAY 200 // settle delay in milliseconds + +#define USB_NUMDEVICES 16 //number of USB devices +//#define HUB_MAX_HUBS 7 // maximum number of hubs that can be attached to the host controller +#define HUB_PORT_RESET_DELAY 20 // hub port reset delay 10 ms recomended, can be up to 20 ms + +/* USB state machine states */ +#define USB_STATE_MASK 0xf0 + +#define USB_STATE_DETACHED 0x10 +#define USB_DETACHED_SUBSTATE_INITIALIZE 0x11 +#define USB_DETACHED_SUBSTATE_WAIT_FOR_DEVICE 0x12 +#define USB_DETACHED_SUBSTATE_ILLEGAL 0x13 +#define USB_ATTACHED_SUBSTATE_SETTLE 0x20 +#define USB_ATTACHED_SUBSTATE_RESET_DEVICE 0x30 +#define USB_ATTACHED_SUBSTATE_WAIT_RESET_COMPLETE 0x40 +#define USB_ATTACHED_SUBSTATE_WAIT_SOF 0x50 +#define USB_ATTACHED_SUBSTATE_WAIT_RESET 0x51 +#define USB_ATTACHED_SUBSTATE_GET_DEVICE_DESCRIPTOR_SIZE 0x60 +#define USB_STATE_ADDRESSING 0x70 +#define USB_STATE_CONFIGURING 0x80 +#define USB_STATE_RUNNING 0x90 +#define USB_STATE_ERROR 0xa0 + +/* Misc.USB constants */ +#define DEV_DESCR_LEN 18 //device descriptor length +#define CONF_DESCR_LEN 9 //configuration descriptor length +#define INTR_DESCR_LEN 9 //interface descriptor length +#define EP_DESCR_LEN 7 //endpoint descriptor length + +/* Standard Device Requests */ + +#define USB_REQUEST_GET_STATUS 0 // Standard Device Request - GET STATUS +#define USB_REQUEST_CLEAR_FEATURE 1 // Standard Device Request - CLEAR FEATURE +#define USB_REQUEST_SET_FEATURE 3 // Standard Device Request - SET FEATURE +#define USB_REQUEST_SET_ADDRESS 5 // Standard Device Request - SET ADDRESS +#define USB_REQUEST_GET_DESCRIPTOR 6 // Standard Device Request - GET DESCRIPTOR +#define USB_REQUEST_SET_DESCRIPTOR 7 // Standard Device Request - SET DESCRIPTOR +#define USB_REQUEST_GET_CONFIGURATION 8 // Standard Device Request - GET CONFIGURATION +#define USB_REQUEST_SET_CONFIGURATION 9 // Standard Device Request - SET CONFIGURATION +#define USB_REQUEST_GET_INTERFACE 10 // Standard Device Request - GET INTERFACE +#define USB_REQUEST_SET_INTERFACE 11 // Standard Device Request - SET INTERFACE +#define USB_REQUEST_SYNCH_FRAME 12 // Standard Device Request - SYNCH FRAME + +#define USB_FEATURE_ENDPOINT_HALT 0 // CLEAR/SET FEATURE - Endpoint Halt +#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // CLEAR/SET FEATURE - Device remote wake-up +#define USB_FEATURE_TEST_MODE 2 // CLEAR/SET FEATURE - Test mode + +/* Setup Data Constants */ + +#define USB_SETUP_HOST_TO_DEVICE 0x00 // Device Request bmRequestType transfer direction - host to device transfer +#define USB_SETUP_DEVICE_TO_HOST 0x80 // Device Request bmRequestType transfer direction - device to host transfer +#define USB_SETUP_TYPE_STANDARD 0x00 // Device Request bmRequestType type - standard +#define USB_SETUP_TYPE_CLASS 0x20 // Device Request bmRequestType type - class +#define USB_SETUP_TYPE_VENDOR 0x40 // Device Request bmRequestType type - vendor +#define USB_SETUP_RECIPIENT_DEVICE 0x00 // Device Request bmRequestType recipient - device +#define USB_SETUP_RECIPIENT_INTERFACE 0x01 // Device Request bmRequestType recipient - interface +#define USB_SETUP_RECIPIENT_ENDPOINT 0x02 // Device Request bmRequestType recipient - endpoint +#define USB_SETUP_RECIPIENT_OTHER 0x03 // Device Request bmRequestType recipient - other + +/* USB descriptors */ + +#define USB_DESCRIPTOR_DEVICE 0x01 // bDescriptorType for a Device Descriptor. +#define USB_DESCRIPTOR_CONFIGURATION 0x02 // bDescriptorType for a Configuration Descriptor. +#define USB_DESCRIPTOR_STRING 0x03 // bDescriptorType for a String Descriptor. +#define USB_DESCRIPTOR_INTERFACE 0x04 // bDescriptorType for an Interface Descriptor. +#define USB_DESCRIPTOR_ENDPOINT 0x05 // bDescriptorType for an Endpoint Descriptor. +#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // bDescriptorType for a Device Qualifier. +#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // bDescriptorType for a Other Speed Configuration. +#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // bDescriptorType for Interface Power. +#define USB_DESCRIPTOR_OTG 0x09 // bDescriptorType for an OTG Descriptor. + +#define HID_DESCRIPTOR_HID 0x21 + + + +/* OTG SET FEATURE Constants */ +#define OTG_FEATURE_B_HNP_ENABLE 3 // SET FEATURE OTG - Enable B device to perform HNP +#define OTG_FEATURE_A_HNP_SUPPORT 4 // SET FEATURE OTG - A device supports HNP +#define OTG_FEATURE_A_ALT_HNP_SUPPORT 5 // SET FEATURE OTG - Another port on the A device supports HNP + +/* USB Endpoint Transfer Types */ +#define USB_TRANSFER_TYPE_CONTROL 0x00 // Endpoint is a control endpoint. +#define USB_TRANSFER_TYPE_ISOCHRONOUS 0x01 // Endpoint is an isochronous endpoint. +#define USB_TRANSFER_TYPE_BULK 0x02 // Endpoint is a bulk endpoint. +#define USB_TRANSFER_TYPE_INTERRUPT 0x03 // Endpoint is an interrupt endpoint. +#define bmUSB_TRANSFER_TYPE 0x03 // bit mask to separate transfer type from ISO attributes + + +/* Standard Feature Selectors for CLEAR_FEATURE Requests */ +#define USB_FEATURE_ENDPOINT_STALL 0 // Endpoint recipient +#define USB_FEATURE_DEVICE_REMOTE_WAKEUP 1 // Device recipient +#define USB_FEATURE_TEST_MODE 2 // Device recipient + +/* descriptor data structures */ + +/* Device descriptor structure */ +typedef struct { + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // DEVICE descriptor type (USB_DESCRIPTOR_DEVICE). + uint16_t bcdUSB; // USB Spec Release Number (BCD). + uint8_t bDeviceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bDeviceSubClass; // Subclass code (assigned by the USB-IF). + uint8_t bDeviceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bMaxPacketSize0; // Maximum packet size for endpoint 0. + uint16_t idVendor; // Vendor ID (assigned by the USB-IF). + uint16_t idProduct; // Product ID (assigned by the manufacturer). + uint16_t bcdDevice; // Device release number (BCD). + uint8_t iManufacturer; // Index of String Descriptor describing the manufacturer. + uint8_t iProduct; // Index of String Descriptor describing the product. + uint8_t iSerialNumber; // Index of String Descriptor with the device's serial number. + uint8_t bNumConfigurations; // Number of possible configurations. +} __attribute__((packed)) USB_DEVICE_DESCRIPTOR; + +/* Configuration descriptor structure */ +typedef struct { + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // CONFIGURATION descriptor type (USB_DESCRIPTOR_CONFIGURATION). + uint16_t wTotalLength; // Total length of all descriptors for this configuration. + uint8_t bNumInterfaces; // Number of interfaces in this configuration. + uint8_t bConfigurationValue; // Value of this configuration (1 based). + uint8_t iConfiguration; // Index of String Descriptor describing the configuration. + uint8_t bmAttributes; // Configuration characteristics. + uint8_t bMaxPower; // Maximum power consumed by this configuration. +} __attribute__((packed)) USB_CONFIGURATION_DESCRIPTOR; + +/* Interface descriptor structure */ +typedef struct { + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // INTERFACE descriptor type (USB_DESCRIPTOR_INTERFACE). + uint8_t bInterfaceNumber; // Number of this interface (0 based). + uint8_t bAlternateSetting; // Value of this alternate interface setting. + uint8_t bNumEndpoints; // Number of endpoints in this interface. + uint8_t bInterfaceClass; // Class code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t bInterfaceSubClass; // Subclass code (assigned by the USB-IF). + uint8_t bInterfaceProtocol; // Protocol code (assigned by the USB-IF). 0xFF-Vendor specific. + uint8_t iInterface; // Index of String Descriptor describing the interface. +} __attribute__((packed)) USB_INTERFACE_DESCRIPTOR; + +/* Endpoint descriptor structure */ +typedef struct { + uint8_t bLength; // Length of this descriptor. + uint8_t bDescriptorType; // ENDPOINT descriptor type (USB_DESCRIPTOR_ENDPOINT). + uint8_t bEndpointAddress; // Endpoint address. Bit 7 indicates direction (0=OUT, 1=IN). + uint8_t bmAttributes; // Endpoint transfer type. + uint16_t wMaxPacketSize; // Maximum packet size. + uint8_t bInterval; // Polling interval in frames. +} __attribute__((packed)) USB_ENDPOINT_DESCRIPTOR; + +/* HID descriptor */ +typedef struct { + uint8_t bLength; + uint8_t bDescriptorType; + uint16_t bcdHID; // HID class specification release + uint8_t bCountryCode; + uint8_t bNumDescriptors; // Number of additional class specific descriptors + uint8_t bDescrType; // Type of class descriptor + uint16_t wDescriptorLength; // Total size of the Report descriptor +} __attribute__((packed)) USB_HID_DESCRIPTOR; + +typedef struct { + uint8_t bDescrType; // Type of class descriptor + uint16_t wDescriptorLength; // Total size of the Report descriptor +} __attribute__((packed)) HID_CLASS_DESCRIPTOR_LEN_AND_TYPE; diff --git a/include/hid.h b/include/hid.h index 435fc4a63..08631b5e3 100644 --- a/include/hid.h +++ b/include/hid.h @@ -100,7 +100,7 @@ void handle_keyboard_leds(uint8_t leds); void tick_leds(void); void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_t report_id); uint8_t hid_get_report(uint8_t *data, uint8_t reqLen, uint8_t reportType, uint8_t report_id); -uint8_t handle_serial_command(uint8_t request, uint16_t wValue, uint8_t* response_buffer, bool* success); +uint16_t handle_serial_command(uint8_t request, uint16_t wValue, uint8_t* response_buffer, bool* success); #if BLUETOOTH_RX void bt_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_t report_id); #endif \ No newline at end of file diff --git a/include/midi.hpp b/include/midi.hpp new file mode 100644 index 000000000..57dbdfc13 --- /dev/null +++ b/include/midi.hpp @@ -0,0 +1,47 @@ +#pragma once +#include +#include +#include "host/usbh.h" +#include "host/usbh_pvt.h" +#include "class/midi/midi.h" +#include "midi_descriptors.h" + +#define MIDI_CONTROL_COMMAND_MOD_WHEEL 1 +#define MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL 64 +#define MIDI_CHANNEL_PROGUITAR 16 +#define USB_PACKET_SIZE 4 + +typedef struct +{ + uint pos; + uint actual_size; + uint8_t data[32]; + bool sysex_in_progress; +} cable_state_t; +class MidiDeviceWithChannel; +class MidiDevice +{ + +public: + MidiDevice(bool usbBased, Midi_Data_t* data); + virtual ~MidiDevice(); + void processMidiData(uint8_t *data, uint16_t len); + virtual void update(bool full_poll, bool send_events); + void rescan(bool first); + + // Endpoint stream + struct + { + tu_edpt_stream_t tx; + tu_edpt_stream_t rx; + + uint8_t rx_ff_buf[512]; + uint8_t tx_ff_buf[512]; + } ep_stream; + CFG_TUSB_MEM_ALIGN uint8_t m_ep_in_buf[TUH_EPSIZE_BULK_MAX]; + CFG_TUSB_MEM_ALIGN uint8_t m_ep_out_buf[TUH_EPSIZE_BULK_MAX]; + Midi_Data_t *midiData; + bool usbBased; + cable_state_t cable_status[16]; + uint8_t usb_pos = 0; +}; diff --git a/include/midi_descriptors.h b/include/midi_descriptors.h index 7bb845180..eb1b5db60 100644 --- a/include/midi_descriptors.h +++ b/include/midi_descriptors.h @@ -338,11 +338,43 @@ typedef struct uint8_t Data3; /**< Third byte of data in the MIDI event. */ } __attribute__((packed)) MIDI_EVENT_PACKET; +typedef struct +{ + uint8_t header[5]; + uint8_t x : 1; // square + uint8_t a : 1; // cross + uint8_t b : 1; // circle + uint8_t y : 1; // triangle + + uint8_t : 1; // orange, l1 + uint8_t : 1; // tilt, r1 + uint8_t : 1; // l2 + uint8_t : 1; // r2 + + uint8_t back : 1; // select + uint8_t start : 1; + uint8_t : 1; + uint8_t : 1; + + uint8_t guide : 1; // ps + uint8_t capture : 1; // switch capture button + uint8_t : 2; + + uint8_t dpad : 4; + uint8_t : 2; + uint8_t tilt : 1; + uint8_t : 1; +} __attribute__((packed)) ProGuitar_Sysex_Buttons_t; typedef struct { uint8_t midiVelocitiesTemp[128]; uint8_t midiVelocities[128]; + uint8_t midiControlChanges[128]; int16_t midiPitchWheel; uint8_t midiModWheel; uint8_t midiSustainPedal; + bool seenProGuitar; + uint8_t midiFrets[6]; + uint8_t midiStringVelocities[6]; + ProGuitar_Sysex_Buttons_t proGuitarData; } __attribute__((packed)) Midi_Data_t; \ No newline at end of file diff --git a/include/shared_main.h b/include/shared_main.h index 2fbb03677..3b7c02600 100644 --- a/include/shared_main.h +++ b/include/shared_main.h @@ -1,6 +1,7 @@ #include "pin_funcs.h" #include "reports/controller_reports.h" #include "config.h" +#include "midi.hpp" typedef struct { uint8_t console_type; @@ -111,6 +112,8 @@ extern USB_Host_Data_t last_usb_host_data; #endif extern USB_Host_Data_t bt_data; extern USB_LastReport_Data_t last_report_bt; +extern MidiDevice usbMidi; +extern MidiDevice serialMidi; #if BLUETOOTH_RX diff --git a/include/usbhid.h b/include/usbhid.h new file mode 100644 index 000000000..e787621bf --- /dev/null +++ b/include/usbhid.h @@ -0,0 +1,115 @@ +/* Copyright (C) 2011 Circuits At Home, LTD. All rights reserved. + +This software may be distributed and modified under the terms of the GNU +General Public License version 2 (GPL2) as published by the Free Software +Foundation and appearing in the file GPL2.TXT included in the packaging of +this file. Please note that GPL2 Section 2[b] requires that all works based +on this software must also be made publicly available under the terms of +the GPL2 ("Copyleft"). + +Contact information +------------------- + +Circuits At Home, LTD +Web : http://www.circuitsathome.com +e-mail : support@circuitsathome.com + */ +#pragma once + +#include "Usb.h" + +#define MAX_REPORT_PARSERS 2 +#define HID_MAX_HID_CLASS_DESCRIPTORS 5 + +#define DATA_SIZE_MASK 0x03 +#define TYPE_MASK 0x0C +#define TAG_MASK 0xF0 + +#define DATA_SIZE_0 0x00 +#define DATA_SIZE_1 0x01 +#define DATA_SIZE_2 0x02 +#define DATA_SIZE_4 0x03 + +#define TYPE_MAIN 0x00 +#define TYPE_GLOBAL 0x04 +#define TYPE_LOCAL 0x08 + +#define TAG_MAIN_INPUT 0x80 +#define TAG_MAIN_OUTPUT 0x90 +#define TAG_MAIN_COLLECTION 0xA0 +#define TAG_MAIN_FEATURE 0xB0 +#define TAG_MAIN_ENDCOLLECTION 0xC0 + +#define TAG_GLOBAL_USAGEPAGE 0x00 +#define TAG_GLOBAL_LOGICALMIN 0x10 +#define TAG_GLOBAL_LOGICALMAX 0x20 +#define TAG_GLOBAL_PHYSMIN 0x30 +#define TAG_GLOBAL_PHYSMAX 0x40 +#define TAG_GLOBAL_UNITEXP 0x50 +#define TAG_GLOBAL_UNIT 0x60 +#define TAG_GLOBAL_REPORTSIZE 0x70 +#define TAG_GLOBAL_REPORTID 0x80 +#define TAG_GLOBAL_REPORTCOUNT 0x90 +#define TAG_GLOBAL_PUSH 0xA0 +#define TAG_GLOBAL_POP 0xB0 + +#define TAG_LOCAL_USAGE 0x00 +#define TAG_LOCAL_USAGEMIN 0x10 +#define TAG_LOCAL_USAGEMAX 0x20 + +/* HID requests */ +#define bmREQ_HID_OUT USB_SETUP_HOST_TO_DEVICE|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_HID_IN USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_CLASS|USB_SETUP_RECIPIENT_INTERFACE +#define bmREQ_HID_REPORT USB_SETUP_DEVICE_TO_HOST|USB_SETUP_TYPE_STANDARD|USB_SETUP_RECIPIENT_INTERFACE + +/* HID constants. Not part of chapter 9 */ +/* Class-Specific Requests */ +#define HID_REQUEST_GET_REPORT 0x01 +#define HID_REQUEST_GET_IDLE 0x02 +#define HID_REQUEST_GET_PROTOCOL 0x03 +#define HID_REQUEST_SET_REPORT 0x09 +#define HID_REQUEST_SET_IDLE 0x0A +#define HID_REQUEST_SET_PROTOCOL 0x0B + +/* Class Descriptor Types */ +#define HID_DESCRIPTOR_HID 0x21 +#define HID_DESCRIPTOR_REPORT 0x22 +#define HID_DESRIPTOR_PHY 0x23 + +/* Protocol Selection */ +#define USB_HID_BOOT_PROTOCOL 0x00 +#define HID_RPT_PROTOCOL 0x01 + +/* HID Interface Class Code */ +#define HID_INTF 0x03 + +/* HID Interface Class SubClass Codes */ +#define HID_BOOT_INTF_SUBCLASS 0x01 + +/* HID Interface Class Protocol Codes */ +#define USB_HID_PROTOCOL_NONE 0x00 +#define USB_HID_PROTOCOL_KEYBOARD 0x01 +#define USB_HID_PROTOCOL_MOUSE 0x02 + +#define HID_ITEM_TYPE_MAIN 0 +#define HID_ITEM_TYPE_GLOBAL 1 +#define HID_ITEM_TYPE_LOCAL 2 +#define HID_ITEM_TYPE_RESERVED 3 + +#define HID_LONG_ITEM_PREFIX 0xfe // Long item prefix value + +#define bmHID_MAIN_ITEM_TAG 0xfc // Main item tag mask + +#define bmHID_MAIN_ITEM_INPUT 0x80 // Main item Input tag value +#define bmHID_MAIN_ITEM_OUTPUT 0x90 // Main item Output tag value +#define bmHID_MAIN_ITEM_FEATURE 0xb0 // Main item Feature tag value +#define bmHID_MAIN_ITEM_COLLECTION 0xa0 // Main item Collection tag value +#define bmHID_MAIN_ITEM_END_COLLECTION 0xce // Main item End Collection tag value + +#define HID_MAIN_ITEM_COLLECTION_PHYSICAL 0 +#define HID_MAIN_ITEM_COLLECTION_APPLICATION 1 +#define HID_MAIN_ITEM_COLLECTION_LOGICAL 2 +#define HID_MAIN_ITEM_COLLECTION_REPORT 3 +#define HID_MAIN_ITEM_COLLECTION_NAMED_ARRAY 4 +#define HID_MAIN_ITEM_COLLECTION_USAGE_SWITCH 5 +#define HID_MAIN_ITEM_COLLECTION_USAGE_MODIFIER 6 diff --git a/platformio.ini b/platformio.ini index 92f72707a..145f96058 100644 --- a/platformio.ini +++ b/platformio.ini @@ -23,8 +23,6 @@ build_src_filter = + + lib_deps = - https://github.com/Santroller/USB_Host_Shield_2.0/archive/refs/heads/master.zip@1.6.3 - https://github.com/FortySevenEffects/arduino_midi_library/archive/refs/tags/5.0.2.zip@5.0.2 SPI [pico] extends = pico_parent diff --git a/src/pico/TUSB-MIDI.hpp b/src/pico/TUSB-MIDI.hpp deleted file mode 100644 index 9c94f2652..000000000 --- a/src/pico/TUSB-MIDI.hpp +++ /dev/null @@ -1,198 +0,0 @@ -#pragma once - -#include -#include -#include "TUSB-MIDI_defs.hpp" -#include "tusb.h" - -namespace usbMidi { - - class UsbMidiTransport { - private: - byte mTxBuffer[4]; - size_t mTxIndex; - MidiType mTxStatus; - - byte mRxBuffer[4]; - size_t mRxLength; - size_t mRxIndex; - - midiEventPacket_t mPacket; - uint8_t cableNumber; - - static const size_t MIDI_QUEUE_SIZE = 16; - midiEventPacket_t midiQueue[MIDI_QUEUE_SIZE] = {{0}}; - size_t midiQueueIndex = 0; - - public: - UsbMidiTransport(uint8_t cableNumber = 0) { - this->cableNumber = cableNumber; - }; - - public: - uint8_t midi_idx = 0; - - static const bool thruActivated = false; - - void begin() { - mTxIndex = 0; - mRxIndex = 0; - mRxLength = 0; - }; - - void pollUsb() { - // if (!midi_idx || !tuh_midi_mounted(midi_idx)) { - // return; - // } - // if (tuh_midi_get_tx_cable_count(midi_idx) < 1) { - // return; - // } - - // tuh_midi_read_poll(midi_idx); // if there is data, then the callback will be called - // tuh_midi_stream_flush(midi_idx); - } - - void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets) { - if (midi_idx != dev_addr) return; - - while (num_packets > 0) { - --num_packets; - uint8_t bytes[4]; - if (tuh_midi_packet_read(dev_addr, bytes)) { - TU_LOG1("Read bytes %u %u %u %u\r\n", bytes[0], bytes[1], bytes[2], bytes[3]); - - midiEventPacket_t packet = { - .header = bytes[0], - .byte1 = bytes[1], - .byte2 = bytes[2], - .byte3 = bytes[3] - }; - - if(midiQueueIndex < MIDI_QUEUE_SIZE - 1) { - midiQueue[midiQueueIndex] = packet; - midiQueueIndex++; - } else { - TU_LOG1("Buffer overflow"); - } - } - } - } - - void end() { - } - - bool beginTransmission(MidiType status) { - mTxStatus = status; - - byte cin = 0; - if (status < SystemExclusive) { - // Non System messages - cin = type2cin[((status & 0xF0) >> 4) - 7][1]; - mPacket.header = MAKEHEADER(cableNumber, cin); - } else { - // Only System messages - cin = system2cin[status & 0x0F][1]; - mPacket.header = MAKEHEADER(cableNumber, cin); - } - - mPacket.byte1 = mPacket.byte2 = mPacket.byte3 = 0; - mTxIndex = 0; - - return true; - }; - - void write(byte byte) { - if (mTxStatus != MidiType::SystemExclusive) { - if (mTxIndex == 0) mPacket.byte1 = byte; - else if (mTxIndex == 1) mPacket.byte2 = byte; - else if (mTxIndex == 2) mPacket.byte3 = byte; - } else if (byte == MidiType::SystemExclusiveStart) { - mPacket.header = MAKEHEADER(cableNumber, 0x04); - mPacket.byte1 = byte; - } else // SystemExclusiveEnd or SysEx data - { - auto i = mTxIndex % 3; - if (byte == MidiType::SystemExclusiveEnd) - mPacket.header = MAKEHEADER(cableNumber, (0x05 + i)); - - if (i == 0) { - mPacket.byte1 = byte; - mPacket.byte2 = mPacket.byte3 = 0x00; - } else if (i == 1) { - mPacket.byte2 = byte; - mPacket.byte3 = 0x00; - } else if (i == 2) { - mPacket.byte3 = byte; - if (byte != MidiType::SystemExclusiveEnd) { - tuh_midi_packet_write(midi_idx, (uint8_t*)&mPacket); - } - } - } - mTxIndex++; - }; - - void endTransmission() { - tuh_midi_packet_write(midi_idx, (uint8_t*)&mPacket); - }; - - byte read() { - RXBUFFER_POPFRONT(byte); - return byte; - }; - - unsigned available() { - // consume mRxBuffer first, before getting a new packet - if (mRxLength > 0) - return mRxLength; - - mRxIndex = 0; - if(midiQueueIndex > 0) { - mPacket = midiQueue[midiQueueIndex - 1]; - midiQueueIndex--; - } else { - pollUsb(); - mPacket.header = 0; - } - - if (mPacket.header != 0) { - auto cn = GETCABLENUMBER(mPacket); - if (cn != cableNumber) - return 0; - - auto cin = GETCIN(mPacket); - auto len = cin2Len[cin][1]; - switch (len) { - case 0: - if (cin == 0x4 || cin == 0x7) RXBUFFER_PUSHBACK3 - else if (cin == 0x5) RXBUFFER_PUSHBACK1 - else if (cin == 0x6) RXBUFFER_PUSHBACK2 - break; - case 1: RXBUFFER_PUSHBACK1 - break; - case 2: RXBUFFER_PUSHBACK2 - break; - case 3: RXBUFFER_PUSHBACK3 - break; - default: - break; // error - } - } - - return mRxLength; - }; - }; - -} - -/*! \brief - */ -#define USBMIDI_CREATE_INSTANCE(CableNr, Name) \ - USBMIDI_NAMESPACE::usbMidiTransport __usb##Name(CableNr);\ - MIDI_NAMESPACE::MidiInterface Name((USBMIDI_NAMESPACE::usbMidiTransport&)__usb##Name); - -#define USBMIDI_CREATE_CUSTOM_INSTANCE(CableNr, Name, Settings) \ - USBMIDI_NAMESPACE::usbMidiTransport __usb##Name(CableNr);\ - MIDI_NAMESPACE::MidiInterface Name((USBMIDI_NAMESPACE::usbMidiTransport&)__usb##Name); - -#define USBMIDI_CREATE_DEFAULT_INSTANCE() \ - USBMIDI_CREATE_INSTANCE(0, MIDI) diff --git a/src/pico/TUSB-MIDI_defs.hpp b/src/pico/TUSB-MIDI_defs.hpp deleted file mode 100644 index 019900487..000000000 --- a/src/pico/TUSB-MIDI_defs.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#pragma once - -#include - -namespace usbMidi { - - using namespace MIDI_NAMESPACE; - -// from https://www.usb.org/sites/default/files/midi10.pdf -// 4 USB-MIDI Event Packets -// Table 4-1: Code Index Number Classifications - - static uint8_t type2cin[][2] = { {MidiType::InvalidType,0}, {MidiType::NoteOff,8}, {MidiType::NoteOn,9}, {MidiType::AfterTouchPoly,0xA}, {MidiType::ControlChange,0xB}, {MidiType::ProgramChange,0xC}, {MidiType::AfterTouchChannel,0xD}, {MidiType::PitchBend,0xE} }; - - static uint8_t system2cin[][2] = { {MidiType::SystemExclusive,0}, {MidiType::TimeCodeQuarterFrame,2}, {MidiType::SongPosition,3}, {MidiType::SongSelect,2}, {0,0}, {0,0}, {MidiType::TuneRequest,5}, {MidiType::SystemExclusiveEnd,0}, {MidiType::Clock,0xF}, {0,0}, {MidiType::Start,0xF}, {MidiType::Continue,0xF}, {MidiType::Stop,0xF}, {0,0}, {MidiType::ActiveSensing,0xF}, {MidiType::SystemReset,0xF} }; - - static uint8_t cin2Len[][2] = { {0,0}, {1,0}, {2,2}, {3,3}, {4,0}, {5,0}, {6,0}, {7,0}, {8,3}, {9,3}, {10,3}, {11,3}, {12,2}, {13,2}, {14,3}, {15,1} }; - -#define GETCABLENUMBER(packet) (packet.header >> 4); -#define GETCIN(packet) (packet.header & 0x0f); -#define MAKEHEADER(cn, cin) (((cn & 0x0f) << 4) | cin) -#define RXBUFFER_PUSHBACK1 { mRxBuffer[mRxLength++] = mPacket.byte1; } -#define RXBUFFER_PUSHBACK2 { mRxBuffer[mRxLength++] = mPacket.byte1; mRxBuffer[mRxLength++] = mPacket.byte2; } -#define RXBUFFER_PUSHBACK3 { mRxBuffer[mRxLength++] = mPacket.byte1; mRxBuffer[mRxLength++] = mPacket.byte2; mRxBuffer[mRxLength++] = mPacket.byte3; } -#define RXBUFFER_POPFRONT(byte) auto byte = mRxBuffer[mRxIndex++]; mRxLength--; -//#define SENDMIDI(packet) { MidiUSB.sendMIDI(packet); MidiUSB.flush(); } - -} - -typedef struct -{ - uint8_t header; - uint8_t byte1; - uint8_t byte2; - uint8_t byte3; -} midiEventPacket_t; \ No newline at end of file diff --git a/src/pico/main.cpp b/src/pico/main.cpp index c4cb1f3bd..ed5ee20b5 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -17,7 +17,6 @@ #include "hardware/structs/usb.h" #include "hardware/watchdog.h" #include "hid.h" -#include "hidescriptorparser.h" #include "host/usbh.h" #include "host/usbh_pvt.h" #include "io.h" @@ -30,9 +29,6 @@ #include "shared_main.h" #include "xinput_device.h" #include "xinput_host.h" -#if defined(INPUT_USB_HOST) || defined(INPUT_SERIAL_MIDI) -#include "TUSB-MIDI.hpp" -#endif #if BLUETOOTH #include "bt.h" #include "pico/cyw43_arch.h" @@ -90,21 +86,6 @@ typedef struct uint8_t prev_bt_report[32]; static const uint8_t capabilitiesRequest[] = {0x00, 0x00, 0x02, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; static const uint8_t xbox360w_prescence[] = {0x08, 0x00, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; -#if defined(INPUT_USB_HOST) || defined(INPUT_SERIAL_MIDI) -using namespace usbMidi; -#endif -#ifdef INPUT_USB_HOST -UsbMidiTransport usbMIDITransport(0); -MidiInterface MIDI(usbMIDITransport); -#endif -#ifdef INPUT_SERIAL_MIDI -#if SERIAL_MIDI_PIN == 5 || SERIAL_MIDI_PIN == 9 || SERIAL_MIDI_PIN == 20 -SerialMIDI serialMIDI(Serial2); -#else -SerialMIDI serialMIDI(Serial1); -#endif -MidiInterface> MIDI2(serialMIDI); -#endif bool ready_for_next_packet() { return tud_xinput_n_ready(0) && tud_ready_for_packet(); @@ -144,6 +125,23 @@ bool foundXB = false; bool authReady = false; bool authDone = false; long test3 = 0; +static void on_uart_rx_0() +{ + while (uart_is_readable(uart0)) + { + uint8_t data = uart_getc(uart0); + serialMidi.processMidiData(&data, 1); + } +} + +static void on_uart_rx_1() +{ + while (uart_is_readable(uart1)) + { + uint8_t data = uart_getc(uart1); + serialMidi.processMidiData(&data, 1); + } +} static void tick_usb() { tud_task(); @@ -151,12 +149,6 @@ static void tick_usb() tuh_task(); #endif tick(); -#ifdef INPUT_USB_HOST - MIDI.read(); -#endif -#ifdef INPUT_SERIAL_MIDI - MIDI2.read(); -#endif } #if BLUETOOTH_RX void tick_bluetooth(const void *buf, uint8_t len, USB_Device_Type_t type) @@ -232,11 +224,22 @@ void setup() #if USB_HOST_STACK set_sys_clock_khz(120000, true); #endif + #ifdef INPUT_SERIAL_MIDI -#if SERIAL_MIDI_PIN == 5 || SERIAL_MIDI_PIN == 9 || SERIAL_MIDI_PIN == 20 - Serial2.setRX(SERIAL_MIDI_PIN); +#if SERIAL_MIDI_PIN == 1 || SERIAL_MIDI_PIN == 13 || SERIAL_MIDI_PIN == 17 + uart_init(uart0, 31250); + gpio_set_function(SERIAL_MIDI_PIN, GPIO_FUNC_UART); + irq_set_exclusive_handler(UART0_IRQ, on_uart_rx_0); + irq_set_enabled(UART0_IRQ, true); + + uart_set_irqs_enabled(uart0, true, false); #else - Serial1.setRX(SERIAL_MIDI_PIN); + uart_init(uart1, 31250); + gpio_set_function(SERIAL_MIDI_PIN, GPIO_FUNC_UART); + irq_set_exclusive_handler(UART1_IRQ, on_uart_rx_1); + irq_set_enabled(UART1_IRQ, true); + + uart_set_irqs_enabled(uart1, true, false); #endif #endif if (persistedConsoleTypeValid == PERSISTED_CONSOLE_TYPE_VALID) @@ -298,29 +301,12 @@ void setup() .speed = TUH_OPT_HIGH_SPEED ? TUSB_SPEED_HIGH : TUSB_SPEED_FULL, }; tuh_rhport_init(TUH_OPT_RHPORT, &rh_init); -#ifdef INPUT_USB_HOST - MIDI.begin(0); - MIDI.setHandleNoteOn(onNote); - MIDI.setHandleNoteOff(offNote); - MIDI.setHandleControlChange(onControlChange); - MIDI.setHandlePitchBend(onPitchBend); - MIDI.setHandleSystemExclusive(onSysEx); -#endif -#ifdef INPUT_SERIAL_MIDI - MIDI2.begin(0); - MIDI2.setHandleNoteOn(onNote); - MIDI2.setHandleNoteOff(offNote); - MIDI2.setHandleControlChange(onControlChange); - MIDI2.setHandlePitchBend(onPitchBend); - MIDI2.setHandleSystemExclusive(onSysEx); -#endif #endif } #ifdef INPUT_USB_HOST void tuh_midi_rx_cb(uint8_t dev_addr, uint32_t num_packets) { - usbMIDITransport.tuh_midi_rx_cb(dev_addr, num_packets); } void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t *mount_cb_data) @@ -328,8 +314,6 @@ void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t *mount_cb_data) printf("MIDI device address = %u, IN endpoint has %u cables, OUT endpoint has %u cables\r\n", mount_cb_data->daddr, mount_cb_data->rx_cable_count, mount_cb_data->tx_cable_count); - usbMIDITransport.midi_idx = idx; - USB_Device_Type_t type = {MIDI_ID, 0, mount_cb_data->daddr, 0}; usb_host_devices[total_usb_host_devices].type = type; total_usb_host_devices++; @@ -340,7 +324,6 @@ void tuh_midi_umount_cb(uint8_t dev_addr, uint8_t instance) { printf("MIDI device address = %d, instance = %d is unmounted\r\n", dev_addr, instance); - usbMIDITransport.midi_idx = 0; // Probably should actulaly work out what was unplugged and all that total_usb_host_devices = 0; } diff --git a/src/pico/midi.cpp b/src/pico/midi.cpp new file mode 100644 index 000000000..03e3b6454 --- /dev/null +++ b/src/pico/midi.cpp @@ -0,0 +1,272 @@ +#include "midi.hpp" +#include "config.h" +MidiDevice::MidiDevice(bool usbBased, Midi_Data_t* data) : usbBased(usbBased), midiData(data) +{ + tu_memclr(&ep_stream, sizeof(ep_stream)); + tu_edpt_stream_init(&ep_stream.rx, true, false, false, + ep_stream.rx_ff_buf, 512, m_ep_in_buf); + tu_edpt_stream_init(&ep_stream.tx, true, true, false, + ep_stream.tx_ff_buf, 512, m_ep_out_buf); + memset(cable_status, 0, sizeof(cable_status)); +} + +MidiDevice::~MidiDevice() +{ + tu_edpt_stream_deinit(&ep_stream.rx); + tu_edpt_stream_deinit(&ep_stream.tx); +} + +void MidiDevice::processMidiData(uint8_t *data, uint16_t len) +{ + tu_edpt_stream_t *ep_str_rx = &ep_stream.rx; + memcpy(ep_str_rx->ep_buf, data, len); + tu_edpt_stream_read_xfer_complete(ep_str_rx, len); +} +void MidiDevice::update(bool full_poll, bool send_events) +{ + uint8_t one_byte; + if (!tu_edpt_stream_peek(&ep_stream.rx, &one_byte)) + { + return; + } + cable_state_t *cable_state = &cable_status[0]; + uint8_t usb_packet[4]; + while (tu_edpt_stream_peek(&ep_stream.rx, &one_byte)) + { + if (!usb_pos && usbBased) + { + tu_fifo_peek_n(&ep_stream.rx.ff, usb_packet, 4); + if (tu_mem_is_zero(usb_packet, 4)) + { + // no data, just empty packet, so skip it + tu_edpt_stream_read(&ep_stream.rx, usb_packet, 4); + continue; + } + // read cable number + uint8_t p_cable_num; + tu_edpt_stream_read(&ep_stream.rx, &p_cable_num, 1); + cable_state = &cable_status[(p_cable_num >> 4) & 0x0f]; + usb_pos++; + continue; + } + else if (cable_state->pos == 0) + { + tu_edpt_stream_read(&ep_stream.rx, cable_state->data, 1); + cable_state->pos++; + uint8_t status = cable_state->data[0]; + if (status == MIDI_STATUS_SYSEX_START) + { + cable_state->sysex_in_progress = true; + // we don't know the actual size of the message yet + cable_state->actual_size = 0xFF; + } + if (status < MIDI_STATUS_SYSEX_START) + { + // then it is a channel message either three bytes or two + uint8_t fake_cin = (status & 0xf0) >> 4; + switch (fake_cin) + { + case MIDI_CIN_NOTE_OFF: + case MIDI_CIN_NOTE_ON: + cable_state->actual_size = 3; + break; + case MIDI_CIN_CONTROL_CHANGE: + cable_state->actual_size = 3; + break; + case MIDI_CIN_PITCH_BEND_CHANGE: + cable_state->actual_size = 3; + break; + case MIDI_CIN_POLY_KEYPRESS: + cable_state->actual_size = 3; + break; + case MIDI_CIN_PROGRAM_CHANGE: + case MIDI_CIN_CHANNEL_PRESSURE: + cable_state->actual_size = 2; + break; + default: + break; // Should not get this + } + cable_state->sysex_in_progress = false; + } + else if (status < MIDI_STATUS_SYSREAL_TIMING_CLOCK) + { + switch (status) + { + case MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME: + case MIDI_STATUS_SYSCOM_SONG_SELECT: + cable_state->actual_size = 2; + break; + case MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER: + cable_state->actual_size = 3; + break; + case MIDI_STATUS_SYSCOM_TUNE_REQUEST: + case MIDI_STATUS_SYSEX_END: + cable_state->actual_size = 1; + break; + default: + break; + } + cable_state->sysex_in_progress = false; + } + else + { + cable_state->actual_size = 1; + cable_state->sysex_in_progress = false; + } + } + else + { + uint8_t d; + tu_edpt_stream_read(&ep_stream.rx, &d, 1); + if (d <= MIDI_MAX_DATA_VAL) + { + if (cable_state->pos < sizeof(cable_state->data)) + { + cable_state->data[cable_state->pos] = d; + } + cable_state->pos++; + } + else if (d == MIDI_STATUS_SYSEX_END) + { + if (cable_state->pos < sizeof(cable_state->data)) + { + cable_state->data[cable_state->pos] = d; + } + cable_state->pos++; + cable_state->sysex_in_progress = false; + cable_state->actual_size = cable_state->pos; + } + else + { + // at this point this is probably a realtime message + // interleaved in the middle of a sysex message + // and we don't care about that right now + // so we ignore it + } + } + usb_pos++; + if (cable_state->actual_size && cable_state->pos >= cable_state->actual_size) + { + // then this is the last byte of the message, so reset pos for next message + cable_state->pos = 0; + // lets not send timing clock signals to the monitor + if (cable_state->data[0] != MIDI_STATUS_SYSREAL_TIMING_CLOCK) + { + uint8_t data_size = MIN(32, cable_state->actual_size); + // proto_Event event = {which_event : proto_Event_midiDebug_tag, event : {midiDebug : {data : {size : data_size, bytes : {0}}}}}; + // memcpy(event.event.midiDebug.data.bytes, cable_state->data, data_size); + // HIDConfigDevice::send_event(event, false); + } + uint8_t status = (cable_state->data[0] & 0xf0) >> 4; + uint8_t channel = cable_state->data[0] & 0x0f; + switch (status) + { + case MIDI_CIN_NOTE_OFF: + // ignore note off since some drums don't send it, or they sent it too quick so we make our own note off later + #if DEVICE_TYPE_IS_DRUM + break; + #endif + // velocity 0 for note off + cable_state->data[2] = 0; + [[fallthrough]]; + case MIDI_CIN_NOTE_ON: + midiData->midiVelocities[cable_state->data[1]] = cable_state->data[2]; + break; + case MIDI_CIN_CONTROL_CHANGE: + midiData->midiControlChanges[cable_state->data[1]] = cable_state->data[2]; + break; + case MIDI_CIN_PITCH_BEND_CHANGE: + midiData->midiPitchWheel = ((int16_t)cable_state->data[3] << 7) | cable_state->data[2]; + break; + case MIDI_CIN_POLY_KEYPRESS: + break; + case MIDI_CIN_PROGRAM_CHANGE: + case MIDI_CIN_CHANNEL_PRESSURE: + break; + default: + break; + } + if (cable_state->data[0] < MIDI_STATUS_SYSEX_START) + { + // if (seenChannels.find({m_id, channel}) == seenChannels.end()) + // { + // if (HIDConfigDevice::tool_closed()) + // { + // printf("Seen new MIDI channel: %d on device %d\r\n", channel, m_id); + // seenChannels.insert_or_assign({m_id, channel}, true); + // reload(); + // } + // } + } + if (cable_state->data[0] == MIDI_STATUS_SYSEX_START) + { + uint8_t buttons_header[] = {MIDI_STATUS_SYSEX_START, 0x08, 0x40}; + if (memcmp(cable_state->data, buttons_header, sizeof(buttons_header)) == 0) + { + // if (seenChannels.find({m_id, MIDI_CHANNEL_PROGUITAR}) == seenChannels.end()) + // { + // printf("Seen new MIDI channel: proguitar on device %d\r\n", m_id); + // seenChannels[{m_id, MIDI_CHANNEL_PROGUITAR}] = true; + // if (HIDConfigDevice::tool_closed()) + // { + // reload(); + // } + // } + midiData->seenProGuitar = true; + if (cable_state->data[4] == 0x08) + { + // button events + memcpy(&midiData->proGuitarData, cable_state->data, sizeof(midiData->proGuitarData)); + } + if (cable_state->data[4] == 0x01) + { + // fret state events + uint8_t string = cable_state->data[5] - 1; + switch (string) + { + case 0: + midiData->midiFrets[string] = cable_state->data[6] - 0x40; + break; + case 1: + midiData->midiFrets[string] = cable_state->data[6] - 0x3B; + break; + case 2: + midiData->midiFrets[string] = cable_state->data[6] - 0x37; + break; + case 3: + midiData->midiFrets[string] = cable_state->data[6] - 0x32; + break; + case 4: + midiData->midiFrets[string] = cable_state->data[6] - 0x2D; + break; + case 5: + midiData->midiFrets[string] = cable_state->data[6] - 0x28; + break; + default: + break; + } + } + if (cable_state->data[4] == 0x05) + { + // picking events + uint8_t string = cable_state->data[5] - 1; + uint8_t velocity = cable_state->data[6]; + midiData->midiStringVelocities[string] = velocity; + } + } + } + // at this point we can look at the state and process the message. + if (usb_pos < USB_PACKET_SIZE && usbBased) + { + // discard the unused bytes in the USB packet if we haven't already read them + tu_edpt_stream_read(&ep_stream.rx, cable_state->data, USB_PACKET_SIZE - usb_pos); + } + usb_pos = 0; + } + if (usb_pos >= USB_PACKET_SIZE) + { + // then this is the end of the USB packet, so reset usb_pos for next packet + usb_pos = 0; + } + } +} \ No newline at end of file diff --git a/src/pico/midi_host.c b/src/pico/midi_host.c deleted file mode 100644 index 7ebe56d57..000000000 --- a/src/pico/midi_host.c +++ /dev/null @@ -1,692 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2019 Ha Thach (tinyusb.org) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - * - * This file is part of the TinyUSB stack. - */ - -#include "tusb_option.h" - -#if (CFG_TUH_ENABLED && CFG_TUH_MIDI_CUSTOM) - -#include "host/usbh.h" -#include "host/usbh_pvt.h" - -#include "midi_host.h" -#include - -// Level where CFG_TUSB_DEBUG must be at least for this driver is logged -#ifndef CFG_TUH_MIDI_CUSTOM_LOG_LEVEL - #define CFG_TUH_MIDI_CUSTOM_LOG_LEVEL 0 -#endif - -#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_MIDI_CUSTOM_LOG_LEVEL, __VA_ARGS__) - -#define MIDI_CS_ROLAND_HEADER 0xF1 -//--------------------------------------------------------------------+ -// Weak stubs: invoked if no strong implementation is available -//--------------------------------------------------------------------+ -TU_ATTR_WEAK void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t * desc_cb_data) { (void) idx; (void) desc_cb_data; } -TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t* mount_cb_data) { (void) idx; (void) mount_cb_data; } -TU_ATTR_WEAK void tuh_midi_umount_cb(uint8_t idx) { (void) idx; } -TU_ATTR_WEAK void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes) { (void) idx; (void) xferred_bytes; } -TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes) { (void) idx; (void) xferred_bytes; } - -//--------------------------------------------------------------------+ -// MACRO CONSTANT TYPEDEF -//--------------------------------------------------------------------+ - -typedef struct { - uint8_t daddr; - uint8_t bInterfaceNumber; // interface number of MIDI streaming - uint8_t iInterface; - uint8_t itf_count; // number of interfaces including Audio Control + MIDI streaming - - uint8_t rx_cable_count; // IN endpoint CS descriptor bNumEmbMIDIJack value - uint8_t tx_cable_count; // OUT endpoint CS descriptor bNumEmbMIDIJack value - - #if CFG_TUH_MIDI_CUSTOM_STREAM_API - // For Stream read()/write() API - // Messages are always 4 bytes long, queue them for reading and writing so the - // callers can use the Stream interface with single-byte read/write calls. - midi_driver_stream_t stream_write; - midi_driver_stream_t stream_read; - #endif - - // Endpoint stream - struct { - tu_edpt_stream_t tx; - tu_edpt_stream_t rx; - - uint8_t rx_ff_buf[CFG_TUH_MIDI_RX_BUFSIZE]; - uint8_t tx_ff_buf[CFG_TUH_MIDI_TX_BUFSIZE]; - } ep_stream; - - bool mounted; -}midih_interface_t; - -typedef struct { - TUH_EPBUF_DEF(tx, TUH_EPSIZE_BULK_MAX); - TUH_EPBUF_DEF(rx, TUH_EPSIZE_BULK_MAX); -} midih_epbuf_t; - - -/// MIDI In Jack Descriptor -typedef struct TU_ATTR_PACKED { - uint8_t bLength; ///< Size of this descriptor in bytes. - uint8_t bDescriptorType; ///< Descriptor Type, must be Class-Specific - uint8_t bDescriptorSubType; ///< Descriptor SubType - uint8_t always_2; /// always 0x2 - uint8_t num_cables_rx; /// rx cable count - uint8_t num_cables_tx; /// tx cable count -} midi_desc_roland_header_t; -static midih_interface_t _midi_host[CFG_TUH_MIDI_CUSTOM]; -CFG_TUH_MEM_SECTION static midih_epbuf_t _midi_epbuf[CFG_TUH_MIDI_CUSTOM]; - -//--------------------------------------------------------------------+ -// Helper -//--------------------------------------------------------------------+ -TU_ATTR_ALWAYS_INLINE static inline uint8_t find_new_midi_index(void) { - for (uint8_t idx = 0; idx < CFG_TUH_MIDI_CUSTOM; idx++) { - if (_midi_host[idx].daddr == 0) { - return idx; - } - } - return TUSB_INDEX_INVALID_8; -} - -static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) { - for (uint8_t idx = 0; idx < CFG_TUH_MIDI_CUSTOM; idx++) { - const midih_interface_t *p_midi = &_midi_host[idx]; - if ((p_midi->daddr == daddr) && - (ep_addr == p_midi->ep_stream.rx.ep_addr || ep_addr == p_midi->ep_stream.tx.ep_addr)) { - return idx; - } - } - return TUSB_INDEX_INVALID_8; -} - -//--------------------------------------------------------------------+ -// USBH API -//--------------------------------------------------------------------+ -bool midih_init(void) { - tu_memclr(&_midi_host, sizeof(_midi_host)); - for (int inst = 0; inst < CFG_TUH_MIDI_CUSTOM; inst++) { - midih_interface_t *p_midi_host = &_midi_host[inst]; - tu_edpt_stream_init(&p_midi_host->ep_stream.rx, true, false, false, - p_midi_host->ep_stream.rx_ff_buf, CFG_TUH_MIDI_RX_BUFSIZE, _midi_epbuf[inst].rx); - tu_edpt_stream_init(&p_midi_host->ep_stream.tx, true, true, false, - p_midi_host->ep_stream.tx_ff_buf, CFG_TUH_MIDI_TX_BUFSIZE, _midi_epbuf[inst].tx); - } - return true; -} - -bool midih_deinit(void) { - for (size_t i = 0; i < CFG_TUH_MIDI_CUSTOM; i++) { - midih_interface_t* p_midi = &_midi_host[i]; - tu_edpt_stream_deinit(&p_midi->ep_stream.rx); - tu_edpt_stream_deinit(&p_midi->ep_stream.tx); - } - return true; -} - -void midih_close(uint8_t daddr) { - for (uint8_t idx = 0; idx < CFG_TUH_MIDI_CUSTOM; idx++) { - midih_interface_t* p_midi = &_midi_host[idx]; - if (p_midi->daddr == daddr) { - TU_LOG_DRV(" MIDI close addr = %u index = %u\r\n", daddr, idx); - tuh_midi_umount_cb(idx); - - p_midi->bInterfaceNumber = 0; - p_midi->rx_cable_count = 0; - p_midi->tx_cable_count = 0; - p_midi->daddr = 0; - p_midi->mounted = false; -#if CFG_TUH_MIDI_CUSTOM_STREAM_API - tu_memclr(&p_midi->stream_read, sizeof(p_midi->stream_read)); - tu_memclr(&p_midi->stream_write, sizeof(p_midi->stream_write)); -#endif - tu_edpt_stream_close(&p_midi->ep_stream.rx); - tu_edpt_stream_close(&p_midi->ep_stream.tx); - } - } -} - -bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) { - (void) result; - const uint8_t idx = get_idx_by_ep_addr(dev_addr, ep_addr); - TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); - midih_interface_t *p_midi = &_midi_host[idx]; - tu_edpt_stream_t *ep_str_rx = &p_midi->ep_stream.rx; - tu_edpt_stream_t *ep_str_tx = &p_midi->ep_stream.tx; - - if (ep_addr == ep_str_rx->ep_addr) { - // receive new data, put it into FIFO and invoke callback if available - // Note: some devices send back all zero packets even if there is no data ready - if (xferred_bytes && !tu_mem_is_zero(ep_str_rx->ep_buf, xferred_bytes)) { - tu_edpt_stream_read_xfer_complete(ep_str_rx, xferred_bytes); - tuh_midi_rx_cb(idx, xferred_bytes); - } - - tu_edpt_stream_read_xfer(ep_str_rx); // prepare for next transfer - } else if (ep_addr == ep_str_tx->ep_addr) { - tuh_midi_tx_cb(idx, xferred_bytes); - - if (0 == tu_edpt_stream_write_xfer(ep_str_tx)) { - // If there is no data left, a ZLP should be sent if - // xferred_bytes is multiple of EP size and not zero - tu_edpt_stream_write_zlp_if_needed(ep_str_tx, xferred_bytes); - } - } - - return true; -} - -//--------------------------------------------------------------------+ -// Enumeration -//--------------------------------------------------------------------+ -uint16_t midih_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *desc_itf, uint16_t max_len) { - (void) rhport; - // Some roland devices use vendor specific and have their own header - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass || TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0); - bool roland = TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass; - const uint8_t *desc_start = (const uint8_t *)desc_itf; - const uint8_t *p_desc = desc_start; - const uint8_t *desc_end = desc_start + max_len; - - const uint8_t idx = find_new_midi_index(); - TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM, 0); - midih_interface_t *p_midi = &_midi_host[idx]; - p_midi->itf_count = 0; - - tuh_midi_descriptor_cb_t desc_cb = { 0 }; - desc_cb.jack_num = 0; - - // There can be just a MIDI or an Audio + MIDI interface - // - If there is Audio Control Interface + Audio Header descriptor, then skip it. - // - If there is an Audio Control Interface + Audio Streaming Interface, then ignore the Audio Streaming Interface. - // Future: - // Note that if this driver is used with an USB Audio Streaming host driver, - // then call that driver first. If the MIDI interface comes before the - // audio streaming interface, then the audio driver will have to call this - // driver after parsing the audio control interface and then resume parsing - // the streaming audio interface. - if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) { - TU_VERIFY(max_len > 2 * sizeof(tusb_desc_interface_t) + sizeof(midi10_desc_cs_ac_interface_t), 0); - p_desc = tu_desc_next(p_desc); - TU_VERIFY(tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && - tu_desc_subtype(p_desc) == AUDIO10_CS_AC_INTERFACE_HEADER, - 0); - desc_cb.desc_audio_control = desc_itf; - - p_desc = tu_desc_next(p_desc); - desc_itf = (const tusb_desc_interface_t *)p_desc; - p_midi->itf_count = 1; - // skip non-interface and non-midi streaming descriptors - while (tu_desc_in_bounds(p_desc, desc_end) && (desc_itf->bDescriptorType != TUSB_DESC_INTERFACE || - (desc_itf->bInterfaceClass == TUSB_CLASS_AUDIO && - desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING))) { - if (desc_itf->bDescriptorType == TUSB_DESC_INTERFACE && desc_itf->bAlternateSetting == 0) { - p_midi->itf_count++; - } - p_desc = tu_desc_next(p_desc); - desc_itf = (const tusb_desc_interface_t *)p_desc; - } - TU_VERIFY(p_desc < desc_end, 0); - TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass, 0); - } - TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass, 0); - - TU_LOG_DRV("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); - p_midi->bInterfaceNumber = desc_itf->bInterfaceNumber; - p_midi->iInterface = desc_itf->iInterface; - p_midi->itf_count++; - desc_cb.desc_midi = desc_itf; - - bool found_new_interface = false; - do { - p_desc = tu_desc_next(p_desc); - if (!tu_desc_in_bounds(p_desc, desc_end)) { - break; - } - switch (tu_desc_type(p_desc)) { - case TUSB_DESC_INTERFACE: - found_new_interface = true; - break; - - case TUSB_DESC_CS_INTERFACE: - switch (tu_desc_subtype(p_desc)) { - case MIDI_CS_INTERFACE_HEADER: - TU_LOG_DRV(" Interface Header descriptor\r\n"); - desc_cb.desc_header = p_desc; - break; - - case MIDI_CS_INTERFACE_IN_JACK: - case MIDI_CS_INTERFACE_OUT_JACK: { - TU_LOG_DRV(" Jack %s %s descriptor \r\n", - tu_desc_subtype(p_desc) == MIDI_CS_INTERFACE_IN_JACK ? "IN" : "OUT", - p_desc[3] == MIDI_JACK_EXTERNAL ? "External" : "Embedded"); - if (desc_cb.jack_num < TU_ARRAY_SIZE(desc_cb.desc_jack)) { - desc_cb.desc_jack[desc_cb.jack_num++] = p_desc; - } - break; - } - - case MIDI_CS_INTERFACE_ELEMENT: - TU_LOG_DRV(" Element descriptor\r\n"); - desc_cb.desc_element = p_desc; - break; - - case MIDI_CS_ROLAND_HEADER: - midi_desc_roland_header_t const *p_rl = (midi_desc_roland_header_t const *)p_desc; - TU_LOG2("Found Roland Header %02x %02x %02x %02x\r\n", p_rl->bLength, p_rl->always_2, p_rl->num_cables_rx, p_rl->num_cables_tx); - if (p_rl->bLength >= sizeof(midi_desc_roland_header_t) && p_rl->always_2 == 0x02) { - TU_VERIFY(p_rl->num_cables_rx < 0x10 && p_rl->num_cables_tx < 0x10); - TU_LOG2("Found Roland Header\r\n"); - p_midi->rx_cable_count = (1 << p_rl->num_cables_rx) - 1; - p_midi->tx_cable_count = (1 << p_rl->num_cables_tx) - 1; - break; - } - TU_LOG_DRV(" Unknown CS Interface sub-type %u\r\n", tu_desc_subtype(p_desc)); - break; - default: - TU_LOG_DRV(" Unknown CS Interface sub-type %u\r\n", tu_desc_subtype(p_desc)); - break; - } - break; - - case TUSB_DESC_ENDPOINT: { - const tusb_desc_endpoint_t *p_ep = (const tusb_desc_endpoint_t *) p_desc; - - p_desc = tu_desc_next(p_desc); // next to CS endpoint - TU_VERIFY(tu_desc_in_bounds(p_desc, desc_end), 0); - tu_edpt_stream_t *ep_stream; - if (roland) { - if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) { - desc_cb.desc_epout = p_ep; - ep_stream = &p_midi->ep_stream.tx; - } else { - desc_cb.desc_epin = p_ep; - ep_stream = &p_midi->ep_stream.rx; - } - } else { - const midi_desc_cs_endpoint_t *p_csep = (const midi_desc_cs_endpoint_t *) p_desc; - - TU_LOG_DRV(" Endpoint and CS_Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress); - if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) { - p_midi->tx_cable_count = p_csep->bNumEmbMIDIJack; - desc_cb.desc_epout = p_ep; - ep_stream = &p_midi->ep_stream.tx; - } else { - p_midi->rx_cable_count = p_csep->bNumEmbMIDIJack; - desc_cb.desc_epin = p_ep; - ep_stream = &p_midi->ep_stream.rx; - } - } - TU_ASSERT(tuh_edpt_open(dev_addr, p_ep), 0); - tu_edpt_stream_open(ep_stream, dev_addr, p_ep, tu_edpt_packet_size(p_ep)); - tu_edpt_stream_clear(ep_stream); - - break; - } - - default: break; // skip unknown descriptor - } - } while (!found_new_interface); - - desc_cb.desc_midi_total_len = (uint16_t)((uintptr_t)p_desc - (uintptr_t)desc_start); - - p_midi->daddr = dev_addr; - tuh_midi_descriptor_cb(idx, &desc_cb); - - return desc_cb.desc_midi_total_len; -} - -bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) { - uint8_t idx = tuh_midi_itf_get_index(dev_addr, itf_num); - TU_ASSERT(idx < CFG_TUH_MIDI_CUSTOM); - midih_interface_t *p_midi = &_midi_host[idx]; - p_midi->mounted = true; - - const tuh_midi_mount_cb_t mount_cb_data = { - .daddr = dev_addr, - .bInterfaceNumber = p_midi->bInterfaceNumber, - .rx_cable_count = p_midi->rx_cable_count, - .tx_cable_count = p_midi->tx_cable_count, - }; - tuh_midi_mount_cb(idx, &mount_cb_data); - - tu_edpt_stream_read_xfer(&p_midi->ep_stream.rx); // prepare for incoming data - - // No special config things to do for MIDI - usbh_driver_set_config_complete(dev_addr, p_midi->bInterfaceNumber); - return true; -} - -//--------------------------------------------------------------------+ -// API -//--------------------------------------------------------------------+ -bool tuh_midi_mounted(uint8_t idx) { - TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); - midih_interface_t *p_midi = &_midi_host[idx]; - return p_midi->mounted; -} - -uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num) { - for (uint8_t idx = 0; idx < CFG_TUH_MIDI_CUSTOM; idx++) { - const midih_interface_t *p_midi = &_midi_host[idx]; - if (p_midi->daddr == daddr && - (p_midi->bInterfaceNumber == itf_num || - p_midi->bInterfaceNumber == (uint8_t) (itf_num + p_midi->itf_count - 1))) { - return idx; - } - } - return TUSB_INDEX_INVALID_8; -} - -bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t* info) { - midih_interface_t* p_midi = &_midi_host[idx]; - TU_VERIFY(p_midi && info); - - info->daddr = p_midi->daddr; - - // re-construct descriptor - tusb_desc_interface_t* desc = &info->desc; - desc->bLength = sizeof(tusb_desc_interface_t); - desc->bDescriptorType = TUSB_DESC_INTERFACE; - - desc->bInterfaceNumber = p_midi->bInterfaceNumber; - desc->bAlternateSetting = 0; - desc->bNumEndpoints = 0; - if (tu_edpt_stream_is_opened(&p_midi->ep_stream.tx)) { - desc->bNumEndpoints++; - } - if (tu_edpt_stream_is_opened(&p_midi->ep_stream.rx)) { - desc->bNumEndpoints++; - } - desc->bInterfaceClass = TUSB_CLASS_AUDIO; - desc->bInterfaceSubClass = AUDIO_SUBCLASS_MIDI_STREAMING; - desc->bInterfaceProtocol = 0; - desc->iInterface = p_midi->iInterface; - - return true; -} - -uint8_t tuh_midi_get_tx_cable_count (uint8_t idx) { - TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); - midih_interface_t *p_midi = &_midi_host[idx]; - TU_VERIFY(p_midi->ep_stream.tx.ep_addr != 0, 0); - return p_midi->tx_cable_count; -} - -uint8_t tuh_midi_get_rx_cable_count (uint8_t idx) { - TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); - midih_interface_t *p_midi = &_midi_host[idx]; - TU_VERIFY(p_midi->ep_stream.rx.ep_addr != 0, 0); - return p_midi->rx_cable_count; -} - -uint32_t tuh_midi_read_available(uint8_t idx) { - TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); - midih_interface_t *p_midi = &_midi_host[idx]; - return tu_edpt_stream_read_available(&p_midi->ep_stream.rx); -} - -uint32_t tuh_midi_write_flush(uint8_t idx) { - TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); - midih_interface_t *p_midi = &_midi_host[idx]; - return tu_edpt_stream_write_xfer(&p_midi->ep_stream.tx); -} - -//--------------------------------------------------------------------+ -// Packet API -//--------------------------------------------------------------------+ -uint32_t tuh_midi_packet_read_n(uint8_t idx, uint8_t* buffer, uint32_t bufsize) { - TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM && buffer && bufsize > 0, 0); - midih_interface_t *p_midi = &_midi_host[idx]; - - uint32_t count4 = tu_min32(bufsize, tu_edpt_stream_read_available(&p_midi->ep_stream.rx)); - count4 = tu_align4(count4); // round down to multiple of 4 - TU_VERIFY(count4 > 0, 0); - return tu_edpt_stream_read(&p_midi->ep_stream.rx, buffer, count4); -} - -uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t* buffer, uint32_t bufsize) { - TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM && buffer && bufsize > 0, 0); - midih_interface_t *p_midi = &_midi_host[idx]; - - const uint32_t bufsize4 = tu_align4(bufsize); - TU_VERIFY(bufsize4 > 0, 0); - return tu_edpt_stream_write(&p_midi->ep_stream.tx, buffer, bufsize4); -} - -//--------------------------------------------------------------------+ -// Stream API -//--------------------------------------------------------------------+ -#if CFG_TUH_MIDI_CUSTOM_STREAM_API -uint32_t tuh_midi_stream_write(uint8_t idx, uint8_t cable_num, uint8_t const *buffer, uint32_t bufsize) { - TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM && buffer && bufsize > 0); - midih_interface_t *p_midi = &_midi_host[idx]; - TU_VERIFY(cable_num < p_midi->tx_cable_count); - midi_driver_stream_t *stream = &p_midi->stream_write; - - uint32_t byte_count = 0; - while ((byte_count < bufsize) && (tu_edpt_stream_write_available(&p_midi->ep_stream.tx) >= 4)) { - const uint8_t data = buffer[byte_count]; - byte_count++; - if (data >= MIDI_STATUS_SYSREAL_TIMING_CLOCK) { - // real-time messages need to be sent right away - midi_driver_stream_t streamrt; - streamrt.buffer[0] = (uint8_t)((cable_num << 4) | MIDI_CIN_SYSEX_END_1BYTE); - streamrt.buffer[1] = data; - streamrt.index = 2; - streamrt.total = 2; - const uint32_t count = tu_edpt_stream_write(&p_midi->ep_stream.tx, streamrt.buffer, 4); - TU_ASSERT(count == 4, byte_count); // Check FIFO overflown, since we already check fifo remaining. It is probably race condition - } else if (stream->index == 0) { - //------------- New event packet -------------// - - uint8_t const msg = data >> 4; - - stream->index = 2; - stream->buffer[1] = data; - - // Check to see if we're still in a SysEx transmit. - if ((stream->buffer[0] & 0xF) == MIDI_CIN_SYSEX_START) { - if (data == MIDI_STATUS_SYSEX_END) { - stream->buffer[0] = (uint8_t)((cable_num << 4) | MIDI_CIN_SYSEX_END_1BYTE); - stream->total = 2; - } else { - stream->total = 4; - } - } else if ((msg >= 0x8 && msg <= 0xB) || msg == 0xE) { - // Channel Voice Messages - stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); - stream->total = 4; - } else if (msg == 0xC || msg == 0xD) { - // Channel Voice Messages, two-byte variants (Program Change and Channel Pressure) - stream->buffer[0] = (uint8_t) ((cable_num << 4) | msg); - stream->total = 3; - } else if (msg == 0xf) { - // System message - if (data == MIDI_STATUS_SYSEX_START) { - stream->buffer[0] = MIDI_CIN_SYSEX_START; - stream->total = 4; - } else if (data == MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME || data == MIDI_STATUS_SYSCOM_SONG_SELECT) { - stream->buffer[0] = MIDI_CIN_SYSCOM_2BYTE; - stream->total = 3; - } else if (data == MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER) { - stream->buffer[0] = MIDI_CIN_SYSCOM_3BYTE; - stream->total = 4; - } else { - stream->buffer[0] = MIDI_CIN_SYSEX_END_1BYTE; - stream->total = 2; - } - stream->buffer[0] |= (uint8_t)(cable_num << 4); - } else { - // Pack individual bytes if we don't support packing them into words. - stream->buffer[0] = (uint8_t) (cable_num << 4 | 0xf); - stream->buffer[2] = 0; - stream->buffer[3] = 0; - stream->index = 2; - stream->total = 2; - } - } else { - //------------- On-going (buffering) packet -------------// - TU_ASSERT(stream->index < 4, byte_count); - stream->buffer[stream->index] = data; - stream->index++; - // See if this byte ends a SysEx. - if ((stream->buffer[0] & 0xF) == MIDI_CIN_SYSEX_START && data == MIDI_STATUS_SYSEX_END) { - stream->buffer[0] = (uint8_t)((cable_num << 4) | (MIDI_CIN_SYSEX_START + (stream->index - 1))); - stream->total = stream->index; - } - } - - // Send out packet - if (stream->index >= 2 && stream->index == stream->total) { - // zeroes unused bytes - for (uint8_t i = stream->total; i < 4; i++) { - stream->buffer[i] = 0; - } - TU_LOG3_MEM(stream->buffer, 4, 2); - - const uint32_t count = tu_edpt_stream_write(&p_midi->ep_stream.tx, stream->buffer, 4); - - // complete current event packet, reset stream - stream->index = 0; - stream->total = 0; - - // FIFO overflown, since we already check fifo remaining. It is probably race condition - TU_ASSERT(count == 4, byte_count); - } - } - return byte_count; -} - -uint32_t tuh_midi_stream_read(uint8_t idx, uint8_t *p_cable_num, uint8_t *p_buffer, uint16_t bufsize) { - TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM && p_cable_num && p_buffer && bufsize > 0); - midih_interface_t *p_midi = &_midi_host[idx]; - uint32_t bytes_buffered = 0; - uint8_t one_byte; - if (!tu_edpt_stream_peek(&p_midi->ep_stream.rx, &one_byte)) { - return 0; - } - *p_cable_num = (one_byte >> 4) & 0xf; - uint32_t nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); - static uint16_t cable_sysex_in_progress;// bit i is set if received MIDI_STATUS_SYSEX_START but not MIDI_STATUS_SYSEX_END - while (nread == 4 && bytes_buffered < bufsize) { - *p_cable_num = (p_midi->stream_read.buffer[0] >> 4) & 0x0f; - uint8_t bytes_to_add_to_stream = 0; - if (*p_cable_num < p_midi->rx_cable_count) { - // ignore the CIN field; too many devices out there encode this wrong - uint8_t status = p_midi->stream_read.buffer[1]; - uint16_t cable_mask = (uint16_t) (1 << *p_cable_num); - if (status <= MIDI_MAX_DATA_VAL || status == MIDI_STATUS_SYSEX_START) { - if (status == MIDI_STATUS_SYSEX_START) { - cable_sysex_in_progress |= cable_mask; - } - // only add the packet if a sysex message is in progress - if (cable_sysex_in_progress & cable_mask) { - ++bytes_to_add_to_stream; - for (uint8_t i = 2; i < 4; i++) { - if (p_midi->stream_read.buffer[i] <= MIDI_MAX_DATA_VAL) { - ++bytes_to_add_to_stream; - } else if (p_midi->stream_read.buffer[i] == MIDI_STATUS_SYSEX_END) { - ++bytes_to_add_to_stream; - cable_sysex_in_progress &= (uint16_t) ~cable_mask; - i = 4;// force the loop to exit; I hate break statements in loops - } - } - } - else { - // bad packet discard - nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); - continue; - } - } else if (status < MIDI_STATUS_SYSEX_START) { - // then it is a channel message either three bytes or two - uint8_t fake_cin = (status & 0xf0) >> 4; - switch (fake_cin) { - case MIDI_CIN_NOTE_OFF: - case MIDI_CIN_NOTE_ON: - case MIDI_CIN_POLY_KEYPRESS: - case MIDI_CIN_CONTROL_CHANGE: - case MIDI_CIN_PITCH_BEND_CHANGE: - bytes_to_add_to_stream = 3; - break; - case MIDI_CIN_PROGRAM_CHANGE: - case MIDI_CIN_CHANNEL_PRESSURE: - bytes_to_add_to_stream = 2; - break; - default: - break;// Should not get this - } - cable_sysex_in_progress &= (uint16_t) ~cable_mask; - } else if (status < MIDI_STATUS_SYSREAL_TIMING_CLOCK) { - switch (status) { - case MIDI_STATUS_SYSCOM_TIME_CODE_QUARTER_FRAME: - case MIDI_STATUS_SYSCOM_SONG_SELECT: - bytes_to_add_to_stream = 2; - break; - case MIDI_STATUS_SYSCOM_SONG_POSITION_POINTER: - bytes_to_add_to_stream = 3; - break; - case MIDI_STATUS_SYSCOM_TUNE_REQUEST: - case MIDI_STATUS_SYSEX_END: - bytes_to_add_to_stream = 1; - break; - default: - break; - } - cable_sysex_in_progress &= (uint16_t) ~cable_mask; - } else { - // Real-time message: can be inserted into a sysex message, - // so do don't clear cable_sysex_in_progress bit - bytes_to_add_to_stream = 1; - } - } - else { - // bad packet discard - nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); - continue; - } - - for (uint8_t i = 1; i <= bytes_to_add_to_stream; i++) { - *p_buffer++ = p_midi->stream_read.buffer[i]; - } - bytes_buffered += bytes_to_add_to_stream; - nread = 0; - if (tu_edpt_stream_peek(&p_midi->ep_stream.rx, &one_byte)) { - uint8_t new_cable = (one_byte >> 4) & 0xf; - if (new_cable == *p_cable_num) { - // still on the same cable. Continue reading the stream - nread = tu_edpt_stream_read(&p_midi->ep_stream.rx, p_midi->stream_read.buffer, 4); - } - } - } - - return bytes_buffered; -} -#endif - -#endif \ No newline at end of file diff --git a/src/pico/midi_host.cpp b/src/pico/midi_host.cpp new file mode 100644 index 000000000..012e0f098 --- /dev/null +++ b/src/pico/midi_host.cpp @@ -0,0 +1,541 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2019 Ha Thach (tinyusb.org) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * This file is part of the TinyUSB stack. + */ + +#include "tusb_option.h" + +#if (CFG_TUH_ENABLED && CFG_TUH_MIDI_CUSTOM) + +#include "host/usbh.h" +#include "host/usbh_pvt.h" + +#include "midi_host.h" +#include "shared_main.h" +#include + +// Level where CFG_TUSB_DEBUG must be at least for this driver is logged +#ifndef CFG_TUH_MIDI_CUSTOM_LOG_LEVEL +#define CFG_TUH_MIDI_CUSTOM_LOG_LEVEL 0 +#endif + +#define TU_LOG_DRV(...) TU_LOG(CFG_TUH_MIDI_CUSTOM_LOG_LEVEL, __VA_ARGS__) + +#define MIDI_CS_ROLAND_HEADER 0xF1 +//--------------------------------------------------------------------+ +// Weak stubs: invoked if no strong implementation is available +//--------------------------------------------------------------------+ +TU_ATTR_WEAK void tuh_midi_descriptor_cb(uint8_t idx, const tuh_midi_descriptor_cb_t *desc_cb_data) +{ + (void)idx; + (void)desc_cb_data; +} +TU_ATTR_WEAK void tuh_midi_mount_cb(uint8_t idx, const tuh_midi_mount_cb_t *mount_cb_data) +{ + (void)idx; + (void)mount_cb_data; +} +TU_ATTR_WEAK void tuh_midi_umount_cb(uint8_t idx) { (void)idx; } +TU_ATTR_WEAK void tuh_midi_rx_cb(uint8_t idx, uint32_t xferred_bytes) +{ + (void)idx; + (void)xferred_bytes; +} +TU_ATTR_WEAK void tuh_midi_tx_cb(uint8_t idx, uint32_t xferred_bytes) +{ + (void)idx; + (void)xferred_bytes; +} + +//--------------------------------------------------------------------+ +// MACRO CONSTANT TYPEDEF +//--------------------------------------------------------------------+ + +typedef struct +{ + uint8_t daddr; + uint8_t bInterfaceNumber; // interface number of MIDI streaming + uint8_t iInterface; + uint8_t itf_count; // number of interfaces including Audio Control + MIDI streaming + + uint8_t rx_cable_count; // IN endpoint CS descriptor bNumEmbMIDIJack value + uint8_t tx_cable_count; // OUT endpoint CS descriptor bNumEmbMIDIJack value + +#if CFG_TUH_MIDI_CUSTOM_STREAM_API + // For Stream read()/write() API + // Messages are always 4 bytes long, queue them for reading and writing so the + // callers can use the Stream interface with single-byte read/write calls. + midi_driver_stream_t stream_write; + midi_driver_stream_t stream_read; +#endif + + bool mounted; +} midih_interface_t; + +typedef struct +{ + TUH_EPBUF_DEF(tx, TUH_EPSIZE_BULK_MAX); + TUH_EPBUF_DEF(rx, TUH_EPSIZE_BULK_MAX); +} midih_epbuf_t; + +/// MIDI In Jack Descriptor +typedef struct TU_ATTR_PACKED +{ + uint8_t bLength; ///< Size of this descriptor in bytes. + uint8_t bDescriptorType; ///< Descriptor Type, must be Class-Specific + uint8_t bDescriptorSubType; ///< Descriptor SubType + uint8_t always_2; /// always 0x2 + uint8_t num_cables_rx; /// rx cable count + uint8_t num_cables_tx; /// tx cable count +} midi_desc_roland_header_t; +static midih_interface_t _midi_host[CFG_TUH_MIDI_CUSTOM]; +CFG_TUH_MEM_SECTION static midih_epbuf_t _midi_epbuf[CFG_TUH_MIDI_CUSTOM]; + +//--------------------------------------------------------------------+ +// Helper +//--------------------------------------------------------------------+ +TU_ATTR_ALWAYS_INLINE static inline uint8_t find_new_midi_index(void) +{ + for (uint8_t idx = 0; idx < CFG_TUH_MIDI_CUSTOM; idx++) + { + if (_midi_host[idx].daddr == 0) + { + return idx; + } + } + return TUSB_INDEX_INVALID_8; +} + +static inline uint8_t get_idx_by_ep_addr(uint8_t daddr, uint8_t ep_addr) +{ + for (uint8_t idx = 0; idx < CFG_TUH_MIDI_CUSTOM; idx++) + { + const midih_interface_t *p_midi = &_midi_host[idx]; + if ((p_midi->daddr == daddr) && + (ep_addr == usbMidi.ep_stream.rx.ep_addr || ep_addr == usbMidi.ep_stream.tx.ep_addr)) + { + return idx; + } + } + return TUSB_INDEX_INVALID_8; +} + +//--------------------------------------------------------------------+ +// USBH API +//--------------------------------------------------------------------+ +bool midih_init(void) +{ + tu_memclr(&_midi_host, sizeof(_midi_host)); + return true; +} + +bool midih_deinit(void) +{ + // for (size_t i = 0; i < CFG_TUH_MIDI_CUSTOM; i++) { + // midih_interface_t* p_midi = &_midi_host[i]; + // tu_edpt_stream_deinit(&usbMidi.ep_stream.rx); + // tu_edpt_stream_deinit(&usbMidi.ep_stream.tx); + // } + return true; +} + +void midih_close(uint8_t daddr) +{ + for (uint8_t idx = 0; idx < CFG_TUH_MIDI_CUSTOM; idx++) + { + midih_interface_t *p_midi = &_midi_host[idx]; + if (p_midi->daddr == daddr) + { + TU_LOG_DRV(" MIDI close addr = %u index = %u\r\n", daddr, idx); + tuh_midi_umount_cb(idx); + + p_midi->bInterfaceNumber = 0; + p_midi->rx_cable_count = 0; + p_midi->tx_cable_count = 0; + p_midi->daddr = 0; + p_midi->mounted = false; +#if CFG_TUH_MIDI_CUSTOM_STREAM_API + tu_memclr(&p_midi->stream_read, sizeof(p_midi->stream_read)); + tu_memclr(&p_midi->stream_write, sizeof(p_midi->stream_write)); +#endif + + tu_edpt_stream_close(&usbMidi.ep_stream.rx); + tu_edpt_stream_close(&usbMidi.ep_stream.tx); + } + } +} + +bool midih_xfer_cb(uint8_t dev_addr, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) +{ + (void)result; + const uint8_t idx = get_idx_by_ep_addr(dev_addr, ep_addr); + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); + midih_interface_t *p_midi = &_midi_host[idx]; + tu_edpt_stream_t *ep_str_rx = &usbMidi.ep_stream.rx; + tu_edpt_stream_t *ep_str_tx = &usbMidi.ep_stream.tx; + + if (ep_addr == ep_str_rx->ep_addr) + { + // receive new data, put it into FIFO and invoke callback if available + // Note: some devices send back all zero packets even if there is no data ready + if (xferred_bytes && !tu_mem_is_zero(ep_str_rx->ep_buf, xferred_bytes)) + { + tu_edpt_stream_read_xfer_complete(ep_str_rx, xferred_bytes); + tuh_midi_rx_cb(idx, xferred_bytes); + } + + tu_edpt_stream_read_xfer(ep_str_rx); // prepare for next transfer + } + else if (ep_addr == ep_str_tx->ep_addr) + { + tuh_midi_tx_cb(idx, xferred_bytes); + + if (0 == tu_edpt_stream_write_xfer(ep_str_tx)) + { + // If there is no data left, a ZLP should be sent if + // xferred_bytes is multiple of EP size and not zero + tu_edpt_stream_write_zlp_if_needed(ep_str_tx, xferred_bytes); + } + } + + return true; +} + +//--------------------------------------------------------------------+ +// Enumeration +//--------------------------------------------------------------------+ +uint16_t midih_open(uint8_t rhport, uint8_t dev_addr, const tusb_desc_interface_t *desc_itf, uint16_t max_len) +{ + (void)rhport; + // Some roland devices use vendor specific and have their own header + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass || TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass, 0); + bool roland = TUSB_CLASS_VENDOR_SPECIFIC == desc_itf->bInterfaceClass; + const uint8_t *desc_start = (const uint8_t *)desc_itf; + const uint8_t *p_desc = desc_start; + const uint8_t *desc_end = desc_start + max_len; + + const uint8_t idx = find_new_midi_index(); + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM, 0); + midih_interface_t *p_midi = &_midi_host[idx]; + p_midi->itf_count = 0; + + tuh_midi_descriptor_cb_t desc_cb = {0}; + desc_cb.jack_num = 0; + + // There can be just a MIDI or an Audio + MIDI interface + // - If there is Audio Control Interface + Audio Header descriptor, then skip it. + // - If there is an Audio Control Interface + Audio Streaming Interface, then ignore the Audio Streaming Interface. + // Future: + // Note that if this driver is used with an USB Audio Streaming host driver, + // then call that driver first. If the MIDI interface comes before the + // audio streaming interface, then the audio driver will have to call this + // driver after parsing the audio control interface and then resume parsing + // the streaming audio interface. + if (AUDIO_SUBCLASS_CONTROL == desc_itf->bInterfaceSubClass) + { + TU_VERIFY(max_len > 2 * sizeof(tusb_desc_interface_t) + sizeof(midi10_desc_cs_ac_interface_t), 0); + p_desc = tu_desc_next(p_desc); + TU_VERIFY(tu_desc_type(p_desc) == TUSB_DESC_CS_INTERFACE && + tu_desc_subtype(p_desc) == AUDIO10_CS_AC_INTERFACE_HEADER, + 0); + desc_cb.desc_audio_control = desc_itf; + + p_desc = tu_desc_next(p_desc); + desc_itf = (const tusb_desc_interface_t *)p_desc; + p_midi->itf_count = 1; + // skip non-interface and non-midi streaming descriptors + while (tu_desc_in_bounds(p_desc, desc_end) && (desc_itf->bDescriptorType != TUSB_DESC_INTERFACE || + (desc_itf->bInterfaceClass == TUSB_CLASS_AUDIO && + desc_itf->bInterfaceSubClass != AUDIO_SUBCLASS_MIDI_STREAMING))) + { + if (desc_itf->bDescriptorType == TUSB_DESC_INTERFACE && desc_itf->bAlternateSetting == 0) + { + p_midi->itf_count++; + } + p_desc = tu_desc_next(p_desc); + desc_itf = (const tusb_desc_interface_t *)p_desc; + } + TU_VERIFY(p_desc < desc_end, 0); + TU_VERIFY(TUSB_CLASS_AUDIO == desc_itf->bInterfaceClass, 0); + } + TU_VERIFY(AUDIO_SUBCLASS_MIDI_STREAMING == desc_itf->bInterfaceSubClass, 0); + + TU_LOG_DRV("MIDI opening Interface %u (addr = %u)\r\n", desc_itf->bInterfaceNumber, dev_addr); + p_midi->bInterfaceNumber = desc_itf->bInterfaceNumber; + p_midi->iInterface = desc_itf->iInterface; + p_midi->itf_count++; + desc_cb.desc_midi = desc_itf; + + bool found_new_interface = false; + do + { + p_desc = tu_desc_next(p_desc); + if (!tu_desc_in_bounds(p_desc, desc_end)) + { + break; + } + switch (tu_desc_type(p_desc)) + { + case TUSB_DESC_INTERFACE: + found_new_interface = true; + break; + + case TUSB_DESC_CS_INTERFACE: + switch (tu_desc_subtype(p_desc)) + { + case MIDI_CS_INTERFACE_HEADER: + TU_LOG_DRV(" Interface Header descriptor\r\n"); + desc_cb.desc_header = p_desc; + break; + + case MIDI_CS_INTERFACE_IN_JACK: + case MIDI_CS_INTERFACE_OUT_JACK: + { + TU_LOG_DRV(" Jack %s %s descriptor \r\n", + tu_desc_subtype(p_desc) == MIDI_CS_INTERFACE_IN_JACK ? "IN" : "OUT", + p_desc[3] == MIDI_JACK_EXTERNAL ? "External" : "Embedded"); + if (desc_cb.jack_num < TU_ARRAY_SIZE(desc_cb.desc_jack)) + { + desc_cb.desc_jack[desc_cb.jack_num++] = p_desc; + } + break; + } + + case MIDI_CS_INTERFACE_ELEMENT: + TU_LOG_DRV(" Element descriptor\r\n"); + desc_cb.desc_element = p_desc; + break; + + case MIDI_CS_ROLAND_HEADER: + { + midi_desc_roland_header_t const *p_rl = (midi_desc_roland_header_t const *)p_desc; + TU_LOG2("Found Roland Header %02x %02x %02x %02x\r\n", p_rl->bLength, p_rl->always_2, p_rl->num_cables_rx, p_rl->num_cables_tx); + if (p_rl->bLength >= sizeof(midi_desc_roland_header_t) && p_rl->always_2 == 0x02) + { + TU_VERIFY(p_rl->num_cables_rx < 0x10 && p_rl->num_cables_tx < 0x10); + TU_LOG2("Found Roland Header\r\n"); + p_midi->rx_cable_count = (1 << p_rl->num_cables_rx) - 1; + p_midi->tx_cable_count = (1 << p_rl->num_cables_tx) - 1; + break; + } + TU_LOG_DRV(" Unknown CS Interface sub-type %u\r\n", tu_desc_subtype(p_desc)); + break; + } + default: + TU_LOG_DRV(" Unknown CS Interface sub-type %u\r\n", tu_desc_subtype(p_desc)); + break; + } + break; + + case TUSB_DESC_ENDPOINT: + { + const tusb_desc_endpoint_t *p_ep = (const tusb_desc_endpoint_t *)p_desc; + + p_desc = tu_desc_next(p_desc); // next to CS endpoint + TU_VERIFY(tu_desc_in_bounds(p_desc, desc_end), 0); + tu_edpt_stream_t *ep_stream; + if (roland) + { + if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) + { + desc_cb.desc_epout = p_ep; + ep_stream = &usbMidi.ep_stream.tx; + } + else + { + desc_cb.desc_epin = p_ep; + ep_stream = &usbMidi.ep_stream.rx; + } + } + else + { + const midi_desc_cs_endpoint_t *p_csep = (const midi_desc_cs_endpoint_t *)p_desc; + + TU_LOG_DRV(" Endpoint and CS_Endpoint descriptor %02x\r\n", p_ep->bEndpointAddress); + if (tu_edpt_dir(p_ep->bEndpointAddress) == TUSB_DIR_OUT) + { + p_midi->tx_cable_count = p_csep->bNumEmbMIDIJack; + desc_cb.desc_epout = p_ep; + ep_stream = &usbMidi.ep_stream.tx; + } + else + { + p_midi->rx_cable_count = p_csep->bNumEmbMIDIJack; + desc_cb.desc_epin = p_ep; + ep_stream = &usbMidi.ep_stream.rx; + } + } + TU_ASSERT(tuh_edpt_open(dev_addr, p_ep), 0); + tu_edpt_stream_open(ep_stream, dev_addr, p_ep, tu_edpt_packet_size(p_ep)); + tu_edpt_stream_clear(ep_stream); + + break; + } + + default: + break; // skip unknown descriptor + } + } while (!found_new_interface); + + desc_cb.desc_midi_total_len = (uint16_t)((uintptr_t)p_desc - (uintptr_t)desc_start); + + p_midi->daddr = dev_addr; + tuh_midi_descriptor_cb(idx, &desc_cb); + + return desc_cb.desc_midi_total_len; +} + +bool midih_set_config(uint8_t dev_addr, uint8_t itf_num) +{ + uint8_t idx = tuh_midi_itf_get_index(dev_addr, itf_num); + TU_ASSERT(idx < CFG_TUH_MIDI_CUSTOM); + midih_interface_t *p_midi = &_midi_host[idx]; + p_midi->mounted = true; + + const tuh_midi_mount_cb_t mount_cb_data = { + .daddr = dev_addr, + .bInterfaceNumber = p_midi->bInterfaceNumber, + .rx_cable_count = p_midi->rx_cable_count, + .tx_cable_count = p_midi->tx_cable_count, + }; + tuh_midi_mount_cb(idx, &mount_cb_data); + + tu_edpt_stream_read_xfer(&usbMidi.ep_stream.rx); // prepare for incoming data + + // No special config things to do for MIDI + usbh_driver_set_config_complete(dev_addr, p_midi->bInterfaceNumber); + return true; +} + +//--------------------------------------------------------------------+ +// API +//--------------------------------------------------------------------+ +bool tuh_midi_mounted(uint8_t idx) +{ + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); + midih_interface_t *p_midi = &_midi_host[idx]; + return p_midi->mounted; +} + +uint8_t tuh_midi_itf_get_index(uint8_t daddr, uint8_t itf_num) +{ + for (uint8_t idx = 0; idx < CFG_TUH_MIDI_CUSTOM; idx++) + { + const midih_interface_t *p_midi = &_midi_host[idx]; + if (p_midi->daddr == daddr && + (p_midi->bInterfaceNumber == itf_num || + p_midi->bInterfaceNumber == (uint8_t)(itf_num + p_midi->itf_count - 1))) + { + return idx; + } + } + return TUSB_INDEX_INVALID_8; +} + +bool tuh_midi_itf_get_info(uint8_t idx, tuh_itf_info_t *info) +{ + midih_interface_t *p_midi = &_midi_host[idx]; + TU_VERIFY(p_midi && info); + + info->daddr = p_midi->daddr; + + // re-construct descriptor + tusb_desc_interface_t *desc = &info->desc; + desc->bLength = sizeof(tusb_desc_interface_t); + desc->bDescriptorType = TUSB_DESC_INTERFACE; + + desc->bInterfaceNumber = p_midi->bInterfaceNumber; + desc->bAlternateSetting = 0; + desc->bNumEndpoints = 0; + if (tu_edpt_stream_is_opened(&usbMidi.ep_stream.tx)) + { + desc->bNumEndpoints++; + } + if (tu_edpt_stream_is_opened(&usbMidi.ep_stream.rx)) + { + desc->bNumEndpoints++; + } + desc->bInterfaceClass = TUSB_CLASS_AUDIO; + desc->bInterfaceSubClass = AUDIO_SUBCLASS_MIDI_STREAMING; + desc->bInterfaceProtocol = 0; + desc->iInterface = p_midi->iInterface; + + return true; +} + +uint8_t tuh_midi_get_tx_cable_count(uint8_t idx) +{ + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); + midih_interface_t *p_midi = &_midi_host[idx]; + TU_VERIFY(usbMidi.ep_stream.tx.ep_addr != 0, 0); + return p_midi->tx_cable_count; +} + +uint8_t tuh_midi_get_rx_cable_count(uint8_t idx) +{ + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); + midih_interface_t *p_midi = &_midi_host[idx]; + TU_VERIFY(usbMidi.ep_stream.rx.ep_addr != 0, 0); + return p_midi->rx_cable_count; +} + +uint32_t tuh_midi_read_available(uint8_t idx) +{ + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); + midih_interface_t *p_midi = &_midi_host[idx]; + return tu_edpt_stream_read_available(&usbMidi.ep_stream.rx); +} + +uint32_t tuh_midi_write_flush(uint8_t idx) +{ + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM); + midih_interface_t *p_midi = &_midi_host[idx]; + return tu_edpt_stream_write_xfer(&usbMidi.ep_stream.tx); +} + +//--------------------------------------------------------------------+ +// Packet API +//--------------------------------------------------------------------+ +uint32_t tuh_midi_packet_read_n(uint8_t idx, uint8_t *buffer, uint32_t bufsize) +{ + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM && buffer && bufsize > 0, 0); + midih_interface_t *p_midi = &_midi_host[idx]; + + uint32_t count4 = tu_min32(bufsize, tu_edpt_stream_read_available(&usbMidi.ep_stream.rx)); + count4 = tu_align4(count4); // round down to multiple of 4 + TU_VERIFY(count4 > 0, 0); + return tu_edpt_stream_read(&usbMidi.ep_stream.rx, buffer, count4); +} + +uint32_t tuh_midi_packet_write_n(uint8_t idx, const uint8_t *buffer, uint32_t bufsize) +{ + TU_VERIFY(idx < CFG_TUH_MIDI_CUSTOM && buffer && bufsize > 0, 0); + midih_interface_t *p_midi = &_midi_host[idx]; + + const uint32_t bufsize4 = tu_align4(bufsize); + TU_VERIFY(bufsize4 > 0, 0); + return tu_edpt_stream_write(&usbMidi.ep_stream.tx, buffer, bufsize4); +} + +#endif \ No newline at end of file diff --git a/src/pico/xinput_device.cpp b/src/pico/xinput_device.cpp index d4b9ebe5e..ce290f769 100644 --- a/src/pico/xinput_device.cpp +++ b/src/pico/xinput_device.cpp @@ -12,6 +12,7 @@ #include "device/usbd_pvt.h" #include "hid.h" #include "xinput_device.h" +#include //--------------------------------------------------------------------+ // MACRO CONSTANT TYPEDEF diff --git a/src/shared/hid/hid.cpp b/src/shared/hid/hid.cpp index b474de498..ebda0660e 100644 --- a/src/shared/hid/hid.cpp +++ b/src/shared/hid/hid.cpp @@ -18,6 +18,7 @@ #include "usbhid.h" #include "util.h" #include "wii.h" +#include "Arduino.h" const PROGMEM char board[] = ARDWIINO_BOARD; const PROGMEM char f_cpu_descriptor_str[] = STR(F_CPU); @@ -913,7 +914,7 @@ void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_ } } long millis_since_command = 0; -uint8_t handle_serial_command(uint8_t request, uint16_t wValue, uint8_t *response_buffer, bool *success) +uint16_t handle_serial_command(uint8_t request, uint16_t wValue, uint8_t *response_buffer, bool *success) { switch (request) { diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 0ac10431d..c9c7976b8 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -27,6 +27,7 @@ #include "wt_drum.h" #include "quadrature_encoder.pio.h" #include "protar_neck.h" +#include "midi.hpp" #define UP 1 << 0 #define DOWN 1 << 1 #define LEFT 1 << 2 @@ -74,6 +75,8 @@ crkd_neck_t lastCrkd; protarneck_t lastProtar; unsigned long lastMidi = 0; Midi_Data_t midiData = {0}; +MidiDevice usbMidi(true, &midiData); +MidiDevice serialMidi(false, &midiData); uint8_t *dj_left = lastSuccessfulTurntablePacketLeft; uint8_t *dj_right = lastSuccessfulTurntablePacketRight; @@ -81,126 +84,6 @@ int8_t dj_turntable_left = 0; int8_t dj_turntable_right = 0; bool djLeftValid = true; bool djRightValid = true; -void onNote(uint8_t channel, uint8_t note, uint8_t velocity) -{ - // velocities are 7 bit - // printf("Note ON ch=%d, note=%d, vel=%d\r\n", channel, note, velocity); - velocity = velocity << 1; -#if DEVICE_TYPE_IS_DRUM - // drums, base inputs on triggers - if (velocity > midiData.midiVelocitiesTemp[note]) - { - midiData.midiVelocities[note] = velocity; - midiData.midiVelocitiesTemp[note] = velocity; - } -#else - // Handle midi normally - midiData.midiVelocities[note] = velocity; - midiData.midiVelocitiesTemp[note] = velocity; -#endif - lastMidi = millis(); -} - -void offNote(uint8_t channel, uint8_t note, uint8_t velocity) -{ - // printf("Note OFF ch=%d, note=%d, vel=%d\r\n", channel, note, velocity); - // ignore note off for drums as we handle that ourselves, and not all drums send it -#if !(DEVICE_TYPE_IS_DRUM) - midiData.midiVelocities[note] = 0; - midiData.midiVelocitiesTemp[note] = 0; -#endif -} - -void onControlChange(uint8_t channel, uint8_t b1, uint8_t b2) -{ - // cc are 7 bit - printf("ControlChange ch=%d, b1=%d, b2=%d\r\n", channel, b1, b2); - if (b1 == MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL) - { - midiData.midiSustainPedal = b2 << 1; - } - if (b1 == MIDI_CONTROL_COMMAND_MOD_WHEEL) - { - midiData.midiModWheel = b2 << 1; - } -} - -void onPitchBend(uint8_t channel, int pitch) -{ - // pitchbend is signed 14 bit - printf("PitchBend ch=%d, pitch=%d\r\n", channel, pitch); - midiData.midiPitchWheel = pitch << 2; -} -PS3RockBandProGuitar_Data_t sysexGuitar = {0}; -void onSysEx(uint8_t *data, unsigned size) -{ -#if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE - uint8_t type, fret, velocity; - type = data[5]; - uint8_t string = (size >= 5) ? (data[6] - 1) % 6 : 0; - // changes to the fret state - if ((type == 0x01) && (size >= 6)) - { - fret = data[7]; - // offset fret numbers relative to the base note of each string - switch (string) - { - case 0: - sysexGuitar.lowEFret = fret - 0x40; - break; - case 1: - sysexGuitar.aFret = fret - 0x3B; - break; - case 2: - sysexGuitar.dFret = fret - 0x37; - break; - case 3: - sysexGuitar.gFret = fret - 0x32; - break; - case 4: - sysexGuitar.bFret = fret - 0x2D; - break; - case 5: - sysexGuitar.highEFret = fret - 0x28; - break; - } - } - // picking events - else if ((type == 0x05) && (size >= 6)) - { - velocity = data[7]; - switch (string) - { - case 0: - sysexGuitar.lowEFretVelocity = velocity; - break; - case 1: - sysexGuitar.aFretVelocity = velocity; - break; - case 2: - sysexGuitar.dFretVelocity = velocity; - break; - case 3: - sysexGuitar.gFretVelocity = velocity; - break; - case 4: - sysexGuitar.bFretVelocity = velocity; - break; - case 5: - sysexGuitar.highEFretVelocity = velocity; - break; - } - } - // button events - else if ((type == 0x08) && (size >= 7)) - { - // PS3 style report starts at byte 4 - memcpy(&sysexGuitar, data + 6, 3); - // tilt however is not in the same spot as a ps3 report - sysexGuitar.tilt = (data[8] & 0x40) ? 0x7f : 0x40; - } -#endif -} uint8_t tmp = 0; long clone_guitar_timer = 0; long clone_guitar_ready_timer = 0; @@ -407,6 +290,15 @@ void init_main(void) #ifdef TICK_WII initWiiOutput(); #endif + + memset(midiData.midiVelocities, 0, sizeof(midiData.midiVelocities)); + midiData.midiPitchWheel = 0; + memset(midiData.midiControlChanges, 0, sizeof(midiData.midiControlChanges)); + memset(midiData.midiFrets, 0, sizeof(midiData.midiFrets)); + memset(midiData.midiStringVelocities, 0, sizeof(midiData.midiStringVelocities)); + memset(&midiData.proGuitarData, 0, sizeof(midiData.proGuitarData)); + // default to neutral + midiData.proGuitarData.dpad = 8; } #ifdef SLAVE_TWI_PORT bool slave_initted = false; @@ -3104,9 +2996,6 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #include "inputs/mustang_neck.h" #include "inputs/crkd.h" #include "inputs/turntable.h" - // #if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE - // convert_report((uint8_t *)&sysexGuitar, sizeof(sysexGuitar), {PS3, ROCK_BAND_PRO_GUITAR_SQUIRE, 0, 0, 0, false}, &usb_host_data); - // #endif TICK_SHARED; if (!startedInactivityPulse) { @@ -3384,6 +3273,35 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->orange = lastProtar.orange; report->soloFlag = lastProtar.soloFlag; #endif + +#if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE + if (midiData.seenProGuitar) + { + report->lowEFretVelocity = midiData.midiVelocities[0]; + report->aFretVelocity = midiData.midiVelocities[1]; + report->dFretVelocity = midiData.midiVelocities[2]; + report->gFretVelocity = midiData.midiVelocities[3]; + report->bFretVelocity = midiData.midiVelocities[4]; + report->highEFretVelocity = midiData.midiVelocities[5]; + report->tilt = midiData.proGuitarData.tilt == INT16_MAX ? 0x7F : 0x60; + for (size_t i = 0; i < TU_ARRAY_SIZE(midiData.midiFrets); i++) + { + uint8_t fret = fret; + report->green |= fret == 1 || fret == 6 || fret == 13; + report->red |= fret == 2 || fret == 7 || fret == 14; + report->yellow |= fret == 3 || fret == 8 || fret == 15; + report->blue |= fret == 4 || fret == 9 || fret == 16; + report->orange |= fret == 5 || fret == 10 || fret == 17; + report->solo |= fret >= 13 && fret <= 17; + } + report->lowEFret = midiData.midiFrets[0]; + report->aFret = midiData.midiFrets[1]; + report->dFret = midiData.midiFrets[2]; + report->gFret = midiData.midiFrets[3]; + report->bFret = midiData.midiFrets[4]; + report->highEFret = midiData.midiFrets[5]; + } +#endif #if PRO_GUITAR && BLUETOOTH_RX TRANSLATE_TO_PRO_GUITAR(bt_data) report->autoCal_Light = report->tilt; @@ -4053,6 +3971,56 @@ bool tick_usb(void) report_requested = true; return ready; } +void onNote(uint8_t channel, uint8_t note, uint8_t velocity) +{ + // velocities are 7 bit + // printf("Note ON ch=%d, note=%d, vel=%d\r\n", channel, note, velocity); + velocity = velocity << 1; +#if DEVICE_TYPE_IS_DRUM + // drums, base inputs on triggers + if (velocity > midiData.midiVelocitiesTemp[note]) + { + midiData.midiVelocities[note] = velocity; + midiData.midiVelocitiesTemp[note] = velocity; + } +#else + // Handle midi normally + midiData.midiVelocities[note] = velocity; + midiData.midiVelocitiesTemp[note] = velocity; +#endif + lastMidi = millis(); +} + +void offNote(uint8_t channel, uint8_t note, uint8_t velocity) +{ + // printf("Note OFF ch=%d, note=%d, vel=%d\r\n", channel, note, velocity); + // ignore note off for drums as we handle that ourselves, and not all drums send it +#if !(DEVICE_TYPE_IS_DRUM) + midiData.midiVelocities[note] = 0; + midiData.midiVelocitiesTemp[note] = 0; +#endif +} + +void onControlChange(uint8_t channel, uint8_t b1, uint8_t b2) +{ + // cc are 7 bit + printf("ControlChange ch=%d, b1=%d, b2=%d\r\n", channel, b1, b2); + if (b1 == MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL) + { + midiData.midiSustainPedal = b2 << 1; + } + if (b1 == MIDI_CONTROL_COMMAND_MOD_WHEEL) + { + midiData.midiModWheel = b2 << 1; + } +} + +void onPitchBend(uint8_t channel, int pitch) +{ + // pitchbend is signed 14 bit + printf("PitchBend ch=%d, pitch=%d\r\n", channel, pitch); + midiData.midiPitchWheel = pitch << 2; +} #if BLUETOOTH_RX int tick_bluetooth_inputs(const void *data, uint8_t len, USB_Device_Type_t device_type) { @@ -4077,6 +4045,9 @@ void tick(void) TICK_LED_BLUETOOTH; #endif + usbMidi.update(false, false); + serialMidi.update(false, false); + if (reset_after_360 && millis() > reset_after_360) { reset_usb(); diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index c5faf1e7f..cd2f54dbf 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -11,6 +11,7 @@ #include "usbhid.h" #include "util.h" #include "xsm3/xsm3.h" +#include "Arduino.h" // We can't use WideStrings below, as the pico has four byte widestrings, and we need them to be two-byte. @@ -1248,7 +1249,7 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const } #endif bool test = true; - uint8_t size = handle_serial_command(request, wValue, requestBuffer, &test); + uint16_t size = handle_serial_command(request, wValue, requestBuffer, &test); if (test) { return size; @@ -1762,7 +1763,7 @@ uint16_t descriptorRequest(const uint16_t wValue, } else if (descriptorNumber < 4) { - str = (uint8_t *)pgm_read_pointer(descriptorStrings + descriptorNumber); + str = (uint8_t *)descriptorStrings[descriptorNumber]; } else if (descriptorNumber == 0xEE) { From aee805793e78da230a26f0ddab437e7b7bc1aed5 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 15 Jul 2026 15:29:58 +1200 Subject: [PATCH 198/239] map missing pro guitar buttons --- src/shared/main/shared_main.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index c9c7976b8..fae0c0999 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3284,6 +3284,13 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->bFretVelocity = midiData.midiVelocities[4]; report->highEFretVelocity = midiData.midiVelocities[5]; report->tilt = midiData.proGuitarData.tilt == INT16_MAX ? 0x7F : 0x60; + report->start |= midiData.proGuitarData.start; + report->back |= midiData.proGuitarData.back; + report->guide |= midiData.proGuitarData.guide; + report->a |= midiData.proGuitarData.a; + report->b |= midiData.proGuitarData.b; + report->x |= midiData.proGuitarData.x; + report->y |= midiData.proGuitarData.y; for (size_t i = 0; i < TU_ARRAY_SIZE(midiData.midiFrets); i++) { uint8_t fret = fret; From fccd615d67e4ed8d0c409edbd4120db7ebde0e58 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 15 Jul 2026 15:42:14 +1200 Subject: [PATCH 199/239] map missing pro guitar buttons --- src/shared/main/shared_main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index fae0c0999..4d27cfa77 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3291,6 +3291,12 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->b |= midiData.proGuitarData.b; report->x |= midiData.proGuitarData.x; report->y |= midiData.proGuitarData.y; + + uint8_t dpad = midiData.proGuitarData.dpad >= 0x08 ? 0 : dpad_bindings_reverse[midiData.proGuitarData.dpad]; + report->dpadUp |= dpad & UP; + report->dpadLeft |= dpad & LEFT; + report->dpadDown |= dpad & DOWN; + report->dpadRight |= dpad & RIGHT; for (size_t i = 0; i < TU_ARRAY_SIZE(midiData.midiFrets); i++) { uint8_t fret = fret; From a51d205b8090cfe34ca9940302dda517ed5fa86e Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 15 Jul 2026 16:11:20 +1200 Subject: [PATCH 200/239] map missing pro guitar buttons --- src/shared/main/shared_main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 4d27cfa77..f578b7b48 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3299,7 +3299,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->dpadRight |= dpad & RIGHT; for (size_t i = 0; i < TU_ARRAY_SIZE(midiData.midiFrets); i++) { - uint8_t fret = fret; + uint8_t fret = midiData.midiFrets[i]; report->green |= fret == 1 || fret == 6 || fret == 13; report->red |= fret == 2 || fret == 7 || fret == 14; report->yellow |= fret == 3 || fret == 8 || fret == 15; From 24f0bde37f2a3325bb7957080c8c74c81ff50d9d Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 15 Jul 2026 16:18:05 +1200 Subject: [PATCH 201/239] map missing pro guitar buttons --- src/shared/main/shared_main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index f578b7b48..ea381bb1d 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3293,6 +3293,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->y |= midiData.proGuitarData.y; uint8_t dpad = midiData.proGuitarData.dpad >= 0x08 ? 0 : dpad_bindings_reverse[midiData.proGuitarData.dpad]; + asm volatile("" :: + : "memory"); report->dpadUp |= dpad & UP; report->dpadLeft |= dpad & LEFT; report->dpadDown |= dpad & DOWN; From a3bf3f92004ba0755bc6c628fa496aa145024bb3 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 15 Jul 2026 16:55:13 +1200 Subject: [PATCH 202/239] map missing pro guitar buttons --- src/shared/main/shared_main.cpp | 119 ++++++++++++++++++++++++++++---- 1 file changed, 104 insertions(+), 15 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index ea381bb1d..2465f9da5 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3277,12 +3277,12 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE if (midiData.seenProGuitar) { - report->lowEFretVelocity = midiData.midiVelocities[0]; - report->aFretVelocity = midiData.midiVelocities[1]; - report->dFretVelocity = midiData.midiVelocities[2]; - report->gFretVelocity = midiData.midiVelocities[3]; - report->bFretVelocity = midiData.midiVelocities[4]; - report->highEFretVelocity = midiData.midiVelocities[5]; + report->lowEFretVelocity = midiData.midiStringVelocities[5]; + report->aFretVelocity = midiData.midiStringVelocities[4]; + report->dFretVelocity = midiData.midiStringVelocities[3]; + report->gFretVelocity = midiData.midiStringVelocities[2]; + report->bFretVelocity = midiData.midiStringVelocities[1]; + report->highEFretVelocity = midiData.midiStringVelocities[0]; report->tilt = midiData.proGuitarData.tilt == INT16_MAX ? 0x7F : 0x60; report->start |= midiData.proGuitarData.start; report->back |= midiData.proGuitarData.back; @@ -3292,9 +3292,10 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->x |= midiData.proGuitarData.x; report->y |= midiData.proGuitarData.y; - uint8_t dpad = midiData.proGuitarData.dpad >= 0x08 ? 0 : dpad_bindings_reverse[midiData.proGuitarData.dpad]; - asm volatile("" :: - : "memory"); + uint8_t dpad = midiData.proGuitarData.dpad & 0x0f; + dpad = dpad >= 0x08 ? 0 : dpad_bindings_reverse[dpad]; + asm volatile("" :: + : "memory"); report->dpadUp |= dpad & UP; report->dpadLeft |= dpad & LEFT; report->dpadDown |= dpad & DOWN; @@ -3309,12 +3310,12 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->orange |= fret == 5 || fret == 10 || fret == 17; report->solo |= fret >= 13 && fret <= 17; } - report->lowEFret = midiData.midiFrets[0]; - report->aFret = midiData.midiFrets[1]; - report->dFret = midiData.midiFrets[2]; - report->gFret = midiData.midiFrets[3]; - report->bFret = midiData.midiFrets[4]; - report->highEFret = midiData.midiFrets[5]; + report->lowEFret = midiData.midiFrets[5]; + report->aFret = midiData.midiFrets[4]; + report->dFret = midiData.midiFrets[3]; + report->gFret = midiData.midiFrets[2]; + report->bFret = midiData.midiFrets[1]; + report->highEFret = midiData.midiFrets[0]; } #endif #if PRO_GUITAR && BLUETOOTH_RX @@ -3536,6 +3537,50 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->blue = lastProtar.blue; report->orange = lastProtar.orange; #endif +#if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE + if (midiData.seenProGuitar) + { + report->lowEFretVelocity = midiData.midiStringVelocities[5]; + report->aFretVelocity = midiData.midiStringVelocities[4]; + report->dFretVelocity = midiData.midiStringVelocities[3]; + report->gFretVelocity = midiData.midiStringVelocities[2]; + report->bFretVelocity = midiData.midiStringVelocities[1]; + report->highEFretVelocity = midiData.midiStringVelocities[0]; + report->tilt = midiData.proGuitarData.tilt == INT16_MAX ? 0x7F : 0x60; + report->start |= midiData.proGuitarData.start; + report->back |= midiData.proGuitarData.back; + report->guide |= midiData.proGuitarData.guide; + report->a |= midiData.proGuitarData.a; + report->b |= midiData.proGuitarData.b; + report->x |= midiData.proGuitarData.x; + report->y |= midiData.proGuitarData.y; + + uint8_t dpad = midiData.proGuitarData.dpad & 0x0f; + dpad = dpad >= 0x08 ? 0 : dpad_bindings_reverse[dpad]; + asm volatile("" :: + : "memory"); + report->dpadUp |= dpad & UP; + report->dpadLeft |= dpad & LEFT; + report->dpadDown |= dpad & DOWN; + report->dpadRight |= dpad & RIGHT; + for (size_t i = 0; i < TU_ARRAY_SIZE(midiData.midiFrets); i++) + { + uint8_t fret = midiData.midiFrets[i]; + report->green |= fret == 1 || fret == 6 || fret == 13; + report->red |= fret == 2 || fret == 7 || fret == 14; + report->yellow |= fret == 3 || fret == 8 || fret == 15; + report->blue |= fret == 4 || fret == 9 || fret == 16; + report->orange |= fret == 5 || fret == 10 || fret == 17; + // report->soloFlag |= fret >= 13 && fret <= 17; + } + report->lowEFret = midiData.midiFrets[5]; + report->aFret = midiData.midiFrets[4]; + report->dFret = midiData.midiFrets[3]; + report->gFret = midiData.midiFrets[2]; + report->bFret = midiData.midiFrets[1]; + report->highEFret = midiData.midiFrets[0]; + } +#endif #if PRO_GUITAR && BLUETOOTH_RX TRANSLATE_TO_PRO_GUITAR(bt_data) #endif @@ -3733,6 +3778,50 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->orange = lastProtar.orange; report->soloFlag = lastProtar.soloFlag; #endif +#if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE + if (midiData.seenProGuitar) + { + report->lowEFretVelocity = midiData.midiStringVelocities[5]; + report->aFretVelocity = midiData.midiStringVelocities[4]; + report->dFretVelocity = midiData.midiStringVelocities[3]; + report->gFretVelocity = midiData.midiStringVelocities[2]; + report->bFretVelocity = midiData.midiStringVelocities[1]; + report->highEFretVelocity = midiData.midiStringVelocities[0]; + report->tilt = midiData.proGuitarData.tilt == INT16_MAX ? 0x7F : 0x60; + report->start |= midiData.proGuitarData.start; + report->back |= midiData.proGuitarData.back; + report->guide |= midiData.proGuitarData.guide; + report->a |= midiData.proGuitarData.a; + report->b |= midiData.proGuitarData.b; + report->x |= midiData.proGuitarData.x; + report->y |= midiData.proGuitarData.y; + + uint8_t dpad = midiData.proGuitarData.dpad & 0x0f; + dpad = dpad >= 0x08 ? 0 : dpad_bindings_reverse[dpad]; + asm volatile("" :: + : "memory"); + report->dpadUp |= dpad & UP; + report->dpadLeft |= dpad & LEFT; + report->dpadDown |= dpad & DOWN; + report->dpadRight |= dpad & RIGHT; + for (size_t i = 0; i < TU_ARRAY_SIZE(midiData.midiFrets); i++) + { + uint8_t fret = midiData.midiFrets[i]; + report->green |= fret == 1 || fret == 6 || fret == 13; + report->red |= fret == 2 || fret == 7 || fret == 14; + report->yellow |= fret == 3 || fret == 8 || fret == 15; + report->blue |= fret == 4 || fret == 9 || fret == 16; + report->orange |= fret == 5 || fret == 10 || fret == 17; + report->soloFlag |= fret >= 13 && fret <= 17; + } + report->lowEFret = midiData.midiFrets[5]; + report->aFret = midiData.midiFrets[4]; + report->dFret = midiData.midiFrets[3]; + report->gFret = midiData.midiFrets[2]; + report->bFret = midiData.midiFrets[1]; + report->highEFret = midiData.midiFrets[0]; + } +#endif #if PRO_GUITAR && BLUETOOTH_RX TRANSLATE_TO_PRO_GUITAR(bt_data) report->autoCal_Light = report->tilt; From 22a7b64acb341dcaec89ecb3985f9465770fbe05 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 15 Jul 2026 18:01:13 +1200 Subject: [PATCH 203/239] map missing pro guitar buttons --- include/midi_descriptors.h | 2 ++ src/shared/main/shared_main.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/midi_descriptors.h b/include/midi_descriptors.h index eb1b5db60..20c74bca5 100644 --- a/include/midi_descriptors.h +++ b/include/midi_descriptors.h @@ -361,9 +361,11 @@ typedef struct uint8_t : 2; uint8_t dpad : 4; + uint8_t : 2; uint8_t tilt : 1; uint8_t : 1; + uint8_t end[2]; } __attribute__((packed)) ProGuitar_Sysex_Buttons_t; typedef struct { diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 2465f9da5..09851c057 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3283,7 +3283,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->gFretVelocity = midiData.midiStringVelocities[2]; report->bFretVelocity = midiData.midiStringVelocities[1]; report->highEFretVelocity = midiData.midiStringVelocities[0]; - report->tilt = midiData.proGuitarData.tilt == INT16_MAX ? 0x7F : 0x60; + report->tilt = midiData.proGuitarData.tilt ? 0x7F : 0x60; report->start |= midiData.proGuitarData.start; report->back |= midiData.proGuitarData.back; report->guide |= midiData.proGuitarData.guide; @@ -3292,7 +3292,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->x |= midiData.proGuitarData.x; report->y |= midiData.proGuitarData.y; - uint8_t dpad = midiData.proGuitarData.dpad & 0x0f; + uint8_t dpad = midiData.proGuitarData.dpad; dpad = dpad >= 0x08 ? 0 : dpad_bindings_reverse[dpad]; asm volatile("" :: : "memory"); @@ -3546,7 +3546,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->gFretVelocity = midiData.midiStringVelocities[2]; report->bFretVelocity = midiData.midiStringVelocities[1]; report->highEFretVelocity = midiData.midiStringVelocities[0]; - report->tilt = midiData.proGuitarData.tilt == INT16_MAX ? 0x7F : 0x60; + report->tilt = midiData.proGuitarData.tilt ? 0x7F : 0x60; report->start |= midiData.proGuitarData.start; report->back |= midiData.proGuitarData.back; report->guide |= midiData.proGuitarData.guide; @@ -3555,7 +3555,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->x |= midiData.proGuitarData.x; report->y |= midiData.proGuitarData.y; - uint8_t dpad = midiData.proGuitarData.dpad & 0x0f; + uint8_t dpad = midiData.proGuitarData.dpad; dpad = dpad >= 0x08 ? 0 : dpad_bindings_reverse[dpad]; asm volatile("" :: : "memory"); @@ -3787,7 +3787,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->gFretVelocity = midiData.midiStringVelocities[2]; report->bFretVelocity = midiData.midiStringVelocities[1]; report->highEFretVelocity = midiData.midiStringVelocities[0]; - report->tilt = midiData.proGuitarData.tilt == INT16_MAX ? 0x7F : 0x60; + report->tilt = midiData.proGuitarData.tilt ? 0x7F : 0x60; report->start |= midiData.proGuitarData.start; report->back |= midiData.proGuitarData.back; report->guide |= midiData.proGuitarData.guide; @@ -3796,7 +3796,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->x |= midiData.proGuitarData.x; report->y |= midiData.proGuitarData.y; - uint8_t dpad = midiData.proGuitarData.dpad & 0x0f; + uint8_t dpad = midiData.proGuitarData.dpad; dpad = dpad >= 0x08 ? 0 : dpad_bindings_reverse[dpad]; asm volatile("" :: : "memory"); From 36589cd902b8a597c67d2f07c69e57a8f1465b2b Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 16 Jul 2026 08:42:04 +1200 Subject: [PATCH 204/239] misc fixes --- include/commands.h | 1 + include/pico_slave.h | 1 + src/shared/hid/hid.cpp | 6 +++ src/shared/main/shared_main.cpp | 65 +++++++++++++++++---------------- 4 files changed, 42 insertions(+), 31 deletions(-) diff --git a/include/commands.h b/include/commands.h index e163902a0..a35119d6b 100644 --- a/include/commands.h +++ b/include/commands.h @@ -56,6 +56,7 @@ enum SerialCommands { COMMAND_READ_CRKD, COMMAND_READ_MATRIX, COMMAND_MUSTANG_NECK_VALID, + COMMAND_READ_PERIPHERAL_ENCODER, MAX=100 }; diff --git a/include/pico_slave.h b/include/pico_slave.h index ccb9fd792..d7615bfdd 100644 --- a/include/pico_slave.h +++ b/include/pico_slave.h @@ -38,4 +38,5 @@ void slaveSetWtCounter(uint16_t counter); void slaveInitLED(uint8_t instance); void slaveWriteLED(uint8_t data); void slaveWriteAnalog(uint8_t pin, uint8_t val); +int slaveReadQuad(); #endif \ No newline at end of file diff --git a/src/shared/hid/hid.cpp b/src/shared/hid/hid.cpp index ebda0660e..333893ea6 100644 --- a/src/shared/hid/hid.cpp +++ b/src/shared/hid/hid.cpp @@ -1131,6 +1131,12 @@ uint16_t handle_serial_command(uint8_t request, uint16_t wValue, uint8_t *respon memcpy(response_buffer, &response, sizeof(response)); return sizeof(response); } + case COMMAND_READ_PERIPHERAL_ENCODER: + { + int response = slaveReadQuad(); + memcpy(response_buffer, &response, sizeof(response)); + return sizeof(response); + } #endif #if LED_COUNT_WS2812 case COMMAND_SET_LEDS: diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 09851c057..b4328d850 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -90,7 +90,7 @@ long clone_guitar_ready_timer = 0; bool clone_ready = false; bool reading = false; Buffer_Report_t last_queue_report; -long last_queue = 0; +uint32_t last_queue = 0; uint8_t brightness = LED_BRIGHTNESS; uint8_t queue_size = 0; uint8_t led_tmp; @@ -2981,6 +2981,29 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #if DIGITAL_COUNT bool drumSeen[DIGITAL_COUNT] = {false}; #endif + if (INPUT_QUEUE) + { + if (micros() - last_queue > 100) + { + last_queue = micros(); + for (int i = 0; i < DIGITAL_COUNT; i++) + { + if (debounce[i]) + { + debounce[i]--; + } + } +#if REQUIRE_LED_DEBOUNCE + for (int i = 0; i < LED_DEBOUNCE_COUNT; i++) + { + if (ledDebounce[i]) + { + ledDebounce[i]--; + } + } +#endif + } + } // Tick Inputs #include "inputs/accel.h" #include "inputs/bh_drum.h" @@ -3019,41 +3042,21 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #endif // We tick the guitar every 5ms to handle inputs if nothing is attempting to read, but this doesn't need to output that data anywhere. // if input queues are enabled, then we just tick as often as possible - if (!buf) + if (INPUT_QUEUE) { - if (INPUT_QUEUE) + if (current_queue_report.val != last_queue_report.val) { - if (micros() - last_queue > 100) - { - last_queue = micros(); - for (int i = 0; i < DIGITAL_COUNT; i++) - { - if (debounce[i]) - { - debounce[i]--; - } - } -#if REQUIRE_LED_DEBOUNCE - for (int i = 0; i < LED_DEBOUNCE_COUNT; i++) - { - if (ledDebounce[i]) - { - ledDebounce[i]--; - } - } -#endif - } - if (current_queue_report.val != last_queue_report.val) + queue[queue_tail] = current_queue_report; + last_queue_report = current_queue_report; + if (queue_size < BUFFER_SIZE_QUEUE) { - queue[queue_tail] = current_queue_report; - last_queue_report = current_queue_report; - if (queue_size < BUFFER_SIZE_QUEUE) - { - queue_size++; - queue_tail++; - } + queue_size++; + queue_tail++; } } + } + if (!buf) + { return 0; } From cf7581e977a67c95eab7e62c7848ca1628e41eb7 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 16 Jul 2026 09:42:13 +1200 Subject: [PATCH 205/239] misc fixes --- src/pico/midi.cpp | 5 +++ src/shared/main/shared_main.cpp | 57 +++++++++++++++++---------------- 2 files changed, 34 insertions(+), 28 deletions(-) diff --git a/src/pico/midi.cpp b/src/pico/midi.cpp index 03e3b6454..f365dcf7b 100644 --- a/src/pico/midi.cpp +++ b/src/pico/midi.cpp @@ -156,6 +156,11 @@ void MidiDevice::update(bool full_poll, bool send_events) // proto_Event event = {which_event : proto_Event_midiDebug_tag, event : {midiDebug : {data : {size : data_size, bytes : {0}}}}}; // memcpy(event.event.midiDebug.data.bytes, cable_state->data, data_size); // HIDConfigDevice::send_event(event, false); + // printf("data: "); + // for (uint8_t i = 0; i < data_size; i++) { + // printf("%02X ", cable_state->data[i]); + // } + // printf("\r\n"); } uint8_t status = (cable_state->data[0] & 0xf0) >> 4; uint8_t channel = cable_state->data[0] & 0x0f; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index b4328d850..f15bf5149 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3259,8 +3259,9 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #endif #if PRO_GUITAR && USB_HOST_STACK TRANSLATE_TO_PRO_GUITAR(usb_host_data) - report->autoCal_Light = report->tilt; - report->autoCal_Microphone = report->tilt; +#endif +#if PRO_GUITAR && BLUETOOTH_RX + TRANSLATE_TO_PRO_GUITAR(bt_data) #endif #ifdef MUSTANG_NECK_SPI_PORT report->lowEFret = lastProtar.lowEFret; @@ -3286,7 +3287,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->gFretVelocity = midiData.midiStringVelocities[2]; report->bFretVelocity = midiData.midiStringVelocities[1]; report->highEFretVelocity = midiData.midiStringVelocities[0]; - report->tilt = midiData.proGuitarData.tilt ? 0x7F : 0x60; + report->tilt = midiData.proGuitarData.tilt ? 0x7F : 0x40; report->start |= midiData.proGuitarData.start; report->back |= midiData.proGuitarData.back; report->guide |= midiData.proGuitarData.guide; @@ -3299,10 +3300,10 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu dpad = dpad >= 0x08 ? 0 : dpad_bindings_reverse[dpad]; asm volatile("" :: : "memory"); - report->dpadUp |= dpad & UP; - report->dpadLeft |= dpad & LEFT; - report->dpadDown |= dpad & DOWN; - report->dpadRight |= dpad & RIGHT; + report->dpadUp |= (dpad & UP) != 0; + report->dpadLeft |= (dpad & LEFT) != 0; + report->dpadDown |= (dpad & DOWN) != 0; + report->dpadRight |= (dpad & RIGHT) != 0; for (size_t i = 0; i < TU_ARRAY_SIZE(midiData.midiFrets); i++) { uint8_t fret = midiData.midiFrets[i]; @@ -3321,10 +3322,9 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->highEFret = midiData.midiFrets[0]; } #endif -#if PRO_GUITAR && BLUETOOTH_RX - TRANSLATE_TO_PRO_GUITAR(bt_data) - report->autoCal_Light = report->tilt; - report->autoCal_Microphone = report->tilt; +#if PRO_GUITAR + report->autoCal_Light = report->tilt; + report->autoCal_Microphone = report->tilt; #endif asm volatile("" :: : "memory"); @@ -3527,6 +3527,9 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu TRANSLATE_TO_PRO_GUITAR(usb_host_data) #endif +#if PRO_GUITAR && BLUETOOTH_RX + TRANSLATE_TO_PRO_GUITAR(bt_data) +#endif #ifdef MUSTANG_NECK_SPI_PORT report->lowEFret = lastProtar.lowEFret; report->aFret = lastProtar.aFret; @@ -3549,7 +3552,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->gFretVelocity = midiData.midiStringVelocities[2]; report->bFretVelocity = midiData.midiStringVelocities[1]; report->highEFretVelocity = midiData.midiStringVelocities[0]; - report->tilt = midiData.proGuitarData.tilt ? 0x7F : 0x60; + report->tilt = midiData.proGuitarData.tilt ? 0x7F : 0x40; report->start |= midiData.proGuitarData.start; report->back |= midiData.proGuitarData.back; report->guide |= midiData.proGuitarData.guide; @@ -3562,10 +3565,10 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu dpad = dpad >= 0x08 ? 0 : dpad_bindings_reverse[dpad]; asm volatile("" :: : "memory"); - report->dpadUp |= dpad & UP; - report->dpadLeft |= dpad & LEFT; - report->dpadDown |= dpad & DOWN; - report->dpadRight |= dpad & RIGHT; + report->dpadUp |= (dpad & UP) != 0; + report->dpadLeft |= (dpad & LEFT) != 0; + report->dpadDown |= (dpad & DOWN) != 0; + report->dpadRight |= (dpad & RIGHT) != 0; for (size_t i = 0; i < TU_ARRAY_SIZE(midiData.midiFrets); i++) { uint8_t fret = midiData.midiFrets[i]; @@ -3583,9 +3586,6 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->bFret = midiData.midiFrets[1]; report->highEFret = midiData.midiFrets[0]; } -#endif -#if PRO_GUITAR && BLUETOOTH_RX - TRANSLATE_TO_PRO_GUITAR(bt_data) #endif asm volatile("" :: : "memory"); @@ -3763,8 +3763,9 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #if PRO_GUITAR && USB_HOST_STACK TRANSLATE_TO_PRO_GUITAR(usb_host_data) - report->autoCal_Light = report->tilt; - report->autoCal_Microphone = report->tilt; +#endif +#if PRO_GUITAR && BLUETOOTH_RX + TRANSLATE_TO_PRO_GUITAR(bt_data) #endif #ifdef MUSTANG_NECK_SPI_PORT @@ -3790,7 +3791,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->gFretVelocity = midiData.midiStringVelocities[2]; report->bFretVelocity = midiData.midiStringVelocities[1]; report->highEFretVelocity = midiData.midiStringVelocities[0]; - report->tilt = midiData.proGuitarData.tilt ? 0x7F : 0x60; + report->tilt = midiData.proGuitarData.tilt ? 0x7F : 0x40; report->start |= midiData.proGuitarData.start; report->back |= midiData.proGuitarData.back; report->guide |= midiData.proGuitarData.guide; @@ -3803,10 +3804,10 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu dpad = dpad >= 0x08 ? 0 : dpad_bindings_reverse[dpad]; asm volatile("" :: : "memory"); - report->dpadUp |= dpad & UP; - report->dpadLeft |= dpad & LEFT; - report->dpadDown |= dpad & DOWN; - report->dpadRight |= dpad & RIGHT; + report->dpadUp |= (dpad & UP) != 0; + report->dpadLeft |= (dpad & LEFT) != 0; + report->dpadDown |= (dpad & DOWN) != 0; + report->dpadRight |= (dpad & RIGHT) != 0; for (size_t i = 0; i < TU_ARRAY_SIZE(midiData.midiFrets); i++) { uint8_t fret = midiData.midiFrets[i]; @@ -3825,8 +3826,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->highEFret = midiData.midiFrets[0]; } #endif -#if PRO_GUITAR && BLUETOOTH_RX - TRANSLATE_TO_PRO_GUITAR(bt_data) + +#if PRO_GUITAR report->autoCal_Light = report->tilt; report->autoCal_Microphone = report->tilt; #endif From e3001071cd273b7ad472be51a044c229ee1d95fb Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 16 Jul 2026 10:36:06 +1200 Subject: [PATCH 206/239] start+select to guide for squier --- src/shared/main/shared_main.cpp | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index f15bf5149..f3fe954b8 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3291,6 +3291,9 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->start |= midiData.proGuitarData.start; report->back |= midiData.proGuitarData.back; report->guide |= midiData.proGuitarData.guide; +#if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE + report->guide |= midiData.proGuitarData.start && midiData.proGuitarData.back; +#endif report->a |= midiData.proGuitarData.a; report->b |= midiData.proGuitarData.b; report->x |= midiData.proGuitarData.x; @@ -3323,8 +3326,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu } #endif #if PRO_GUITAR - report->autoCal_Light = report->tilt; - report->autoCal_Microphone = report->tilt; + report->autoCal_Light = report->tilt; + report->autoCal_Microphone = report->tilt; #endif asm volatile("" :: : "memory"); @@ -3556,6 +3559,9 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->start |= midiData.proGuitarData.start; report->back |= midiData.proGuitarData.back; report->guide |= midiData.proGuitarData.guide; +#if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE + report->guide |= midiData.proGuitarData.start && midiData.proGuitarData.back; +#endif report->a |= midiData.proGuitarData.a; report->b |= midiData.proGuitarData.b; report->x |= midiData.proGuitarData.x; @@ -3795,6 +3801,9 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->start |= midiData.proGuitarData.start; report->back |= midiData.proGuitarData.back; report->guide |= midiData.proGuitarData.guide; +#if DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE + report->guide |= midiData.proGuitarData.start && midiData.proGuitarData.back; +#endif report->a |= midiData.proGuitarData.a; report->b |= midiData.proGuitarData.b; report->x |= midiData.proGuitarData.x; From 59e6440944ae30626f3ab920118511ae1fce3b7d Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 16 Jul 2026 12:52:55 +1200 Subject: [PATCH 207/239] flip velocity if same as previous velocity --- src/pico/midi.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/pico/midi.cpp b/src/pico/midi.cpp index f365dcf7b..c79ec8998 100644 --- a/src/pico/midi.cpp +++ b/src/pico/midi.cpp @@ -256,6 +256,9 @@ void MidiDevice::update(bool full_poll, bool send_events) // picking events uint8_t string = cable_state->data[5] - 1; uint8_t velocity = cable_state->data[6]; + if (midiData->midiStringVelocities[string] == velocity) { + velocity ^= 1; + } midiData->midiStringVelocities[string] = velocity; } } From d4c0b1e85a450595fae51655a75d5f930faa7d20 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 16 Jul 2026 15:12:22 +1200 Subject: [PATCH 208/239] poll encoder at 8ms for now --- src/pico_slave/main.cpp | 2 +- src/shared/main/shared_main.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pico_slave/main.cpp b/src/pico_slave/main.cpp index a7f4e0190..c6641cfee 100644 --- a/src/pico_slave/main.cpp +++ b/src/pico_slave/main.cpp @@ -218,7 +218,7 @@ void loop() { checkWtSlave(6); rawWt = checkWtSlave(1) | (checkWtSlave(0) << 1) | (checkWtSlave(2) << 2) | (checkWtSlave(3) << 3) | (checkWtSlave(4) << 4); } - if (hasInitQuad && (lastQuadPoll - millis()) > quadPollRate) { + if (hasInitQuad && (millis()-lastQuadPoll) > quadPollRate) { lastQuadPoll = millis(); new_value = quadrature_encoder_get_count(pio, sm); delta = new_value - old_value; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index f3fe954b8..87011f16a 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -328,7 +328,7 @@ void tick_slave() slaveInitWt(); #endif #ifdef INPUT_QUAD_SLAVE - slaveInitQuad(INPUT_QUAD_SLAVE, 1); + slaveInitQuad(INPUT_QUAD_SLAVE, 8); #endif } #endif From 43670c959f5fa8669f7fc242bc7968d42abbd200 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 16 Jul 2026 15:34:32 +1200 Subject: [PATCH 209/239] poll encoder at 5ms, add multipler to scale values --- src/shared/main/inputs/slave.h | 4 +++- src/shared/main/shared_main.cpp | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/shared/main/inputs/slave.h b/src/shared/main/inputs/slave.h index 49649ac26..995b5e343 100644 --- a/src/shared/main/inputs/slave.h +++ b/src/shared/main/inputs/slave.h @@ -111,7 +111,9 @@ int slaveReadQuad() { for (int i = 0; i < RETRY_COUNT; i++) { int data = 0; slave_initted = twi_readFromPointer(SLAVE_TWI_PORT, SLAVE_ADDR, SLAVE_COMMAND_GET_QUAD, sizeof(data), (uint8_t*)&data); - + #if DEVICE_TYPE == DJ_HERO_TURNTABLE + data <<= 9; + #endif if (slave_initted) { return data; } diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 87011f16a..184cb188b 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -328,7 +328,7 @@ void tick_slave() slaveInitWt(); #endif #ifdef INPUT_QUAD_SLAVE - slaveInitQuad(INPUT_QUAD_SLAVE, 8); + slaveInitQuad(INPUT_QUAD_SLAVE, 5); #endif } #endif From 3505309e44d6e8e27225659603091fed161ce550 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 16 Jul 2026 16:17:06 +1200 Subject: [PATCH 210/239] adjustible encoder pollrate --- include/pico_slave.h | 2 +- src/pico_slave/main.cpp | 4 ++-- src/shared/main/inputs/slave.h | 4 ++-- src/shared/main/shared_main.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/include/pico_slave.h b/include/pico_slave.h index d7615bfdd..88ba50373 100644 --- a/include/pico_slave.h +++ b/include/pico_slave.h @@ -38,5 +38,5 @@ void slaveSetWtCounter(uint16_t counter); void slaveInitLED(uint8_t instance); void slaveWriteLED(uint8_t data); void slaveWriteAnalog(uint8_t pin, uint8_t val); -int slaveReadQuad(); +int32_t slaveReadQuad(); #endif \ No newline at end of file diff --git a/src/pico_slave/main.cpp b/src/pico_slave/main.cpp index c6641cfee..90529d6f8 100644 --- a/src/pico_slave/main.cpp +++ b/src/pico_slave/main.cpp @@ -28,8 +28,8 @@ volatile bool quadShouldInit = false; volatile bool hasInitWt = false; volatile bool hasInitQuad = false; volatile int quadPollRate = 0; -volatile int new_value, delta, old_value = 0; -volatile int last_value = -1, last_delta = -1; +volatile int32_t new_value, delta, old_value = 0; +volatile int32_t last_value = -1, last_delta = -1; PIO pio = pio0; const uint sm = 0; spi_inst_t* hardware; diff --git a/src/shared/main/inputs/slave.h b/src/shared/main/inputs/slave.h index 995b5e343..d3a74fcd9 100644 --- a/src/shared/main/inputs/slave.h +++ b/src/shared/main/inputs/slave.h @@ -104,12 +104,12 @@ void slaveInitQuad(uint8_t pin, uint8_t rate) { } } } -int slaveReadQuad() { +int32_t slaveReadQuad() { if (!slave_initted) { return 0; } for (int i = 0; i < RETRY_COUNT; i++) { - int data = 0; + int32_t data = 0; slave_initted = twi_readFromPointer(SLAVE_TWI_PORT, SLAVE_ADDR, SLAVE_COMMAND_GET_QUAD, sizeof(data), (uint8_t*)&data); #if DEVICE_TYPE == DJ_HERO_TURNTABLE data <<= 9; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 184cb188b..3c8d27ce9 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -328,7 +328,7 @@ void tick_slave() slaveInitWt(); #endif #ifdef INPUT_QUAD_SLAVE - slaveInitQuad(INPUT_QUAD_SLAVE, 5); + slaveInitQuad(INPUT_QUAD_SLAVE, INPUT_QUAD_RATE); #endif } #endif From 2bcb9afd113b8919b17330071887c769fa3c3d06 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 19 Jul 2026 10:22:33 +1200 Subject: [PATCH 211/239] handle midi using the older logic to make sure drums work --- src/pico/midi.cpp | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/pico/midi.cpp b/src/pico/midi.cpp index c79ec8998..2fec28731 100644 --- a/src/pico/midi.cpp +++ b/src/pico/midi.cpp @@ -1,5 +1,6 @@ #include "midi.hpp" #include "config.h" +#include "shared_main.h" MidiDevice::MidiDevice(bool usbBased, Midi_Data_t* data) : usbBased(usbBased), midiData(data) { tu_memclr(&ep_stream, sizeof(ep_stream)); @@ -167,21 +168,16 @@ void MidiDevice::update(bool full_poll, bool send_events) switch (status) { case MIDI_CIN_NOTE_OFF: - // ignore note off since some drums don't send it, or they sent it too quick so we make our own note off later - #if DEVICE_TYPE_IS_DRUM - break; - #endif - // velocity 0 for note off - cable_state->data[2] = 0; - [[fallthrough]]; + offNote(channel, cable_state->data[1], 0); + break; case MIDI_CIN_NOTE_ON: - midiData->midiVelocities[cable_state->data[1]] = cable_state->data[2]; + onNote(channel, cable_state->data[1], cable_state->data[2]); break; case MIDI_CIN_CONTROL_CHANGE: - midiData->midiControlChanges[cable_state->data[1]] = cable_state->data[2]; + onControlChange(channel, cable_state->data[1], cable_state->data[2]); break; case MIDI_CIN_PITCH_BEND_CHANGE: - midiData->midiPitchWheel = ((int16_t)cable_state->data[3] << 7) | cable_state->data[2]; + onPitchBend(channel, ((int16_t)cable_state->data[3] << 7) | cable_state->data[2]); break; case MIDI_CIN_POLY_KEYPRESS: break; From fa9c1a3f20bd0f61226935d5d36c9ab98e9ca09b Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 21 Jul 2026 12:34:38 +1200 Subject: [PATCH 212/239] add enable pin to wii output --- src/shared/main/wii_emu.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/shared/main/wii_emu.cpp b/src/shared/main/wii_emu.cpp index ae5fb2c7e..66da9c291 100644 --- a/src/shared/main/wii_emu.cpp +++ b/src/shared/main/wii_emu.cpp @@ -37,7 +37,7 @@ const unsigned char id[6] = {0x01, 0x00, 0xA4, 0x20, 0x01, 0x01}; // virtual register static unsigned char twi_reg[256]; - +static bool wiiOutEnabled = false; void initWiiOutput() { memset(twi_reg, 0, sizeof(twi_reg)); twi_reg[0xF0] = 0; // disable encryption @@ -52,6 +52,18 @@ void initWiiOutput() { } } void setInputs(uint8_t* inputs, uint8_t len) { +#ifdef WII_OUTPUT_EN_READ + if (!wiiOutEnabled && WII_OUTPUT_EN_READ()) { + wiiOutEnabled = true; + initWiiOutput(); + } + if (wiiOutEnabled && !WII_OUTPUT_EN_READ()) { + wiiOutEnabled = false; + } + if (!wiiOutEnabled) { + return; + } +#endif memcpy(twi_reg, inputs, len); } /* From 3d780e008684654467f43bf2c518806b59c991c9 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 22 Jul 2026 09:11:04 +1200 Subject: [PATCH 213/239] add enable pin to wii output, fix issues with emulating wii drums, fix some more issues --- src/shared/main/shared_main.cpp | 3 +- src/shared/main/wii_emu.cpp | 109 ++++++++++++++++++++++---------- 2 files changed, 78 insertions(+), 34 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 3c8d27ce9..e2599a2a8 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -287,7 +287,8 @@ void init_main(void) ps2_emu_init(); #endif memset(midiData.midiVelocities, 0, sizeof(midiData.midiVelocities)); -#ifdef TICK_WII + // if we have an enable line, we defer init until it goes high +#if defined(TICK_WII) && !defined(WII_OUTPUT_EN_READ) initWiiOutput(); #endif diff --git a/src/shared/main/wii_emu.cpp b/src/shared/main/wii_emu.cpp index 66da9c291..94582991b 100644 --- a/src/shared/main/wii_emu.cpp +++ b/src/shared/main/wii_emu.cpp @@ -9,6 +9,7 @@ #include "shared_main.h" #include "wii.h" #include "wm_crypto.h" +#include #ifdef TICK_WII static volatile unsigned char wm_rand[10]; @@ -38,29 +39,44 @@ const unsigned char id[6] = {0x01, 0x00, 0xA4, 0x20, 0x01, 0x01}; // virtual register static unsigned char twi_reg[256]; static bool wiiOutEnabled = false; -void initWiiOutput() { +void initWiiOutput() +{ +#ifdef TWI_1_OUTPUT + RXWIRE.end(); + RXWIRE.begin(WII_ADDR); +#endif +#ifdef TWI_0_OUTPUT + RXWIRE.end(); + RXWIRE.begin(WII_ADDR); +#endif memset(twi_reg, 0, sizeof(twi_reg)); - twi_reg[0xF0] = 0; // disable encryption + twi_reg[0xF0] = 0; // disable encryption // set id - for (unsigned int i = 0, j = 0xFA; i < 6; i++, j++) { + for (unsigned int i = 0, j = 0xFA; i < 6; i++, j++) + { twi_reg[j] = id[i]; } // set calibration data - for (unsigned int i = 0, j = 0x20; i < 6; i++, j++) { + for (unsigned int i = 0, j = 0x20; i < 6; i++, j++) + { twi_reg[j] = cal_data[i]; } } -void setInputs(uint8_t* inputs, uint8_t len) { +void setInputs(uint8_t *inputs, uint8_t len) +{ #ifdef WII_OUTPUT_EN_READ - if (!wiiOutEnabled && WII_OUTPUT_EN_READ()) { + if (!wiiOutEnabled && WII_OUTPUT_EN_READ()) + { wiiOutEnabled = true; initWiiOutput(); } - if (wiiOutEnabled && !WII_OUTPUT_EN_READ()) { + if (wiiOutEnabled && !WII_OUTPUT_EN_READ()) + { wiiOutEnabled = false; } - if (!wiiOutEnabled) { + if (!wiiOutEnabled) + { return; } #endif @@ -74,29 +90,35 @@ Decryption method found at https://web.archive.org/web/20131106235350/http://www */ -unsigned char wm_ror8(unsigned char a, unsigned char b) { +unsigned char wm_ror8(unsigned char a, unsigned char b) +{ // bit shift with roll-over return (a >> b) | ((a << (8 - b)) & 0xFF); } -uint8_t wii_data_format() { +uint8_t wii_data_format() +{ return twi_reg[0xFE]; } -void wm_gentabs() { +void wm_gentabs() +{ unsigned char idx; // check all idx - for (idx = 0; idx < 7; idx++) { + for (idx = 0; idx < 7; idx++) + { // generate test key unsigned char ans[6]; unsigned char tkey[6]; unsigned char t0[10]; - for (unsigned char i = 0; i < 6; i++) { + for (unsigned char i = 0; i < 6; i++) + { ans[i] = pgm_read_byte(&(ans_tbl[idx][i])); } - for (unsigned char i = 0; i < 10; i++) { + for (unsigned char i = 0; i < 10; i++) + { t0[i] = pgm_read_byte(&(sboxes[0][wm_rand[i]])); } @@ -109,13 +131,16 @@ void wm_gentabs() { // compare with actual key bool found = true; - for (unsigned char i = 0; i < 6; i++) { - if (tkey[i] != wm_key[i]) { + for (unsigned char i = 0; i < 6; i++) + { + if (tkey[i] != wm_key[i]) + { found = false; break; } } - if (found) break; // if match, then use this idx + if (found) + break; // if match, then use this idx } // generate encryption from idx key and rand @@ -137,38 +162,53 @@ void wm_gentabs() { wm_sb[6] = pgm_read_byte(&(sboxes[idx + 1][wm_rand[3]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[5]])); wm_sb[7] = pgm_read_byte(&(sboxes[idx + 1][wm_rand[2]])) ^ pgm_read_byte(&(sboxes[idx + 2][wm_rand[6]])); } -void recv_data(uint8_t addr, uint8_t data) { - if (twi_reg[0xF0] == 0xAA && addr != 0xF0) // if encryption is on +void recv_data(uint8_t addr, uint8_t data) +{ + if (twi_reg[0xF0] == 0xAA && addr != 0xF0) // if encryption is on { // decrypt twi_reg[addr] = (data ^ wm_sb[addr % 8]) + wm_ft[addr % 8]; - } else { + } + else + { twi_reg[addr] = data; } // Euphoria LED #if DEVICE_TYPE == DJ_HERO_TURNTABLE - if (addr == 0xFB) { + if (addr == 0xFB) + { handle_rumble(twi_reg[addr] * 0xFF, RUMBLE_SANTROLLER_EUPHORIA_LED); } #endif } -void recv_end(uint8_t addr, uint8_t len) { - if (addr >= 0x40 && addr < 0x46) { - for (unsigned int i = 0; i < 6; i++) { +void recv_end(uint8_t addr, uint8_t len) +{ + if (addr >= 0x40 && addr < 0x46) + { + for (unsigned int i = 0; i < 6; i++) + { wm_rand[9 - i] = twi_reg[0x40 + i]; } - } else if (addr >= 0x46 && addr < 0x4C) { - for (unsigned int i = 6; i < 10; i++) { + } + else if (addr >= 0x46 && addr < 0x4C) + { + for (unsigned int i = 6; i < 10; i++) + { wm_rand[9 - i] = twi_reg[0x40 + i]; } - for (unsigned int i = 0; i < 2; i++) { + for (unsigned int i = 0; i < 2; i++) + { wm_key[5 - i] = twi_reg[0x40 + 10 + i]; } - } else if (addr >= 0x4C && addr < 0x50) { - for (unsigned int i = 2; i < 6; i++) { + } + else if (addr >= 0x4C && addr < 0x50) + { + for (unsigned int i = 2; i < 6; i++) + { wm_key[5 - i] = twi_reg[0x40 + 10 + i]; } - if (addr + len == 0x50) { + if (addr + len == 0x50) + { // generate decryption once all data is loaded wm_gentabs(); } @@ -176,12 +216,15 @@ void recv_end(uint8_t addr, uint8_t len) { } // Called when the I2C slave is read from -uint8_t req_data(uint8_t addr) { - if (twi_reg[0xF0] == 0xAA) // encryption is on +uint8_t req_data(uint8_t addr) +{ + if (twi_reg[0xF0] == 0xAA) // encryption is on { // encrypt return (twi_reg[addr] - wm_ft[addr % 8]) ^ wm_sb[addr % 8]; - } else { + } + else + { return twi_reg[addr]; } } From 1295e84b52cc96da2dd83559e04e4b51328d9176 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 22 Jul 2026 15:01:08 +1200 Subject: [PATCH 214/239] reset pico when plugged into wiimote --- src/pico/bt.cpp | 1 + src/shared/main/shared_main.cpp | 4 ++-- src/shared/main/wii_emu.cpp | 33 ++++++++++++++++----------------- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/pico/bt.cpp b/src/pico/bt.cpp index 4d837d9df..a37e70784 100644 --- a/src/pico/bt.cpp +++ b/src/pico/bt.cpp @@ -282,6 +282,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe } int btstack_main(void); + int btstack_main(void) { printf("Bt tx init\r\n"); le_keyboard_setup(); diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index e2599a2a8..fce976895 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -288,9 +288,9 @@ void init_main(void) #endif memset(midiData.midiVelocities, 0, sizeof(midiData.midiVelocities)); // if we have an enable line, we defer init until it goes high -#if defined(TICK_WII) && !defined(WII_OUTPUT_EN_READ) +// #if defined(TICK_WII) && !defined(WII_OUTPUT_EN_READ) initWiiOutput(); -#endif +// #endif memset(midiData.midiVelocities, 0, sizeof(midiData.midiVelocities)); midiData.midiPitchWheel = 0; diff --git a/src/shared/main/wii_emu.cpp b/src/shared/main/wii_emu.cpp index 94582991b..75736ab4c 100644 --- a/src/shared/main/wii_emu.cpp +++ b/src/shared/main/wii_emu.cpp @@ -39,16 +39,9 @@ const unsigned char id[6] = {0x01, 0x00, 0xA4, 0x20, 0x01, 0x01}; // virtual register static unsigned char twi_reg[256]; static bool wiiOutEnabled = false; +static uint32_t startTimer = 0; void initWiiOutput() { -#ifdef TWI_1_OUTPUT - RXWIRE.end(); - RXWIRE.begin(WII_ADDR); -#endif -#ifdef TWI_0_OUTPUT - RXWIRE.end(); - RXWIRE.begin(WII_ADDR); -#endif memset(twi_reg, 0, sizeof(twi_reg)); twi_reg[0xF0] = 0; // disable encryption // set id @@ -66,18 +59,24 @@ void initWiiOutput() void setInputs(uint8_t *inputs, uint8_t len) { #ifdef WII_OUTPUT_EN_READ - if (!wiiOutEnabled && WII_OUTPUT_EN_READ()) - { - wiiOutEnabled = true; - initWiiOutput(); - } - if (wiiOutEnabled && !WII_OUTPUT_EN_READ()) + + if (!startTimer) { - wiiOutEnabled = false; + startTimer = millis(); + if (WII_OUTPUT_EN_READ()) + { + wiiOutEnabled = true; + } } - if (!wiiOutEnabled) + if (millis() - startTimer > 1000) { - return; + if (!wiiOutEnabled && (WII_OUTPUT_EN_READ())) + { + reset_usb(); + } + if (wiiOutEnabled && !(WII_OUTPUT_EN_READ())) { + wiiOutEnabled = false; + } } #endif memcpy(twi_reg, inputs, len); From d396f385029a57a96d124d3eeb9be510f02cf3e0 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 23 Jul 2026 08:48:56 +1200 Subject: [PATCH 215/239] reset pico when plugged into wiimote --- src/shared/main/shared_main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index fce976895..c6dcbe68e 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -288,9 +288,9 @@ void init_main(void) #endif memset(midiData.midiVelocities, 0, sizeof(midiData.midiVelocities)); // if we have an enable line, we defer init until it goes high -// #if defined(TICK_WII) && !defined(WII_OUTPUT_EN_READ) +#if defined(TICK_WII) initWiiOutput(); -// #endif +#endif memset(midiData.midiVelocities, 0, sizeof(midiData.midiVelocities)); midiData.midiPitchWheel = 0; From fa093f8de11559ca3a5617d3618e35f8f9635fde Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Thu, 23 Jul 2026 10:41:05 +1200 Subject: [PATCH 216/239] fix buffer being too small for midi --- src/pico/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pico/main.cpp b/src/pico/main.cpp index ed5ee20b5..472f38f88 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -34,7 +34,7 @@ #include "pico/cyw43_arch.h" #endif -CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t buf[255]; +CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t buf[512]; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN uint8_t buf2[255]; CFG_TUSB_MEM_SECTION CFG_TUSB_MEM_ALIGN STRING_DESCRIPTOR_PICO serialstring = { .bLength = (sizeof(uint8_t) + sizeof(uint8_t) + (SERIAL_LEN + 3) * 2), From a5a38ce4e20479189b97fffdd790fb9039015b50 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 24 Jul 2026 11:04:51 +1200 Subject: [PATCH 217/239] implement switch guitar support with riffmaster mappings --- include/reports/switch_reports.h | 46 ++++++++++++++++++++++++++++++++ src/shared/main/shared_main.cpp | 27 ++++++++++++++++++- 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/include/reports/switch_reports.h b/include/reports/switch_reports.h index 8bb955729..423a9e329 100644 --- a/include/reports/switch_reports.h +++ b/include/reports/switch_reports.h @@ -172,6 +172,52 @@ typedef struct } __attribute__((packed)) SwitchGamepad_Data_t; + +// Festivals default mappings suck, so its easiest to set up custom mappings for that here +typedef struct +{ + // Button bits + uint8_t x : 1; + uint8_t b : 1; + uint8_t a : 1; + uint8_t y : 1; + + uint8_t leftShoulder : 1; // l1 + uint8_t rightShoulder : 1; // r1 + uint8_t l2 : 1; // l2 + uint8_t r2 : 1; // r2 + + uint8_t back : 1; // select + uint8_t start : 1; + uint8_t solo : 1; // l3 + uint8_t rightThumbClick : 1; // r3 + + uint8_t guide : 1; // ps + uint8_t capture : 1; // switch capture button + uint8_t : 2; + + // To make things easier, we use bitfields here, and then we map to a proper hat later + uint8_t dpadUp : 1; + uint8_t dpadDown : 1; + uint8_t dpadLeft : 1; + uint8_t dpadRight : 1; + uint8_t : 4; + + // Stick axes + // Neutral state is 0x80 + // X axis is left at 0x00, right at 0xFF + // Y axis is top at 0x00, bottom at 0xFF + uint8_t slider; + uint8_t pickup; + uint8_t whammy; + uint8_t unused; + + uint16_t tilt; // accelX + uint16_t accelZ; + uint16_t accelY; + uint16_t unused3; +} __attribute__((packed)) SwitchFestivalGuitar_Data_t; + // Festivals default mappings suck, so its easiest to set up custom mappings for that here typedef struct { diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index c6dcbe68e..6c264087f 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3734,8 +3734,33 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu gamepad->rightStickY = PS3_STICK_CENTER; #endif +#if DEVICE_TYPE_IS_GUITAR + + if (output_console_type == SWITCH) + { + SwitchFestivalGuitar_Data_t *report = (SwitchFestivalGuitar_Data_t *)report_data; + TICK_PS3; + bool dpadLeft = report->dpadLeft; + bool back = report->back; + report->dpadLeft = false; + report->back = false; + report->whammy = 255 - report->whammy; + if (dpadLeft) { + report->back = true; + } + if (back) { + report->dpadLeft = true; + } + if (report->tilt < 0x190) { + report->dpadLeft = true; + } + asm volatile("" :: + : "memory"); + gamepad->dpad = (gamepad->dpad & 0xf) > 0x0a ? 0x08 : dpad_bindings[gamepad->dpad]; + } +#endif #if DEVICE_TYPE == GUITAR_HERO_GUITAR - if (output_console_type == PS2_ON_PS3) + else if (output_console_type == PS2_ON_PS3) { PS2GuitarOnPS3_Data_t *report = (PS2GuitarOnPS3_Data_t *)report_data; From ba1c73269fd97038cc32e82055e30307cf05ecb4 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 25 Jul 2026 09:08:46 +1200 Subject: [PATCH 218/239] fix running status --- include/midi.hpp | 1 + src/pico/midi.cpp | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/include/midi.hpp b/include/midi.hpp index 57dbdfc13..5479d9c10 100644 --- a/include/midi.hpp +++ b/include/midi.hpp @@ -13,6 +13,7 @@ typedef struct { + uint status; uint pos; uint actual_size; uint8_t data[32]; diff --git a/src/pico/midi.cpp b/src/pico/midi.cpp index 2fec28731..a473b1848 100644 --- a/src/pico/midi.cpp +++ b/src/pico/midi.cpp @@ -61,6 +61,14 @@ void MidiDevice::update(bool full_poll, bool send_events) // we don't know the actual size of the message yet cable_state->actual_size = 0xFF; } + // Running status + if (status < MIDI_MAX_DATA_VAL) { + // The status byte is reused, so shift the packet and insert it back + status = cable_state->status; + cable_state->data[1] = cable_state->data[0]; + cable_state->data[0] = status; + cable_state->pos++; + } if (status < MIDI_STATUS_SYSEX_START) { // then it is a channel message either three bytes or two @@ -114,6 +122,7 @@ void MidiDevice::update(bool full_poll, bool send_events) cable_state->actual_size = 1; cable_state->sysex_in_progress = false; } + cable_state->status = status; } else { From 9e0b0258b8a7e5eb56ddb7bd7207d7cef2681c75 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 25 Jul 2026 11:56:16 +1200 Subject: [PATCH 219/239] fix running status --- src/pico/midi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pico/midi.cpp b/src/pico/midi.cpp index a473b1848..dca08a412 100644 --- a/src/pico/midi.cpp +++ b/src/pico/midi.cpp @@ -62,7 +62,7 @@ void MidiDevice::update(bool full_poll, bool send_events) cable_state->actual_size = 0xFF; } // Running status - if (status < MIDI_MAX_DATA_VAL) { + if (status <= MIDI_MAX_DATA_VAL) { // The status byte is reused, so shift the packet and insert it back status = cable_state->status; cable_state->data[1] = cable_state->data[0]; From e8232c87ff5c634b926babfd3e02205362761447 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 29 Jul 2026 09:19:57 +1200 Subject: [PATCH 220/239] fix bt receiver --- src/pico/bt_rx_cnt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pico/bt_rx_cnt.cpp b/src/pico/bt_rx_cnt.cpp index 71ab65eb7..ce51f4339 100644 --- a/src/pico/bt_rx_cnt.cpp +++ b/src/pico/bt_rx_cnt.cpp @@ -59,7 +59,7 @@ enum STATE state = INIT; static uint16_t hid_host_cid = 0; static bool hid_host_descriptor_available = false; -static hid_protocol_mode_t hid_host_report_mode = HID_PROTOCOL_MODE_REPORT_WITH_FALLBACK_TO_BOOT; +static hid_protocol_mode_t hid_host_report_mode = HID_PROTOCOL_MODE_REPORT; static HID_ReportInfo_t *info; int get_bt_address(uint8_t *addr) { From 8a3646b056c1f828fdb21b557a779bb6a4b6fd83 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Mon, 3 Aug 2026 09:20:48 +1200 Subject: [PATCH 221/239] add signed fxptatan2 --- lib/fxpt_math/src/fxpt_math.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/fxpt_math/src/fxpt_math.h b/lib/fxpt_math/src/fxpt_math.h index d860c5e2d..cc0d7d308 100644 --- a/lib/fxpt_math/src/fxpt_math.h +++ b/lib/fxpt_math/src/fxpt_math.h @@ -47,6 +47,9 @@ extern "C" { #endif uint16_t fxpt_atan2(const int16_t y, const int16_t x); uint16_t fxpt_asin(int16_t x); +inline int16_t fxpt_atan2s(const int16_t y, const int16_t x) { + return fxpt_atan2(y, x); +} #ifdef __cplusplus } From 32bacabd8d6c44bfcf850d0c29407cb716bb92cc Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 5 Aug 2026 08:51:01 +1200 Subject: [PATCH 222/239] adjust thresholds for mpr121 --- include/mpr121.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mpr121.h b/include/mpr121.h index 16b42dfb0..a36bc426c 100644 --- a/include/mpr121.h +++ b/include/mpr121.h @@ -1,6 +1,6 @@ #define MPR121_I2CADDR_DEFAULT 0x5A ///< default I2C address -#define MPR121_TOUCH_THRESHOLD_DEFAULT 5 ///< default touch threshold value -#define MPR121_RELEASE_THRESHOLD_DEFAULT 1 ///< default relese threshold value +#define MPR121_TOUCH_THRESHOLD_DEFAULT 12 ///< default touch threshold value +#define MPR121_RELEASE_THRESHOLD_DEFAULT 6 ///< default relese threshold value enum { MPR121_TOUCHSTATUS_L = 0x00, MPR121_TOUCHSTATUS_H = 0x01, From 1464cda1c20c350d3a30b1c4d236e37869492cef Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 5 Aug 2026 09:29:18 +1200 Subject: [PATCH 223/239] more usb host fixes, pro guitar autodetection, mpr121 fixes --- include/config.h | 2 ++ include/midi.hpp | 5 ++++- include/mpr121.h | 2 +- platformio.ini | 2 +- src/pico/main.cpp | 16 ++++++++++++++- src/pico/midi.cpp | 9 +++++++++ src/shared/config/config.c | 1 + src/shared/main/shared_main.cpp | 8 ++++++++ src/shared/usb/descriptors.cpp | 35 +++++++++++++++++++++++++++++++++ 9 files changed, 76 insertions(+), 4 deletions(-) diff --git a/include/config.h b/include/config.h index edeeeadbf..1281df330 100644 --- a/include/config.h +++ b/include/config.h @@ -14,6 +14,7 @@ extern "C" { // ConsoleType can change due to console detection extern uint8_t consoleType; extern uint8_t arcadeSide; +extern uint8_t proGuitarType; void setArcadeSide(uint8_t side); #ifdef CONFIGURABLE_BLOBS extern const uint8_t* config; @@ -33,6 +34,7 @@ extern const uint8_t config[CONFIGURATION_LEN]; #define DEVICE_TYPE_IS_KEYBOARD (DEVICE_TYPE == KEYBOARD_MOUSE_TYPE) #define DEVICE_TYPE_IS_GAMEPAD (!(DEVICE_TYPE_IS_KEYBOARD)) #define DEVICE_TYPE_IS_PRO (DEVICE_TYPE == ROCK_BAND_PRO_DRUM || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE || DEVICE_TYPE == ROCK_BAND_PRO_KEYS) +#define DEVICE_TYPE_IS_PRO_GUITAR (DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_MUSTANG || DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE) #if DEVICE_TYPE == SKYLANDERS #define SUB_TYPE XINPUT_SKYLANDERS #define OG_XBOX_REPORT OGXboxGamepad_Data_t diff --git a/include/midi.hpp b/include/midi.hpp index 5479d9c10..a09a1f82d 100644 --- a/include/midi.hpp +++ b/include/midi.hpp @@ -8,7 +8,10 @@ #define MIDI_CONTROL_COMMAND_MOD_WHEEL 1 #define MIDI_CONTROL_COMMAND_SUSTAIN_PEDAL 64 -#define MIDI_CHANNEL_PROGUITAR 16 +#define MIDI_CHANNEL_PROGUITAR_SQUIER 16 +#define MIDI_CHANNEL_PROGUITAR_MUSTANG 17 +#define MIDI_SYSEX_ID_PROGUITAR_SQUIER 0x08 +#define MIDI_SYSEX_ID_PROGUITAR_MUSTANG 0x0A #define USB_PACKET_SIZE 4 typedef struct diff --git a/include/mpr121.h b/include/mpr121.h index a36bc426c..28d812b54 100644 --- a/include/mpr121.h +++ b/include/mpr121.h @@ -1,5 +1,5 @@ #define MPR121_I2CADDR_DEFAULT 0x5A ///< default I2C address -#define MPR121_TOUCH_THRESHOLD_DEFAULT 12 ///< default touch threshold value +#define MPR121_TOUCH_THRESHOLD_DEFAULT 14 ///< default touch threshold value #define MPR121_RELEASE_THRESHOLD_DEFAULT 6 ///< default relese threshold value enum { MPR121_TOUCHSTATUS_L = 0x00, diff --git a/platformio.ini b/platformio.ini index 145f96058..7c4e7be9e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ board_upload.ardwiino_bootloader_teensy = true board_build.use_usb = 1 platform = https://github.com/maxgerhardt/platform-raspberrypi/archive/39b90392af50585e429941bd2561a91949a2ba46.zip@1.15.0 platform_packages = - framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.14-sanjay/rp2040-4.6.14-sanjay.zip@1.50404.0 + framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.15-sanjay/rp2040-4.6.15-sanjay.zip@1.50404.0 board = pico framework = arduino board_build.core = earlephilhower diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 472f38f88..7b2f896e0 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -46,6 +46,7 @@ static uint32_t __uninitialized_ram(windows_in_hid); static uint32_t __uninitialized_ram(persistedConsoleTypeValid); static uint32_t __uninitialized_ram(xboxAuthValid); static uint32_t __uninitialized_ram(pico_is_sleeping); +static uint32_t __uninitialized_ram(persistedProGuitarType); #if USB_HOST_STACK USB_Device_Type_t xone_dev_addr = {}; USB_Device_Type_t x360_dev_addr = {}; @@ -222,7 +223,7 @@ void wakeup_360() void setup() { #if USB_HOST_STACK - set_sys_clock_khz(120000, true); + set_sys_clock_khz(180000, true); #endif #ifdef INPUT_SERIAL_MIDI @@ -245,6 +246,7 @@ void setup() if (persistedConsoleTypeValid == PERSISTED_CONSOLE_TYPE_VALID) { consoleType = persistedConsoleType; + proGuitarType = persistedProGuitarType; if (SLEEP_PIN != -1) { // Sleep works best when nothing else is started, so we reboot the pico before and after sleep @@ -264,6 +266,7 @@ void setup() windows_in_hid = false; xboxAuthValid = false; consoleType = UNIVERSAL; + proGuitarType = DEVICE_TYPE; pico_is_sleeping = false; } generateSerialString(&serialstring, consoleType); @@ -768,6 +771,16 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c usb_host_devices[i].type.sub_type = XINPUT_GUITAR_WT; printf("Found wt\r\n"); } + + if (DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != ROCK_BAND_PRO_GUITAR_MUSTANG && caps->leftStickY == XBOX_360_MUSTANG_PID) { + proGuitarType = ROCK_BAND_PRO_GUITAR_MUSTANG; + reset_usb(); + } + + if (DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != ROCK_BAND_PRO_GUITAR_SQUIRE && caps->leftStickY == XBOX_360_SQUIRE_PID) { + proGuitarType = ROCK_BAND_PRO_GUITAR_SQUIRE; + reset_usb(); + } } } continue; @@ -1056,5 +1069,6 @@ void reset_usb(void) { persistedConsoleType = consoleType; persistedConsoleTypeValid = PERSISTED_CONSOLE_TYPE_VALID; + persistedProGuitarType = proGuitarType; reboot(); } \ No newline at end of file diff --git a/src/pico/midi.cpp b/src/pico/midi.cpp index dca08a412..bf18bbf03 100644 --- a/src/pico/midi.cpp +++ b/src/pico/midi.cpp @@ -222,6 +222,15 @@ void MidiDevice::update(bool full_poll, bool send_events) // reload(); // } // } + + if (cable_state->data[3] == MIDI_SYSEX_ID_PROGUITAR_MUSTANG && DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != ROCK_BAND_PRO_GUITAR_MUSTANG) { + proGuitarType = ROCK_BAND_PRO_GUITAR_MUSTANG; + reset_usb(); + } + if (cable_state->data[3] == MIDI_SYSEX_ID_PROGUITAR_SQUIER && DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != ROCK_BAND_PRO_GUITAR_SQUIRE) { + proGuitarType = ROCK_BAND_PRO_GUITAR_SQUIRE; + reset_usb(); + } midiData->seenProGuitar = true; if (cable_state->data[4] == 0x08) { diff --git a/src/shared/config/config.c b/src/shared/config/config.c index 01f544344..6c1502f0d 100644 --- a/src/shared/config/config.c +++ b/src/shared/config/config.c @@ -13,6 +13,7 @@ const uint8_t PROGMEM config[CONFIGURATION_LEN] = CONFIGURATION; #endif uint8_t consoleType = 0xFF; uint8_t arcadeSide = 1; +uint8_t proGuitarType = DEVICE_TYPE; #if DEVICE_TYPE_IS_GUITAR const uint8_t announce[] = {0x02, 0x20, 0x01, 0x1c, 0x7e, 0xed, 0x81, TEMP, TEMP, TEMP, 0x00, 0x00, 0x6f, 0x0e, 0x48, 0x02, 0x01, 0x00, 0x00, 0x00, 0xe5, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00}; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 6c264087f..31468723a 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -4701,11 +4701,19 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D case PS3_MUSTANG_MPA_PID: type->console_type = PS3; type->sub_type = ROCK_BAND_PRO_GUITAR_MUSTANG; + if (DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != type->sub_type) { + proGuitarType = type->sub_type; + reset_usb(); + } break; case PS3_SQUIRE_PID: case PS3_SQUIRE_MPA_PID: type->console_type = PS3; type->sub_type = ROCK_BAND_PRO_GUITAR_SQUIRE; + if (DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != type->sub_type) { + proGuitarType = type->sub_type; + reset_usb(); + } break; } break; diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index cd2f54dbf..83fd7c7e2 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1311,6 +1311,19 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const else if (request == HID_REQUEST_GET_REPORT && wIndex == INTERFACE_ID_Device && wValue == INPUT_CAPABILITIES_WVALUE) { memcpy_P(requestBuffer, &XInputInputCapabilities, sizeof(XInputInputCapabilities)); + + if (DEVICE_TYPE_IS_PRO_GUITAR) + { + XInputInputCapabilities_t *caps = (XInputInputCapabilities_t *)requestBuffer; + if (proGuitarType == ROCK_BAND_PRO_GUITAR_MUSTANG) + { + caps->leftThumbY = XBOX_360_SQUIRE_PID; + } + if (proGuitarType == ROCK_BAND_PRO_GUITAR_SQUIRE) + { + caps->leftThumbY = XBOX_360_MUSTANG_PID; + } + } return sizeof(XInputInputCapabilities); } } @@ -1487,6 +1500,17 @@ uint16_t descriptorRequest(const uint16_t wValue, { dev->idVendor = HARMONIX_VID; dev->idProduct = WII_TYPE; + if (DEVICE_TYPE_IS_PRO_GUITAR) + { + if (proGuitarType == ROCK_BAND_PRO_GUITAR_MUSTANG) + { + dev->idProduct = WII_SQUIRE_PID; + } + if (proGuitarType == ROCK_BAND_PRO_GUITAR_SQUIRE) + { + dev->idProduct = WII_MUSTANG_PID; + } + } } #endif #ifdef PS3_TYPE @@ -1494,6 +1518,17 @@ uint16_t descriptorRequest(const uint16_t wValue, { dev->idVendor = REDOCTANE_VID; dev->idProduct = PS3_TYPE; + if (DEVICE_TYPE_IS_PRO_GUITAR) + { + if (proGuitarType == ROCK_BAND_PRO_GUITAR_MUSTANG) + { + dev->idProduct = PS3_SQUIRE_PID; + } + if (proGuitarType == ROCK_BAND_PRO_GUITAR_SQUIRE) + { + dev->idProduct = PS3_MUSTANG_PID; + } + } } #elif DEVICE_TYPE == GAMEPAD else if (consoleType == PS3) From d883be29136830e0299fe5086619c145fb515fd5 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Wed, 5 Aug 2026 09:36:18 +1200 Subject: [PATCH 224/239] squire never supported usb so use the mpa PID --- include/config.h | 4 ++-- include/endpoints.h | 5 ++--- src/pico/main.cpp | 8 ++++---- src/shared/main/shared_main.cpp | 2 -- src/shared/usb/descriptors.cpp | 6 +++--- src/shared/usb/xbox.c | 2 +- 6 files changed, 12 insertions(+), 15 deletions(-) diff --git a/include/config.h b/include/config.h index 1281df330..c7d07ab1b 100644 --- a/include/config.h +++ b/include/config.h @@ -316,8 +316,8 @@ extern const uint8_t config[CONFIGURATION_LEN]; BTN_USAGE(BTN_THUMBR) #elif DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE #define SUB_TYPE XINPUT_PRO_GUITAR -#define PS3_TYPE PS3_SQUIRE_PID -#define WII_TYPE WII_SQUIRE_PID +#define PS3_TYPE PS3_SQUIRE_MPA_PID +#define WII_TYPE WII_SQUIRE_MPA_PID #define OG_XBOX_REPORT OGXboxGamepad_Data_t #define XINPUT_REPORT XInputRockBandProGuitar_Data_t #define XBOX_ONE_REPORT XboxOneRockBandProGuitar_Data_t diff --git a/include/endpoints.h b/include/endpoints.h index 880ab38d5..8cd6d83f6 100644 --- a/include/endpoints.h +++ b/include/endpoints.h @@ -61,7 +61,6 @@ enum endpoints_t { #define PS3_MPA_DRUM_PID 0x0218 #define PS3_DJ_TURNTABLE_PID 0x0140 #define PS3_MUSTANG_PID 0x2430 -#define PS3_SQUIRE_PID 0x2530 #define PS3_MUSTANG_MPA_PID 0x2438 #define PS3_SQUIRE_MPA_PID 0x2538 #define PS3_DRUMS_PID 0x0210 @@ -76,7 +75,6 @@ enum endpoints_t { #define WII_RB_DRUM_PID 0x0005 #define WII_RB_DRUM_2_PID 0x3110 #define WII_MUSTANG_PID 0x3430 -#define WII_SQUIRE_PID 0x3530 #define WII_MUSTANG_MPA_PID 0x3438 #define WII_SQUIRE_MPA_PID 0x3538 #define WII_DRUMS_PID 0x3130 @@ -89,7 +87,8 @@ enum endpoints_t { #define XBOX_REDOCTANE_VID 0x1430 #define XBOX_POWERA_VID 0x24c6 #define XBOX_360_MUSTANG_PID 0x1430 -#define XBOX_360_SQUIRE_PID 0x1530 +#define XBOX_360_MUSTANG_MPA_PID 0x1438 +#define XBOX_360_SQUIRE_MPA_PID 0x1538 #define XBOX_ONE_GHLIVE_DONGLE_PID 0x079B #define XBOX_360_GHLIVE_DONGLE_PID 0x070B #define XBOX_360_WT_KIOSK_PID 0x4734 diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 7b2f896e0..8f961b4ec 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -732,7 +732,7 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c usb_host_devices[i].type.drum_type = DRUM_RB2; } } - if (usb_host_devices[i].type.sub_type == XINPUT_GUITAR_ALTERNATE && usb_host_devices[i].type.drum_type == GUITAR_CHECK) + if ((usb_host_devices[i].type.sub_type == XINPUT_GUITAR_ALTERNATE || usb_host_devices[i].type.sub_type == XINPUT_PRO_GUITAR) && usb_host_devices[i].type.drum_type == GUITAR_CHECK) { // request capabilities send_report_to_controller(dev_addr, instance, capabilitiesRequest, sizeof(capabilitiesRequest)); @@ -752,7 +752,7 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c printf("Found subtype: %02x %02x %02x\r\n", sub_type, dev_addr, instance); xinput_w_controller_connected(); // Request capabilities so we can figure out WT guitars - if (sub_type == XINPUT_GUITAR_ALTERNATE) + if (sub_type == XINPUT_GUITAR_ALTERNATE || sub_type == XINPUT_PRO_GUITAR) { usb_host_devices[i].type.drum_type = GUITAR_CHECK; } @@ -772,12 +772,12 @@ void tuh_xinput_report_received_cb(uint8_t dev_addr, uint8_t instance, uint8_t c printf("Found wt\r\n"); } - if (DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != ROCK_BAND_PRO_GUITAR_MUSTANG && caps->leftStickY == XBOX_360_MUSTANG_PID) { + if (DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != ROCK_BAND_PRO_GUITAR_MUSTANG && (caps->leftStickY == XBOX_360_MUSTANG_PID || caps->leftStickY == XBOX_360_MUSTANG_MPA_PID) ) { proGuitarType = ROCK_BAND_PRO_GUITAR_MUSTANG; reset_usb(); } - if (DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != ROCK_BAND_PRO_GUITAR_SQUIRE && caps->leftStickY == XBOX_360_SQUIRE_PID) { + if (DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != ROCK_BAND_PRO_GUITAR_SQUIRE && caps->leftStickY == XBOX_360_SQUIRE_MPA_PID) { proGuitarType = ROCK_BAND_PRO_GUITAR_SQUIRE; reset_usb(); } diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 31468723a..eacd3b0a0 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -4706,7 +4706,6 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D reset_usb(); } break; - case PS3_SQUIRE_PID: case PS3_SQUIRE_MPA_PID: type->console_type = PS3; type->sub_type = ROCK_BAND_PRO_GUITAR_SQUIRE; @@ -4757,7 +4756,6 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D type->console_type = PS3; type->sub_type = ROCK_BAND_PRO_GUITAR_MUSTANG; break; - case WII_SQUIRE_PID: case WII_SQUIRE_MPA_PID: type->console_type = PS3; type->sub_type = ROCK_BAND_PRO_GUITAR_SQUIRE; diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 83fd7c7e2..63a8be315 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1317,7 +1317,7 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const XInputInputCapabilities_t *caps = (XInputInputCapabilities_t *)requestBuffer; if (proGuitarType == ROCK_BAND_PRO_GUITAR_MUSTANG) { - caps->leftThumbY = XBOX_360_SQUIRE_PID; + caps->leftThumbY = XBOX_360_SQUIRE_MPA_PID; } if (proGuitarType == ROCK_BAND_PRO_GUITAR_SQUIRE) { @@ -1504,7 +1504,7 @@ uint16_t descriptorRequest(const uint16_t wValue, { if (proGuitarType == ROCK_BAND_PRO_GUITAR_MUSTANG) { - dev->idProduct = WII_SQUIRE_PID; + dev->idProduct = WII_SQUIRE_MPA_PID; } if (proGuitarType == ROCK_BAND_PRO_GUITAR_SQUIRE) { @@ -1522,7 +1522,7 @@ uint16_t descriptorRequest(const uint16_t wValue, { if (proGuitarType == ROCK_BAND_PRO_GUITAR_MUSTANG) { - dev->idProduct = PS3_SQUIRE_PID; + dev->idProduct = PS3_SQUIRE_MPA_PID; } if (proGuitarType == ROCK_BAND_PRO_GUITAR_SQUIRE) { diff --git a/src/shared/usb/xbox.c b/src/shared/usb/xbox.c index 48c0cf9f2..5f381125f 100644 --- a/src/shared/usb/xbox.c +++ b/src/shared/usb/xbox.c @@ -25,7 +25,7 @@ const XInputInputCapabilities_t PROGMEM XInputInputCapabilities = { leftThumbY : XBOX_360_MUSTANG_PID, #elif DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE leftThumbX : HARMONIX_VID, - leftThumbY : XBOX_360_SQUIRE_PID, + leftThumbY : XBOX_360_SQUIRE_MPA_PID, #else leftThumbX : ARDWIINO_VID, leftThumbY : ARDWIINO_PID, From 3db3c051dd58d7dcde4eb8ec368c5912f99ee1ef Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 7 Aug 2026 08:56:40 +1200 Subject: [PATCH 225/239] fix issues with switch guitar report --- include/reports/switch_reports.h | 1 + src/shared/main/shared_main.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/include/reports/switch_reports.h b/include/reports/switch_reports.h index 423a9e329..24e967c0b 100644 --- a/include/reports/switch_reports.h +++ b/include/reports/switch_reports.h @@ -212,6 +212,7 @@ typedef struct uint8_t whammy; uint8_t unused; + uint8_t unused2[12]; uint16_t tilt; // accelX uint16_t accelZ; uint16_t accelY; diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index eacd3b0a0..d05430501 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -3740,6 +3740,8 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu { SwitchFestivalGuitar_Data_t *report = (SwitchFestivalGuitar_Data_t *)report_data; TICK_PS3; + asm volatile("" :: + : "memory"); bool dpadLeft = report->dpadLeft; bool back = report->back; report->dpadLeft = false; From 66ad8575bce464aaae493531812788340f580974 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 7 Aug 2026 14:20:17 +1200 Subject: [PATCH 226/239] more usbhost changes --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index 7c4e7be9e..fe5e6f391 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ board_upload.ardwiino_bootloader_teensy = true board_build.use_usb = 1 platform = https://github.com/maxgerhardt/platform-raspberrypi/archive/39b90392af50585e429941bd2561a91949a2ba46.zip@1.15.0 platform_packages = - framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.15-sanjay/rp2040-4.6.15-sanjay.zip@1.50404.0 + framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.16-sanjay/rp2040-4.6.16-sanjay.zip@1.50404.0 board = pico framework = arduino board_build.core = earlephilhower From e3ab469d08ae878ae8b0eb9a208cd6ee9712ab0c Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 9 Aug 2026 19:07:23 +1200 Subject: [PATCH 227/239] fix mpu6050 --- include/accel.h | 8 +++++- src/shared/main/accel.cpp | 53 ++++++++++++++++++++++++++++++++------- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/include/accel.h b/include/accel.h index 16b28d03a..5a1cb49df 100644 --- a/include/accel.h +++ b/include/accel.h @@ -27,12 +27,18 @@ extern "C" { #define SC7A20_ID 0x11 #define LIS3DH_REG_TEMPCFG 0x1F #define MPU6050_ADDRESS 0x68 +#define MPU6050_ADDRESS_ALT 0x69 #define MPU6050_REG_ACCEL_OUT 0x3B #define MPU6050_REG_WHO_AM_I 0x75 #define MPU6050_REG_ACCEL_CONFIG 0x1C #define MPU6050_REG_PWR_MGMT_1 0x6B #define MPU6050_ID 0x68 -#define MPU6050_ID2 0x98 +#define MPU6050_ID2 0x98 // Common register-compatible clone +#define MPU6050_ID3 0x70 // Register-compatible MPU-6500/clone ID accepted by other mature drivers +#define MPU6050_PWR1_SLEEP (1U << 6) +#define MPU6050_PWR1_CLKSEL_MASK 0x07 +#define MPU6050_PWR1_CLKSEL_XGYRO 0x01 +#define MPU6050_ACCEL_CONFIG_2G 0x00 void tick_accel(); #ifdef __cplusplus } diff --git a/src/shared/main/accel.cpp b/src/shared/main/accel.cpp index 5c66af844..3ac6cb9c0 100644 --- a/src/shared/main/accel.cpp +++ b/src/shared/main/accel.cpp @@ -8,6 +8,7 @@ uint16_t accel_adc[3] = {0}; double currentLowPassAlpha = LOW_PASS_ALPHA; bool accel_found = false; uint8_t lis3dh_address = LIS3DH_ADDRESS; +uint8_t mpu6050_address = MPU6050_ADDRESS; uint8_t type = NONE; #ifdef ACCEL_TWI_PORT void init_lis3dh() @@ -57,20 +58,46 @@ void init_adxl() twi_writeSingleToPointer(ACCEL_TWI_PORT, ADXL345_ADDRESS, ADXL345_POWER_CTL, 0x08); twi_writeSingleToPointer(ACCEL_TWI_PORT, ADXL345_ADDRESS, ADXL345_DATA_FORMAT, 0x0B); } -void init_mpu6050() +static bool probe_mpu6050(uint8_t address) { uint8_t id = 0; - twi_readFromPointer(ACCEL_TWI_PORT, MPU6050_ADDRESS, MPU6050_REG_WHO_AM_I, 1, &id); - if (id != MPU6050_ID && id != MPU6050_ID2) + return twi_readFromPointerRepeatedStart(ACCEL_TWI_PORT, address, MPU6050_REG_WHO_AM_I, 1, &id) && + (id == MPU6050_ID || id == MPU6050_ID2 || id == MPU6050_ID3); +} + +void init_mpu6050() +{ + uint8_t address = MPU6050_ADDRESS; + if (!probe_mpu6050(address)) + { + address = MPU6050_ADDRESS_ALT; + if (!probe_mpu6050(address)) + { + return; + } + } + + uint8_t power_management = 0; + if (!twi_readFromPointerRepeatedStart(ACCEL_TWI_PORT, address, MPU6050_REG_PWR_MGMT_1, 1, &power_management)) { return; } + + power_management &= (uint8_t) ~(MPU6050_PWR1_SLEEP | MPU6050_PWR1_CLKSEL_MASK); + power_management |= MPU6050_PWR1_CLKSEL_XGYRO; + if (!twi_writeSingleToPointer(ACCEL_TWI_PORT, address, MPU6050_REG_PWR_MGMT_1, power_management)) + { + return; + } + + if (!twi_writeSingleToPointer(ACCEL_TWI_PORT, address, MPU6050_REG_ACCEL_CONFIG, MPU6050_ACCEL_CONFIG_2G)) + { + return; + } + + mpu6050_address = address; type = MPU6050; accel_found = true; - twi_writeSingleToPointer(ACCEL_TWI_PORT, MPU6050_ADDRESS, MPU6050_REG_ACCEL_CONFIG, 0b11100111); - twi_readFromPointer(ACCEL_TWI_PORT, MPU6050_ADDRESS, MPU6050_REG_PWR_MGMT_1, 1, &id); - id &= ~(1 << 6); - twi_writeSingleToPointer(ACCEL_TWI_PORT, MPU6050_ADDRESS, MPU6050_REG_PWR_MGMT_1, id); } void init_accel() { @@ -113,10 +140,18 @@ void tick_accel() } if (type == MPU6050) { - accel_found = twi_readFromPointer(ACCEL_TWI_PORT, MPU6050_ADDRESS, MPU6050_REG_ACCEL_OUT, 6, (uint8_t *)raw); + uint8_t raw_bytes[6]; + accel_found = twi_readFromPointerRepeatedStart(ACCEL_TWI_PORT, mpu6050_address, MPU6050_REG_ACCEL_OUT, + sizeof(raw_bytes), raw_bytes); + if (!accel_found) + { + return; + } + for (int i = 0; i < 3; i++) { - filtered[i] = (raw[i]) * currentLowPassAlpha + (filtered[i] * (1.0 - currentLowPassAlpha)); + raw[i] = (int16_t) (((uint16_t) raw_bytes[i * 2] << 8) | raw_bytes[i * 2 + 1]); + filtered[i] = raw[i] * currentLowPassAlpha + (filtered[i] * (1.0 - currentLowPassAlpha)); } } } From 44127839bf162a914953df3cc4360f7e87fd177a Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 9 Aug 2026 19:29:49 +1200 Subject: [PATCH 228/239] mpu6050 fixes --- include/accel.h | 2 +- src/shared/main/accel.cpp | 5 ----- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/include/accel.h b/include/accel.h index 5a1cb49df..e04010bff 100644 --- a/include/accel.h +++ b/include/accel.h @@ -34,7 +34,7 @@ extern "C" { #define MPU6050_REG_PWR_MGMT_1 0x6B #define MPU6050_ID 0x68 #define MPU6050_ID2 0x98 // Common register-compatible clone -#define MPU6050_ID3 0x70 // Register-compatible MPU-6500/clone ID accepted by other mature drivers +#define MPU6050_ID3 0x70 // Register-compatible MPU-6500/clone ID #define MPU6050_PWR1_SLEEP (1U << 6) #define MPU6050_PWR1_CLKSEL_MASK 0x07 #define MPU6050_PWR1_CLKSEL_XGYRO 0x01 diff --git a/src/shared/main/accel.cpp b/src/shared/main/accel.cpp index 3ac6cb9c0..68b36606b 100644 --- a/src/shared/main/accel.cpp +++ b/src/shared/main/accel.cpp @@ -143,11 +143,6 @@ void tick_accel() uint8_t raw_bytes[6]; accel_found = twi_readFromPointerRepeatedStart(ACCEL_TWI_PORT, mpu6050_address, MPU6050_REG_ACCEL_OUT, sizeof(raw_bytes), raw_bytes); - if (!accel_found) - { - return; - } - for (int i = 0; i < 3; i++) { raw[i] = (int16_t) (((uint16_t) raw_bytes[i * 2] << 8) | raw_bytes[i * 2 + 1]); From 4ef56d41215e6ec3e2289cad03b569aa7a3fd80b Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sun, 9 Aug 2026 19:31:38 +1200 Subject: [PATCH 229/239] if accel is not detected, zero out readings --- src/shared/main/accel.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/shared/main/accel.cpp b/src/shared/main/accel.cpp index 68b36606b..76ce0dd02 100644 --- a/src/shared/main/accel.cpp +++ b/src/shared/main/accel.cpp @@ -109,6 +109,10 @@ void tick_accel() { if (!accel_found) { + for (int i = 0; i < 3; i++) + { + filtered[i] = raw[i] = 0; + } init_accel(); return; } From f6276bdc697423aa1f0633836c876ed137478b7a Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 18 Aug 2026 09:11:16 +1200 Subject: [PATCH 230/239] use standard pid for squire, not mpa --- include/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/config.h b/include/config.h index c7d07ab1b..1281df330 100644 --- a/include/config.h +++ b/include/config.h @@ -316,8 +316,8 @@ extern const uint8_t config[CONFIGURATION_LEN]; BTN_USAGE(BTN_THUMBR) #elif DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE #define SUB_TYPE XINPUT_PRO_GUITAR -#define PS3_TYPE PS3_SQUIRE_MPA_PID -#define WII_TYPE WII_SQUIRE_MPA_PID +#define PS3_TYPE PS3_SQUIRE_PID +#define WII_TYPE WII_SQUIRE_PID #define OG_XBOX_REPORT OGXboxGamepad_Data_t #define XINPUT_REPORT XInputRockBandProGuitar_Data_t #define XBOX_ONE_REPORT XboxOneRockBandProGuitar_Data_t From 1b9cd8be898c8c1a5b822ce2dbbb9d3ea615c003 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Tue, 18 Aug 2026 09:27:21 +1200 Subject: [PATCH 231/239] fix flipped pro guitar ids --- include/config.h | 4 ++-- src/shared/usb/descriptors.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/include/config.h b/include/config.h index 1281df330..c7d07ab1b 100644 --- a/include/config.h +++ b/include/config.h @@ -316,8 +316,8 @@ extern const uint8_t config[CONFIGURATION_LEN]; BTN_USAGE(BTN_THUMBR) #elif DEVICE_TYPE == ROCK_BAND_PRO_GUITAR_SQUIRE #define SUB_TYPE XINPUT_PRO_GUITAR -#define PS3_TYPE PS3_SQUIRE_PID -#define WII_TYPE WII_SQUIRE_PID +#define PS3_TYPE PS3_SQUIRE_MPA_PID +#define WII_TYPE WII_SQUIRE_MPA_PID #define OG_XBOX_REPORT OGXboxGamepad_Data_t #define XINPUT_REPORT XInputRockBandProGuitar_Data_t #define XBOX_ONE_REPORT XboxOneRockBandProGuitar_Data_t diff --git a/src/shared/usb/descriptors.cpp b/src/shared/usb/descriptors.cpp index 63a8be315..81ecaeba6 100644 --- a/src/shared/usb/descriptors.cpp +++ b/src/shared/usb/descriptors.cpp @@ -1317,11 +1317,11 @@ uint16_t controlRequest(const uint8_t requestType, const uint8_t request, const XInputInputCapabilities_t *caps = (XInputInputCapabilities_t *)requestBuffer; if (proGuitarType == ROCK_BAND_PRO_GUITAR_MUSTANG) { - caps->leftThumbY = XBOX_360_SQUIRE_MPA_PID; + caps->leftThumbY = XBOX_360_MUSTANG_PID; } if (proGuitarType == ROCK_BAND_PRO_GUITAR_SQUIRE) { - caps->leftThumbY = XBOX_360_MUSTANG_PID; + caps->leftThumbY = XBOX_360_SQUIRE_MPA_PID; } } return sizeof(XInputInputCapabilities); @@ -1504,11 +1504,11 @@ uint16_t descriptorRequest(const uint16_t wValue, { if (proGuitarType == ROCK_BAND_PRO_GUITAR_MUSTANG) { - dev->idProduct = WII_SQUIRE_MPA_PID; + dev->idProduct = WII_MUSTANG_PID; } if (proGuitarType == ROCK_BAND_PRO_GUITAR_SQUIRE) { - dev->idProduct = WII_MUSTANG_PID; + dev->idProduct = WII_SQUIRE_MPA_PID; } } } @@ -1522,11 +1522,11 @@ uint16_t descriptorRequest(const uint16_t wValue, { if (proGuitarType == ROCK_BAND_PRO_GUITAR_MUSTANG) { - dev->idProduct = PS3_SQUIRE_MPA_PID; + dev->idProduct = PS3_MUSTANG_PID; } if (proGuitarType == ROCK_BAND_PRO_GUITAR_SQUIRE) { - dev->idProduct = PS3_MUSTANG_PID; + dev->idProduct = PS3_SQUIRE_MPA_PID; } } } From 72c6544e8268497da95a03259c82aa14d7667e72 Mon Sep 17 00:00:00 2001 From: Saand1338 Date: Tue, 18 Aug 2026 16:00:31 +1000 Subject: [PATCH 232/239] Forward PS3 player ID updates over BT, send Player ID on BT LE reconnect --- include/hid.h | 3 +++ src/pico/bt.cpp | 1 + src/pico/bt_rx.cpp | 11 ++++++++++- src/shared/hid/hid.cpp | 23 ++++++++++++++++++++--- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/include/hid.h b/include/hid.h index 08631b5e3..d1c1fc8e9 100644 --- a/include/hid.h +++ b/include/hid.h @@ -84,6 +84,7 @@ extern const uint8_t fnf_descriptor[53]; extern long last_strobe; extern uint8_t stage_kit_millis[5]; extern uint8_t strobe_delay; +extern uint8_t current_player; #if DEVICE_TYPE_IS_INSTRUMENT #if HID_BUTTON_PADDING extern const uint8_t pc_descriptor[90 + 2*HID_BUTTON_COUNT + 2*HID_AXIS_COUNT]; @@ -95,6 +96,7 @@ extern const uint8_t pc_descriptor[158]; #endif void handle_auth_led(void); void handle_player_leds(uint8_t player); +void reset_player_leds(void); void handle_rumble(uint8_t rumble_left, uint8_t rumble_right); void handle_keyboard_leds(uint8_t leds); void tick_leds(void); @@ -103,4 +105,5 @@ uint8_t hid_get_report(uint8_t *data, uint8_t reqLen, uint8_t reportType, uint8_ uint16_t handle_serial_command(uint8_t request, uint16_t wValue, uint8_t* response_buffer, bool* success); #if BLUETOOTH_RX void bt_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_t report_id); +void send_player_leds_bt(void); #endif \ No newline at end of file diff --git a/src/pico/bt.cpp b/src/pico/bt.cpp index a37e70784..cb29d91b2 100644 --- a/src/pico/bt.cpp +++ b/src/pico/bt.cpp @@ -184,6 +184,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe switch (hci_event_packet_get_type(packet)) { case HCI_EVENT_DISCONNECTION_COMPLETE: con_handle = HCI_CON_HANDLE_INVALID; + reset_player_leds(); printf("Disconnected\r\n"); break; case SM_EVENT_JUST_WORKS_REQUEST: diff --git a/src/pico/bt_rx.cpp b/src/pico/bt_rx.cpp index 31ac39245..a2afa1e03 100644 --- a/src/pico/bt_rx.cpp +++ b/src/pico/bt_rx.cpp @@ -65,6 +65,9 @@ static uint8_t hid_descriptor_storage[500]; static uint8_t send_report_buf[64]; static uint8_t send_report_len = 0; +// Set up simulated GATTSERVICE_SUBEVENT_HID_SERVICE_REPORTS_NOTIFICATION +static bool reports_notif_pending = false; + // used to implement connection timeout and reconnect timer static btstack_timer_source_t connection_timer; static btstack_timer_source_t reconnect_timer; @@ -113,9 +116,10 @@ int get_bt_address(uint8_t *addr) void bt_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_t report_id) { - hids_host_send_write_report(hids_cid, 1, HID_REPORT_TYPE_OUTPUT, send_report_buf, send_report_len); memcpy(send_report_buf, data, len); send_report_len = len; + // Reorder to after memcopy so that reports get properly flushed, needed for 360. + hids_host_send_write_report(hids_cid, 1, HID_REPORT_TYPE_OUTPUT, send_report_buf, send_report_len); } bool check_bluetooth_ready() @@ -337,10 +341,15 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint type.console_type = PS3; } } + reports_notif_pending = true; break; } case GATTSERVICE_SUBEVENT_HID_REPORT: { + // On first report after connection, send Player IDs + if (reports_notif_pending && current_player != 0xFF) { + reports_notif_pending = false; + } if (type.console_type == GENERIC) { fill_generic_report(info, gattservice_subevent_hid_report_get_report(packet), &bt_data); diff --git a/src/shared/hid/hid.cpp b/src/shared/hid/hid.cpp index 333893ea6..1c0128e48 100644 --- a/src/shared/hid/hid.cpp +++ b/src/shared/hid/hid.cpp @@ -309,6 +309,11 @@ void handle_player_leds(uint8_t player) } #endif } +void reset_player_leds(void) { + uint8_t player = 0; + current_player = 0xFF; + HANDLE_PLAYER_LED; +} // PS3 controllers and other controllers use different LED bitmasks #if DEVICE_TYPE == GAMEPAD void handle_player_leds_ps3(uint8_t player_mask) @@ -387,6 +392,16 @@ void handle_lightbar_leds(uint8_t red, uint8_t green, uint8_t blue) } } } +#if BLUETOOTH_RX +void send_player_leds_bt(void) +{ + if (current_player != 0xFF) + { + uint8_t player_leds_report[8] = {PS3_REPORT_ID, PS3_RUMBLE_ID, 0, (uint8_t)(1 << (current_player - 1)), 0, 0, 0, 0}; + bt_set_report(player_leds_report, sizeof(player_leds_report), 1, 1); + } +} +#endif void handle_rumble(uint8_t rumble_left, uint8_t rumble_right) { @@ -713,9 +728,7 @@ void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_ if (player) { handle_player_leds(player); - data_hid[1] = PS3_RUMBLE_ID; - data_hid[3] = 1 << player; - bt_set_report(data_hid, 8, reportType, report_id); + send_player_leds_bt(); } } else if (id == XBOX_RUMBLE_ID) @@ -749,6 +762,10 @@ void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_ { bt_set_report(data, len, reportType, report_id); } + else if (id == PS3_REPORT_ID && data[1] == 0x08) // PS3s apparently send an 8 byte Player ID report, and that length is in data[1] + { + bt_set_report(data, len, reportType, report_id); + } #endif } From 85da03175fb7041a6cd187620f0641abfc2d8491 Mon Sep 17 00:00:00 2001 From: Saand1338 Date: Tue, 18 Aug 2026 16:01:25 +1000 Subject: [PATCH 233/239] Hoisted accel raw, due to debug compile errors --- src/shared/main/accel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/shared/main/accel.cpp b/src/shared/main/accel.cpp index 76ce0dd02..c5c62900a 100644 --- a/src/shared/main/accel.cpp +++ b/src/shared/main/accel.cpp @@ -107,6 +107,7 @@ void init_accel() } void tick_accel() { + int16_t raw[3]; if (!accel_found) { for (int i = 0; i < 3; i++) @@ -116,7 +117,6 @@ void tick_accel() init_accel(); return; } - int16_t raw[3]; if (type == LIS3DH) { accel_found = twi_readFromPointer(ACCEL_TWI_PORT, lis3dh_address, LIS3DH_REG_OUT, 6, (uint8_t *)raw); From 534c2c6d01caf76b7f166ce01659cf52f0fd7bd3 Mon Sep 17 00:00:00 2001 From: Saand1338 Date: Tue, 18 Aug 2026 16:16:12 +1000 Subject: [PATCH 234/239] wired in player ID send on report --- src/pico/bt_rx.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pico/bt_rx.cpp b/src/pico/bt_rx.cpp index a2afa1e03..9e2ca6fcc 100644 --- a/src/pico/bt_rx.cpp +++ b/src/pico/bt_rx.cpp @@ -349,6 +349,7 @@ static void handle_gatt_client_event(uint8_t packet_type, uint16_t channel, uint // On first report after connection, send Player IDs if (reports_notif_pending && current_player != 0xFF) { reports_notif_pending = false; + send_player_leds_bt(); } if (type.console_type == GENERIC) { From 0bea894873edd9cdfa9fbdd96090c625ba52bbf3 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 28 Aug 2026 11:17:32 +1200 Subject: [PATCH 235/239] handle xb1 auth better --- include/controllers.h | 5 --- include/shared_main.h | 2 +- src/pico/main.cpp | 5 +-- src/shared/controllers/controllers.c | 4 --- src/shared/hid/hid.cpp | 15 ++++++--- src/shared/main/shared_main.cpp | 46 ++++++++++------------------ 6 files changed, 30 insertions(+), 47 deletions(-) diff --git a/include/controllers.h b/include/controllers.h index 78be1ffbe..d643d0fa1 100644 --- a/include/controllers.h +++ b/include/controllers.h @@ -8,11 +8,6 @@ extern Xbox_One_State_t xbox_one_state; extern Xbox_360_State_t xbox_360_state; extern long reset_after_360; -// Used for passing authentication data between the console and authentication controller -extern uint8_t data_from_console_size; -extern uint8_t data_from_controller_size; -extern uint8_t data_from_console[64]; -extern uint8_t data_from_controller[64]; // Sequence numbers used for sending reports to the xbox one extern uint8_t report_sequence_number; diff --git a/include/shared_main.h b/include/shared_main.h index 3b7c02600..6e82f57f3 100644 --- a/include/shared_main.h +++ b/include/shared_main.h @@ -22,7 +22,7 @@ void tick_wiioutput(); uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t output_console_type); void reset_usb(void); uint32_t transfer_with_usb_controller(const USB_Device_Type_t dev, const uint8_t requestType, const uint8_t request, const uint16_t wValue, const uint16_t wLength, uint8_t *buffer, bool *status); -void send_report_to_controller(uint8_t dev_addr, uint8_t instance, const uint8_t *report, uint8_t len); +bool send_report_to_controller(uint8_t dev_addr, uint8_t instance, const uint8_t *report, uint8_t len); void send_report_to_pc(const void *report, uint8_t len); bool ready_for_next_packet(void); bool usb_configured(void); diff --git a/src/pico/main.cpp b/src/pico/main.cpp index 8f961b4ec..4396fc570 100644 --- a/src/pico/main.cpp +++ b/src/pico/main.cpp @@ -359,12 +359,13 @@ USB_Device_Type_t get_device_address_for(uint8_t deviceType) return {0}; } #endif -void send_report_to_controller(uint8_t dev_addr, uint8_t instance, const uint8_t *report, uint8_t len) +bool send_report_to_controller(uint8_t dev_addr, uint8_t instance, const uint8_t *report, uint8_t len) { if (dev_addr && tuh_xinput_mounted(dev_addr, instance)) { - tuh_xinput_send_report(dev_addr, instance, report, len); + return tuh_xinput_send_report(dev_addr, instance, report, len); } + return false; } extern "C" void tud_mount_cb(void) { diff --git a/src/shared/controllers/controllers.c b/src/shared/controllers/controllers.c index f9aea67c3..8040adf95 100644 --- a/src/shared/controllers/controllers.c +++ b/src/shared/controllers/controllers.c @@ -9,10 +9,6 @@ bool seen_rpcs3 = false; bool descriptor_requested = false; Xbox_One_State_t xbox_one_state = Announce; Xbox_360_State_t xbox_360_state = Auth1; -uint8_t data_from_console_size = 0; -uint8_t data_from_controller_size = 0; -uint8_t data_from_console[64]; -uint8_t data_from_controller[64]; uint8_t keystroke_sequence_number; uint8_t report_sequence_number; uint8_t hid_sequence_number; diff --git a/src/shared/hid/hid.cpp b/src/shared/hid/hid.cpp index 333893ea6..3aa55d766 100644 --- a/src/shared/hid/hid.cpp +++ b/src/shared/hid/hid.cpp @@ -771,19 +771,24 @@ void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_ } else if (xbox_one_state == Auth) { - delay(1); if (data[0] == GIP_AUTHENTICATION && len == 6 && data[3] == 2 && data[4] == 1 && data[5] == 0) { handle_auth_led(); printf("Ready!\r\n"); xbox_one_state = Ready; - data_from_console_size = len; - memcpy(data_from_console, data, len); + USB_Device_Type_t type = get_device_address_for(XBOXONE); + while (!send_report_to_controller(type.dev_addr, type.instance, data, len)) + { + tuh_task(); + } } else if (data[0] != GIP_POWER_MODE_DEVICE_CONFIG && data[0] != 2 && data[0] != 4) { - data_from_console_size = len; - memcpy(data_from_console, data, len); + USB_Device_Type_t type = get_device_address_for(XBOXONE); + while (!send_report_to_controller(type.dev_addr, type.instance, data, len)) + { + tuh_task(); + } } } else if (xbox_one_state == Ready) diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index d05430501..7c9a1400f 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -659,13 +659,6 @@ uint8_t tick_xbox_one() return sizeof(xb1_descriptor_end); } case Auth: - if (data_from_controller_size) - { - uint8_t size = data_from_controller_size; - data_from_controller_size = 0; - memcpy(&combined_report, data_from_controller, size); - return size; - } return 0; case Ready: return 0; @@ -3735,7 +3728,7 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu #endif #if DEVICE_TYPE_IS_GUITAR - + if (output_console_type == SWITCH) { SwitchFestivalGuitar_Data_t *report = (SwitchFestivalGuitar_Data_t *)report_data; @@ -3747,13 +3740,16 @@ uint8_t tick_inputs(void *buf, USB_LastReport_Data_t *last_report, uint8_t outpu report->dpadLeft = false; report->back = false; report->whammy = 255 - report->whammy; - if (dpadLeft) { + if (dpadLeft) + { report->back = true; } - if (back) { + if (back) + { report->dpadLeft = true; } - if (report->tilt < 0x190) { + if (report->tilt < 0x190) + { report->dpadLeft = true; } asm volatile("" :: @@ -4062,23 +4058,10 @@ bool tick_usb(void) #endif if (!ready) return 0; -#if USB_HOST_STACK - if (data_from_console_size) - { - USB_Device_Type_t type = get_device_address_for(XBOXONE); - send_report_to_controller(type.dev_addr, type.instance, data_from_console, data_from_console_size); - data_from_console_size = 0; - } -#endif // If we have something pending to send to the xbox one controller, send it if (consoleType == XBOXONE && xbox_one_state != Ready) { size = tick_xbox_one(); - if (!size) - { - // We don't want the controller ticked due to usb being stated as "not ready" - return true; - } } // #if DEVICE_TYPE == SKYLANDERS // if (consoleType == XBOX360) { @@ -4422,13 +4405,12 @@ void device_reset(void) } #endif xbox_one_state = Announce; - data_from_controller_size = 0; - data_from_console_size = 0; hid_sequence_number = 1; report_sequence_number = 1; } uint8_t last_len = 0; +#include void receive_report_from_controller(uint8_t const *report, uint16_t len) { if (report[0] == GIP_INPUT_REPORT) @@ -4444,8 +4426,10 @@ void receive_report_from_controller(uint8_t const *report, uint16_t len) { return; } - data_from_controller_size = len; - memcpy(data_from_controller, report, len); + while (!ready_for_next_packet()) { + tud_task(); + } + send_report_to_pc(report, len); } void xinput_controller_connected(uint16_t vid, uint16_t pid) @@ -4703,7 +4687,8 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D case PS3_MUSTANG_MPA_PID: type->console_type = PS3; type->sub_type = ROCK_BAND_PRO_GUITAR_MUSTANG; - if (DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != type->sub_type) { + if (DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != type->sub_type) + { proGuitarType = type->sub_type; reset_usb(); } @@ -4711,7 +4696,8 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D case PS3_SQUIRE_MPA_PID: type->console_type = PS3; type->sub_type = ROCK_BAND_PRO_GUITAR_SQUIRE; - if (DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != type->sub_type) { + if (DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != type->sub_type) + { proGuitarType = type->sub_type; reset_usb(); } From eda2d3514953c0686c05fd983388021ff306eced Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 28 Aug 2026 11:45:20 +1200 Subject: [PATCH 236/239] add missing crkd / ro pids --- include/endpoints.h | 1 + src/shared/main/shared_main.cpp | 20 +++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/include/endpoints.h b/include/endpoints.h index 8cd6d83f6..aaef3d01b 100644 --- a/include/endpoints.h +++ b/include/endpoints.h @@ -36,6 +36,7 @@ enum endpoints_t { #define SWITCH_2_JOY_R_PID 0x2066 #define SWITCH_2_JOY_L_PID 0x2067 #define REDOCTANE_VID 0x12ba +#define REDOCTANE_GAMES_VID 0x3651 #define SONY_VID 0x054c #define SONY_DS3_PID 0x0268 #define PS4_DS_PID_1 0x05c4 diff --git a/src/shared/main/shared_main.cpp b/src/shared/main/shared_main.cpp index 7c9a1400f..9c0164bbe 100644 --- a/src/shared/main/shared_main.cpp +++ b/src/shared/main/shared_main.cpp @@ -4426,7 +4426,8 @@ void receive_report_from_controller(uint8_t const *report, uint16_t len) { return; } - while (!ready_for_next_packet()) { + while (!ready_for_next_packet()) + { tud_task(); } send_report_to_pc(report, len); @@ -4753,10 +4754,27 @@ void get_usb_device_type_for(uint16_t vid, uint16_t pid, uint16_t version, USB_D break; } + break; + case REDOCTANE_GAMES_VID: + switch (pid) + { + case CRKD_XB_MODE9: + type->console_type = XBOXONE; + type->sub_type = ROCK_BAND_GUITAR; + break; + case 0xD300: + type->console_type = XBOXONE; + type->sub_type = ROCK_BAND_DRUMS; + type->drum_type = DRUM_RB2; + break; + } break; case CRKD_VID: switch (pid) { + case 0x2200: + case 0x8200: + case 0x8210: case CRKD_XB_MODE9: type->console_type = XBOXONE; type->sub_type = ROCK_BAND_GUITAR; From fbbdd52a7dc8e4d0bf0d0d4adc98d8de981dfdf7 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 28 Aug 2026 13:30:47 +1200 Subject: [PATCH 237/239] handle xb1 auth better --- src/shared/hid/hid.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/shared/hid/hid.cpp b/src/shared/hid/hid.cpp index 287adbf4e..cc3759d10 100644 --- a/src/shared/hid/hid.cpp +++ b/src/shared/hid/hid.cpp @@ -309,7 +309,8 @@ void handle_player_leds(uint8_t player) } #endif } -void reset_player_leds(void) { +void reset_player_leds(void) +{ uint8_t player = 0; current_player = 0xFF; HANDLE_PLAYER_LED; @@ -793,19 +794,24 @@ void hid_set_report(const uint8_t *data, uint8_t len, uint8_t reportType, uint8_ handle_auth_led(); printf("Ready!\r\n"); xbox_one_state = Ready; + +#if USB_HOST_STACK USB_Device_Type_t type = get_device_address_for(XBOXONE); while (!send_report_to_controller(type.dev_addr, type.instance, data, len)) { tuh_task(); } +#endif } else if (data[0] != GIP_POWER_MODE_DEVICE_CONFIG && data[0] != 2 && data[0] != 4) { +#if USB_HOST_STACK USB_Device_Type_t type = get_device_address_for(XBOXONE); while (!send_report_to_controller(type.dev_addr, type.instance, data, len)) { tuh_task(); } +#endif } } else if (xbox_one_state == Ready) From 5eb15965de361f5034055ba25789599598c4f532 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Sat, 29 Aug 2026 17:55:50 +1200 Subject: [PATCH 238/239] bump tinyusb again --- platformio.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platformio.ini b/platformio.ini index fe5e6f391..52b1c5d2e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,7 +9,7 @@ board_upload.ardwiino_bootloader_teensy = true board_build.use_usb = 1 platform = https://github.com/maxgerhardt/platform-raspberrypi/archive/39b90392af50585e429941bd2561a91949a2ba46.zip@1.15.0 platform_packages = - framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.6.16-sanjay/rp2040-4.6.16-sanjay.zip@1.50404.0 + framework-arduinopico@https://github.com/Santroller/arduino-pico/releases/download/4.7.0-sanjay/rp2040-4.7.0-sanjay.zip@1.50404.0 board = pico framework = arduino board_build.core = earlephilhower From 93a55f0907138b286ba881be219a4f56e5ceb218 Mon Sep 17 00:00:00 2001 From: Sanjay Govind Date: Fri, 4 Sep 2026 13:54:16 +1200 Subject: [PATCH 239/239] fix some midi parsing bugs --- src/pico/midi.cpp | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/pico/midi.cpp b/src/pico/midi.cpp index bf18bbf03..963472b64 100644 --- a/src/pico/midi.cpp +++ b/src/pico/midi.cpp @@ -1,7 +1,7 @@ #include "midi.hpp" #include "config.h" #include "shared_main.h" -MidiDevice::MidiDevice(bool usbBased, Midi_Data_t* data) : usbBased(usbBased), midiData(data) +MidiDevice::MidiDevice(bool usbBased, Midi_Data_t *data) : usbBased(usbBased), midiData(data) { tu_memclr(&ep_stream, sizeof(ep_stream)); tu_edpt_stream_init(&ep_stream.rx, true, false, false, @@ -62,7 +62,8 @@ void MidiDevice::update(bool full_poll, bool send_events) cable_state->actual_size = 0xFF; } // Running status - if (status <= MIDI_MAX_DATA_VAL) { + if (status <= MIDI_MAX_DATA_VAL) + { // The status byte is reused, so shift the packet and insert it back status = cable_state->status; cable_state->data[1] = cable_state->data[0]; @@ -122,7 +123,10 @@ void MidiDevice::update(bool full_poll, bool send_events) cable_state->actual_size = 1; cable_state->sysex_in_progress = false; } - cable_state->status = status; + if (status < MIDI_STATUS_SYSEX_START) + { + cable_state->status = status; + } } else { @@ -153,6 +157,15 @@ void MidiDevice::update(bool full_poll, bool send_events) // and we don't care about that right now // so we ignore it } + if (cable_state->sysex_in_progress && cable_state->pos >= sizeof(cable_state->data)) + { + // No 0xF7 yet after filling the whole buffer - drop this message instead of + // treating it as "complete" once pos catches up to the 0xFF sentinel. + cable_state->pos = 0; + cable_state->actual_size = 0; + cable_state->sysex_in_progress = false; + continue; + } } usb_pos++; if (cable_state->actual_size && cable_state->pos >= cable_state->actual_size) @@ -223,11 +236,13 @@ void MidiDevice::update(bool full_poll, bool send_events) // } // } - if (cable_state->data[3] == MIDI_SYSEX_ID_PROGUITAR_MUSTANG && DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != ROCK_BAND_PRO_GUITAR_MUSTANG) { + if (cable_state->data[3] == MIDI_SYSEX_ID_PROGUITAR_MUSTANG && DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != ROCK_BAND_PRO_GUITAR_MUSTANG) + { proGuitarType = ROCK_BAND_PRO_GUITAR_MUSTANG; reset_usb(); } - if (cable_state->data[3] == MIDI_SYSEX_ID_PROGUITAR_SQUIER && DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != ROCK_BAND_PRO_GUITAR_SQUIRE) { + if (cable_state->data[3] == MIDI_SYSEX_ID_PROGUITAR_SQUIER && DEVICE_TYPE_IS_PRO_GUITAR && proGuitarType != ROCK_BAND_PRO_GUITAR_SQUIRE) + { proGuitarType = ROCK_BAND_PRO_GUITAR_SQUIRE; reset_usb(); } @@ -270,7 +285,8 @@ void MidiDevice::update(bool full_poll, bool send_events) // picking events uint8_t string = cable_state->data[5] - 1; uint8_t velocity = cable_state->data[6]; - if (midiData->midiStringVelocities[string] == velocity) { + if (midiData->midiStringVelocities[string] == velocity) + { velocity ^= 1; } midiData->midiStringVelocities[string] = velocity;