From 5587ab4f8b0695f3b2afb4ca6de3545a4f2da5c9 Mon Sep 17 00:00:00 2001 From: DiktatorShadaloo <42413627+DiktatorShadaloo@users.noreply.github.com> Date: Wed, 2 Nov 2022 23:00:42 -0300 Subject: [PATCH] Adding some usb hid drivers (#14581) * Added usb hid controllers for the famous ZeroDelay encoder and also for "Kade: Kick Ass Dynamic Encoder" to be able to use some custom arcade sticks. * Add accidentally missing change to Makefile Co-authored-by: DiktatorShadaloo --- Makefile.common | 2 + griffin/griffin.c | 2 + input/connect/connect_kade.c | 165 ++++++++++++++++ input/connect/connect_zerodelay_dragonrise.c | 187 +++++++++++++++++++ input/connect/joypad_connection.c | 10 + input/connect/joypad_connection.h | 6 + 6 files changed, 372 insertions(+) create mode 100644 input/connect/connect_kade.c create mode 100644 input/connect/connect_zerodelay_dragonrise.c diff --git a/Makefile.common b/Makefile.common index 40c3ad2d5a..3b0b5d2349 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1382,6 +1382,8 @@ ifeq ($(HAVE_HID), 1) input/connect/connect_nesusb.o \ input/connect/connect_snesusb.o \ input/connect/connect_wiiupro.o \ + input/connect/connect_kade.o \ + input/connect/connect_zerodelay_dragonrise.o \ input/connect/connect_wiiugca.o endif diff --git a/griffin/griffin.c b/griffin/griffin.c index 8482a73a53..213028f7db 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -850,6 +850,8 @@ INPUT (HID) #include "../input/connect/connect_psxadapter.c" #include "../input/connect/connect_retrode.c" #include "../input/connect/connect_ps4_hori_mini.c" +#include "../input/connect/connect_kade.c" +#include "../input/connect/connect_zerodelay_dragonrise.c" #endif /*============================================================ diff --git a/input/connect/connect_kade.c b/input/connect/connect_kade.c new file mode 100644 index 0000000000..fafc5d2847 --- /dev/null +++ b/input/connect/connect_kade.c @@ -0,0 +1,165 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2013-2014 - Jason Fetters + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch 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 Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch 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 RetroArch. + * If not, see . + */ + +#include +#include +#include + +#include +#include "joypad_connection.h" + +#include "../input_defines.h" + +struct hidpad_kade_data +{ + struct pad_connection* connection; + uint32_t slot; + uint32_t buttons; + uint8_t data[64]; +}; + +static void* hidpad_kade_init(void* data, uint32_t slot, hid_driver_t* driver) +{ + struct pad_connection* connection = (struct pad_connection*)data; + struct hidpad_kade_data* device = (struct hidpad_kade_data*) + calloc(1, sizeof(struct hidpad_kade_data)); + + if (!device) + return NULL; + + if (!connection) + { + free(device); + return NULL; + } + + device->connection = connection; + device->slot = slot; + + return device; +} + +static void hidpad_kade_deinit(void* data) +{ + struct hidpad_kade_data* device = (struct hidpad_kade_data*)data; + + if (device) + free(device); +} + +static void hidpad_kade_get_buttons(void* data, input_bits_t* state) +{ + struct hidpad_kade_data* device = (struct hidpad_kade_data*)data; + if (device) + { + BITS_COPY16_PTR(state, device->buttons); + } + else + BIT256_CLEAR_ALL_PTR(state); +} + +/*This is being implemented for use with an arcade stick, so there are no axis values on this control, only a hat values . +If your device with kade firmware uses analog controls this function must be implemented.*/ +static int16_t hidpad_kade_get_axis(void* data, unsigned axis) +{ + return 0; +} + +#define KADE_H_GET(a) (a & 0x0F) /*HAT MASK = 0x0F */ +#define KADE_H_LEFT(a) (a == 0x05) || (a == 0x06) || (a == 0x07) +#define KADE_H_RIGHT(a) (a == 0x01) || (a == 0x02) || (a == 0x03) +#define KADE_H_UP(a) (a == 0x07) || (a == 0x00) || (a == 0x01) +#define KADE_H_DOWN(a) (a == 0x03) || (a == 0x04) || (a == 0x05) + +static void hidpad_kade_packet_handler(void* data, uint8_t* packet, uint16_t size) +{ + uint32_t i, pressed_keys; + int16_t hat_value; + static const uint32_t button_mapping[16] = + { + RETRO_DEVICE_ID_JOYPAD_SELECT, + RETRO_DEVICE_ID_JOYPAD_START, + NO_BTN, + NO_BTN, + NO_BTN, + NO_BTN, + NO_BTN, + NO_BTN, + RETRO_DEVICE_ID_JOYPAD_Y, + RETRO_DEVICE_ID_JOYPAD_B, + RETRO_DEVICE_ID_JOYPAD_A, + RETRO_DEVICE_ID_JOYPAD_X, + RETRO_DEVICE_ID_JOYPAD_L, + RETRO_DEVICE_ID_JOYPAD_R, + RETRO_DEVICE_ID_JOYPAD_L2, + RETRO_DEVICE_ID_JOYPAD_R2 + }; + struct hidpad_kade_data* device = (struct hidpad_kade_data*)data; + + if (!device) + return; + + memcpy(device->data, packet, size); + + device->buttons = 0; + + pressed_keys = device->data[1] | (device->data[0] << 8); + + for (i = 0; i < 16; i++) + if (button_mapping[i] != NO_BTN) + device->buttons |= (pressed_keys & (1 << i)) ? (1 << button_mapping[i]) : 0; + + hat_value = KADE_H_GET(device->data[2]); + device->buttons |= KADE_H_LEFT(hat_value) ? (1 << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0; + device->buttons |= KADE_H_RIGHT(hat_value) ? (1 << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0; + device->buttons |= KADE_H_UP(hat_value) ? (1 << RETRO_DEVICE_ID_JOYPAD_UP) : 0; + device->buttons |= KADE_H_DOWN(hat_value) ? (1 << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0; +} + +static void hidpad_kade_set_rumble(void* data, + enum retro_rumble_effect effect, uint16_t strength) +{ + (void)data; + (void)effect; + (void)strength; +} + +const char* hidpad_kade_get_name(void* data) +{ + (void)data; + /* For now we return a single static name */ + return "KADE: Kick Ass Dynamic Encoder"; +} + +static int32_t hidpad_kade_button(void* data, uint16_t joykey) +{ + struct hidpad_kade_data* pad = (struct hidpad_kade_data*)data; + if (!pad || joykey > 31) + return 0; + return pad->buttons & (1 << joykey); +} + +pad_connection_interface_t pad_connection_kade = { + hidpad_kade_init, + hidpad_kade_deinit, + hidpad_kade_packet_handler, + hidpad_kade_set_rumble, + hidpad_kade_get_buttons, + hidpad_kade_get_axis, + hidpad_kade_get_name, + hidpad_kade_button, + false +}; diff --git a/input/connect/connect_zerodelay_dragonrise.c b/input/connect/connect_zerodelay_dragonrise.c new file mode 100644 index 0000000000..88a81d9aa9 --- /dev/null +++ b/input/connect/connect_zerodelay_dragonrise.c @@ -0,0 +1,187 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2013-2014 - Jason Fetters + * Copyright (C) 2011-2017 - Daniel De Matteis + * + * RetroArch 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 Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch 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 RetroArch. + * If not, see . + */ + +#include +#include +#include + +#include +#include "joypad_connection.h" +#include "../input_defines.h" + +struct hidpad_dragonrise_data +{ + struct pad_connection* connection; + uint32_t slot; + uint32_t buttons; + uint8_t data[64]; +}; + +static void* hidpad_dragonrise_init(void* data, uint32_t slot, hid_driver_t* driver) +{ + struct pad_connection* connection = (struct pad_connection*)data; + struct hidpad_dragonrise_data* device = (struct hidpad_dragonrise_data*) + calloc(1, sizeof(struct hidpad_dragonrise_data)); + + if (!device) + return NULL; + + if (!connection) + { + free(device); + return NULL; + } + + device->connection = connection; + device->slot = slot; + + return device; +} + +static void hidpad_dragonrise_deinit(void* data) +{ + struct hidpad_dragonrise_data* device = + (struct hidpad_dragonrise_data*)data; + + if (device) + free(device); +} + +static void hidpad_dragonrise_get_buttons(void* data, input_bits_t* state) +{ + struct hidpad_dragonrise_data* device = + (struct hidpad_dragonrise_data*)data; + + if (device) + { + BITS_COPY16_PTR(state, device->buttons); + } + else + BIT256_CLEAR_ALL_PTR(state); +} + +static int16_t hidpad_dragonrise_get_axis(void* data, unsigned axis) +{ + int val = 0; + struct hidpad_dragonrise_data* device = + (struct hidpad_dragonrise_data*)data; + + if (!device + || axis >= 2 + || (device->data[3] != 0x7F)) /* analog mode detection */ + return 0; + + val = device->data[axis]; + val = (val << 8) - 0x8000; + + /* hard coded deadzone */ + if (abs(val) > 0x1000) + return val; + return 0; +} + +#define DRAGONRISE_H_GET(a) (a & 0x0F) /*HAT MASK = 0x0F */ +#define DRAGONRISE_H_LEFT(a) (a == 0x05) || (a == 0x06) || (a == 0x07) +#define DRAGONRISE_H_RIGHT(a) (a == 0x01) || (a == 0x02) || (a == 0x03) +#define DRAGONRISE_H_UP(a) (a == 0x07) || (a == 0x00) || (a == 0x01) +#define DRAGONRISE_H_DOWN(a) (a == 0x03) || (a == 0x04) || (a == 0x05) + +static void hidpad_dragonrise_packet_handler(void* data, + uint8_t* packet, uint16_t size) +{ + uint32_t i, pressed_keys; + int16_t hat_value; + static const uint32_t button_mapping[16] = + { + RETRO_DEVICE_ID_JOYPAD_L2, + RETRO_DEVICE_ID_JOYPAD_R2, + RETRO_DEVICE_ID_JOYPAD_L, + RETRO_DEVICE_ID_JOYPAD_R, + RETRO_DEVICE_ID_JOYPAD_SELECT, + RETRO_DEVICE_ID_JOYPAD_START, + RETRO_DEVICE_ID_JOYPAD_L3, + RETRO_DEVICE_ID_JOYPAD_R3, + NO_BTN, + NO_BTN, + NO_BTN, + NO_BTN, + RETRO_DEVICE_ID_JOYPAD_X, + RETRO_DEVICE_ID_JOYPAD_A, + RETRO_DEVICE_ID_JOYPAD_B, + RETRO_DEVICE_ID_JOYPAD_Y, + }; + struct hidpad_dragonrise_data* device = + (struct hidpad_dragonrise_data*)data; + + if (!device) + return; + + memcpy(device->data, packet, size); + + device->buttons = 0; + + pressed_keys = device->data[6] | (device->data[5] << 8); + + for (i = 0; i < 16; i++) + if (button_mapping[i] != NO_BTN) + device->buttons |= (pressed_keys & (1 << i)) ? (1 << button_mapping[i]) : 0; + + if (device->data[3] != 0x7F) /* digital mode detection */ + { + /* We're in digital mode, process the hat values*/ + hat_value = DRAGONRISE_H_GET(device->data[5]); + device->buttons |= DRAGONRISE_H_LEFT(hat_value) ? (1 << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0; + device->buttons |= DRAGONRISE_H_RIGHT(hat_value) ? (1 << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0; + device->buttons |= DRAGONRISE_H_UP(hat_value) ? (1 << RETRO_DEVICE_ID_JOYPAD_UP) : 0; + device->buttons |= DRAGONRISE_H_DOWN(hat_value) ? (1 << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0; + } +} + +static void hidpad_dragonrise_set_rumble(void* data, + enum retro_rumble_effect effect, uint16_t strength) +{ + (void)data; + (void)effect; + (void)strength; +} + +const char* hidpad_dragonrise_get_name(void* data) +{ + (void)data; + /* For now we return a single static name */ + return "DRAGONRISE Zero Delay Encoder"; +} + +static int32_t hidpad_dragonrise_button(void* data, uint16_t joykey) +{ + struct hidpad_dragonrise_data* pad = + (struct hidpad_dragonrise_data*)data; + if (!pad || joykey > 31) + return 0; + return pad->buttons & (1 << joykey); +} + +pad_connection_interface_t pad_connection_dragonrise = { + hidpad_dragonrise_init, + hidpad_dragonrise_deinit, + hidpad_dragonrise_packet_handler, + hidpad_dragonrise_set_rumble, + hidpad_dragonrise_get_buttons, + hidpad_dragonrise_get_axis, + hidpad_dragonrise_get_name, + hidpad_dragonrise_button, + false +}; diff --git a/input/connect/joypad_connection.c b/input/connect/joypad_connection.c index 0e595f7429..3eb4316676 100644 --- a/input/connect/joypad_connection.c +++ b/input/connect/joypad_connection.c @@ -96,6 +96,16 @@ static joypad_connection_entry_t pad_map[] = { PID_HORI_MINI_WIRED_PS4, &pad_connection_ps4_hori_mini }, + { "Kade Kick Ass Dynamic Encoder", + VID_KADE, + PID_KADE, + &pad_connection_kade + }, + { "DragonRise ZeroDelay Encoder", + VID_DRAGONRISE, + PID_DRAGONRISE, + &pad_connection_dragonrise + }, { 0, 0} }; diff --git a/input/connect/joypad_connection.h b/input/connect/joypad_connection.h index c585740ba5..e73eb94e96 100644 --- a/input/connect/joypad_connection.h +++ b/input/connect/joypad_connection.h @@ -41,6 +41,8 @@ #define VID_SNES_CLONE SWAP_IF_BIG(0x081f) #define VID_RETRODE SWAP_IF_BIG(0x0403) #define VID_HORI_1 SWAP_IF_BIG(0x0f0d) +#define VID_KADE SWAP_IF_BIG(0x10c4) +#define VID_DRAGONRISE SWAP_IF_BIG(0x0079) #define PID_NONE 0x0000 #define PID_NINTENDO_PRO SWAP_IF_BIG(0x0330) @@ -55,6 +57,8 @@ #define PID_PCS_PSX2PS3 SWAP_IF_BIG(0x0003) #define PID_RETRODE SWAP_IF_BIG(0x97c1) #define PID_HORI_MINI_WIRED_PS4 SWAP_IF_BIG(0x00ee) +#define PID_KADE SWAP_IF_BIG(0x82c0) +#define PID_DRAGONRISE SWAP_IF_BIG(0x0006) struct joypad_connection { @@ -111,6 +115,8 @@ extern pad_connection_interface_t pad_connection_ps2adapter; extern pad_connection_interface_t pad_connection_psxadapter; extern pad_connection_interface_t pad_connection_retrode; extern pad_connection_interface_t pad_connection_ps4_hori_mini; +extern pad_connection_interface_t pad_connection_kade; +extern pad_connection_interface_t pad_connection_dragonrise; int32_t pad_connection_pad_init(joypad_connection_t *joyconn, const char* name, uint16_t vid, uint16_t pid,