-
-
Notifications
You must be signed in to change notification settings - Fork 182
Implement OpenGC (GameCube) HID Protocol #1081
Description
BlueRetro firmware version
24.04
BlueRetro firmware specification
HW2
BlueRetro firmware variant
Universal
BlueRetro hardware type
External adapter dongle (1 port only)
Manufacturer
N/A
System used
Nintendo GameCube
Bluetooth controller brand & name
N/A
What is problem? (only list ONE problem per report)
This is a request to implement a specific HID descriptor specification to support future Bluetooth gamepads that can utilize the full GameCube pad functionality. This includes dual-stage triggers with a separate analog/digital press. This descriptor also includes other button inputs to add compatibility with other consoles (Stick click, Home/Select/4 triggers).
This also supports an output report to set Rumble and the current Player number (Shared output report)
The device name is
OpenGC BT Gamepad
I'm using
Vendor ID: 0x057E
Product ID: 0x0337 (Equal to the GC adapter for Wii U/Switch)
Here's the HID descriptor (Size 145 bytes):
/**** GameCube HID Report Descriptor ****/
const uint8_t gc_hid_report_descriptor[] = {
0x05, 0x01, // Usage Page (Generic Desktop Ctrls)
0x09, 0x05, // Usage (Game Pad)
0xA1, 0x01, // Collection (Application)
// Report ID for input
0x85, 0x01, // Report ID (1)
// Left Joystick X and Y
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
0x09, 0x30, // Usage (X)
0x09, 0x31, // Usage (Y)
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
// Right Joystick X and Y
0x09, 0x01, // Usage (Pointer)
0xA1, 0x00, // Collection (Physical)
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, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
0xC0, // End Collection
// Left and Right Triggers
0x09, 0x32, // Usage (Z) - Left Trigger
0x09, 0x35, // Usage (Rz) - Right Trigger
0x15, 0x00, // Logical Minimum (0)
0x26, 0xFF, 0x00, // Logical Maximum (255)
0x75, 0x08, // Report Size (8)
0x95, 0x02, // Report Count (2)
0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
// Buttons (ABXY, L3/R3, L, R, ZL, ZR, Start, Select, Home, Capture)
0x05, 0x09, // Usage Page (Button)
0x19, 0x01, // Usage Minimum (Button 1)
0x29, 0x0E, // Usage Maximum (Button 14)
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)
// Padding (to align to a full byte after 14 buttons)
0x75, 0x02, // Report Size (2)
0x95, 0x01, // Report Count (1)
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
// D-Pad (as a Hat switch)
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 (Degrees)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x81, 0x42, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,Null State)
// Padding (to align the D-Pad to a full byte)
0x75, 0x04, // Report Size (4)
0x95, 0x01, // Report Count (1)
0x81, 0x03, // Input (Const,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
// Output report (for rumble and player number)
0x85, 0x02, // Report ID (2)
0x09, 0x21, // Usage (Pwr)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x01, // Logical Maximum (1)
0x75, 0x01, // Report Size (1)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x09, 0x37, // Usage (Dial)
0x15, 0x00, // Logical Minimum (0)
0x25, 0x04, // Logical Maximum (4)
0x75, 0x03, // Report Size (3)
0x95, 0x01, // Report Count (1)
0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0x75, 0x04, // Report Size (4) - Padding to make it a full byte
0x95, 0x01, // Report Count (1)
0x91, 0x03, // Output (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position,Non-volatile)
0xC0 // End Collection
};Here's some struct definitions to help along the way
typedef struct {
//uint8_t report_id Should be set to 0x01
uint8_t left_x; // Left joystick X axis
uint8_t left_y; // Left joystick Y axis
uint8_t right_x; // Right joystick X axis
uint8_t right_y; // Right joystick Y axis
uint8_t left_trigger; // Left analog trigger
uint8_t right_trigger; // Right analog trigger
struct {
uint8_t a : 1;
uint8_t b : 1;
uint8_t x : 1;
uint8_t y : 1;
uint8_t l3 : 1;
uint8_t r3 : 1;
uint8_t l : 1; // Mirrored Z button/Switch L Button
uint8_t r : 1; // GameCube Z Button/Switch R Button
} buttons1;
struct {
uint8_t zl : 1; // GameCube L trigger
uint8_t zr : 1; // GameCube R trigger
uint8_t start : 1;
uint8_t select : 1;
uint8_t home : 1;
uint8_t capture : 1;
uint8_t reserved : 2; // Padding bits
} buttons2;
struct {
uint8_t dpad : 4; // D-pad as hat switch
uint8_t padding : 4; // Padding to complete the byte
} dpad;
} gc_input_s;
typedef struct {
// uint8_t report_id is 0x02
struct {
uint8_t rumble : 1; // Rumble on/off
uint8_t player_number : 3; // Player number (0-4)
uint8_t padding : 4;
} feedback;
} gc_output_s;What did you expect to happen?
N/A
Attach files like logs or Bluetooth traces here
No response