From 09a239afdcdb8b40fe6b1e0f18ad84c9e43d9c53 Mon Sep 17 00:00:00 2001 From: Aleksander Rem Date: Wed, 7 Oct 2020 23:00:57 +0200 Subject: [PATCH] USB: Add keyboardmania Signed-off-by: jackun --- pcsx2/USB/device_init.cpp | 1 + pcsx2/USB/deviceproxy.h | 3 +- pcsx2/USB/linux/config-gtk.cpp | 1 - pcsx2/USB/usb-pad/dx/dinput-config.cpp | 78 +++++++++++ pcsx2/USB/usb-pad/dx/dx.h | 11 ++ pcsx2/USB/usb-pad/dx/usb-pad-dx.cpp | 13 ++ pcsx2/USB/usb-pad/dx/versionproxy.h | 24 ++++ pcsx2/USB/usb-pad/dx/versionproxy.rc | 80 ++++++++++++ pcsx2/USB/usb-pad/raw/raw-config.cpp | 2 +- pcsx2/USB/usb-pad/raw/usb-pad-raw.cpp | 5 +- pcsx2/USB/usb-pad/usb-pad.cpp | 102 ++++++++++++++- pcsx2/USB/usb-pad/usb-pad.h | 173 ++++++++++++++++++++++++- 12 files changed, 481 insertions(+), 12 deletions(-) diff --git a/pcsx2/USB/device_init.cpp b/pcsx2/USB/device_init.cpp index 5b6e93e5e0124..b8afa97121045 100644 --- a/pcsx2/USB/device_init.cpp +++ b/pcsx2/USB/device_init.cpp @@ -39,6 +39,7 @@ void RegisterDevice::Register() inst.Add(DEVTYPE_EYETOY, new DeviceProxy()); inst.Add(DEVTYPE_BEATMANIA_DADADA, new DeviceProxy()); inst.Add(DEVTYPE_SEGA_SEAMIC, new DeviceProxy()); + inst.Add(DEVTYPE_KEYBOARDMANIA, new DeviceProxy()); RegisterAPIs(); } diff --git a/pcsx2/USB/deviceproxy.h b/pcsx2/USB/deviceproxy.h index 1e8e658f9331f..50f7ee4cab3b2 100644 --- a/pcsx2/USB/deviceproxy.h +++ b/pcsx2/USB/deviceproxy.h @@ -46,6 +46,7 @@ enum DeviceType DEVTYPE_EYETOY, DEVTYPE_BEATMANIA_DADADA, DEVTYPE_SEGA_SEAMIC, + DEVTYPE_KEYBOARDMANIA, }; struct SelectDeviceName @@ -210,7 +211,7 @@ class RegisterDevice return *registerDevice; } - ~RegisterDevice() { } + ~RegisterDevice() {} static void Register(); void Unregister(); diff --git a/pcsx2/USB/linux/config-gtk.cpp b/pcsx2/USB/linux/config-gtk.cpp index 3700621844535..7ea571af2223e 100644 --- a/pcsx2/USB/linux/config-gtk.cpp +++ b/pcsx2/USB/linux/config-gtk.cpp @@ -235,7 +235,6 @@ void USBconfigure() const char* players[] = {"Player 1:", "Player 2:"}; GtkWidget *rs_cb, *vbox; - uint32_t sel_idx = 0; // Create the dialog window GtkWidget* dlg = gtk_dialog_new_with_buttons( diff --git a/pcsx2/USB/usb-pad/dx/dinput-config.cpp b/pcsx2/USB/usb-pad/dx/dinput-config.cpp index eff1e45ba69d0..9bbec4b696744 100644 --- a/pcsx2/USB/usb-pad/dx/dinput-config.cpp +++ b/pcsx2/USB/usb-pad/dx/dinput-config.cpp @@ -108,6 +108,17 @@ namespace usb_pad IDC_LABEL17, IDC_LABEL18, IDC_LABEL19, + IDC_LABEL20, + IDC_LABEL21, + IDC_LABEL22, + IDC_LABEL23, + IDC_LABEL24, + IDC_LABEL25, + IDC_LABEL26, + IDC_LABEL27, + IDC_LABEL28, + IDC_LABEL29, + IDC_LABEL30, }; struct DXDlgSettings @@ -990,6 +1001,14 @@ namespace usb_pad } } break; + case IDC_DELALL: + { + for (int i = 0; i < CID_COUNT; i++) + { + DeleteControl(s->port, (ControlID)i); + } + } + break; case IDC_ASS0: { @@ -1091,6 +1110,61 @@ namespace usb_pad StartListen(CID_START); break; } + case IDC_ASS20: + { + StartListen(CID_BUTTON20); + break; + } + case IDC_ASS21: + { + StartListen(CID_BUTTON21); + break; + } + case IDC_ASS22: + { + StartListen(CID_BUTTON22); + break; + } + case IDC_ASS23: + { + StartListen(CID_BUTTON23); + break; + } + case IDC_ASS24: + { + StartListen(CID_BUTTON24); + break; + } + case IDC_ASS25: + { + StartListen(CID_BUTTON25); + break; + } + case IDC_ASS26: + { + StartListen(CID_BUTTON26); + break; + } + case IDC_ASS27: + { + StartListen(CID_BUTTON27); + break; + } + case IDC_ASS28: + { + StartListen(CID_BUTTON28); + break; + } + case IDC_ASS29: + { + StartListen(CID_BUTTON29); + break; + } + case IDC_ASS30: + { + StartListen(CID_BUTTON30); + break; + } case IDC_DEL0: { DeleteControl(s->port, CID_STEERING); @@ -1390,6 +1464,10 @@ namespace usb_pad { return DialogBoxParam(h.hInst, MAKEINTRESOURCE(IDD_DLG_BUZZ), h.hWnd, DxDialogProc, (LPARAM)&s); } + if (strcmp(dev_type, "keyboardmania") == 0) + { + return DialogBoxParam(h.hInst, MAKEINTRESOURCE(IDD_DLG_KEYBOARDMANIA), h.hWnd, DxDialogProc, (LPARAM)&s); + } return DialogBoxParam(h.hInst, MAKEINTRESOURCE(IDD_DIALOG1), h.hWnd, DxDialogProc, (LPARAM)&s); } diff --git a/pcsx2/USB/usb-pad/dx/dx.h b/pcsx2/USB/usb-pad/dx/dx.h index 84bb27491f986..060c0a31dc46b 100644 --- a/pcsx2/USB/usb-pad/dx/dx.h +++ b/pcsx2/USB/usb-pad/dx/dx.h @@ -74,6 +74,17 @@ namespace usb_pad CID_R3, CID_SELECT, CID_START, + CID_BUTTON20, + CID_BUTTON21, + CID_BUTTON22, + CID_BUTTON23, + CID_BUTTON24, + CID_BUTTON25, + CID_BUTTON26, + CID_BUTTON27, + CID_BUTTON28, + CID_BUTTON29, + CID_BUTTON30, CID_COUNT, }; diff --git a/pcsx2/USB/usb-pad/dx/usb-pad-dx.cpp b/pcsx2/USB/usb-pad/dx/usb-pad-dx.cpp index a5c59b165b5c7..5468098a38dbe 100644 --- a/pcsx2/USB/usb-pad/dx/usb-pad-dx.cpp +++ b/pcsx2/USB/usb-pad/dx/usb-pad-dx.cpp @@ -58,6 +58,19 @@ namespace usb_pad return 5; } + if (mType == WT_KEYBOARDMANIA_CONTROLLER) + { + for (int i = 0; i < 31; i++) + { + if (GetControl(mPort, i)) + { + mWheelData.buttons |= 1 << i; + } + } + pad_copy_data(mType, buf, mWheelData); + return len; + } + //Allow in both ports but warn in configure dialog that only one DX wheel is supported for now //if(idx == 0){ //mWheelData.steering = 8191 + (int)(GetControl(STEERING, false)* 8191.0f) ; diff --git a/pcsx2/USB/usb-pad/dx/versionproxy.h b/pcsx2/USB/usb-pad/dx/versionproxy.h index 9b7f4200df23a..f8f74b4ebe063 100644 --- a/pcsx2/USB/usb-pad/dx/versionproxy.h +++ b/pcsx2/USB/usb-pad/dx/versionproxy.h @@ -5,6 +5,7 @@ #define IDC_STATIC -1 #define IDOK2 2 #define IDD_DLG_BUZZ 114 +#define IDD_DLG_KEYBOARDMANIA 115 #define IDD_DIALOG1 202 #define IDC_DEL0 1001 #define IDC_ASS0 1002 @@ -165,6 +166,29 @@ #define IDC_BZ_CTL4_LBL3 1135 #define IDC_BZ_CTL4_LBL4 1136 #define IDC_BZ_CTL4_LBL5 1137 +#define IDC_LABEL20 1138 +#define IDC_ASS20 1139 +#define IDC_LABEL21 1140 +#define IDC_ASS21 1141 +#define IDC_LABEL22 1142 +#define IDC_ASS22 1143 +#define IDC_LABEL23 1144 +#define IDC_ASS23 1145 +#define IDC_LABEL24 1146 +#define IDC_ASS24 1147 +#define IDC_LABEL25 1148 +#define IDC_ASS25 1149 +#define IDC_LABEL26 1150 +#define IDC_ASS26 1151 +#define IDC_LABEL27 1152 +#define IDC_ASS27 1153 +#define IDC_LABEL28 1154 +#define IDC_ASS28 1155 +#define IDC_LABEL29 1156 +#define IDC_ASS29 1157 +#define IDC_LABEL30 1158 +#define IDC_ASS30 1159 +#define IDC_DELALL 1160 // Next default values for new objects // diff --git a/pcsx2/USB/usb-pad/dx/versionproxy.rc b/pcsx2/USB/usb-pad/dx/versionproxy.rc index b326ff49b5770..96a466892d6aa 100644 --- a/pcsx2/USB/usb-pad/dx/versionproxy.rc +++ b/pcsx2/USB/usb-pad/dx/versionproxy.rc @@ -256,6 +256,77 @@ BEGIN PUSHBUTTON "Cancel",IDCANCEL,354,142,50,14 END +IDD_DLG_KEYBOARDMANIA DIALOGEX 0, 0, 580, 160 +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +CAPTION "Keyboardmania controller" +FONT 8, "MS Shell Dlg", 400, 0, 0x1 +BEGIN + GROUPBOX "Buttons",IDC_STATIC,5,5,140,50 + PUSHBUTTON "Start",IDC_ASS22,90,15,50,15 + PUSHBUTTON "Select",IDC_ASS14,90,35,50,15 + LTEXT "1/1/1/1",IDC_LABEL22,10,17,50,8 + LTEXT "1/1/1/1",IDC_LABEL14,10,37,50,8 + GROUPBOX "Wheel",IDC_STATIC,150,5,140,50 + PUSHBUTTON "Up",IDC_ASS29,235,15,50,15 + PUSHBUTTON "Down",IDC_ASS30,235,35,50,15 + LTEXT "1/1/1/1",IDC_LABEL29,155,17,50,8 + LTEXT "1/1/1/1",IDC_LABEL30,155,37,50,8 + + GROUPBOX "Keys",IDC_STATIC,5,60,570,70 + PUSHBUTTON "C 1",IDC_ASS0,10,95,40,15 + PUSHBUTTON "C# 1",IDC_ASS1,30,80,40,15 + PUSHBUTTON "D 1",IDC_ASS2,50,95,40,15 + PUSHBUTTON "D# 1",IDC_ASS3,70,80,40,15 + PUSHBUTTON "E 1",IDC_ASS4,90,95,40,15 + PUSHBUTTON "F 1",IDC_ASS5,130,95,40,15 + PUSHBUTTON "F# 1",IDC_ASS6,150,80,40,15 + PUSHBUTTON "G 1",IDC_ASS8,170,95,40,15 + PUSHBUTTON "G# 1",IDC_ASS9,190,80,40,15 + PUSHBUTTON "A 1",IDC_ASS10,210,95,40,15 + PUSHBUTTON "A# 1",IDC_ASS11,230,80,40,15 + PUSHBUTTON "B 1",IDC_ASS12,250,95,40,15 + PUSHBUTTON "C 2",IDC_ASS13,290,95,40,15 + PUSHBUTTON "C# 2",IDC_ASS16,310,80,40,15 + PUSHBUTTON "D 2",IDC_ASS17,330,95,40,15 + PUSHBUTTON "D# 2",IDC_ASS18,350,80,40,15 + PUSHBUTTON "E 2",IDC_ASS19,370,95,40,15 + PUSHBUTTON "F 2",IDC_ASS20,410,95,40,15 + PUSHBUTTON "F# 2",IDC_ASS21,430,80,40,15 + PUSHBUTTON "G 2",IDC_ASS24,450,95,40,15 + PUSHBUTTON "G# 2",IDC_ASS25,470,80,40,15 + PUSHBUTTON "A 2",IDC_ASS26,490,95,40,15 + PUSHBUTTON "A# 2",IDC_ASS27,510,80,40,15 + PUSHBUTTON "B 2",IDC_ASS28,530,95,40,15 + LTEXT "1/1/1/1",IDC_LABEL0,10,110,38,8 + LTEXT "1/1/1/1",IDC_LABEL1,30,70,38,8 + LTEXT "1/1/1/1",IDC_LABEL2,50,110,38,8 + LTEXT "1/1/1/1",IDC_LABEL3,70,70,38,8 + LTEXT "1/1/1/1",IDC_LABEL4,90,110,38,8 + LTEXT "1/1/1/1",IDC_LABEL5,130,110,38,8 + LTEXT "1/1/1/1",IDC_LABEL6,150,70,38,8 + LTEXT "1/1/1/1",IDC_LABEL8,170,110,38,8 + LTEXT "1/1/1/1",IDC_LABEL9,190,70,38,8 + LTEXT "1/1/1/1",IDC_LABEL10,210,110,38,8 + LTEXT "1/1/1/1",IDC_LABEL11,230,70,38,8 + LTEXT "1/1/1/1",IDC_LABEL12,250,110,38,8 + LTEXT "1/1/1/1",IDC_LABEL13,290,110,38,8 + LTEXT "1/1/1/1",IDC_LABEL16,310,70,38,8 + LTEXT "1/1/1/1",IDC_LABEL17,330,110,38,8 + LTEXT "1/1/1/1",IDC_LABEL18,350,70,38,8 + LTEXT "1/1/1/1",IDC_LABEL19,370,110,38,8 + LTEXT "1/1/1/1",IDC_LABEL20,410,110,38,8 + LTEXT "1/1/1/1",IDC_LABEL21,430,70,38,8 + LTEXT "1/1/1/1",IDC_LABEL24,450,110,38,8 + LTEXT "1/1/1/1",IDC_LABEL25,470,70,38,8 + LTEXT "1/1/1/1",IDC_LABEL26,490,110,38,8 + LTEXT "1/1/1/1",IDC_LABEL27,510,70,38,8 + LTEXT "1/1/1/1",IDC_LABEL28,530,110,38,8 + + PUSHBUTTON "Reset all",IDC_DELALL,5,140,50,15 + DEFPUSHBUTTON "OK",IDOK,470,140,50,15 + PUSHBUTTON "Cancel",IDCANCEL,525,140,50,15 +END + ///////////////////////////////////////////////////////////////////////////// // @@ -276,6 +347,10 @@ BEGIN IDD_DLG_BUZZ, DIALOG BEGIN END + + IDD_DLG_KEYBOARDMANIA, DIALOG + BEGIN + END END #endif // APSTUDIO_INVOKED @@ -295,6 +370,11 @@ BEGIN 0 END +IDD_DLG_KEYBOARDMANIA AFX_DIALOG_LAYOUT +BEGIN + 0 +END + #endif // English (United States) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/pcsx2/USB/usb-pad/raw/raw-config.cpp b/pcsx2/USB/usb-pad/raw/raw-config.cpp index b124d07286bc8..bc47eb95ae8c3 100644 --- a/pcsx2/USB/usb-pad/raw/raw-config.cpp +++ b/pcsx2/USB/usb-pad/raw/raw-config.cpp @@ -313,7 +313,7 @@ namespace usb_pad HidP_GetCaps(pPreparsedData, &caps); if (caps.UsagePage == HID_USAGE_PAGE_GENERIC && - caps.Usage == HID_USAGE_GENERIC_JOYSTICK) + (caps.Usage == HID_USAGE_GENERIC_JOYSTICK || caps.Usage == HID_USAGE_GENERIC_GAMEPAD)) { std::wstring strPath(didData->DevicePath); std::transform(strPath.begin(), strPath.end(), strPath.begin(), ::toupper); diff --git a/pcsx2/USB/usb-pad/raw/usb-pad-raw.cpp b/pcsx2/USB/usb-pad/raw/usb-pad-raw.cpp index 032ffe5a57f5d..4cfd9d579d28f 100644 --- a/pcsx2/USB/usb-pad/raw/usb-pad-raw.cpp +++ b/pcsx2/USB/usb-pad/raw/usb-pad-raw.cpp @@ -443,7 +443,10 @@ namespace usb_pad mOLWrite.hEvent = CreateEvent(0, 0, 0, 0); HidD_GetAttributes(mUsbHandle, &(attr)); - if (attr.VendorID != PAD_VID || attr.ProductID == 0xC262) + + bool isClassicLogitech = (attr.VendorID == PAD_VID) && (attr.ProductID != 0xC262); + bool isKeyboardmania = (attr.VendorID == 0x0507) && (attr.ProductID == 0x0010); + if (!isClassicLogitech && !isKeyboardmania) { Console.Warning("USB: Vendor is not Logitech or wheel is G920. Not sending force feedback commands for safety reasons.\n"); mDoPassthrough = 0; diff --git a/pcsx2/USB/usb-pad/usb-pad.cpp b/pcsx2/USB/usb-pad/usb-pad.cpp index a75c3922cc598..5d3ade30e2f5c 100644 --- a/pcsx2/USB/usb-pad/usb-pad.cpp +++ b/pcsx2/USB/usb-pad/usb-pad.cpp @@ -52,6 +52,11 @@ namespace usb_pad "Logitech Buzz(tm) Controller V1", "", "Logitech"}; + static const USBDescStrings kbm_desc_strings = { + "", + "USB Multipurpose Controller", + "", + "KONAMI"}; std::list PadDevice::ListAPIs() { @@ -86,6 +91,16 @@ namespace usb_pad return PadDevice::LongAPIName(name); } + std::list KeyboardmaniaDevice::ListAPIs() + { + return PadDevice::ListAPIs(); + } + + const TCHAR* KeyboardmaniaDevice::LongAPIName(const std::string& name) + { + return PadDevice::LongAPIName(name); + } + #ifdef _DEBUG void PrintBits(void* data, int size) { @@ -100,7 +115,6 @@ namespace usb_pad *(ptrB++) = ' '; } *ptrB = '\0'; - } #else @@ -240,6 +254,11 @@ namespace usb_pad ret = sizeof(pad_gtforce_hid_report_descriptor); memcpy(data, pad_gtforce_hid_report_descriptor, ret); } + else if (t == WT_KEYBOARDMANIA_CONTROLLER) + { + ret = sizeof(kbm_hid_report_descriptor); + memcpy(data, kbm_hid_report_descriptor, ret); + } else { ret = sizeof(pad_driving_force_hid_separate_report_descriptor); @@ -409,6 +428,14 @@ namespace usb_pad buf[4] = (data.buttons >> 4) & 0x3F; // 10 - 4 = 6 bits break; + case WT_KEYBOARDMANIA_CONTROLLER: + buf[0] = 0x3F; + buf[1] = data.buttons & 0xFF; + buf[2] = (data.buttons >> 8) & 0xFF; + buf[3] = (data.buttons >> 16) & 0xFF; + buf[4] = (data.buttons >> 24) & 0xFF; + break; + default: break; } @@ -785,4 +812,77 @@ namespace usb_pad return PadDevice::Freeze(mode, dev, data); } + // ---- Keyboardmania ---- + + USBDevice* KeyboardmaniaDevice::CreateDevice(int port) + { + std::string varApi; +#ifdef _WIN32 + std::wstring tmp; + LoadSetting(nullptr, port, TypeName(), N_DEVICE_API, tmp); + varApi = wstr_to_str(tmp); +#else + LoadSetting(nullptr, port, TypeName(), N_DEVICE_API, varApi); +#endif + PadProxyBase* proxy = RegisterPad::instance().Proxy(varApi); + if (!proxy) + { + Console.WriteLn("usb-pad: %s: Invalid input API.", TypeName()); + return NULL; + } + + Pad* pad = proxy->CreateObject(port, TypeName()); + + if (!pad) + return NULL; + + pad->Type(WT_KEYBOARDMANIA_CONTROLLER); + PADState* s = new PADState(); + + s->desc.full = &s->desc_dev; + s->desc.str = kbm_desc_strings; + + if (usb_desc_parse_dev(kbm_dev_descriptor, sizeof(kbm_dev_descriptor), s->desc, s->desc_dev) < 0) + goto fail; + if (usb_desc_parse_config(kbm_config_descriptor, sizeof(kbm_config_descriptor), s->desc_dev) < 0) + goto fail; + + s->f.dev_subtype = pad->Type(); + s->pad = pad; + s->port = port; + s->dev.speed = USB_SPEED_FULL; + s->dev.klass.handle_attach = usb_desc_attach; + s->dev.klass.handle_reset = pad_handle_reset; + s->dev.klass.handle_control = pad_handle_control; + s->dev.klass.handle_data = pad_handle_data; + s->dev.klass.unrealize = pad_handle_destroy; + s->dev.klass.open = pad_open; + s->dev.klass.close = pad_close; + s->dev.klass.usb_desc = &s->desc; + s->dev.klass.product_desc = s->desc.str[2]; + + usb_desc_init(&s->dev); + usb_ep_init(&s->dev); + pad_handle_reset((USBDevice*)s); + + return (USBDevice*)s; + + fail: + pad_handle_destroy((USBDevice*)s); + return nullptr; + } + + int KeyboardmaniaDevice::Configure(int port, const std::string& api, void* data) + { + auto proxy = RegisterPad::instance().Proxy(api); + if (proxy) + return proxy->Configure(port, TypeName(), data); + return RESULT_CANCELED; + } + + int KeyboardmaniaDevice::Freeze(int mode, USBDevice* dev, void* data) + { + return PadDevice::Freeze(mode, dev, data); + } + } // namespace usb_pad diff --git a/pcsx2/USB/usb-pad/usb-pad.h b/pcsx2/USB/usb-pad/usb-pad.h index 74f73bf9b297d..d9b599efedad1 100644 --- a/pcsx2/USB/usb-pad/usb-pad.h +++ b/pcsx2/USB/usb-pad/usb-pad.h @@ -45,7 +45,7 @@ namespace usb_pad class PadDevice { public: - virtual ~PadDevice() { } + virtual ~PadDevice() {} static USBDevice* CreateDevice(int port); static const TCHAR* Name() { @@ -135,6 +135,29 @@ namespace usb_pad } }; + class KeyboardmaniaDevice + { + public: + virtual ~KeyboardmaniaDevice() {} + static USBDevice* CreateDevice(int port); + static const TCHAR* Name() + { + return TEXT("Keyboardmania"); + } + static const char* TypeName() + { + return "keyboardmania"; + } + static std::list ListAPIs(); + static const TCHAR* LongAPIName(const std::string& name); + static int Configure(int port, const std::string& api, void* data); + static int Freeze(int mode, USBDevice* dev, void* data); + static std::vector SubTypes() + { + return {}; + } + }; + // Most likely as seen on https://github.com/matlo/GIMX #define CMD_DOWNLOAD 0x00 #define CMD_DOWNLOAD_AND_PLAY 0x01 @@ -184,6 +207,7 @@ namespace usb_pad WT_ROCKBAND1_DRUMKIT, WT_BUZZ_CONTROLLER, WT_SEGA_SEAMIC, + WT_KEYBOARDMANIA_CONTROLLER, }; inline int range_max(PS2WheelTypes type) @@ -451,16 +475,16 @@ namespace usb_pad static const int HATS_8TO4[] = {PAD_HAT_N, PAD_HAT_E, PAD_HAT_S, PAD_HAT_W}; #define PAD_VID 0x046D -#define PAD_PID 0xCA03 //black MOMO +#define PAD_PID 0xCA03 //black MOMO #define GENERIC_PID 0xC294 //actually Driving Force aka PID that most logitech wheels initially report #define PID_DF 0xC294 #define PID_DFP 0xC298 //SELECT + R3 + RIGHT SHIFT PADDLE (R1) ??? #define PID_DFGT 0xC29A #define PID_FORMULA 0xC202 //Yellow Wingman Formula -#define PID_FGP 0xC20E //Formula GP (maybe GT FORCE LPRC-1000) -#define PID_FFGP 0xC293 // Formula Force GP -#define PID_GTF 0xC293 // as is Formula Force GP -#define PID_G25 0xC299 // OutRun 2 (jp) supports it apparently +#define PID_FGP 0xC20E //Formula GP (maybe GT FORCE LPRC-1000) +#define PID_FFGP 0xC293 // Formula Force GP +#define PID_GTF 0xC293 // as is Formula Force GP +#define PID_G25 0xC299 // OutRun 2 (jp) supports it apparently #define MAX_BUTTONS 32 #define MAX_AXES 7 //random 7: axes + hatswitch #define MAX_JOYS 32 @@ -1121,7 +1145,7 @@ namespace usb_pad 0x03, // bmAttributes (Interrupt) 0x40, 0x00, // wMaxPacketSize 64 0x0A, // bInterval 10 (unit depends on device speed) - // 41 bytes + // 41 bytes }; //Wii Rock Band drum kit @@ -1294,6 +1318,141 @@ namespace usb_pad // 78 bytes }; + /////////////////// + // Keyboardmania // + /////////////////// + static const uint8_t kbm_dev_descriptor[] = { + 0x12, // bLength + 0x01, // bDescriptorType (Device) + 0x10, 0x01, // bcdUSB 1.10 + 0x00, // bDeviceClass (Use class information in the Interface Descriptors) + 0x00, // bDeviceSubClass + 0x00, // bDeviceProtocol + 0x08, // bMaxPacketSize0 8 + 0x07, 0x05, // idVendor 0x0507 + 0x10, 0x00, // idProduct 0x0010 + 0x00, 0x01, // bcdDevice 01.00 + 0x01, // iManufacturer (String Index) + 0x02, // iProduct (String Index) + 0x00, // iSerialNumber (String Index) + 0x01, // bNumConfigurations 1 + }; + + static const uint8_t kbm_config_descriptor[] = { + 0x09, // bLength + 0x02, // bDescriptorType (Configuration) + 0x22, 0x00, // wTotalLength 34 + 0x01, // bNumInterfaces 1 + 0x01, // bConfigurationValue + 0x00, // iConfiguration (String Index) + 0x80, // bmAttributes + 0x19, // bMaxPower 50mA + + 0x09, // bLength + 0x04, // bDescriptorType (Interface) + 0x00, // bInterfaceNumber 0 + 0x00, // bAlternateSetting + 0x01, // bNumEndpoints 1 + 0x03, // bInterfaceClass + 0x00, // bInterfaceSubClass + 0x00, // bInterfaceProtocol + 0x02, // iInterface (String Index) + + 0x09, // bLength + 0x21, // bDescriptorType (HID) + 0x10, 0x01, // bcdHID 1.11 + 0x00, // bCountryCode + 0x01, // bNumDescriptors + 0x22, // bDescriptorType[0] (HID) + 0x96, 0x00, // wDescriptorLength[0] 150 + + 0x07, // bLength + 0x05, // bDescriptorType (Endpoint) + 0x81, // bEndpointAddress (IN/D2H) + 0x03, // bmAttributes (Interrupt) + 0x08, 0x00, // wMaxPacketSize 8 + 0x04, // bInterval 4 (unit depends on device speed) + }; + + static const uint8_t kbm_hid_report_descriptor[] = { + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x05, // USAGE (Game Pad) + 0xA1, 0x01, // COLLECTION (Application) + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x3A, // USAGE_MINIMUM (Button 58) + 0x29, 0x3F, // USAGE_MAXIMUM (Button 63) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x06, // REPORT_COUNT (6) + 0x81, 0x02, // INPUT (Data,Variable,Absolute,NoWrap,Linear,PrefState,NoNull,NonVolatile,Bitmap) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x02, // REPORT_COUNT (2) + 0x81, 0x01, // INPUT (Constant,Array,Absolute) + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x01, // USAGE_MINIMUM (Button 1) + 0x29, 0x07, // USAGE_MAXIMUM (Button 7) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x07, // REPORT_COUNT (7) + 0x81, 0x02, // INPUT (Data,Variable,Absolute,NoWrap,Linear,PrefState,NoNull,NonVolatile,Bitmap) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x01, // INPUT (Constant,Array,Absolute) + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x08, // USAGE_MINIMUM (Button 8) + 0x29, 0x0E, // USAGE_MAXIMUM (Button 14) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x07, // REPORT_COUNT (7) + 0x81, 0x02, // INPUT (Data,Variable,Absolute,NoWrap,Linear,PrefState,NoNull,NonVolatile,Bitmap) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x01, // INPUT (Constant,Array,Absolute) + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x0F, // USAGE_MINIMUM (Button 15) + 0x29, 0x15, // USAGE_MAXIMUM (Button 21) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x07, // REPORT_COUNT (7) + 0x81, 0x02, // INPUT (Data,Variable,Absolute,NoWrap,Linear,PrefState,NoNull,NonVolatile,Bitmap) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x01, // INPUT (Constant,Array,Absolute) + 0x05, 0x09, // USAGE_PAGE (Button) + 0x19, 0x16, // USAGE_MINIMUM (Button 22) + 0x29, 0x1C, // USAGE_MAXIMUM (Button 28) + 0x15, 0x00, // LOGICAL_MINIMUM (0) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x07, // REPORT_COUNT (7) + 0x81, 0x02, // INPUT (Data,Variable,Absolute,NoWrap,Linear,PrefState,NoNull,NonVolatile,Bitmap) + 0x75, 0x01, // REPORT_SIZE (1) + 0x95, 0x01, // REPORT_COUNT (1) + 0x81, 0x01, // INPUT (Constant,Array,Absolute) + 0x05, 0x01, // USAGE_PAGE (Generic Desktop) + 0x09, 0x01, // USAGE (Pointer) + 0xA1, 0x00, // COLLECTION (Physical) + 0x09, 0x30, // USAGE (X) + 0x09, 0x31, // USAGE (Y) + 0x15, 0xFF, // LOGICAL_MINIMUM (-1) + 0x25, 0x01, // LOGICAL_MAXIMUM (1) + 0x95, 0x02, // REPORT_COUNT (2) + 0x75, 0x02, // REPORT_SIZE (2) + 0x81, 0x02, // INPUT (Data,Variable,Absolute,NoWrap,Linear,PrefState,NoNull,NonVolatile,Bitmap) + 0x95, 0x04, // REPORT_COUNT (4) + 0x75, 0x01, // REPORT_SIZE (1) + 0x81, 0x01, // INPUT (Constant,Array,Absolute) + 0xC0, // END_COLLECTION + 0x75, 0x08, // REPORT_SIZE (8) + 0x95, 0x02, // REPORT_COUNT (2) + 0x81, 0x01, // INPUT (Constant,Array,Absolute) + 0xc0 // END_COLLECTION + }; + struct dfp_buttons_t { uint16_t cross : 1;