From 9edb449471fb2bdf44558c4ace4335fd37b50018 Mon Sep 17 00:00:00 2001 From: Nathan Strong Date: Sat, 25 Sep 2021 10:41:06 -0700 Subject: [PATCH 01/10] wip commit --- .vscode/c_cpp_properties.json | 3 +- Makefile.common | 6 --- Makefile.wiiu | 1 + input/drivers_hid/wiiu_hid.c | 66 ++++++++++++++++------- input/drivers_joypad/wiiu/hidpad_driver.c | 49 +++++++++++++---- input/drivers_joypad/wiiu_joypad.c | 2 - input/include/hid_driver.h | 27 ---------- input/include/hid_types.h | 1 - input/include/wiiu/hid.h | 5 +- input/include/wiiu/input.h | 9 +++- input/input_driver.c | 3 ++ input/input_driver.h | 1 + 12 files changed, 104 insertions(+), 69 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index 54e784c61d..b68a4af620 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -160,7 +160,8 @@ "${workspaceFolder}/**" ], "defines": [ - "WIIU" + "WIIU", + "WIIU_HID" ], "windowsSdkVersion": "10.0.17763.0", "compilerPath": "/opt/devkitpro/devkitPPC/bin/powerpc-eabi-gcc", diff --git a/Makefile.common b/Makefile.common index 9f5f1f0dfd..60fd4b4e36 100644 --- a/Makefile.common +++ b/Makefile.common @@ -1182,12 +1182,6 @@ ifeq ($(TARGET), retroarch_wiiu) INCLUDE_DIRS += -Iinput/include OBJ += input/drivers_joypad/wiiu/hidpad_driver.o OBJ += input/drivers_hid/wiiu_hid.o - OBJ += input/connect/joypad_connection.o \ - input/common/hid/hid_device_driver.o \ - input/common/hid/device_wiiu_gca.o \ - input/common/hid/device_ds3.o \ - input/common/hid/device_ds4.o \ - input/common/hid/device_null.o endif endif diff --git a/Makefile.wiiu b/Makefile.wiiu index 1d4d07450a..ac54a772ee 100644 --- a/Makefile.wiiu +++ b/Makefile.wiiu @@ -7,6 +7,7 @@ GRIFFIN_BUILD = 0 SALAMANDER_BUILD = 0 WHOLE_ARCHIVE_LINK = 0 WIIU_HID = 1 +HAVE_HID = 1 HAVE_RUNAHEAD = 1 WIIU_LOG_RPX = 0 BUILD_DIR = objs/wiiu diff --git a/input/drivers_hid/wiiu_hid.c b/input/drivers_hid/wiiu_hid.c index 256562a988..87a8f175af 100644 --- a/input/drivers_hid/wiiu_hid.c +++ b/input/drivers_hid/wiiu_hid.c @@ -363,17 +363,12 @@ static void log_device(HIDDevice *device) RARCH_LOG(" max_packet_size_tx: %d\n", device->max_packet_size_tx); } + static uint8_t try_init_driver(wiiu_adapter_t *adapter) { - adapter->driver_handle = adapter->driver->init(adapter); - if (!adapter->driver_handle) - { - RARCH_ERR("[hid]: Failed to initialize driver: %s\n", - adapter->driver->name); - return ADAPTER_STATE_DONE; - } + int32_t pad = pad_connection_pad_init(HID_PAD_CONNECTION_PTR(0), &adapter->device_name[0], adapter->vendor_id, adapter->product_id, adapter, &wiiu_hid); - return ADAPTER_STATE_READY; + return (pad >= 0) ? ADAPTER_STATE_READY : ADAPTER_STATE_DONE; } static void synchronized_process_adapters(wiiu_hid_t *hid) @@ -509,9 +504,10 @@ static void wiiu_hid_attach(wiiu_hid_t *hid, wiiu_attach_event *event) goto error; } - adapter->hid = hid; - adapter->driver = event->driver; - adapter->state = ADAPTER_STATE_NEW; + adapter->hid = hid; + adapter->vendor_id = event->vendor_id; + adapter->product_id = event->product_id; + adapter->state = ADAPTER_STATE_NEW; synchronized_add_to_adapters_list(adapter); @@ -775,8 +771,11 @@ static wiiu_adapter_t *new_adapter(wiiu_attach_event *event) adapter->handle = event->handle; adapter->interface_index = event->interface_index; + adapter->product_id = event->product_id; + adapter->vendor_id = event->vendor_id; init_cachealigned_buffer(event->max_packet_size_rx, &adapter->rx_buffer, &adapter->rx_size); init_cachealigned_buffer(event->max_packet_size_tx, &adapter->tx_buffer, &adapter->tx_size); + memcpy(adapter->device_name, event->device_name, sizeof(adapter->device_name)); adapter->connected = true; return adapter; @@ -806,20 +805,48 @@ static void delete_adapter(wiiu_adapter_t *adapter) free(adapter); } +static void get_descriptor_string_ascii(wiiu_adapter_t *adapter, uint8_t *buffer, size_t buffer_size) { + int32_t result = HIDGetDescriptor(adapter->handle, 3, 2, 0, adapter->rx_buffer, adapter->rx_size, NULL, NULL); + memset(buffer, 0, buffer_size); + uint8_t *top; + if(result > 0) { + top = buffer; + for(int i = 2; i < result; i += 2) { + top[0] = adapter->rx_buffer[i]; + top++; + } + } else { + RARCH_ERR("Failed to read descriptor string (0x%08x). Will attempt match by VID/PID\n", result); + } +} + + +static void get_device_name(HIDDevice *device, wiiu_attach_event *event) +{ + int32_t result; + uint8_t *name_buffer = alloc_zeroed(4, device->max_packet_size_rx); + uint8_t *top = &event->device_name[0]; + + if(name_buffer == NULL) { + return; + } + result = HIDGetDescriptor(device->handle, 3, 2, 0, name_buffer, device->max_packet_size_rx, NULL, NULL); + if(result > 0) { + for(int i = 2; i < result; i += 2) { + top[0] = name_buffer[i]; + top++; + } + } + free(name_buffer); +} + static wiiu_attach_event *new_attach_event(HIDDevice *device) { - hid_device_t *driver = hid_device_driver_lookup(device->vid, device->pid); - if (!driver) - { - RARCH_ERR("[hid]: Failed to locate driver for device vid=%04x pid=%04x\n", - device->vid, device->pid); - return NULL; - } wiiu_attach_event *event = alloc_zeroed(4, sizeof(wiiu_attach_event)); + if (!event) return NULL; - event->driver = driver; event->handle = device->handle; event->vendor_id = device->vid; event->product_id = device->pid; @@ -830,6 +857,7 @@ static wiiu_attach_event *new_attach_event(HIDDevice *device) && device->protocol == 2); event->max_packet_size_rx = device->max_packet_size_rx; event->max_packet_size_tx = device->max_packet_size_tx; + get_device_name(device, event); return event; } diff --git a/input/drivers_joypad/wiiu/hidpad_driver.c b/input/drivers_joypad/wiiu/hidpad_driver.c index 454b91d54a..48e9f76a8f 100644 --- a/input/drivers_joypad/wiiu/hidpad_driver.c +++ b/input/drivers_joypad/wiiu/hidpad_driver.c @@ -16,18 +16,37 @@ #include "../../include/wiiu/input.h" +static hidpad_driver_t instance; + /* TODO/FIXME - static global variables */ static bool hidpad_ready = false; +static bool init_pad_list(unsigned slots) +{ + if (slots > MAX_USERS) + return false; + + if (instance.pad_list) + return true; + + instance.pad_list = pad_connection_init(slots); + if (!instance.pad_list) + return false; + + instance.max_slot = slots; + + return true; +} + static bool init_hid_driver(void) { - return hid_init(&hid_instance, &wiiu_hid, &hidpad_driver, MAX_USERS); + return init_pad_list(MAX_USERS); } static void hidpad_poll(void) { if (hidpad_ready) - HID_POLL(); + wiiu_hid.poll(hid_driver_get_data()); } static void *hidpad_init(void *data) @@ -53,29 +72,37 @@ static void hidpad_destroy(void) { hidpad_ready = false; - hid_deinit(&hid_instance); + if(instance.pad_list) { + pad_connection_destroy(instance.pad_list); + instance.pad_list = NULL; + } + + /* Wiping instance data.. */ + memset(&instance, 0, sizeof(instance)); } static int32_t hidpad_button(unsigned port, uint16_t joykey) { if (!hidpad_query_pad(port)) return 0; - return (HID_BUTTON(port, joykey)); + + return wiiu_hid.button(hid_driver_get_data(), port, joykey); } static void hidpad_get_buttons(unsigned port, input_bits_t *state) { - if (!hidpad_query_pad(port)) - BIT256_CLEAR_ALL_PTR(state); + if (!hidpad_query_pad(port)) + BIT256_CLEAR_ALL_PTR(state); - HID_GET_BUTTONS(port, state); + wiiu_hid.get_buttons(hid_driver_get_data(), port, state); } static int16_t hidpad_axis(unsigned port, uint32_t axis) { if (!hidpad_query_pad(port)) return 0; - return HID_AXIS(port, axis); + + return wiiu_hid.axis(hid_driver_get_data(), port, axis); } static int16_t hidpad_state( @@ -116,7 +143,7 @@ static const char *hidpad_name(unsigned port) if (!hidpad_query_pad(port)) return "N/A"; - return HID_PAD_NAME(port); + return wiiu_hid.name(hid_driver_get_data(), port); } input_device_driver_t hidpad_driver = @@ -129,8 +156,8 @@ input_device_driver_t hidpad_driver = hidpad_get_buttons, hidpad_axis, hidpad_poll, - NULL, - NULL, + NULL, /* set_rumble */ + NULL, /* set_rumble_gain */ hidpad_name, "hid" }; diff --git a/input/drivers_joypad/wiiu_joypad.c b/input/drivers_joypad/wiiu_joypad.c index 18eb5db822..18380a7cee 100644 --- a/input/drivers_joypad/wiiu_joypad.c +++ b/input/drivers_joypad/wiiu_joypad.c @@ -27,8 +27,6 @@ static bool wiiu_joypad_ready = false; static void *wiiu_joypad_init(void *data) { set_connection_listener(&wiiu_pad_connection_listener); - hid_instance.pad_list = pad_connection_init(MAX_USERS); - hid_instance.max_slot = MAX_USERS; wpad_driver.init(data); kpad_driver.init(data); diff --git a/input/include/hid_driver.h b/input/include/hid_driver.h index b7c8a56fd3..127b477d94 100644 --- a/input/include/hid_driver.h +++ b/input/include/hid_driver.h @@ -54,31 +54,4 @@ struct hid_driver int32_t (*read)(void *handle, void *buf, size_t size); }; -#define HID_GET_BUTTONS(pad, state) hid_instance.os_driver->get_buttons( \ - hid_instance.os_driver_data, pad, state) -#define HID_BUTTON(pad, key) hid_instance.os_driver->button( \ - hid_instance.os_driver_data, pad, key) -#define HID_AXIS(pad, a) hid_instance.os_driver->axis( \ - hid_instance.os_driver_data, pad, (a)) -#define HID_PAD_NAME(pad) \ - hid_instance.os_driver->name(hid_instance.os_driver_data, pad) -#define HID_SET_PROTOCOL(pad, protocol) \ - hid_instance.os_driver->set_protocol(pad, protocol) -#define HID_SET_REPORT(pad, rpttype, rptid, data, len) \ - hid_instance.os_driver->set_report(pad, rpttype, rptid, data, len) -#define HID_SEND_CONTROL(pad, data, len) \ - hid_instance.os_driver->send_control(pad, data, len) -#define HID_POLL() hid_instance.os_driver->poll( \ - hid_instance.os_driver_data) -#define HID_MAX_SLOT() hid_instance.max_slot -#define HID_PAD_CONNECTION_PTR(slot) &(hid_instance.pad_list[(slot)]) - -struct hid_driver_instance { - hid_driver_t *os_driver; - void *os_driver_data; - input_device_driver_t *pad_driver; - joypad_connection_t *pad_list; - unsigned max_slot; -}; - #endif /* HID_DRIVER_H__ */ diff --git a/input/include/hid_types.h b/input/include/hid_types.h index 28734e9dd8..a2af1af661 100644 --- a/input/include/hid_types.h +++ b/input/include/hid_types.h @@ -19,6 +19,5 @@ #define HID_TYPES_H__ typedef struct hid_driver hid_driver_t; -typedef struct hid_driver_instance hid_driver_instance_t; #endif /* HID_TYPES_H__ */ diff --git a/input/include/wiiu/hid.h b/input/include/wiiu/hid.h index 3d2a44301e..20aafb3e10 100644 --- a/input/include/wiiu/hid.h +++ b/input/include/wiiu/hid.h @@ -55,6 +55,8 @@ struct wiiu_adapter { hid_device_t *driver; void *driver_handle; wiiu_hid_t *hid; + uint16_t vendor_id; + uint16_t product_id; uint8_t state; uint8_t *rx_buffer; int32_t rx_size; @@ -62,6 +64,7 @@ struct wiiu_adapter { int32_t tx_size; uint32_t handle; uint8_t interface_index; + uint8_t device_name[32]; bool connected; }; @@ -72,7 +75,6 @@ struct wiiu_adapter { */ struct wiiu_attach { wiiu_attach_event *next; - hid_device_t *driver; uint32_t type; uint32_t handle; uint16_t vendor_id; @@ -82,6 +84,7 @@ struct wiiu_attach { uint8_t is_mouse; uint16_t max_packet_size_rx; uint16_t max_packet_size_tx; + uint8_t device_name[32]; }; struct _wiiu_event_list { diff --git a/input/include/wiiu/input.h b/input/include/wiiu/input.h index 401dbaa426..8126c86e09 100644 --- a/input/include/wiiu/input.h +++ b/input/include/wiiu/input.h @@ -30,7 +30,6 @@ #include #include -#include "../../common/hid/hid_device_driver.h" #include "../../connect/joypad_connection.h" #include "../../../retroarch.h" #include "../../../verbosity.h" @@ -64,6 +63,14 @@ struct _wiiu_pad_functions { void (*connect)(unsigned pad, input_device_driver_t *driver); }; +struct hidpad_driver_t { + input_device_driver_t *pad_driver; + joypad_connection_t *pad_list; + unsigned max_slot; +}; + +typedef struct hidpad_driver_t hidpad_driver_t; + extern wiiu_pad_functions_t pad_functions; extern input_device_driver_t wiiu_joypad; extern input_device_driver_t wpad_driver; diff --git a/input/input_driver.c b/input/input_driver.c index c13eba5f01..9d4f84760f 100644 --- a/input/input_driver.c +++ b/input/input_driver.c @@ -305,6 +305,9 @@ hid_driver_t *hid_drivers[] = { #endif #ifdef HW_RVL &wiiusb_hid, +#endif +#if defined(WIIU) && defined(WIIU_HID) + &wiiu_hid, #endif &null_hid, NULL, diff --git a/input/input_driver.h b/input/input_driver.h index d372ebc22e..2dde9f6f98 100644 --- a/input/input_driver.h +++ b/input/input_driver.h @@ -1037,6 +1037,7 @@ extern hid_driver_t iohidmanager_hid; extern hid_driver_t btstack_hid; extern hid_driver_t libusb_hid; extern hid_driver_t wiiusb_hid; +extern hid_driver_t wiiu_hid; #endif /* HAVE_HID */ RETRO_END_DECLS From 5da1cd08ff6ef1d18df867e5af35e58543e7e766 Mon Sep 17 00:00:00 2001 From: Nathan Strong Date: Fri, 1 Oct 2021 00:02:11 -0700 Subject: [PATCH 02/10] Unify the HID driver architecture == DETAILS When I first implemented the Wii U HID architecture, I ended up having to design my own implementation because, at the time, I did not have a way to read the HID device string to allow the existing code to successfully detect the gamepad. After spending some time experimenting, I've figured out how to do this. And that means I can better align the HID driver with other platforms. change summary: - create a single state structure for all three sub-types of wiiu pads (kpad, wpad, and hid) - eliminate confusing duplicate pad lists - eliminate confusing duplicate HID pad drivers (ds3, gamecube adapter, etc) - ensure the ds3 driver still works --- input/common/hid/device_ds3.c | 347 --------------------- input/common/hid/device_ds4.c | 128 -------- input/common/hid/device_null.c | 199 ------------ input/common/hid/device_wiiu_gca.c | 345 --------------------- input/common/hid/hid_device_driver.c | 159 ---------- input/common/hid/hid_device_driver.h | 46 --- input/connect/connect_ps3.c | 360 ++++++++++++---------- input/connect/connect_ps4.c | 1 - input/connect/connect_wii.c | 1 - input/connect/connect_wiiugca.c | 1 - input/connect/connect_wiiupro.c | 1 - input/connect/joypad_connection.c | 6 +- input/drivers_hid/wiiu_hid.c | 150 ++++----- input/drivers_joypad/wiiu/hidpad_driver.c | 53 +--- input/drivers_joypad/wiiu/kpad_driver.c | 88 +++--- input/drivers_joypad/wiiu/wpad_driver.c | 52 ++-- input/drivers_joypad/wiiu_joypad.c | 55 ++-- input/include/gamepad.h | 5 - input/include/wiiu/hid.h | 6 +- input/include/wiiu/input.h | 44 ++- input/input_autodetect_builtin.c | 2 +- input/input_driver.c | 11 +- input/input_driver.h | 11 +- input/input_types.h | 3 - retroarch.c | 2 +- 25 files changed, 411 insertions(+), 1665 deletions(-) delete mode 100644 input/common/hid/device_ds3.c delete mode 100644 input/common/hid/device_ds4.c delete mode 100644 input/common/hid/device_null.c delete mode 100644 input/common/hid/device_wiiu_gca.c delete mode 100644 input/common/hid/hid_device_driver.c delete mode 100644 input/common/hid/hid_device_driver.h diff --git a/input/common/hid/device_ds3.c b/input/common/hid/device_ds3.c deleted file mode 100644 index 2c33050cae..0000000000 --- a/input/common/hid/device_ds3.c +++ /dev/null @@ -1,347 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2014 - Hans-Kristian Arntzen - * 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 "hid_device_driver.h" - -#define DS3_ACTIVATION_REPORT_ID 0xf4 -#define DS3_RUMBLE_REPORT_ID 0x01 - -typedef struct ds3_instance { - void *handle; - joypad_connection_t *pad; - int slot; - bool led_set; - uint32_t buttons; - int16_t analog_state[3][2]; - uint16_t motors[2]; - uint8_t data[64]; -} ds3_instance_t; - -static uint8_t ds3_activation_packet[] = { -#if defined(IOS) - 0x53, 0xF4, -#elif defined(HAVE_WIIUSB_HID) - 0x02, -#endif - 0x42, 0x0c, 0x00, 0x00 -}; - -#if defined(WIIU) -#define PACKET_OFFSET 2 -#elif defined(HAVE_WIIUSB_HID) -#define PACKET_OFFSET 1 -#else -#define PACKET_OFFSET 0 -#endif - -#define LED_OFFSET 11 -#define MOTOR1_OFFSET 4 -#define MOTOR2_OFFSET 6 - -static uint8_t ds3_control_packet[] = { - 0x52, 0x01, - 0x00, 0xff, 0x00, 0xff, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00 -}; - -extern pad_connection_interface_t ds3_pad_connection; - -static void ds3_update_pad_state(ds3_instance_t *instance) -{ - uint32_t i, pressed_keys; - - static const uint32_t button_mapping[17] = - { - RETRO_DEVICE_ID_JOYPAD_SELECT, - RETRO_DEVICE_ID_JOYPAD_L3, - RETRO_DEVICE_ID_JOYPAD_R3, - RETRO_DEVICE_ID_JOYPAD_START, - RETRO_DEVICE_ID_JOYPAD_UP, - RETRO_DEVICE_ID_JOYPAD_RIGHT, - RETRO_DEVICE_ID_JOYPAD_DOWN, - RETRO_DEVICE_ID_JOYPAD_LEFT, - RETRO_DEVICE_ID_JOYPAD_L2, - RETRO_DEVICE_ID_JOYPAD_R2, - RETRO_DEVICE_ID_JOYPAD_L, - RETRO_DEVICE_ID_JOYPAD_R, - RETRO_DEVICE_ID_JOYPAD_X, - RETRO_DEVICE_ID_JOYPAD_A, - RETRO_DEVICE_ID_JOYPAD_B, - RETRO_DEVICE_ID_JOYPAD_Y, - 16 /* PS button */ - }; - - instance->buttons = 0; - - pressed_keys = instance->data[2] | - (instance->data[3] << 8) | - ((instance->data[4] & 0x01) << 16); - - for (i = 0; i < 17; i++) - instance->buttons |= (pressed_keys & (1 << i)) ? - (1 << button_mapping[i]) : 0; -} - -static void ds3_update_analog_state(ds3_instance_t *instance) -{ - int pad_axis; - int16_t interpolated; - unsigned stick, axis; - - for (pad_axis = 0; pad_axis < 4; pad_axis++) - { - axis = pad_axis % 2 ? 0 : 1; - stick = pad_axis / 2; - interpolated = instance->data[6+pad_axis]; - instance->analog_state[stick][axis] = (interpolated - 128) * 256; - } -} - -#if defined(WIIU) -static int32_t ds3_send_activation_packet(ds3_instance_t *instance) -{ - return HID_SET_REPORT(instance->handle, - HID_REPORT_FEATURE, - DS3_ACTIVATION_REPORT_ID, - ds3_activation_packet, - sizeof(ds3_activation_packet)); -} - -static uint32_t set_protocol(ds3_instance_t *instance, int protocol) -{ - return HID_SET_PROTOCOL(instance->handle, 1); -} -#else -static int32_t ds3_send_activation_packet(ds3_instance_t *instance) -{ - HID_SEND_CONTROL(instance->handle, - ds3_activation_packet, sizeof(ds3_activation_packet)); - return 0; -} - -static uint32_t set_protocol(ds3_instance_t *instance, int protocol) -{ - return 0; -} -#endif - -static int32_t ds3_send_control_packet(ds3_instance_t *instance) -{ - /* TODO/FIXME - C89-incompatible */ - int32_t result = 0; - uint8_t packet_buffer[sizeof(ds3_control_packet)]; - memcpy(packet_buffer, ds3_control_packet, sizeof(ds3_control_packet)); - - packet_buffer[LED_OFFSET] = 0; - if (instance->pad) - packet_buffer[LED_OFFSET] = 1 << ((instance->slot % 4) + 1); - packet_buffer[MOTOR1_OFFSET] = instance->motors[1] >> 8; - packet_buffer[MOTOR2_OFFSET] = instance->motors[0] >> 8; - -#if defined(HAVE_WIIUSB_HID) - packet_buffer[1] = 0x03; -#endif - -#if defined(WIIU) - result = HID_SET_REPORT(instance->handle, - HID_REPORT_OUTPUT, - DS3_RUMBLE_REPORT_ID, - packet_buffer+PACKET_OFFSET, - sizeof(ds3_control_packet)-PACKET_OFFSET); -#else - HID_SEND_CONTROL(instance->handle, - packet_buffer+PACKET_OFFSET, - sizeof(ds3_control_packet)-PACKET_OFFSET); -#endif /* WIIU */ - return result; -} - -static void *ds3_init(void *handle) -{ - int errors = 0; - ds3_instance_t *instance = (ds3_instance_t *) - malloc(sizeof(ds3_instance_t)); - if (!instance) - return NULL; - - memset(instance, 0, sizeof(ds3_instance_t)); - instance->handle = handle; - - /* Setting protocol */ - - /* this might fail, but we don't care. */ - set_protocol(instance, 1); - - /* Sending control packet.. */ - if (ds3_send_control_packet(instance) < 0) - errors++; - - /* Sending activation packet.. */ - if (ds3_send_activation_packet(instance) < 0) - errors++; - - if (errors) - goto error; - - instance->pad = hid_pad_register(instance, &ds3_pad_connection); - if (!instance->pad) - goto error; - - return instance; - -error: - if (instance) - free(instance); - return NULL; -} - -static void ds3_free(void *data) -{ - ds3_instance_t *instance = (ds3_instance_t *)data; - - if (!instance) - return; - - hid_pad_deregister(instance->pad); - free(instance); -} - -static void ds3_handle_packet(void *data, uint8_t *packet, size_t size) -{ - ds3_instance_t *instance = (ds3_instance_t *)data; - - if (!instance || !instance->pad) - return; - - instance->pad->iface->packet_handler(data, packet, size); -} - -static bool ds3_detect(uint16_t vendor_id, uint16_t product_id) -{ - return vendor_id == VID_SONY && product_id == PID_SONY_DS3; -} - -hid_device_t ds3_hid_device = { - ds3_init, - ds3_free, - ds3_handle_packet, - ds3_detect, - "Sony DualShock 3" -}; - -/** - * pad interface implementation - */ - -static void *ds3_pad_init(void *data, uint32_t slot, hid_driver_t *driver) -{ - ds3_instance_t *pad = (ds3_instance_t *)data; - pad->slot = slot; - - return data; -} - -static void ds3_pad_deinit(void *data) -{ - ds3_instance_t *pad = (ds3_instance_t *)data; - if (pad) - input_autoconfigure_disconnect(pad->slot, - ds3_pad_connection.get_name(pad)); -} - -static void ds3_get_buttons(void *data, input_bits_t *state) -{ - ds3_instance_t *pad = (ds3_instance_t *)data; - - if (pad) - { - BITS_COPY16_PTR(state, pad->buttons); - - if (pad->buttons & 0x10000) - BIT256_SET_PTR(state, RARCH_MENU_TOGGLE); - } - else - { - BIT256_CLEAR_ALL_PTR(state); - } -} - -static void ds3_packet_handler(void *data, uint8_t *packet, uint16_t size) -{ - ds3_instance_t *instance = (ds3_instance_t *)data; - - if (instance->pad && !instance->led_set) - { - ds3_send_control_packet(instance); - instance->led_set = true; - } - - if (size > sizeof(ds3_control_packet)) - { - RARCH_ERR("[ds3]: Expecting packet to be %d but was %d\n", - sizeof(ds3_control_packet), size); - return; - } - - memcpy(instance->data, packet, size); - ds3_update_pad_state(instance); - ds3_update_analog_state(instance); -} - -static void ds3_set_rumble(void *data, - enum retro_rumble_effect effect, uint16_t strength) { } - -static int16_t ds3_get_axis(void *data, unsigned axis) -{ - axis_data axis_data; - ds3_instance_t *pad = (ds3_instance_t *)data; - - gamepad_read_axis_data(axis, &axis_data); - - if (!pad || axis_data.axis >= 4) - return 0; - - return gamepad_get_axis_value(pad->analog_state, &axis_data); -} - -static const char *ds3_get_name(void *data) { return "Sony DualShock 3"; } - -static int32_t ds3_button(void *data, uint16_t joykey) -{ - ds3_instance_t *pad = (ds3_instance_t *)data; - if (!pad || joykey > 31) - return 0; - return pad->buttons & (1 << joykey); -} - -pad_connection_interface_t ds3_pad_connection = { - ds3_pad_init, - ds3_pad_deinit, - ds3_packet_handler, - ds3_set_rumble, - ds3_get_buttons, - ds3_get_axis, - ds3_get_name, - ds3_button -}; diff --git a/input/common/hid/device_ds4.c b/input/common/hid/device_ds4.c deleted file mode 100644 index c95fca7f2a..0000000000 --- a/input/common/hid/device_ds4.c +++ /dev/null @@ -1,128 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2014 - Hans-Kristian Arntzen - * 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 "hid_device_driver.h" - -extern pad_connection_interface_t ds4_pad_connection; - -typedef struct ds4_instance -{ - void *handle; - joypad_connection_t *pad; - int slot; - uint32_t buttons; - uint16_t motors[2]; - uint8_t data[64]; -} ds4_instance_t; - -/** - * I'm leaving this code in here for posterity, and because maybe it can - * be used on other platforms. But using the DS4 on the Wii U directly is - * impossible because it doesn't generate a HID event. Which makes me think - * it's not a HID device at all--at least, not over USB. - * - * I imagine it might be useful in Bluetooth mode, though. - */ -static void *ds4_init(void *handle) -{ - ds4_instance_t *instance = (ds4_instance_t *) - malloc(sizeof(ds4_instance_t)); - if (!instance) - return NULL; - - memset(instance, 0, sizeof(ds4_instance_t)); - instance->handle = handle; - instance->pad = hid_pad_register(instance, &ds4_pad_connection); - - if (!instance->pad) - { - free(instance); - return NULL; - } - - return instance; -} - -static void ds4_free(void *data) -{ - ds4_instance_t *instance = (ds4_instance_t *)data; - - if (!instance) - return; - - hid_pad_deregister(instance->pad); - free(instance); -} - -static void ds4_handle_packet(void *data, uint8_t *buffer, size_t size) -{ - ds4_instance_t *instance = (ds4_instance_t *)data; - - if (instance && instance->pad) - instance->pad->iface->packet_handler(instance->pad->data, buffer, size); -} - -static bool ds4_detect(uint16_t vendor_id, uint16_t product_id) -{ - return vendor_id == VID_SONY && product_id == PID_SONY_DS4; -} - -hid_device_t ds4_hid_device = { - ds4_init, - ds4_free, - ds4_handle_packet, - ds4_detect, - "Sony DualShock 4" -}; - -static void *ds4_pad_init(void *data, uint32_t slot, hid_driver_t *driver) -{ - ds4_instance_t *instance = (ds4_instance_t *)data; - - if (!instance) - return NULL; - - instance->slot = slot; - return instance; -} - -static void ds4_packet_handler(void *data, uint8_t *packet, uint16_t size) -{ -#ifdef DEBUG - ds4_instance_t *instance = (ds4_instance_t *)data; - if (!instance) - return; - RARCH_LOG_BUFFER(packet, size); -#endif -} - -static void ds4_set_rumble(void *data, enum retro_rumble_effect effect, uint16_t strength) { } -static int16_t ds4_get_axis(void *data, unsigned axis) { return 0; } -static const char *ds4_get_name(void *data) { return "Sony DualShock 4"; } -static int32_t ds4_button(void *data, uint16_t joykey) { return 0; } -static void ds4_pad_deinit(void *data) { } -static void ds4_get_buttons(void *data, input_bits_t *state) { } - -pad_connection_interface_t ds4_pad_connection = { - ds4_pad_init, - ds4_pad_deinit, - ds4_packet_handler, - ds4_set_rumble, - ds4_get_buttons, - ds4_get_axis, - ds4_get_name, - ds4_button -}; diff --git a/input/common/hid/device_null.c b/input/common/hid/device_null.c deleted file mode 100644 index e335a376c6..0000000000 --- a/input/common/hid/device_null.c +++ /dev/null @@ -1,199 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2014 - Hans-Kristian Arntzen - * 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 "hid_device_driver.h" - -extern pad_connection_interface_t hid_null_pad_connection; - -/* - * This is the instance data structure for the pad you are implementing. - * This is a good starting point, but you can add/remove things as makes - * sense for the pad you're writing for. The pointer to this structure - * will be passed in as a void pointer to the methods you implement below. - */ -typedef struct hid_null_instance -{ - void *handle; /* a handle to the HID subsystem adapter */ - joypad_connection_t *pad; /* a pointer to the joypad connection you assign - in init() */ - int slot; /* which slot does this pad occupy? */ - uint32_t buttons; /* a bitmap of the digital buttons for the pad */ - uint16_t motors[2]; /* rumble strength, if appropriate */ - uint8_t data[64]; /* a buffer large enough to hold the device's - max rx packet */ -} hid_null_instance_t; - -/** - * Use the HID_ macros (see input/include/hid_driver.h) to send data packets - * to the device. When this method returns, the device needs to be in a state - * where we can read data packets from the device. So, if there's any - * activation packets (see the ds3 and Wii U GameCube adapter drivers for - * examples), send them here. - * - * While you *can* allocate the retro pad here, it isn't mandatory (see - * the Wii U GC adapter). - * - * If initialization fails, return NULL. - */ -static void *hid_null_init(void *handle) -{ - hid_null_instance_t *instance = (hid_null_instance_t *)calloc(1, sizeof(hid_null_instance_t)); - if (!instance) - return NULL; - - memset(instance, 0, sizeof(hid_null_instance_t)); - instance->handle = handle; - instance->pad = hid_pad_register(instance, &hid_null_pad_connection); - if (!instance->pad) - { - free(instance); - return NULL; - } - - return instance; -} - -/* - * Gets called when the pad is disconnected. It must clean up any memory - * allocated and used by the instance data. - */ -static void hid_null_free(void *data) -{ - hid_null_instance_t *instance = (hid_null_instance_t *)data; - - if (!instance) - return; - - hid_pad_deregister(instance->pad); - free(instance); -} - -/** - * Handle a single packet from the device. - * For most pads you'd just forward it onto the pad driver (see below). - * A more complicated example is in the Wii U GC adapter driver. - */ -static void hid_null_handle_packet(void *data, uint8_t *buffer, size_t size) -{ - hid_null_instance_t *instance = (hid_null_instance_t *)data; - - if (instance && instance->pad) - instance->pad->iface->packet_handler(instance->pad->data, buffer, size); -} - -/** - * Return true if the passed in VID and PID are supported by the driver. - */ -static bool hid_null_detect(uint16_t vendor_id, uint16_t product_id) -{ - return vendor_id == VID_NONE && product_id == PID_NONE; -} - -/** - * Assign function pointers to the driver structure. - */ -hid_device_t null_hid_device = { - hid_null_init, - hid_null_free, - hid_null_handle_packet, - hid_null_detect, - "Null HID device" -}; - -/** - * This is called via hid_pad_register(). In the common case where the - * device only controls one pad, you can simply return the data parameter. - * But if you need to track multiple pads attached to the same HID device - * (see: Wii U GC adapter), you can allocate that memory here. - */ -static void *hid_null_pad_init(void *data, uint32_t slot, hid_driver_t *driver) -{ - hid_null_instance_t *instance = (hid_null_instance_t *)data; - - if (!instance) - return NULL; - - instance->slot = slot; - return instance; -} - -/** - * If you allocate any memory in hid_null_pad_init() above, de-allocate it here. - */ -static void hid_null_pad_deinit(void *data) { } - -/** - * Translate the button data from the pad into the input_bits_t format - * that RetroArch can use. - */ -static void hid_null_get_buttons(void *data, input_bits_t *state) { } - -/** - * Handle a single packet for the pad. - */ -static void hid_null_packet_handler(void *data, uint8_t *packet, uint16_t size) -{ -#ifdef DEBUG - hid_null_instance_t *instance = (hid_null_instance_t *)data; - if (!instance) - return; - RARCH_LOG_BUFFER(packet, size); -#endif -} - -/** - * If the pad doesn't support rumble, then this can just be a no-op. - */ -static void hid_null_set_rumble(void *data, enum retro_rumble_effect effect, uint16_t strength) { } - -/** - * Read analog sticks. - * If the pad doesn't have any analog axis, just return 0 here. - * - * The return value must conform to the following characteristics: - * - (0, 0) is center - * - (-32768,-32768) is top-left - * - (32767,32767) is bottom-right - */ -static int16_t hid_null_get_axis(void *data, unsigned axis) { return 0; } - -/** - * The name the pad will show up as in the UI, also used to auto-assign - * buttons in input/input_autodetect_builtin.c - */ -static const char *hid_null_get_name(void *data) -{ - return "Null HID Pad"; -} - -/** - * Read the state of a single button. - */ -static int32_t hid_null_button(void *data, uint16_t joykey) { return 0; } - -/** - * Fill in the joypad interface - */ -pad_connection_interface_t hid_null_pad_connection = { - hid_null_pad_init, - hid_null_pad_deinit, - hid_null_packet_handler, - hid_null_set_rumble, - hid_null_get_buttons, - hid_null_get_axis, - hid_null_get_name, - hid_null_button -}; diff --git a/input/common/hid/device_wiiu_gca.c b/input/common/hid/device_wiiu_gca.c deleted file mode 100644 index 01e1eccee7..0000000000 --- a/input/common/hid/device_wiiu_gca.c +++ /dev/null @@ -1,345 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2014 - Hans-Kristian Arntzen - * 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 "hid_device_driver.h" - -#ifdef WII -static uint8_t activation_packet[] = { 0x01, 0x13 }; -#else -static uint8_t activation_packet[] = { 0x13 }; -#endif - -#define GCA_PORT_INITIALIZING 0x00 -#define GCA_PORT_POWERED 0x04 -#define GCA_PORT_CONNECTED 0x10 -#define GCA_WAVEBIRD_CONNECTED 0x22 - -typedef struct hid_wiiu_gca_instance -{ - void *handle; - bool online; - uint8_t device_state[37]; - joypad_connection_t *pads[4]; -} hid_wiiu_gca_instance_t; - -typedef struct gca_pad_data -{ - void *gca_handle; /* instance handle for the GCA adapter */ - hid_driver_t *driver; /* HID system driver interface */ - uint8_t data[9]; /* pad data */ - uint32_t slot; /* slot this pad occupies */ - uint32_t buttons; /* digital button state */ - int16_t analog_state[3][2]; /* analog state */ -} gca_pad_t; - -extern pad_connection_interface_t wiiu_gca_pad_connection; - -static void wiiu_gca_unregister_pad(hid_wiiu_gca_instance_t *instance, int slot) -{ - joypad_connection_t *pad = NULL; - if (!instance || slot < 0 || slot >= 4 || !instance->pads[slot]) - return; - - pad = instance->pads[slot]; - instance->pads[slot] = NULL; - - hid_pad_deregister(pad); -} - -static void wiiu_gca_update_pad_state(hid_wiiu_gca_instance_t *instance) -{ - int i, port; - unsigned char port_connected; - joypad_connection_t *pad; - - if (!instance || !instance->online) - return; - - /* process each pad */ - for (i = 1; i < 37; i += 9) - { - port = i / 9; - pad = instance->pads[port]; - port_connected = instance->device_state[i]; - - if (port_connected > GCA_PORT_POWERED) - { - if (!pad) - { - RARCH_LOG("[gca]: Gamepad at port %d connected.\n", port+1); - instance->pads[port] = hid_pad_register( - instance, &wiiu_gca_pad_connection); - pad = instance->pads[port]; - if (!pad) - { - RARCH_ERR("[gca]: Failed to register pad.\n"); - break; - } - } - - pad->iface->packet_handler(pad->data, &instance->device_state[i], 9); - } - else - { - if (pad) - { - RARCH_LOG("[gca]: Gamepad at port %d disconnected.\n", port+1); - wiiu_gca_unregister_pad(instance, port); - } - } - } -} - -static void *wiiu_gca_init(void *handle) -{ - unsigned i; - hid_wiiu_gca_instance_t *instance = (hid_wiiu_gca_instance_t*) - malloc(sizeof(hid_wiiu_gca_instance_t)); - - if (!instance) - return NULL; - - instance->handle = handle; - instance->online = true; - - for (i = 0; i < 37; i++) - instance->device_state[i] = 0; - for (i = 0; i < 4; i++) - instance->pads[i] = NULL; - - hid_instance.os_driver->send_control(handle, activation_packet, sizeof(activation_packet)); - hid_instance.os_driver->read(handle, instance->device_state, sizeof(instance->device_state)); - - return instance; -} - -static void wiiu_gca_free(void *data) -{ - int i; - hid_wiiu_gca_instance_t *instance = (hid_wiiu_gca_instance_t *)data; - - if (!instance) - return; - - instance->online = false; - - for (i = 0; i < 4; i++) - wiiu_gca_unregister_pad(instance, i); - - free(instance); -} - -static void wiiu_gca_handle_packet(void *data, uint8_t *buffer, size_t size) -{ - hid_wiiu_gca_instance_t *instance = (hid_wiiu_gca_instance_t *)data; - if (!instance || !instance->online) - return; - - if (size > sizeof(instance->device_state)) - { - RARCH_WARN("[gca]: packet size %d is too big for buffer of size %d\n", - size, sizeof(instance->device_state)); - return; - } - - memcpy(instance->device_state, buffer, size); - wiiu_gca_update_pad_state(instance); -} - -static bool wiiu_gca_detect(uint16_t vendor_id, uint16_t product_id) -{ - return vendor_id == VID_NINTENDO && product_id == PID_NINTENDO_GCA; -} - -hid_device_t wiiu_gca_hid_device = { - wiiu_gca_init, - wiiu_gca_free, - wiiu_gca_handle_packet, - wiiu_gca_detect, - "Wii U Gamecube Adapter" -}; - -/** - * Pad connection interface implementation. This handles each individual - * GC controller (as opposed to the above that handles the GCA itself). - */ - -static void *wiiu_gca_pad_init(void *data, uint32_t slot, hid_driver_t *driver) -{ - gca_pad_t *pad = (gca_pad_t *)malloc(sizeof(gca_pad_t)); - - if (!pad) - return NULL; - - memset(pad, 0, sizeof(gca_pad_t)); - - pad->gca_handle = data; - pad->driver = driver; - pad->slot = slot; - - return pad; -} - -static void wiiu_gca_pad_deinit(void *data) -{ - gca_pad_t *pad = (gca_pad_t *)data; - - if (!pad) - return; - - input_autoconfigure_disconnect(pad->slot, - wiiu_gca_pad_connection.get_name(pad)); - free(pad); -} - -static void wiiu_gca_get_buttons(void *data, input_bits_t *state) -{ - gca_pad_t *pad = (gca_pad_t *)data; - if (pad) - { - BITS_COPY16_PTR(state, pad->buttons); - } - else - { - BIT256_CLEAR_ALL_PTR(state); - } -} - -static void update_buttons(gca_pad_t *pad) -{ - uint32_t i, pressed_keys; - - static const uint32_t button_mapping[12] = - { - RETRO_DEVICE_ID_JOYPAD_A, - RETRO_DEVICE_ID_JOYPAD_B, - RETRO_DEVICE_ID_JOYPAD_X, - RETRO_DEVICE_ID_JOYPAD_Y, - RETRO_DEVICE_ID_JOYPAD_LEFT, - RETRO_DEVICE_ID_JOYPAD_RIGHT, - RETRO_DEVICE_ID_JOYPAD_DOWN, - RETRO_DEVICE_ID_JOYPAD_UP, - RETRO_DEVICE_ID_JOYPAD_START, - RETRO_DEVICE_ID_JOYPAD_SELECT, - RETRO_DEVICE_ID_JOYPAD_R, - RETRO_DEVICE_ID_JOYPAD_L, - }; - - if (!pad) - return; - - pressed_keys = pad->data[1] | (pad->data[2] << 8); - pad->buttons = 0; - - for (i = 0; i < 12; i++) - pad->buttons |= (pressed_keys & (1 << i)) ? - (1 << button_mapping[i]) : 0; -} - -static void wiiu_gca_update_analog_state(gca_pad_t *pad) -{ - int pad_axis; - int16_t interpolated; - unsigned stick, axis; - - /* GameCube analog axis are 8-bit unsigned, where 128/128 is center. - * So, we subtract 128 to get a signed, 0-based value and then mulitply - * by 256 to get the 16-bit range RetroArch expects. */ - for (pad_axis = 0; pad_axis < 4; pad_axis++) - { - axis = (pad_axis % 2) ? 0 : 1; - stick = pad_axis / 2; - interpolated = pad->data[3 + pad_axis]; - /* libretro requires "up" to be negative, so we invert the y axis */ - interpolated = (axis) ? - ((interpolated - 128) * 256) : - ((interpolated - 128) * -256); - - pad->analog_state[stick][axis] = interpolated; -#if 0 - RARCH_LOG("%s: %d\n", axes[pad_axis], interpolated); -#endif - } -} - -/** - * The USB packet provides a 9-byte data packet for each pad. - * - * byte 0: connection status (0x14 = connected, 0x04 = disconnected) - * bytes 1-2: digital buttons - * bytes 3-4: left analog stick x/y - * bytes 5-6: right analog stick x/y - * bytes 7-8: L/R analog state (note that these have digital buttons too) - */ -static void wiiu_gca_packet_handler(void *data, uint8_t *packet, uint16_t size) -{ - gca_pad_t *pad = (gca_pad_t *)data; - - if (!pad || !packet || size > sizeof(pad->data)) - return; - - memcpy(pad->data, packet, size); - update_buttons(pad); - wiiu_gca_update_analog_state(pad); -} - -static void wiiu_gca_set_rumble(void *data, enum retro_rumble_effect effect, uint16_t strength) { } - -static int16_t wiiu_gca_get_axis(void *data, unsigned axis) -{ - axis_data axis_data; - - gca_pad_t *pad = (gca_pad_t *)data; - - gamepad_read_axis_data(axis, &axis_data); - - if (!pad || axis_data.axis >= 4) - return 0; - - return gamepad_get_axis_value(pad->analog_state, &axis_data); -} - -static const char *wiiu_gca_get_name(void *data) -{ - return "GameCube Controller"; -} - -/** - * Button bitmask values: - * 0x0001 - A 0x0010 - left 0x0100 - Start/Pause - * 0x0002 - B 0x0020 - right 0x0200 - Z - * 0x0004 - X 0x0040 - down 0x0400 - R - * 0x0008 - Y 0x0080 - up 0x0800 - L - */ - -static int32_t wiiu_gca_button(void *data, uint16_t joykey) -{ - gca_pad_t *pad = (gca_pad_t *)data; - if(!pad || joykey > 31) - return 0; - return pad->buttons & (1 << joykey); -} - -pad_connection_interface_t wiiu_gca_pad_connection = { - wiiu_gca_pad_init, - wiiu_gca_pad_deinit, - wiiu_gca_packet_handler, - wiiu_gca_set_rumble, - wiiu_gca_get_buttons, - wiiu_gca_get_axis, - wiiu_gca_get_name, - wiiu_gca_button -}; diff --git a/input/common/hid/hid_device_driver.c b/input/common/hid/hid_device_driver.c deleted file mode 100644 index d9d8bb8d98..0000000000 --- a/input/common/hid/hid_device_driver.c +++ /dev/null @@ -1,159 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2014 - Hans-Kristian Arntzen - * 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 "hid_device_driver.h" - -hid_driver_instance_t hid_instance = {0}; - -hid_device_t *hid_device_list[] = -{ - &wiiu_gca_hid_device, - &ds3_hid_device, -#if 0 - &ds4_hid_device, -#endif - NULL /* must be last entry in list */ -}; - -hid_device_t *hid_device_driver_lookup( - uint16_t vendor_id, uint16_t product_id) -{ - int i = 0; - - for (i = 0; hid_device_list[i] != NULL; i++) - { - if (hid_device_list[i]->detect(vendor_id, product_id)) - return hid_device_list[i]; - } - - return NULL; -} - -joypad_connection_t *hid_pad_register( - void *pad_handle, pad_connection_interface_t *iface) -{ - int slot; - joypad_connection_t *result; - - if (!pad_handle) - return NULL; - - slot = pad_connection_find_vacant_pad(hid_instance.pad_list); - - if (slot < 0) - { - RARCH_ERR("[hid]: failed to find a vacant pad.\n"); - return NULL; - } - - result = &(hid_instance.pad_list[slot]); - result->iface = iface; - result->data = iface->init(pad_handle, slot, hid_instance.os_driver); - result->connected = true; - input_pad_connect(slot, hid_instance.pad_driver); - - return result; -} - -void hid_pad_deregister(joypad_connection_t *pad) -{ - if (!pad) - return; - - if (pad->data) - { - pad->iface->deinit(pad->data); - pad->data = NULL; - } - - pad->iface = NULL; - pad->connected = false; -} - -static bool init_pad_list(hid_driver_instance_t *instance, unsigned slots) -{ - if (!instance || slots > MAX_USERS) - return false; - - if (instance->pad_list) - return true; - - /* Initializing pad list.. */ - instance->pad_list = pad_connection_init(slots); - if (!instance->pad_list) - return false; - - instance->max_slot = slots; - - return true; -} - -/** - * Fill in instance with data from initialized hid subsystem. - * - * @argument instance the hid_driver_instance_t struct to fill in - * @argument hid_driver the HID driver to initialize - * @argument pad_driver the gamepad driver to handle HID pads - * detected by the HID driver. - * - * @returns true if init is successful, false otherwise. - */ -bool hid_init(hid_driver_instance_t *instance, - hid_driver_t *hid_driver, - input_device_driver_t *pad_driver, - unsigned slots) -{ - void *os_driver_data = NULL; - if (!instance || !hid_driver || !pad_driver || slots > MAX_USERS) - return false; - - /* Initializing HID subsystem driver */ - os_driver_data = hid_driver->init(); - if (!os_driver_data) - return false; - - if (!init_pad_list(instance, slots)) - { - hid_driver->free(os_driver_data); - return false; - } - - instance->os_driver_data = os_driver_data; - instance->os_driver = hid_driver; - instance->pad_driver = pad_driver; - - return true; -} - -/** - * Tear down the HID system set up by hid_init() - * - * @argument instance the hid_driver_instance_t to tear down. - */ -void hid_deinit(hid_driver_instance_t *instance) -{ - if (!instance) - return; - - if (instance->os_driver && instance->os_driver_data) - instance->os_driver->free(instance->os_driver_data); - - /* Destroying pad data.. */ - pad_connection_destroy(instance->pad_list); - - /* Wiping instance data.. */ - memset(instance, 0, sizeof(hid_driver_instance_t)); -} diff --git a/input/common/hid/hid_device_driver.h b/input/common/hid/hid_device_driver.h deleted file mode 100644 index 8e764f0f78..0000000000 --- a/input/common/hid/hid_device_driver.h +++ /dev/null @@ -1,46 +0,0 @@ -/* RetroArch - A frontend for libretro. - * Copyright (C) 2010-2014 - Hans-Kristian Arntzen - * 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 . - */ - -#ifndef HID_DEVICE_DRIVER__H -#define HID_DEVICE_DRIVER__H - -#include "../../input_driver.h" -#include "../../connect/joypad_connection.h" -#include "../../include/hid_driver.h" -#include "../../include/gamepad.h" -#include "../../../verbosity.h" -#include "../../../tasks/tasks_internal.h" - -typedef struct hid_device { - void *(*init)(void *handle); - void (*free)(void *data); - void (*handle_packet)(void *data, uint8_t *buffer, size_t size); - bool (*detect)(uint16_t vid, uint16_t pid); - const char *name; -} hid_device_t; - -extern hid_device_t wiiu_gca_hid_device; -extern hid_device_t ds3_hid_device; -extern hid_device_t ds4_hid_device; -extern hid_driver_instance_t hid_instance; - -hid_device_t *hid_device_driver_lookup(uint16_t vendor_id, uint16_t product_id); -joypad_connection_t *hid_pad_register(void *pad_handle, pad_connection_interface_t *iface); -void hid_pad_deregister(joypad_connection_t *pad); -bool hid_init(hid_driver_instance_t *instance, hid_driver_t *hid_driver, input_device_driver_t *pad_driver, unsigned slots); -void hid_deinit(hid_driver_instance_t *instance); - -#endif /* HID_DEVICE_DRIVER__H */ diff --git a/input/connect/connect_ps3.c b/input/connect/connect_ps3.c index 5ea88264ad..70aa6d3e0f 100644 --- a/input/connect/connect_ps3.c +++ b/input/connect/connect_ps3.c @@ -21,148 +21,205 @@ #include #include "joypad_connection.h" #include "../input_defines.h" -#include "../common/hid/hid_device_driver.h" - -struct hidpad_ps3_data -{ - struct pad_connection* connection; - hid_driver_t *driver; - uint32_t slot; - uint32_t buttons; - uint16_t motors[2]; - uint8_t data[512]; - bool have_led; -}; - -/* - * TODO: give these more meaningful names. - */ +#include "verbosity.h" #define DS3_ACTIVATION_REPORT_ID 0xf4 #define DS3_RUMBLE_REPORT_ID 0x01 -static void hidpad_ps3_send_control(struct hidpad_ps3_data* device) -{ - /* TODO: Can this be modified to turn off motion tracking? */ - static uint8_t report_buffer[] = { - 0x52, 0x01, - 0x00, 0xFF, 0x00, 0xFF, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0xff, 0x27, 0x10, 0x00, 0x32, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; +typedef struct ds3_instance { + hid_driver_t *hid_driver; + void *handle; + int slot; + bool led_set; + uint32_t buttons; + int16_t analog_state[3][2]; + uint16_t motors[2]; + uint8_t data[64]; +} ds3_instance_t; - /* Turn on the appropriate LED */ - report_buffer[11] = 1 << ((device->slot % 4) + 1); - /* Set rumble state */ - report_buffer[4] = device->motors[1] >> 8; - report_buffer[6] = device->motors[0] >> 8; -#ifdef HAVE_WIIUSB_HID - report_buffer[1] = 0x03; /* send control message type */ - device->driver->send_control(device->connection, &report_buffer[1], sizeof(report_buffer)-1); -#elif defined(WIIU) - device->driver->set_report(device->connection, - HID_REPORT_OUTPUT, - DS3_RUMBLE_REPORT_ID, - report_buffer+2, - sizeof(report_buffer) - (2*sizeof(uint8_t))); -#else - device->driver->send_control(device->connection, report_buffer, sizeof(report_buffer)); +static void ds3_update_pad_state(ds3_instance_t *instance); +static void ds3_update_analog_state(ds3_instance_t *instance); + +static uint8_t ds3_activation_packet[] = { +#if defined(IOS) + 0x53, 0xF4, +#elif defined(HAVE_WIIUSB_HID) + 0x02, #endif + 0x42, 0x0c, 0x00, 0x00 +}; + +#if defined(WIIU) +#define PACKET_OFFSET 2 +#elif defined(HAVE_WIIUSB_HID) +#define PACKET_OFFSET 1 +#else +#define PACKET_OFFSET 0 +#endif + +#define LED_OFFSET 11 +#define MOTOR1_OFFSET 4 +#define MOTOR2_OFFSET 6 + +static uint8_t ds3_control_packet[] = { + 0x52, 0x01, + 0x00, 0xff, 0x00, 0xff, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0xff, 0x27, 0x10, 0x00, 0x32, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00 +}; + + +static int32_t ds3_send_control_packet(void *data, uint32_t slot, hid_driver_t *driver) { + int32_t result = 0; + uint8_t packet_buffer[64] = {0}; + memcpy(packet_buffer, ds3_control_packet, sizeof(ds3_control_packet)); + + packet_buffer[LED_OFFSET] = 0; + packet_buffer[LED_OFFSET] = 1 << ((slot % 4) + 1); + packet_buffer[MOTOR1_OFFSET] = 0; + packet_buffer[MOTOR2_OFFSET] = 0; + +#if defined(HAVE_WIIUSB_HID) + packet_buffer[1] = 0x03; +#endif + +#if defined(WIIU) + result = driver->set_report(data, HID_REPORT_OUTPUT, DS3_RUMBLE_REPORT_ID, packet_buffer+PACKET_OFFSET, 64-PACKET_OFFSET); +#else + result = driver->send_control(data, packet_buffer+PACKET_OFFSET, 64-PACKET_OFFSET); +#endif /* WIIU */ + return result; } -static void* hidpad_ps3_init(void *data, uint32_t slot, hid_driver_t *driver) +static int32_t ds3_send_activation_packet(void *data, uint32_t slot, hid_driver_t *driver) { + #ifdef WIIU + return driver->set_report(data, HID_REPORT_FEATURE, DS3_ACTIVATION_REPORT_ID, ds3_activation_packet, sizeof(ds3_activation_packet)); + #else + return driver->send_control(data, ds3_activation_packet, sizeof(ds3_activation_packet)); + #endif +} + +static void *ds3_pad_init(void *data, uint32_t slot, hid_driver_t *driver) { -#if defined(HAVE_WIIUSB_HID) || defined(WIIU) - /* Special command to enable Sixaxis, first byte defines the message type */ - static uint8_t magic_data[] = {0x02, 0x42, 0x0c, 0x00, 0x00}; -#elif defined(IOS) - /* Magic packet to start reports. */ - static uint8_t magic_data[] = {0x53, 0xF4, 0x42, 0x03, 0x00, 0x00}; -#endif - struct pad_connection* connection = (struct pad_connection*)data; - struct hidpad_ps3_data* device = (struct hidpad_ps3_data*) - calloc(1, sizeof(struct hidpad_ps3_data)); + ds3_instance_t *instance = (ds3_instance_t *)calloc(1, sizeof(ds3_instance_t)); + int errors = 0; - if (!device) - return NULL; + driver->set_protocol(data, 1); - if (!connection) + if (ds3_send_control_packet(data, slot, driver) < 0) + errors++; + + /* Sending activation packet.. */ + if (ds3_send_activation_packet(data, slot, driver) < 0) + errors++; + + if (errors) + goto error; + + instance->hid_driver = driver; + instance->handle = data; + instance->slot = slot; + instance->led_set = true; + + return instance; + + error: + free(instance); + return NULL; +} + +static void ds3_pad_deinit(void *data) +{ + ds3_instance_t *pad = (ds3_instance_t *)data; + if (pad) + free(pad); +} + +static void ds3_get_buttons(void *data, input_bits_t *state) +{ + ds3_instance_t *pad = (ds3_instance_t *)data; + + if (pad) { - free(device); - return NULL; + BITS_COPY16_PTR(state, pad->buttons); + + if (pad->buttons & 0x10000) + BIT256_SET_PTR(state, RARCH_MENU_TOGGLE); + } + else + { + BIT256_CLEAR_ALL_PTR(state); + } +} + +static void ds3_packet_handler(void *data, uint8_t *packet, uint16_t size) +{ + ds3_instance_t *instance = (ds3_instance_t *)data; + if(!instance) { + return; } - device->connection = connection; - device->slot = slot; - device->driver = driver; + if (!instance->led_set) + { + ds3_send_control_packet(instance->handle, instance->slot, instance->hid_driver); + instance->led_set = true; + } -#if defined(IOS) || defined(HAVE_WIIUSB_HID) - device->driver->send_control(device->connection, magic_data, sizeof(magic_data)); -#endif + if (size > sizeof(instance->data)) + { + RARCH_ERR("[ds3]: Expecting packet to be %d but was %d\n", + sizeof(instance->data), size); + return; + } + RARCH_LOG_BUFFER(packet, size); -#ifdef WIIU - device->driver->set_protocol(device->connection, 1); - hidpad_ps3_send_control(device); - device->driver->set_report(device->connection, - HID_REPORT_FEATURE, - DS3_ACTIVATION_REPORT_ID, - magic_data+1, - (sizeof(magic_data) - sizeof(uint8_t))); -#endif - -#ifndef HAVE_WIIUSB_HID - /* Without this, the digital buttons won't be reported. */ - hidpad_ps3_send_control(device); -#endif - return device; + memcpy(instance->data, packet, size); + ds3_update_pad_state(instance); + ds3_update_analog_state(instance); } -static void hidpad_ps3_deinit(void *data) +const char * ds3_get_name(void *data) { - struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data; - - if (device) - free(device); + (void)data; + /* For now we return a single static name */ + return "PLAYSTATION(R)3 Controller"; } -static void hidpad_ps3_get_buttons(void *data, input_bits_t *state) -{ - struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data; - if ( device ) - { - /* copy 32 bits : needed for PS button? */ - BITS_COPY32_PTR(state, device->buttons); - } - else - BIT256_CLEAR_ALL_PTR(state); -} +static void ds3_set_rumble(void *data, + enum retro_rumble_effect effect, uint16_t strength) { } -static int16_t hidpad_ps3_get_axis(void *data, unsigned axis) +static int16_t ds3_get_axis(void *data, unsigned axis) { - int val; - struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data; + axis_data axis_data; + ds3_instance_t *pad = (ds3_instance_t *)data; - if (!device || axis >= 4) + gamepad_read_axis_data(axis, &axis_data); + + if (!pad || axis_data.axis >= 4) return 0; - val = device->data[7 + axis]; - val = (val << 8) - 0x8000; - - if (abs(val) > 0x1000) - return val; - return 0; + return gamepad_get_axis_value(pad->analog_state, &axis_data); } -static void hidpad_ps3_packet_handler(void *data, - uint8_t *packet, uint16_t size) +static int32_t ds3_button(void *data, uint16_t joykey) +{ + ds3_instance_t *pad = (ds3_instance_t *)data; + if (!pad || joykey > 31) + return 0; + return pad->buttons & (1 << joykey); +} + +static void ds3_update_pad_state(ds3_instance_t *instance) { uint32_t i, pressed_keys; + static const uint32_t button_mapping[17] = { RETRO_DEVICE_ID_JOYPAD_SELECT, @@ -181,59 +238,42 @@ static void hidpad_ps3_packet_handler(void *data, RETRO_DEVICE_ID_JOYPAD_A, RETRO_DEVICE_ID_JOYPAD_B, RETRO_DEVICE_ID_JOYPAD_Y, - 16 /* PS Button */ + 16 /* PS button */ }; - struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data; - if (!device) - return; + instance->buttons = 0; - if (!device->have_led) + pressed_keys = instance->data[2] | + (instance->data[3] << 8) | + ((instance->data[4] & 0x01) << 16); + + for (i = 0; i < 17; i++) + instance->buttons |= (pressed_keys & (1 << i)) ? + (1 << button_mapping[i]) : 0; +} + +static void ds3_update_analog_state(ds3_instance_t *instance) +{ + int pad_axis; + int16_t interpolated; + unsigned stick, axis; + + for (pad_axis = 0; pad_axis < 4; pad_axis++) { - hidpad_ps3_send_control(device); - device->have_led = true; + axis = pad_axis % 2 ? 0 : 1; + stick = pad_axis / 2; + interpolated = instance->data[6+pad_axis]; + instance->analog_state[stick][axis] = (interpolated - 128) * 256; } - - memcpy(device->data, packet, size); - - device->buttons = 0; - - pressed_keys = device->data[3] | (device->data[4] << 8) | - ((device->data[5] & 1) << 16); - - for (i = 0; i < 17; i ++) - device->buttons |= (pressed_keys & (1 << i)) ? - (1 << button_mapping[i]) : 0; -} - -static void hidpad_ps3_set_rumble(void *data, - enum retro_rumble_effect effect, uint16_t strength) -{ - struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data; - unsigned idx = (effect == RETRO_RUMBLE_STRONG) ? 0 : 1; - - if (!device) - return; - if (device->motors[idx] == strength) - return; - - device->motors[idx] = strength; - hidpad_ps3_send_control(device); -} - -const char * hidpad_ps3_get_name(void *data) -{ - (void)data; - /* For now we return a single static name */ - return "PLAYSTATION(R)3 Controller"; } pad_connection_interface_t pad_connection_ps3 = { - hidpad_ps3_init, - hidpad_ps3_deinit, - hidpad_ps3_packet_handler, - hidpad_ps3_set_rumble, - hidpad_ps3_get_buttons, - hidpad_ps3_get_axis, - hidpad_ps3_get_name, -}; + ds3_pad_init, + ds3_pad_deinit, + ds3_packet_handler, + ds3_set_rumble, + ds3_get_buttons, + ds3_get_axis, + ds3_get_name, + ds3_button +}; \ No newline at end of file diff --git a/input/connect/connect_ps4.c b/input/connect/connect_ps4.c index 5f9ae933b6..31ccfe3f64 100644 --- a/input/connect/connect_ps4.c +++ b/input/connect/connect_ps4.c @@ -26,7 +26,6 @@ #include "joypad_connection.h" #include "../input_defines.h" #include "../../driver.h" -#include "../common/hid/hid_device_driver.h" enum connect_ps4_dpad_states { diff --git a/input/connect/connect_wii.c b/input/connect/connect_wii.c index 974e9c61ad..7807be18d0 100644 --- a/input/connect/connect_wii.c +++ b/input/connect/connect_wii.c @@ -26,7 +26,6 @@ #include "joypad_connection.h" #include "../input_defines.h" -#include "../common/hid/hid_device_driver.h" /* wiimote state flags*/ #define WIIMOTE_STATE_DEV_FOUND 0x0001 diff --git a/input/connect/connect_wiiugca.c b/input/connect/connect_wiiugca.c index 012d29e6d0..08421437ff 100644 --- a/input/connect/connect_wiiugca.c +++ b/input/connect/connect_wiiugca.c @@ -21,7 +21,6 @@ #include #include "joypad_connection.h" #include "../input_defines.h" -#include "../common/hid/hid_device_driver.h" struct hidpad_wiiugca_data { diff --git a/input/connect/connect_wiiupro.c b/input/connect/connect_wiiupro.c index 01e20252c5..a6b1f11ff5 100644 --- a/input/connect/connect_wiiupro.c +++ b/input/connect/connect_wiiupro.c @@ -23,7 +23,6 @@ #include "joypad_connection.h" #include "../input_defines.h" #include "../../driver.h" -#include "../common/hid/hid_device_driver.h" struct wiiupro_buttons { diff --git a/input/connect/joypad_connection.c b/input/connect/joypad_connection.c index 6174c7f45b..4887f3c921 100644 --- a/input/connect/joypad_connection.c +++ b/input/connect/joypad_connection.c @@ -183,7 +183,8 @@ int32_t pad_connection_pad_init(joypad_connection_t *joyconn, if (name_match || (pad_map[i].vid == vid && pad_map[i].pid == pid)) { - RARCH_DBG("Pad was matched to \"%s\". Setting up an interface.\n", name_match); + RARCH_LOG("Pad was matched to \"%s\". Setting up an interface.\n", name_match); + // RARCH_DBG("Pad was matched to \"%s\". Setting up an interface.\n", name_match); s->iface = pad_map[i].iface; s->data = data; s->connection = s->iface->init(data, pad, driver); @@ -205,7 +206,8 @@ int32_t pad_connection_pad_init(joypad_connection_t *joyconn, * set up one without an interface */ if (!s->connected) { - RARCH_DBG("Pad was not matched. Setting up without an interface.\n"); + RARCH_LOG("Pad was not matched. Setting up without an interface.\n"); + // RARCH_DBG("Pad was not matched. Setting up without an interface.\n"); s->iface = NULL; s->data = data; s->connected = true; diff --git a/input/drivers_hid/wiiu_hid.c b/input/drivers_hid/wiiu_hid.c index 87a8f175af..ae94ee7214 100644 --- a/input/drivers_hid/wiiu_hid.c +++ b/input/drivers_hid/wiiu_hid.c @@ -31,17 +31,21 @@ static bool wiiu_hid_joypad_query(void *data, unsigned slot) if (!hid) return false; - return slot < HID_MAX_SLOT(); + return slot < joypad_state.max_slot; } static joypad_connection_t *get_pad(wiiu_hid_t *hid, unsigned slot) { joypad_connection_t *result; - if (!wiiu_hid_joypad_query(hid, slot)) + if (!wiiu_hid_joypad_query(hid, slot)) { + RARCH_LOG("wiiu_hid: get_pad: invalid slot: %d", slot); return NULL; - result = HID_PAD_CONNECTION_PTR(slot); - if (!result || !result->connected || !result->iface || !result->data) + } + result = &joypad_state.pads[slot]; + if (!result->connected || !result->iface || !result->connection) { + RARCH_LOG("Pad not ready (connected: %d, iface: %08lx, connection: %08lx)\n", result->connected, (unsigned long)result->iface, (unsigned long)result->connection); return NULL; + } return result; } @@ -49,27 +53,27 @@ static const char *wiiu_hid_joypad_name(void *data, unsigned slot) { joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot); - if (!pad) + if (!pad || !pad->iface->get_name) return NULL; - return pad->iface->get_name(pad->data); + return pad->iface->get_name(pad->connection); } static void wiiu_hid_joypad_get_buttons(void *data, unsigned slot, input_bits_t *state) { joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot); - if (pad) - pad->iface->get_buttons(pad->data, state); + if (pad && pad->iface->get_buttons) + pad->iface->get_buttons(pad->connection, state); } static int16_t wiiu_hid_joypad_button(void *data, unsigned slot, uint16_t joykey) { joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot); - if (!pad) + if (!pad || !pad->iface->button) return 0; - return pad->iface->button(pad->data, joykey); + return pad->iface->button(pad->connection, joykey); } static int16_t wiiu_hid_joypad_axis(void *data, unsigned slot, uint32_t joyaxis) @@ -79,7 +83,7 @@ static int16_t wiiu_hid_joypad_axis(void *data, unsigned slot, uint32_t joyaxis) if (!pad) return 0; - return pad->iface->get_axis(pad->data, joyaxis); + return pad->iface->get_axis(pad->connection, joyaxis); } static int16_t wiiu_hid_joypad_state( @@ -106,10 +110,10 @@ static int16_t wiiu_hid_joypad_state( ? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis; if ( (uint16_t)joykey != NO_BTN - && pad->iface->button(pad->data, (uint16_t)joykey)) + && pad->iface->button && pad->iface->button(pad->connection, (uint16_t)joykey)) ret |= ( 1 << i); - else if (joyaxis != AXIS_NONE && - ((float)abs(pad->iface->get_axis(pad->data, joyaxis)) + else if (joyaxis != AXIS_NONE && pad->iface->get_axis && + ((float)abs(pad->iface->get_axis(pad->connection, joyaxis)) / 0x8000) > joypad_info->axis_threshold) ret |= (1 << i); } @@ -122,10 +126,10 @@ static bool wiiu_hid_joypad_rumble(void *data, unsigned slot, { joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot); - if (!pad) + if (!pad || !pad->iface->set_rumble) return false; - pad->iface->set_rumble(pad->data, effect, strength); + pad->iface->set_rumble(pad->connection, effect, strength); return false; } @@ -366,9 +370,17 @@ static void log_device(HIDDevice *device) static uint8_t try_init_driver(wiiu_adapter_t *adapter) { - int32_t pad = pad_connection_pad_init(HID_PAD_CONNECTION_PTR(0), &adapter->device_name[0], adapter->vendor_id, adapter->product_id, adapter, &wiiu_hid); - - return (pad >= 0) ? ADAPTER_STATE_READY : ADAPTER_STATE_DONE; + RARCH_LOG("Trying to find pad driver for vid 0x%04x pid 0x%04x\n", adapter->vendor_id, adapter->product_id); + int32_t pad = pad_connection_pad_init(joypad_state.pads, &adapter->device_name[0], adapter->vendor_id, adapter->product_id, adapter, &wiiu_hid); + if(pad >= 0) { + RARCH_LOG("Attached to pad %d\n", pad); + joypad_state.pad_drivers[pad] = &hidpad_driver; + adapter->pad = pad; + input_pad_connect(pad, &hidpad_driver); + return ADAPTER_STATE_READY; + } + RARCH_LOG("Failed to find pad driver\n"); + return ADAPTER_STATE_DONE; } static void synchronized_process_adapters(wiiu_hid_t *hid) @@ -381,35 +393,41 @@ static void synchronized_process_adapters(wiiu_hid_t *hid) for (adapter = adapters.list; adapter != NULL; adapter = adapter_next) { - adapter_next = adapter->next; + adapter_next = adapter->next; - switch(adapter->state) - { - case ADAPTER_STATE_NEW: - adapter->state = try_init_driver(adapter); - break; - case ADAPTER_STATE_READY: - case ADAPTER_STATE_READING: - case ADAPTER_STATE_DONE: - break; - case ADAPTER_STATE_GC: - /* remove from the list */ - if (!prev) - adapters.list = adapter->next; - else - prev->next = adapter->next; + switch(adapter->state) + { + case ADAPTER_STATE_NEW: + adapter->state = try_init_driver(adapter); + break; + case ADAPTER_STATE_READY: + case ADAPTER_STATE_READING: + case ADAPTER_STATE_DONE: + break; + case ADAPTER_STATE_GC: + { + const char *pad_name = joypad_state.pads[adapter->pad].iface->get_name(joypad_state.pads[adapter->pad].connection); + /* remove from the list */ + if (!prev) + adapters.list = adapter->next; + else + prev->next = adapter->next; + + input_autoconfigure_disconnect(adapter->pad, pad_name); + pad_connection_pad_deinit(&joypad_state.pads[adapter->pad], adapter->pad); + /* adapter is no longer valid after this point */ + delete_adapter(adapter); + /* signal not to update prev ptr since adapter is now invalid */ + keep_prev = true; + } + break; - /* adapter is no longer valid after this point */ - delete_adapter(adapter); - /* signal not to update prev ptr since adapter is now invalid */ - keep_prev = true; - break; - default: - RARCH_ERR("[hid]: Invalid adapter state: %d\n", adapter->state); - break; - } - prev = keep_prev ? prev : adapter; - keep_prev = false; + default: + RARCH_ERR("[hid]: Invalid adapter state: %d\n", adapter->state); + break; + } + prev = keep_prev ? prev : adapter; + keep_prev = false; } OSFastMutex_Unlock(&(adapters.lock)); } @@ -536,8 +554,9 @@ static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error, if (error == 0) { - adapter->driver->handle_packet(adapter->driver_handle, - buffer, buffer_size); + joypad_state.pads[adapter->pad].iface->packet_handler( + joypad_state.pads[adapter->pad].connection, buffer, buffer_size + ); } } } @@ -549,7 +568,8 @@ static void report_hid_error(const char *msg, wiiu_adapter_t *adapter, int32_t e int16_t hid_error_code = error & 0xffff; int16_t error_category = (error >> 16) & 0xffff; - const char *device = (adapter && adapter->driver) ? adapter->driver->name : "unknown"; + const char *device = (adapter && adapter->pad >= 0) ? + joypad_state.pads[adapter->pad].iface->get_name(joypad_state.pads[adapter->pad].connection) : "unknown"; switch(hid_error_code) { @@ -684,8 +704,10 @@ static void wiiu_poll_adapters(wiiu_hid_t *hid) if (it->state == ADAPTER_STATE_READY) wiiu_poll_adapter(it); - if (it->state == ADAPTER_STATE_DONE) + if (it->state == ADAPTER_STATE_DONE) { + it->state = ADAPTER_STATE_GC; + } } OSFastMutex_Unlock(&(adapters.lock)); @@ -796,31 +818,17 @@ static void delete_adapter(wiiu_adapter_t *adapter) free(adapter->tx_buffer); adapter->tx_buffer = NULL; } - if (adapter->driver && adapter->driver_handle) { - adapter->driver->free(adapter->driver_handle); - adapter->driver_handle = NULL; - adapter->driver = NULL; - } + if(adapter->pad >= 0 && + joypad_state.pads[adapter->pad].iface && + joypad_state.pads[adapter->pad].connection) { + joypad_state.pads[adapter->pad].iface->deinit(joypad_state.pads[adapter->pad].connection); + joypad_state.pads[adapter->pad].connection = NULL; + joypad_state.pads[adapter->pad].iface = NULL; + } free(adapter); } -static void get_descriptor_string_ascii(wiiu_adapter_t *adapter, uint8_t *buffer, size_t buffer_size) { - int32_t result = HIDGetDescriptor(adapter->handle, 3, 2, 0, adapter->rx_buffer, adapter->rx_size, NULL, NULL); - memset(buffer, 0, buffer_size); - uint8_t *top; - if(result > 0) { - top = buffer; - for(int i = 2; i < result; i += 2) { - top[0] = adapter->rx_buffer[i]; - top++; - } - } else { - RARCH_ERR("Failed to read descriptor string (0x%08x). Will attempt match by VID/PID\n", result); - } -} - - static void get_device_name(HIDDevice *device, wiiu_attach_event *event) { int32_t result; diff --git a/input/drivers_joypad/wiiu/hidpad_driver.c b/input/drivers_joypad/wiiu/hidpad_driver.c index 48e9f76a8f..9504acc66e 100644 --- a/input/drivers_joypad/wiiu/hidpad_driver.c +++ b/input/drivers_joypad/wiiu/hidpad_driver.c @@ -16,69 +16,28 @@ #include "../../include/wiiu/input.h" -static hidpad_driver_t instance; - -/* TODO/FIXME - static global variables */ -static bool hidpad_ready = false; - -static bool init_pad_list(unsigned slots) -{ - if (slots > MAX_USERS) - return false; - - if (instance.pad_list) - return true; - - instance.pad_list = pad_connection_init(slots); - if (!instance.pad_list) - return false; - - instance.max_slot = slots; - - return true; -} - -static bool init_hid_driver(void) -{ - return init_pad_list(MAX_USERS); -} - static void hidpad_poll(void) { - if (hidpad_ready) + if (joypad_state.hid.ready) wiiu_hid.poll(hid_driver_get_data()); } static void *hidpad_init(void *data) { - if(!init_hid_driver()) - { - RARCH_ERR("Failed to initialize HID driver.\n"); - return NULL; - } - hidpad_poll(); - hidpad_ready = true; + joypad_state.hid.ready = true; return (void*)-1; } static bool hidpad_query_pad(unsigned port) { - return hidpad_ready && port < MAX_USERS; + return joypad_state.hid.ready && port < MAX_USERS; } static void hidpad_destroy(void) { - hidpad_ready = false; - - if(instance.pad_list) { - pad_connection_destroy(instance.pad_list); - instance.pad_list = NULL; - } - - /* Wiping instance data.. */ - memset(&instance, 0, sizeof(instance)); + joypad_state.hid.ready = false; } static int32_t hidpad_button(unsigned port, uint16_t joykey) @@ -126,11 +85,11 @@ static int16_t hidpad_state( ? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis; if ( (uint16_t)joykey != NO_BTN - && HID_BUTTON(port_idx, (uint16_t)joykey) + && wiiu_hid.button(hid_driver_get_data(), port_idx, (uint16_t)joykey) ) ret |= ( 1 << i); else if (joyaxis != AXIS_NONE && - ((float)abs(HID_AXIS(port_idx, joyaxis)) + ((float)abs(wiiu_hid.axis(hid_driver_get_data(), port_idx, joyaxis)) / 0x8000) > joypad_info->axis_threshold) ret |= (1 << i); } diff --git a/input/drivers_joypad/wiiu/kpad_driver.c b/input/drivers_joypad/wiiu/kpad_driver.c index 86e8bec846..2f07f56fa5 100644 --- a/input/drivers_joypad/wiiu/kpad_driver.c +++ b/input/drivers_joypad/wiiu/kpad_driver.c @@ -29,34 +29,12 @@ static void kpad_poll(void); static void kpad_deregister(unsigned channel); -typedef struct _wiimote_state wiimote_state; - -struct _wiimote_state -{ - uint64_t button_state; - int16_t analog_state[3][2]; - uint8_t type; -}; - -/* static global variables */ -static bool kpad_ready = false; -static int channel_slot_map[] = { -1, -1, -1, -1 }; -static int poll_failures[WIIU_WIIMOTE_CHANNELS] = { 0, 0, 0, 0 }; -static wiimote_state -wiimotes[WIIU_WIIMOTE_CHANNELS] = { - { 0, {{0,0},{0,0},{0,0}}, WIIMOTE_TYPE_NONE }, - { 0, {{0,0},{0,0},{0,0}}, WIIMOTE_TYPE_NONE }, - { 0, {{0,0},{0,0},{0,0}}, WIIMOTE_TYPE_NONE }, - { 0, {{0,0},{0,0},{0,0}}, WIIMOTE_TYPE_NONE }, -}; - - static int to_wiimote_channel(unsigned pad) { unsigned i; for (i = 0; i < WIIU_WIIMOTE_CHANNELS; i++) - if (channel_slot_map[i] == pad) + if (joypad_state.kpad.channel_slot_map[i] == pad) return i; return -1; @@ -64,11 +42,11 @@ static int to_wiimote_channel(unsigned pad) static int get_slot_for_channel(unsigned channel) { - int slot = pad_connection_find_vacant_pad(hid_instance.pad_list); + int slot = pad_connection_find_vacant_pad(joypad_state.pads); if (slot >= 0) { - channel_slot_map[channel] = slot; - hid_instance.pad_list[slot].connected = true; + joypad_state.kpad.channel_slot_map[channel] = slot; + joypad_state.pads[slot].connected = true; } return slot; @@ -76,20 +54,26 @@ static int get_slot_for_channel(unsigned channel) static void *kpad_init(void *data) { + memset(&joypad_state.kpad, 0, sizeof(joypad_state.kpad)); + + for(int i = 0; i < WIIU_WIIMOTE_CHANNELS; i++) { + joypad_state.kpad.channel_slot_map[i] = -1; + } + kpad_poll(); - kpad_ready = true; + joypad_state.kpad.ready = true; return (void*)-1; } static bool kpad_query_pad(unsigned pad) { - return kpad_ready && pad < MAX_USERS; + return joypad_state.kpad.ready && pad < MAX_USERS; } static void kpad_destroy(void) { - kpad_ready = false; + joypad_state.kpad.ready = false; } static int32_t kpad_button(unsigned port, uint16_t joykey) @@ -101,7 +85,7 @@ static int32_t kpad_button(unsigned port, uint16_t joykey) channel = to_wiimote_channel(port); if (channel < 0) return 0; - return (wiimotes[channel].button_state + return (joypad_state.kpad.wiimotes[channel].button_state & (UINT64_C(1) << joykey)); } @@ -112,7 +96,7 @@ static void kpad_get_buttons(unsigned port, input_bits_t *state) if (!kpad_query_pad(port) || channel < 0) BIT256_CLEAR_ALL_PTR(state); else - BITS_COPY16_PTR(state, wiimotes[channel].button_state); + BITS_COPY16_PTR(state, joypad_state.kpad.wiimotes[channel].button_state); } static int16_t kpad_axis(unsigned port, uint32_t axis) @@ -125,7 +109,7 @@ static int16_t kpad_axis(unsigned port, uint32_t axis) pad_functions.read_axis_data(axis, &data); return pad_functions.get_axis_value(data.axis, - wiimotes[channel].analog_state, + joypad_state.kpad.wiimotes[channel].analog_state, data.is_negative); } @@ -160,7 +144,7 @@ static int16_t kpad_state( static void kpad_register(unsigned channel, uint8_t device_type) { - if (wiimotes[channel].type != device_type) + if (joypad_state.kpad.wiimotes[channel].type != device_type) { int slot; @@ -173,7 +157,8 @@ static void kpad_register(unsigned channel, uint8_t device_type) return; } - wiimotes[channel].type = device_type; + joypad_state.kpad.wiimotes[channel].type = device_type; + joypad_state.pad_drivers[slot] = &kpad_driver; input_pad_connect(slot, &kpad_driver); } } @@ -184,32 +169,32 @@ static void kpad_poll_one_channel(unsigned channel, KPADData *kpad) switch(kpad->device_type) { case WIIMOTE_TYPE_PRO: - wiimotes[channel].button_state = kpad->classic.btns_h + joypad_state.kpad.wiimotes[channel].button_state = kpad->classic.btns_h & ~WIIU_PRO_BUTTON_MASK; - pad_functions.set_axis_value(wiimotes[channel].analog_state, + pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state, WIIU_READ_STICK(kpad->classic.lstick_x), WIIU_READ_STICK(kpad->classic.lstick_y), WIIU_READ_STICK(kpad->classic.rstick_x), WIIU_READ_STICK(kpad->classic.rstick_y), 0, 0); break; case WIIMOTE_TYPE_CLASSIC: - wiimotes[channel].button_state = kpad->classic.btns_h + joypad_state.kpad.wiimotes[channel].button_state = kpad->classic.btns_h & ~CLASSIC_BUTTON_MASK; - pad_functions.set_axis_value(wiimotes[channel].analog_state, + pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state, WIIU_READ_STICK(kpad->classic.lstick_x), WIIU_READ_STICK(kpad->classic.lstick_y), WIIU_READ_STICK(kpad->classic.rstick_x), WIIU_READ_STICK(kpad->classic.rstick_y), 0, 0); break; case WIIMOTE_TYPE_NUNCHUK: - wiimotes[channel].button_state = kpad->btns_h; - pad_functions.set_axis_value(wiimotes[channel].analog_state, + joypad_state.kpad.wiimotes[channel].button_state = kpad->btns_h; + pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state, WIIU_READ_STICK(kpad->nunchuck.stick_x), WIIU_READ_STICK(kpad->nunchuck.stick_y), 0, 0, 0, 0); break; case WIIMOTE_TYPE_WIIPLUS: - wiimotes[channel].button_state = kpad->btns_h; - pad_functions.set_axis_value(wiimotes[channel].analog_state, + joypad_state.kpad.wiimotes[channel].button_state = kpad->btns_h; + pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state, 0, 0, 0, 0, 0, 0); break; } @@ -217,14 +202,15 @@ static void kpad_poll_one_channel(unsigned channel, KPADData *kpad) static void kpad_deregister(unsigned channel) { - int slot = channel_slot_map[channel]; + int slot = joypad_state.kpad.channel_slot_map[channel]; if (slot >= 0) { input_autoconfigure_disconnect(slot, kpad_driver.name(slot)); - wiimotes[channel].type = WIIMOTE_TYPE_NONE; - hid_instance.pad_list[slot].connected = false; - channel_slot_map[channel] = -1; + joypad_state.kpad.wiimotes[channel].type = WIIMOTE_TYPE_NONE; + joypad_state.pads[slot].connected = false; + + joypad_state.kpad.channel_slot_map[channel] = -1; } } @@ -244,12 +230,12 @@ static void kpad_poll(void) /* pad disconnects properly. */ if (result == 0) { - poll_failures[channel]++; - if (poll_failures[channel] > 5) + joypad_state.kpad.poll_failures[channel]++; + if (joypad_state.kpad.poll_failures[channel] > 5) kpad_deregister(channel); continue; } - poll_failures[channel] = 0; + joypad_state.kpad.poll_failures[channel] = 0; /* Several reads when a device is connected or an attachment added give */ /* bogus results, try to weed them out */ @@ -267,7 +253,7 @@ static const char *kpad_name(unsigned pad) if (channel < 0) return "unknown"; - switch(wiimotes[channel].type) + switch(joypad_state.kpad.wiimotes[channel].type) { case WIIMOTE_TYPE_PRO: return PAD_NAME_WIIU_PRO; @@ -280,7 +266,7 @@ static const char *kpad_name(unsigned pad) case WIIMOTE_TYPE_NONE: default: #ifdef DEBUG - RARCH_LOG("[kpad]: Unknown pad type %d\n", wiimotes[pad].type); + RARCH_LOG("[kpad]: Unknown pad type %d\n", joypad_state.kpad.wiimotes[pad].type); #endif break; } diff --git a/input/drivers_joypad/wiiu/wpad_driver.c b/input/drivers_joypad/wiiu/wpad_driver.c index 7fb4cf4047..8f1b0b316b 100644 --- a/input/drivers_joypad/wiiu/wpad_driver.c +++ b/input/drivers_joypad/wiiu/wpad_driver.c @@ -27,24 +27,13 @@ #define WPAD_INVALID_CHANNEL -1 -typedef struct _drc_state drc_state; -struct _drc_state -{ - uint64_t button_state; - int16_t analog_state[3][2]; -}; - -/* TODO/FIXME - static global variables */ -static drc_state gamepads[WIIU_GAMEPAD_CHANNELS] = { 0 }; -static int channel_slot_map[WIIU_GAMEPAD_CHANNELS] = { WPAD_INVALID_CHANNEL, WPAD_INVALID_CHANNEL }; - static VPADChan to_gamepad_channel(unsigned pad) { unsigned i; for (i = 0; i < WIIU_GAMEPAD_CHANNELS; i++) { - if (channel_slot_map[i] == pad) + if (joypad_state.wpad.channel_slot_map[i] == pad) return i; } @@ -59,23 +48,23 @@ static void wpad_deregister(unsigned channel) return; /* See if Gamepad is already disconnected */ - if (channel_slot_map[channel] == WPAD_INVALID_CHANNEL) + if (joypad_state.wpad.channel_slot_map[channel] == WPAD_INVALID_CHANNEL) return; /* Sanity check, about to use as unsigned */ - if (channel_slot_map[channel] < 0) + if (joypad_state.wpad.channel_slot_map[channel] < 0) { - channel_slot_map[channel] = WPAD_INVALID_CHANNEL; + joypad_state.wpad.channel_slot_map[channel] = WPAD_INVALID_CHANNEL; return; } - slot = (unsigned)channel_slot_map[channel]; + slot = (unsigned)joypad_state.wpad.channel_slot_map[channel]; if (slot >= MAX_USERS) return; input_autoconfigure_disconnect(slot, wpad_driver.ident); - hid_instance.pad_list[slot].connected = false; - channel_slot_map[channel] = WPAD_INVALID_CHANNEL; + joypad_state.pads[slot].connected = false; + joypad_state.wpad.channel_slot_map[channel] = WPAD_INVALID_CHANNEL; } static void wpad_register(unsigned channel) @@ -87,17 +76,18 @@ static void wpad_register(unsigned channel) /* Check if gamepad is already handled Other checks not needed here - about to overwrite - channel_slot_map entry*/ - if (channel_slot_map[channel] != WPAD_INVALID_CHANNEL) + joypad_state.wpad.channel_slot_map entry*/ + if (joypad_state.wpad.channel_slot_map[channel] != WPAD_INVALID_CHANNEL) return; - slot = pad_connection_find_vacant_pad(hid_instance.pad_list); + slot = pad_connection_find_vacant_pad(joypad_state.pads); if(slot < 0) return; - hid_instance.pad_list[slot].connected = true; + joypad_state.pads[slot].connected = true; + joypad_state.pad_drivers[slot] = &wpad_driver; input_pad_connect(slot, &wpad_driver); - channel_slot_map[channel] = slot; + joypad_state.wpad.channel_slot_map[channel] = slot; } static void update_button_state(uint64_t *state, uint32_t held_buttons) @@ -255,9 +245,9 @@ static void wpad_poll(void) if (error == VPAD_READ_SUCCESS) { - update_button_state(&gamepads[channel].button_state, vpad.hold); - update_analog_state(gamepads[channel].analog_state, &vpad); - update_touch_state(gamepads[channel].analog_state, &gamepads[channel].button_state, &vpad, channel); + update_button_state(&joypad_state.wpad.pads[channel].button_state, vpad.hold); + update_analog_state(joypad_state.wpad.pads[channel].analog_state, &vpad); + update_touch_state(joypad_state.wpad.pads[channel].analog_state, &joypad_state.wpad.pads[channel].button_state, &vpad, channel); check_panic_button(vpad.hold); } } @@ -265,6 +255,10 @@ static void wpad_poll(void) static void *wpad_init(void *data) { + memset(&joypad_state.wpad, 0, sizeof(joypad_state.wpad)); + for(int i = 0; i < WIIU_GAMEPAD_CHANNELS; i++) { + joypad_state.wpad.channel_slot_map[i] = WPAD_INVALID_CHANNEL; + } wpad_poll(); return (void*)-1; } @@ -285,7 +279,7 @@ static int32_t wpad_button(unsigned port, uint16_t joykey) channel = to_gamepad_channel(port); if (channel < 0) return 0; - return (gamepads[channel].button_state & (UINT64_C(1) << joykey)); + return (joypad_state.wpad.pads[channel].button_state & (UINT64_C(1) << joykey)); } static void wpad_get_buttons(unsigned port, input_bits_t *state) @@ -305,7 +299,7 @@ static void wpad_get_buttons(unsigned port, input_bits_t *state) return; } - BITS_COPY32_PTR(state, gamepads[channel].button_state); + BITS_COPY32_PTR(state, joypad_state.wpad.pads[channel].button_state); } static int16_t wpad_axis(unsigned port, uint32_t axis) @@ -322,7 +316,7 @@ static int16_t wpad_axis(unsigned port, uint32_t axis) pad_functions.read_axis_data(axis, &data); return pad_functions.get_axis_value(data.axis, - gamepads[channel].analog_state, data.is_negative); + joypad_state.wpad.pads[channel].analog_state, data.is_negative); } static int16_t wpad_state( diff --git a/input/drivers_joypad/wiiu_joypad.c b/input/drivers_joypad/wiiu_joypad.c index 18380a7cee..60c720ac7b 100644 --- a/input/drivers_joypad/wiiu_joypad.c +++ b/input/drivers_joypad/wiiu_joypad.c @@ -16,46 +16,41 @@ #include "../include/wiiu/input.h" -#include "wiiu_dbg.h" -extern pad_connection_listener_t wiiu_pad_connection_listener; -/* TODO/FIXME - static globals */ -static input_device_driver_t *wiiu_pad_drivers[MAX_USERS]; -static bool wiiu_joypad_ready = false; +static bool ready = false; + +wiiu_joypad_t joypad_state = {0}; static void *wiiu_joypad_init(void *data) { - set_connection_listener(&wiiu_pad_connection_listener); + memset(&joypad_state, 0, sizeof(wiiu_joypad_t)); + joypad_state.max_slot = MAX_USERS; + input_hid_init_first(); wpad_driver.init(data); kpad_driver.init(data); -#ifdef WIIU_HID hidpad_driver.init(data); -#endif + ready = true; - wiiu_joypad_ready = true; - - return (void*)-1; + return (void *)-1; } static bool wiiu_joypad_query_pad(unsigned pad) { - return wiiu_joypad_ready && + return ready && pad < MAX_USERS && - wiiu_pad_drivers[pad] && - wiiu_pad_drivers[pad]->query_pad(pad); + joypad_state.pad_drivers[pad] && + joypad_state.pad_drivers[pad]->query_pad(pad); } static void wiiu_joypad_destroy(void) { - wiiu_joypad_ready = false; + ready = false; wpad_driver.destroy(); kpad_driver.destroy(); -#ifdef WIIU_HID hidpad_driver.destroy(); -#endif } static int32_t wiiu_joypad_button(unsigned port, uint16_t joykey) @@ -64,21 +59,21 @@ static int32_t wiiu_joypad_button(unsigned port, uint16_t joykey) return 0; if (port >= DEFAULT_MAX_PADS) return 0; - return (wiiu_pad_drivers[port]->button(port, joykey)); + return (joypad_state.pad_drivers[port]->button(port, joykey)); } static void wiiu_joypad_get_buttons(unsigned port, input_bits_t *state) { if (!wiiu_joypad_query_pad(port)) return; - wiiu_pad_drivers[port]->get_buttons(port, state); + joypad_state.pad_drivers[port]->get_buttons(port, state); } static int16_t wiiu_joypad_axis(unsigned port, uint32_t joyaxis) { if (!wiiu_joypad_query_pad(port)) return 0; - return wiiu_pad_drivers[port]->axis(port, joyaxis); + return joypad_state.pad_drivers[port]->axis(port, joyaxis); } static int16_t wiiu_joypad_state( @@ -104,11 +99,11 @@ static int16_t wiiu_joypad_state( ? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis; if ( (uint16_t)joykey != NO_BTN - && (wiiu_pad_drivers[port]->button(port_idx, (uint16_t)joykey)) + && (joypad_state.pad_drivers[port]->button(port_idx, (uint16_t)joykey)) ) ret |= ( 1 << i); else if (joyaxis != AXIS_NONE && - ((float)abs(wiiu_pad_drivers[port]->axis(port_idx, joyaxis)) + ((float)abs(joypad_state.pad_drivers[port]->axis(port_idx, joyaxis)) / 0x8000) > joypad_info->axis_threshold) ret |= (1 << i); } @@ -120,9 +115,7 @@ static void wiiu_joypad_poll(void) { wpad_driver.poll(); kpad_driver.poll(); -#ifdef WIIU_HID hidpad_driver.poll(); -#endif } static const char* wiiu_joypad_name(unsigned pad) @@ -130,14 +123,7 @@ static const char* wiiu_joypad_name(unsigned pad) if (!wiiu_joypad_query_pad(pad)) return "N/A"; - return wiiu_pad_drivers[pad]->name(pad); -} - -static void wiiu_joypad_connection_listener(unsigned pad, - input_device_driver_t *driver) -{ - if (pad < MAX_USERS) - wiiu_pad_drivers[pad] = driver; + return joypad_state.pad_drivers[pad]->name(pad); } input_device_driver_t wiiu_joypad = @@ -155,8 +141,3 @@ input_device_driver_t wiiu_joypad = wiiu_joypad_name, "wiiu", }; - -pad_connection_listener_t wiiu_pad_connection_listener = -{ - wiiu_joypad_connection_listener -}; diff --git a/input/include/gamepad.h b/input/include/gamepad.h index a3fd5dff1e..802f0b5718 100644 --- a/input/include/gamepad.h +++ b/input/include/gamepad.h @@ -20,11 +20,6 @@ #include "../input_driver.h" -struct pad_connection_listener_interface -{ - void (*connected)(unsigned port, input_device_driver_t *driver); -}; - typedef struct _axis_data { int32_t axis; diff --git a/input/include/wiiu/hid.h b/input/include/wiiu/hid.h index 20aafb3e10..fc8142028c 100644 --- a/input/include/wiiu/hid.h +++ b/input/include/wiiu/hid.h @@ -19,7 +19,6 @@ #include "hid_types.h" #include "input.h" -#include "../../common/hid/hid_device_driver.h" #define DEVICE_UNUSED 0 #define DEVICE_USED 1 @@ -52,8 +51,7 @@ struct wiiu_hid { */ struct wiiu_adapter { wiiu_adapter_t *next; - hid_device_t *driver; - void *driver_handle; + int pad; wiiu_hid_t *hid; uint16_t vendor_id; uint16_t product_id; @@ -64,7 +62,7 @@ struct wiiu_adapter { int32_t tx_size; uint32_t handle; uint8_t interface_index; - uint8_t device_name[32]; + char device_name[32]; bool connected; }; diff --git a/input/include/wiiu/input.h b/input/include/wiiu/input.h index 8126c86e09..6bb20f06ae 100644 --- a/input/include/wiiu/input.h +++ b/input/include/wiiu/input.h @@ -63,14 +63,46 @@ struct _wiiu_pad_functions { void (*connect)(unsigned pad, input_device_driver_t *driver); }; -struct hidpad_driver_t { - input_device_driver_t *pad_driver; - joypad_connection_t *pad_list; - unsigned max_slot; -}; +typedef struct _wiimote_state { + uint64_t button_state; + int16_t analog_state[3][2]; + uint8_t type; +} wiimote_state; -typedef struct hidpad_driver_t hidpad_driver_t; +typedef struct _drc_state +{ + uint64_t button_state; + int16_t analog_state[3][2]; +} drc_state; +typedef struct wiiu_kpad { + bool ready; + int channel_slot_map[WIIU_WIIMOTE_CHANNELS]; + int poll_failures[WIIU_WIIMOTE_CHANNELS]; + wiimote_state wiimotes[WIIU_WIIMOTE_CHANNELS]; +} wiiu_kpad_t; + +typedef struct wiiu_wpad { + drc_state pads[WIIU_GAMEPAD_CHANNELS]; + int channel_slot_map[WIIU_GAMEPAD_CHANNELS]; + bool ready; +} wiiu_wpad_t; + +typedef struct wiiu_hidpad { + bool ready; +} wiiu_hidpad_t; + +typedef struct wiiu_joypad { + joypad_connection_t pads[MAX_USERS]; + input_device_driver_t *pad_drivers[MAX_USERS]; + int max_slot; + + wiiu_kpad_t kpad; + wiiu_wpad_t wpad; + wiiu_hidpad_t hid; +} wiiu_joypad_t; + +extern wiiu_joypad_t joypad_state; extern wiiu_pad_functions_t pad_functions; extern input_device_driver_t wiiu_joypad; extern input_device_driver_t wpad_driver; diff --git a/input/input_autodetect_builtin.c b/input/input_autodetect_builtin.c index ed0966c666..8a38736c84 100644 --- a/input/input_autodetect_builtin.c +++ b/input/input_autodetect_builtin.c @@ -744,7 +744,7 @@ const char* const input_builtin_autoconfs[] = DECL_AUTOCONF_DEVICE(PAD_NAME_CLASSIC, "wiiu", WIIUINPUT_CLASSIC_CONTROLLER_DEFAULT_BINDS), DECL_AUTOCONF_DEVICE(PAD_NAME_HID, "wiiu", WIIUINPUT_GAMEPAD_DEFAULT_BINDS), DECL_AUTOCONF_DEVICE("GameCube Controller", "wiiu", WIIUINPUT_GAMECUBE_DEFAULT_BINDS), - DECL_AUTOCONF_DEVICE("Sony DualShock 3", "wiiu", WIIUINPUT_DS3_DEFAULT_BINDS), + DECL_AUTOCONF_DEVICE("PLAYSTATION(R)3 Controller", "wiiu", WIIUINPUT_DS3_DEFAULT_BINDS), #endif #ifdef __PS3__ DECL_AUTOCONF_DEVICE("SixAxis Controller", "ps3", PS3INPUT_DEFAULT_BINDS), diff --git a/input/input_driver.c b/input/input_driver.c index 9d4f84760f..f9eabff8aa 100644 --- a/input/input_driver.c +++ b/input/input_driver.c @@ -306,7 +306,7 @@ hid_driver_t *hid_drivers[] = { #ifdef HW_RVL &wiiusb_hid, #endif -#if defined(WIIU) && defined(WIIU_HID) +#if defined(WIIU) &wiiu_hid, #endif &null_hid, @@ -3297,23 +3297,14 @@ void input_overlay_init(void) } #endif -void set_connection_listener(pad_connection_listener_t *listener) -{ - input_driver_st.pad_connection_listener = listener; -} - void input_pad_connect(unsigned port, input_device_driver_t *driver) { - input_driver_state_t *input_st = &input_driver_st; if (port >= MAX_USERS || !driver) { RARCH_ERR("[Input]: input_pad_connect: bad parameters\n"); return; } - if (input_st->pad_connection_listener) - input_st->pad_connection_listener->connected(port, driver); - input_autoconfigure_connect(driver->name(port), NULL, driver->ident, port, 0, 0); } diff --git a/input/input_driver.h b/input/input_driver.h index 2dde9f6f98..75a70400ac 100644 --- a/input/input_driver.h +++ b/input/input_driver.h @@ -389,7 +389,6 @@ typedef struct #ifdef HAVE_NETWORKGAMEPAD input_remote_t *remote; #endif - pad_connection_listener_t *pad_connection_listener; char *osk_grid[45]; /* ptr alignment */ int osk_ptr; @@ -588,7 +587,7 @@ const hid_driver_t *input_hid_init_first(void); * * @return Pointer to hid_data struct **/ -const void *hid_driver_get_data(void); +void *hid_driver_get_data(void); /** * This should be called after we've invoked free() on the HID driver; the @@ -679,14 +678,6 @@ void input_config_set_device_name_index(unsigned port, unsigned name_index); */ void input_config_set_device(unsigned port, unsigned id); -/** - * Registers a pad_connection_listener_interface with a function pointer that - * is called when a joypad is connected. Only used by the wiiu_joypad driver. - * - * @param listener a struct that implements pad_connection_listener_interface - */ -void set_connection_listener(pad_connection_listener_t *listener); - /* Clear input_device_info */ void input_config_clear_device_name(unsigned port); void input_config_clear_device_display_name(unsigned port); diff --git a/input/input_types.h b/input/input_types.h index 4712d90cbe..141ea1830a 100644 --- a/input/input_types.h +++ b/input/input_types.h @@ -106,9 +106,6 @@ typedef struct input_keyboard_line input_keyboard_line_t; typedef struct rarch_joypad_info rarch_joypad_info_t; typedef struct input_driver input_driver_t; typedef struct input_keyboard_ctx_wait input_keyboard_ctx_wait_t; - -typedef struct joypad_connection joypad_connection_t; -typedef struct pad_connection_listener_interface pad_connection_listener_t; typedef struct turbo_buttons turbo_buttons_t; #endif /* __INPUT_TYPES__H */ diff --git a/retroarch.c b/retroarch.c index f46ca6add7..25e106f68b 100644 --- a/retroarch.c +++ b/retroarch.c @@ -15434,7 +15434,7 @@ const char* config_get_joypad_driver_options(void) } #ifdef HAVE_HID -const void *hid_driver_get_data(void) +void *hid_driver_get_data(void) { struct rarch_state *p_rarch = &rarch_st; return p_rarch->hid_data; From 9846ebb1712c4c5f913fe201085259222734604b Mon Sep 17 00:00:00 2001 From: Nathan Strong Date: Fri, 1 Oct 2021 22:22:11 -0700 Subject: [PATCH 03/10] enable GCA adapter, minor cleanup == DETAILS I'm going to need to re-implement the abstraction between HID device and gamepad; the changes here lay down some foundation for that work. - reduce logging priority of some statements I modified while debugging - factor out the pad driver lookup into its own method - fix so the pad driver list isn't re-initialized every invocation - add the button() method for the GCA driver --- input/connect/connect_wiiugca.c | 10 ++ input/connect/joypad_connection.c | 160 ++++++++++++++---------------- input/connect/joypad_connection.h | 11 +- input/input_autodetect_builtin.c | 2 +- 4 files changed, 95 insertions(+), 88 deletions(-) diff --git a/input/connect/connect_wiiugca.c b/input/connect/connect_wiiugca.c index 08421437ff..2988357b82 100644 --- a/input/connect/connect_wiiugca.c +++ b/input/connect/connect_wiiugca.c @@ -26,6 +26,7 @@ struct hidpad_wiiugca_data { struct pad_connection* connection; hid_driver_t *driver; + int pad_slots_map[4]; uint8_t data[64]; uint32_t slot; uint32_t buttons; @@ -148,6 +149,14 @@ const char *hidpad_wiiugca_get_name(void *data) return "Wii U GC Controller Adapter"; } +static int32_t hidpad_wiiugca_button(void *data, uint16_t joykey) { + struct hidpad_wiiugca_data *device = (struct hidpad_wiiugca_data*)data; + if (!device || joykey > 31) + return 0; + + return device->buttons & (1 << joykey); +} + pad_connection_interface_t pad_connection_wiiugca = { hidpad_wiiugca_init, hidpad_wiiugca_deinit, @@ -156,4 +165,5 @@ pad_connection_interface_t pad_connection_wiiugca = { hidpad_wiiugca_get_buttons, hidpad_wiiugca_get_axis, hidpad_wiiugca_get_name, + hidpad_wiiugca_button, }; diff --git a/input/connect/joypad_connection.c b/input/connect/joypad_connection.c index 4887f3c921..6148990019 100644 --- a/input/connect/joypad_connection.c +++ b/input/connect/joypad_connection.c @@ -24,6 +24,26 @@ #include "joypad_connection.h" + + +/* we init the hid/vid to 0 because we need to do endian magic that we can't do during the declaration */ +joypad_connection_entry_t pad_map[] = { + { "Nintendo RVL-CNT-01", 0, 0, &pad_connection_wii }, + { "Nintendo RVL-CNT-01-UC", 0, 0, &pad_connection_wiiupro }, + { "Wireless Controller", 0, 0, &pad_connection_ps4 }, + { "PLAYSTATION(R)3 Controller", 0, 0, &pad_connection_ps3 }, + { "PLAYSTATION(R)3 Controller", 0, 0, &pad_connection_ps3 }, + { "Generic SNES USB Controller", 0, 0, &pad_connection_snesusb }, + { "Generic NES USB Controller", 0, 0, &pad_connection_nesusb }, + { "Wii U GC Controller Adapter", 0, 0, &pad_connection_wiiugca }, + { "PS2/PSX Controller Adapter", 0, 0, &pad_connection_ps2adapter }, + { "PSX to PS3 Controller Adapter", 0, 0, &pad_connection_psxadapter }, + { "Mayflash DolphinBar", 0, 0, &pad_connection_wii }, + { "Retrode", 0, 0, &pad_connection_retrode }, + { "HORI mini wired PS4", 0, 0, &pad_connection_ps4_hori_mini }, + { 0, 0} +}; + static bool joypad_is_end_of_list(joypad_connection_t *pad) { return pad @@ -93,42 +113,7 @@ joypad_connection_t *pad_connection_init(unsigned pads) return joyconn; } -int32_t pad_connection_pad_init(joypad_connection_t *joyconn, - const char *name, uint16_t vid, uint16_t pid, - void *data, hid_driver_t *driver) -{ - - static struct - { - const char* name; - uint16_t vid; - uint16_t pid; - pad_connection_interface_t *iface; - } pad_map[] = - { - { "Nintendo RVL-CNT-01", 0, 0, &pad_connection_wii }, - { "Nintendo RVL-CNT-01-UC", 0, 0, &pad_connection_wiiupro }, - { "Wireless Controller", 0, 0, &pad_connection_ps4 }, - { "PLAYSTATION(R)3 Controller", 0, 0, &pad_connection_ps3 }, - { "PLAYSTATION(R)3 Controller", 0, 0, &pad_connection_ps3 }, - { "Generic SNES USB Controller", 0, 0, &pad_connection_snesusb }, - { "Generic NES USB Controller", 0, 0, &pad_connection_nesusb }, - { "Wii U GC Controller Adapter", 0, 0, &pad_connection_wiiugca }, - { "PS2/PSX Controller Adapter", 0, 0, &pad_connection_ps2adapter }, - { "PSX to PS3 Controller Adapter", 0, 0, &pad_connection_psxadapter }, - { "Mayflash DolphinBar", 0, 0, &pad_connection_wii }, - { "Retrode", 0, 0, &pad_connection_retrode }, - { "HORI mini wired PS4", 0, 0, &pad_connection_ps4_hori_mini }, - { 0, 0} - }; - joypad_connection_t *s = NULL; - int pad = pad_connection_find_vacant_pad(joyconn); - - if (pad == -1) - return -1; - - s = &joyconn[pad]; - +void init_pad_map() { pad_map[0].vid = VID_NINTENDO; pad_map[0].pid = PID_NINTENDO_PRO; pad_map[1].vid = VID_NINTENDO; @@ -155,59 +140,62 @@ int32_t pad_connection_pad_init(joypad_connection_t *joyconn, pad_map[11].pid = PID_RETRODE; pad_map[12].vid = VID_HORI_1; pad_map[12].pid = PID_HORI_MINI_WIRED_PS4; +} + +joypad_connection_entry_t *find_connection_entry(int16_t vid, int16_t pid, const char *name) { + unsigned i; + const bool has_name = !string_is_empty(name); + + for(i = 0; pad_map[i].name != NULL; i++) { + const char *name_match = has_name ? strstr(pad_map[i].name, name) : NULL; + /* The Wii Pro Controller and Wii U pro controller have the same VID/PID, so we have to use the + * descriptor string to differentiate them. */ + if(pad_map[i].vid == VID_NINTENDO && pad_map[i].pid == PID_NINTENDO_PRO) + { + if(!string_is_equal(pad_map[i].name, name)) + continue; + } + + if(name_match || (pad_map[i].vid == vid && pad_map[i].pid == pid)) { + return &pad_map[i]; + } + } + + return NULL; +} + +int32_t pad_connection_pad_init(joypad_connection_t *joyconn, + const char *name, uint16_t vid, uint16_t pid, + void *data, hid_driver_t *driver) +{ + joypad_connection_entry_t *entry = NULL; + joypad_connection_t *s = NULL; + int pad = -1; + + if(pad_map[0].vid == 0) { + init_pad_map(); + } + + entry = find_connection_entry(vid, pid, name); + pad = pad_connection_find_vacant_pad(joyconn); + + if (pad == -1) + return -1; + + s = &joyconn[pad]; if (s) { - unsigned i; - - const bool has_name = !string_is_empty(name); - - for (i = 0; name && pad_map[i].name; i++) - { - const char *name_match = has_name ? strstr(pad_map[i].name, name) : NULL; - - /* Never change, Nintendo. */ - if(pad_map[i].vid == 1406 && pad_map[i].pid == 816) - { - if(!string_is_equal(pad_map[i].name, name)) - continue; - } - -#if 0 - RARCH_LOG("[connect] %s\n", pad_map[i].name); - RARCH_LOG("[connect] VID: Expected: %04x got: %04x\n", - pad_map[i].vid, vid); - RARCH_LOG("[connect] PID: Expected: %04x got: %04x\n", - pad_map[i].pid, pid); -#endif - - if (name_match || (pad_map[i].vid == vid && pad_map[i].pid == pid)) - { - RARCH_LOG("Pad was matched to \"%s\". Setting up an interface.\n", name_match); - // RARCH_DBG("Pad was matched to \"%s\". Setting up an interface.\n", name_match); - s->iface = pad_map[i].iface; - s->data = data; - s->connection = s->iface->init(data, pad, driver); - s->connected = true; -#if 0 - RARCH_LOG("%s found \n", pad_map[i].name); -#endif - break; - } -#if 0 - else - { - RARCH_LOG("%s not found \n", pad_map[i].name); - } -#endif - } - - /* We failed to find a matching pad, - * set up one without an interface */ - if (!s->connected) - { - RARCH_LOG("Pad was not matched. Setting up without an interface.\n"); - // RARCH_DBG("Pad was not matched. Setting up without an interface.\n"); + if(entry) { + RARCH_DBG("Pad was matched to \"%s\". Setting up an interface.\n", entry->name); + s->iface = entry->iface; + s->data = data; + s->connection = s->iface->init(data, pad, driver); + s->connected = true; + } else { + /* We failed to find a matching pad, + * set up one without an interface */ + RARCH_DBG("Pad was not matched. Setting up without an interface.\n"); s->iface = NULL; s->data = data; s->connected = true; diff --git a/input/connect/joypad_connection.h b/input/connect/joypad_connection.h index f68eadb5cd..45b9808b4b 100644 --- a/input/connect/joypad_connection.h +++ b/input/connect/joypad_connection.h @@ -73,9 +73,16 @@ typedef struct pad_connection_interface void (*get_buttons)(void *data, input_bits_t *state); int16_t (*get_axis)(void *data, unsigned axis); const char* (*get_name)(void *data); - int32_t (*button)(void *data, uint16_t joykey); + int32_t (*button)(void *data, uint16_t joykey); } pad_connection_interface_t; +typedef struct joypad_connection_entry { + const char* name; + uint16_t vid; + uint16_t pid; + pad_connection_interface_t *iface; +} joypad_connection_entry_t; + extern pad_connection_interface_t pad_connection_wii; extern pad_connection_interface_t pad_connection_wiiupro; extern pad_connection_interface_t pad_connection_ps3; @@ -122,4 +129,6 @@ bool pad_connection_rumble(joypad_connection_t *s, const char* pad_connection_get_name(joypad_connection_t *joyconn, unsigned idx); +joypad_connection_entry_t *find_connection_entry(int16_t vid, int16_t pid, const char *name); + #endif diff --git a/input/input_autodetect_builtin.c b/input/input_autodetect_builtin.c index 8a38736c84..7636821d77 100644 --- a/input/input_autodetect_builtin.c +++ b/input/input_autodetect_builtin.c @@ -743,7 +743,7 @@ const char* const input_builtin_autoconfs[] = DECL_AUTOCONF_DEVICE(PAD_NAME_NUNCHUK, "wiiu", WIIUINPUT_NUNCHUK_DEFAULT_BINDS), DECL_AUTOCONF_DEVICE(PAD_NAME_CLASSIC, "wiiu", WIIUINPUT_CLASSIC_CONTROLLER_DEFAULT_BINDS), DECL_AUTOCONF_DEVICE(PAD_NAME_HID, "wiiu", WIIUINPUT_GAMEPAD_DEFAULT_BINDS), - DECL_AUTOCONF_DEVICE("GameCube Controller", "wiiu", WIIUINPUT_GAMECUBE_DEFAULT_BINDS), + DECL_AUTOCONF_DEVICE("Wii U GC Controller Adapter", "wiiu", WIIUINPUT_GAMECUBE_DEFAULT_BINDS), DECL_AUTOCONF_DEVICE("PLAYSTATION(R)3 Controller", "wiiu", WIIUINPUT_DS3_DEFAULT_BINDS), #endif #ifdef __PS3__ From a4d8ce77533a5a90f84723561779b85cfa9c2d55 Mon Sep 17 00:00:00 2001 From: Nathan Strong Date: Sun, 3 Oct 2021 23:27:07 +0000 Subject: [PATCH 04/10] Try to support multi-pad HID devices == DETAILS I tried to modify the joypad connection interface to support multi-pad HID devices ... it doesn't work. I'm not sure why. --- input/connect/connect_nesusb.c | 2 + input/connect/connect_ps2adapter.c | 2 + input/connect/connect_ps3.c | 4 +- input/connect/connect_ps4.c | 4 +- input/connect/connect_ps4_hori_mini.c | 2 + input/connect/connect_psxadapter.c | 2 + input/connect/connect_retrode.c | 2 + input/connect/connect_snesusb.c | 2 + input/connect/connect_wii.c | 4 +- input/connect/connect_wiiugca.c | 249 +++++++++++++++++++----- input/connect/connect_wiiupro.c | 4 +- input/connect/joypad_connection.c | 174 ++++++++++++++--- input/connect/joypad_connection.h | 21 +- input/drivers_hid/wiiu_hid.c | 107 ++++++---- input/drivers_joypad/wiiu/kpad_driver.c | 2 +- input/drivers_joypad/wiiu/wpad_driver.c | 2 +- input/drivers_joypad/wiiu_joypad.c | 16 +- input/include/wiiu/hid.h | 3 +- input/include/wiiu/input.h | 1 - input/input_autodetect_builtin.c | 25 ++- 20 files changed, 492 insertions(+), 136 deletions(-) diff --git a/input/connect/connect_nesusb.c b/input/connect/connect_nesusb.c index cc557cee46..38493c4556 100644 --- a/input/connect/connect_nesusb.c +++ b/input/connect/connect_nesusb.c @@ -147,4 +147,6 @@ pad_connection_interface_t pad_connection_nesusb = { hidpad_nesusb_get_buttons, hidpad_nesusb_get_axis, hidpad_nesusb_get_name, + NULL, /* button */ + false, }; diff --git a/input/connect/connect_ps2adapter.c b/input/connect/connect_ps2adapter.c index 6a324b9491..74b1cd47be 100644 --- a/input/connect/connect_ps2adapter.c +++ b/input/connect/connect_ps2adapter.c @@ -182,4 +182,6 @@ pad_connection_interface_t pad_connection_ps2adapter = { hidpad_ps2adapter_get_buttons, hidpad_ps2adapter_get_axis, hidpad_ps2adapter_get_name, + NULL, + false, }; diff --git a/input/connect/connect_ps3.c b/input/connect/connect_ps3.c index 70aa6d3e0f..009c8c5b90 100644 --- a/input/connect/connect_ps3.c +++ b/input/connect/connect_ps3.c @@ -178,7 +178,6 @@ static void ds3_packet_handler(void *data, uint8_t *packet, uint16_t size) sizeof(instance->data), size); return; } - RARCH_LOG_BUFFER(packet, size); memcpy(instance->data, packet, size); ds3_update_pad_state(instance); @@ -275,5 +274,6 @@ pad_connection_interface_t pad_connection_ps3 = { ds3_get_buttons, ds3_get_axis, ds3_get_name, - ds3_button + ds3_button, + false, }; \ No newline at end of file diff --git a/input/connect/connect_ps4.c b/input/connect/connect_ps4.c index 31ccfe3f64..33e9ccc782 100644 --- a/input/connect/connect_ps4.c +++ b/input/connect/connect_ps4.c @@ -292,5 +292,7 @@ pad_connection_interface_t pad_connection_ps4 = { hidpad_ps4_set_rumble, hidpad_ps4_get_buttons, hidpad_ps4_get_axis, - NULL, + NULL, /* get_name */ + NULL, /* button */ + false }; diff --git a/input/connect/connect_ps4_hori_mini.c b/input/connect/connect_ps4_hori_mini.c index cd4e529622..ee38f5d73a 100644 --- a/input/connect/connect_ps4_hori_mini.c +++ b/input/connect/connect_ps4_hori_mini.c @@ -186,4 +186,6 @@ pad_connection_interface_t pad_connection_ps4_hori_mini = { hidpad_ps4_hori_mini_get_buttons, hidpad_ps4_hori_mini_get_axis, hidpad_ps4_hori_mini_get_name, + NULL, /* button */ + false }; diff --git a/input/connect/connect_psxadapter.c b/input/connect/connect_psxadapter.c index 27332a149f..89ec500e84 100644 --- a/input/connect/connect_psxadapter.c +++ b/input/connect/connect_psxadapter.c @@ -191,4 +191,6 @@ pad_connection_interface_t pad_connection_psxadapter = { hidpad_psxadapter_get_buttons, hidpad_psxadapter_get_axis, hidpad_psxadapter_get_name, + NULL, /* button */ + false }; diff --git a/input/connect/connect_retrode.c b/input/connect/connect_retrode.c index 58fc31f504..eaf5bd8d51 100644 --- a/input/connect/connect_retrode.c +++ b/input/connect/connect_retrode.c @@ -197,4 +197,6 @@ pad_connection_interface_t pad_connection_retrode = { hidpad_retrode_get_buttons, hidpad_retrode_get_axis, hidpad_retrode_get_name, + NULL, /* button */ + false, }; diff --git a/input/connect/connect_snesusb.c b/input/connect/connect_snesusb.c index 13bf4a0d14..7a452abe41 100644 --- a/input/connect/connect_snesusb.c +++ b/input/connect/connect_snesusb.c @@ -148,4 +148,6 @@ pad_connection_interface_t pad_connection_snesusb = { hidpad_snesusb_get_buttons, hidpad_snesusb_get_axis, hidpad_snesusb_get_name, + NULL, /* button */ + false }; diff --git a/input/connect/connect_wii.c b/input/connect/connect_wii.c index 7807be18d0..c3d5a5a783 100644 --- a/input/connect/connect_wii.c +++ b/input/connect/connect_wii.c @@ -729,5 +729,7 @@ pad_connection_interface_t pad_connection_wii = { hidpad_wii_set_rumble, hidpad_wii_get_buttons, hidpad_wii_get_axis, - NULL, + NULL, /* get_name */ + NULL, /* button */ + false, }; diff --git a/input/connect/connect_wiiugca.c b/input/connect/connect_wiiugca.c index 2988357b82..784bbc5d15 100644 --- a/input/connect/connect_wiiugca.c +++ b/input/connect/connect_wiiugca.c @@ -22,16 +22,39 @@ #include "joypad_connection.h" #include "../input_defines.h" +#define GCA_MAX_PAD 4 + +#define GCA_PORT_INITIALIZING 0x00 +#define GCA_PORT_POWERED 0x04 +#define GCA_PORT_CONNECTED 0x10 +#define GCA_WAVEBIRD_CONNECTED 0x22 + +typedef struct hidpad_wiiugca_pad_data gca_pad_data_t; +typedef struct hidpad_wiiugca_data gca_device_data_t; + +struct hidpad_wiiugca_pad_data +{ + gca_device_data_t *device_data; + joypad_connection_t *joypad; + int pad_index; + uint32_t buttons; + int16_t analog[3][2]; + uint8_t data[9]; +}; + struct hidpad_wiiugca_data { - struct pad_connection* connection; + void *handle; hid_driver_t *driver; - int pad_slots_map[4]; + char connected[GCA_MAX_PAD]; + gca_pad_data_t pad_data[GCA_MAX_PAD]; uint8_t data[64]; - uint32_t slot; - uint32_t buttons; }; +const char *GAMECUBE_PAD = "GameCube controller"; +const char *WAVEBIRD_PAD = "WaveBird controller"; +const char *DEVICE_NAME = "Wii U GC Controller Adapter"; + static void* hidpad_wiiugca_init(void *data, uint32_t slot, hid_driver_t *driver) { #ifdef WIIU @@ -39,70 +62,69 @@ static void* hidpad_wiiugca_init(void *data, uint32_t slot, hid_driver_t *driver #else static uint8_t magic_data[] = {0x01, 0x13}; /* Special command to enable reading */ #endif - struct pad_connection* connection = (struct pad_connection*)data; - struct hidpad_wiiugca_data* device = (struct hidpad_wiiugca_data*) - calloc(1, sizeof(struct hidpad_wiiugca_data)); + int i; + gca_device_data_t * device = (gca_device_data_t *)calloc(1, sizeof(gca_device_data_t)); if (!device) return NULL; - if (!connection) + if (!data) { free(device); return NULL; } - device->connection = connection; - device->slot = slot; + device->handle = data; + for(i = 0; i < GCA_MAX_PAD; i++) { + device->pad_data[i].device_data = device; + device->pad_data[i].joypad = NULL; + device->pad_data[i].pad_index = i; + } + device->driver = driver; - device->driver->send_control(device->connection, magic_data, sizeof(magic_data)); + device->driver->send_control(device->handle, magic_data, sizeof(magic_data)); return device; } -static void hidpad_wiiugca_deinit(void *data) +static void hidpad_wiiugca_deinit(void *device_data) { - struct hidpad_wiiugca_data *device = (struct hidpad_wiiugca_data*)data; + gca_device_data_t *device = (gca_device_data_t *)device_data; if (device) free(device); } -static void hidpad_wiiugca_get_buttons(void *data, input_bits_t *state) +static void hidpad_wiiugca_get_buttons(void *pad_data, input_bits_t *state) { - struct hidpad_wiiugca_data *device = (struct hidpad_wiiugca_data*)data; - if (device) - { - BITS_COPY16_PTR(state, device->buttons); - } - else - BIT256_CLEAR_ALL_PTR(state); + gca_pad_data_t *pad = (gca_pad_data_t *)pad_data; + if (pad) + { + BITS_COPY16_PTR(state, pad->buttons); + } + else + { + BIT256_CLEAR_ALL_PTR(state); + } } -static int16_t hidpad_wiiugca_get_axis(void *data, unsigned axis) +static int16_t hidpad_wiiugca_get_axis(void *pad_data, unsigned axis) { - int val; - struct hidpad_wiiugca_data *device = (struct hidpad_wiiugca_data*)data; + gca_pad_data_t *pad = (gca_pad_data_t *)pad_data; + axis_data axis_data; - if (!device || axis >= 4) + gamepad_read_axis_data(axis, &axis_data); + + if (!pad || axis_data.axis >= 4) return 0; - val = device->data[5 + axis]; - - if (axis % 2) /* the Y axis is inverted */ - val = 0x8000 - (val << 8); - else - val = (val << 8) - 0x8000; - - if (abs(val) > 0x1000) - return val; - return 0; + return gamepad_get_axis_value(pad->analog, &axis_data); } -static void hidpad_wiiugca_packet_handler(void *data, uint8_t *packet, uint16_t size) -{ +static void update_button_state(gca_pad_data_t *pad) { uint32_t i, pressed_keys; + static const uint32_t button_mapping[12] = { RETRO_DEVICE_ID_JOYPAD_A, @@ -118,20 +140,80 @@ static void hidpad_wiiugca_packet_handler(void *data, uint8_t *packet, uint16_t RETRO_DEVICE_ID_JOYPAD_R, RETRO_DEVICE_ID_JOYPAD_L, }; - struct hidpad_wiiugca_data *device = (struct hidpad_wiiugca_data*)data; + + if (!pad) + return; + + pressed_keys = pad->data[1] | (pad->data[2] << 8); + pad->buttons = 0; + + for (i = 0; i < 12; i++) + pad->buttons |= (pressed_keys & (1 << i)) ? + (1 << button_mapping[i]) : 0; +} + +static void update_analog_state(gca_pad_data_t *pad) { + int pad_axis; + int16_t interpolated; + unsigned stick, axis; + + /* GameCube analog axis are 8-bit unsigned, where 128/128 is center. + * So, we subtract 128 to get a signed, 0-based value and then mulitply + * by 256 to get the 16-bit range RetroArch expects. */ + for (pad_axis = 0; pad_axis < 4; pad_axis++) + { + axis = (pad_axis % 2) ? 0 : 1; + stick = pad_axis / 2; + interpolated = pad->data[3 + pad_axis]; + /* libretro requires "up" to be negative, so we invert the y axis */ + interpolated = (axis) ? + ((interpolated - 128) * 256) : + ((interpolated - 128) * -256); + + pad->analog[stick][axis] = interpolated; + } +} + +static void hidpad_wiiugca_pad_packet_handler(gca_pad_data_t *pad, uint8_t *packet, size_t size) { + if(size > 9) { + return; + } + + memcpy(pad->data, packet, size); + update_button_state(pad); + update_analog_state(pad); +} + + + +static void hidpad_wiiugca_packet_handler(void *device_data, uint8_t *packet, uint16_t size) +{ + uint32_t i; + int port; + unsigned char port_connected; + + gca_device_data_t *device = (gca_device_data_t *)device_data; if (!device) return; memcpy(device->data, packet, size); - device->buttons = 0; + for (i = 1; i < 37; i += 9) + { + port = i / 9; + port_connected = device->data[i]; - pressed_keys = device->data[3] | (device->data[4] << 8); - - for (i = 0; i < 12; i ++) - device->buttons |= (pressed_keys & (1 << i)) ? - (1 << button_mapping[i]) : 0; + if (port_connected > GCA_PORT_POWERED) + { + device->connected[port] = port_connected; + hidpad_wiiugca_pad_packet_handler(&device->pad_data[port], &device->data[i], 9); + } + else + { + device->connected[port] = 0; + } + } } static void hidpad_wiiugca_set_rumble(void *data, @@ -142,19 +224,78 @@ static void hidpad_wiiugca_set_rumble(void *data, (void)strength; } -const char *hidpad_wiiugca_get_name(void *data) +const char *hidpad_wiiugca_get_name(void *pad_data) { - (void)data; + gca_pad_data_t *pad = (gca_pad_data_t *)pad_data; + if(!pad) { + return DEVICE_NAME; + } + + switch(pad->device_data->connected[pad->pad_index]) { + case 0: + return DEVICE_NAME; + case GCA_WAVEBIRD_CONNECTED: + return WAVEBIRD_PAD; + default: + return GAMECUBE_PAD; + } + /* For now we return a single static name */ - return "Wii U GC Controller Adapter"; + } -static int32_t hidpad_wiiugca_button(void *data, uint16_t joykey) { - struct hidpad_wiiugca_data *device = (struct hidpad_wiiugca_data*)data; - if (!device || joykey > 31) +static int32_t hidpad_wiiugca_button(void *pad_data, uint16_t joykey) { + gca_pad_data_t *pad = (gca_pad_data_t *)pad_data; + if (!pad || !pad->device_data || joykey > 31 || pad->joypad == NULL) return 0; - return device->buttons & (1 << joykey); + return pad->buttons & (1 << joykey); +} + +static void *hidpad_wiiugca_pad_init(void *device_data, int pad_index, joypad_connection_t *joypad) { + gca_device_data_t *device = (gca_device_data_t *)device_data; + + if(!device || pad_index < 0 || pad_index >= GCA_MAX_PAD || joypad == NULL || device->pad_data[pad_index].joypad != NULL || !device->connected[pad_index]) { + return NULL; + } + + device->pad_data[pad_index].joypad = joypad; + return &device->pad_data[pad_index]; +} + +static void hidpad_wiiugca_pad_deinit(void *pad_data) { + gca_pad_data_t *pad = (gca_pad_data_t *)pad_data; + + if(!pad) { + return; + } + + pad->joypad = NULL; +} + +static int8_t hidpad_wiiugca_status(void *device_data, int pad_index) { + gca_device_data_t *device = (gca_device_data_t *)device_data; + int8_t result = 0; + + if(!device || pad_index < 0 || pad_index >= GCA_MAX_PAD) return 0; + + if(device->connected[pad_index]) { + result |= PAD_CONNECT_READY; + } + + if(device->pad_data[pad_index].joypad != NULL) { + result |= PAD_CONNECT_BOUND; + } + + return result; +} + +static joypad_connection_t *hidpad_wiiugca_joypad(void *device_data, int pad_index) { + gca_device_data_t *device = (gca_device_data_t *)device_data; + + if(!device || pad_index < 0 || pad_index >= GCA_MAX_PAD) return 0; + + return device->pad_data[pad_index].joypad; } pad_connection_interface_t pad_connection_wiiugca = { @@ -166,4 +307,10 @@ pad_connection_interface_t pad_connection_wiiugca = { hidpad_wiiugca_get_axis, hidpad_wiiugca_get_name, hidpad_wiiugca_button, + true, + GCA_MAX_PAD, + hidpad_wiiugca_pad_init, + hidpad_wiiugca_pad_deinit, + hidpad_wiiugca_status, + hidpad_wiiugca_joypad, }; diff --git a/input/connect/connect_wiiupro.c b/input/connect/connect_wiiupro.c index a6b1f11ff5..ff26bb5064 100644 --- a/input/connect/connect_wiiupro.c +++ b/input/connect/connect_wiiupro.c @@ -255,5 +255,7 @@ pad_connection_interface_t pad_connection_wiiupro = { hidpad_wiiupro_set_rumble, hidpad_wiiupro_get_buttons, hidpad_wiiupro_get_axis, - NULL, + NULL, /* get_name */ + NULL, /* button */ + false }; diff --git a/input/connect/joypad_connection.c b/input/connect/joypad_connection.c index 6148990019..1b6ad4c750 100644 --- a/input/connect/joypad_connection.c +++ b/input/connect/joypad_connection.c @@ -18,6 +18,7 @@ #include #include +#include "../tasks/tasks_internal.h" #include "../input_driver.h" #include "../../verbosity.h" @@ -164,45 +165,161 @@ joypad_connection_entry_t *find_connection_entry(int16_t vid, int16_t pid, const return NULL; } +void pad_connection_pad_deregister(joypad_connection_t *joyconn, pad_connection_interface_t *iface, void *pad_data) { + int i; + + RARCH_LOG("pad_connection_pad_deregister\n"); + for(i = 0; !joypad_is_end_of_list(&joyconn[i]); i++) { + RARCH_LOG("joyconn[i].connected = %d, joyconn[i].iface == iface = %d\n", joyconn[i].connected, joyconn[i].iface == iface); + if(joyconn[i].connected && joyconn[i].iface == iface) { + if(iface->set_rumble) { + RARCH_LOG("set_rumble"); + iface->set_rumble(joyconn[i].connection, RETRO_RUMBLE_STRONG, 0); + iface->set_rumble(joyconn[i].connection, RETRO_RUMBLE_WEAK, 0); + } + RARCH_LOG("deregistering pad"); + input_autoconfigure_disconnect(i, iface->get_name(joyconn[i].connection)); + if(iface->multi_pad) { + RARCH_LOG("multi-pad cleanup"); + iface->pad_deinit(&joyconn[i].connection); + } + RARCH_LOG("zeroing pad %d\n", i); + memset(&joyconn[i], 0, sizeof(joypad_connection_t)); + } + } +} + +static int joypad_to_slot(joypad_connection_t *haystack, joypad_connection_t *needle) { + int i; + + for(i = 0; !joypad_is_end_of_list(&haystack[i]); i++) { + if(&haystack[i] == needle) { + return i; + } + } + return -1; +} + +void pad_connection_pad_refresh(joypad_connection_t *joyconn, pad_connection_interface_t *iface, void *device_data, void *handle, input_device_driver_t *input_driver) { + int i, slot; + int8_t state; + joypad_connection_t *joypad; + + if(!iface->multi_pad || iface->max_pad < 1) { + return; + } + + for(i = 0; i < iface->max_pad; i++) { + state = iface->status(device_data, i); + switch(state) { + /* The pad slot is bound to a joypad that's no longer connected */ + case PAD_CONNECT_BOUND: + joypad = iface->joypad(device_data, i); + slot = joypad_to_slot(joyconn, joypad); + input_autoconfigure_disconnect(slot, iface->get_name(joypad->connection)); + + iface->pad_deinit(joypad->connection); + memset(joypad, 0, sizeof(joypad_connection_t)); + break; + /* The joypad is connected but has not been bound */ + case PAD_CONNECT_READY: + slot = pad_connection_find_vacant_pad(joyconn); + if(slot >= 0) { + joypad = &joyconn[slot]; + joypad->connection = iface->pad_init(device_data, i, joypad); + joypad->data = handle; + joypad->iface = iface; + joypad->input_driver = input_driver; + input_pad_connect(slot, input_driver); + } + break; + default: + break; + } + } +} + +void pad_connection_pad_register(joypad_connection_t *joyconn, pad_connection_interface_t *iface, void *device_data, void *handle, input_device_driver_t *input_driver, int slot) { + int i, status; + int found_slot; + int max_pad; + void *connection; + + if(iface->multi_pad && (iface->max_pad <= 1 || !iface->status || !iface->pad_init)) { + RARCH_ERR("pad_connection_pad_register: multi-pad driver has incomplete implementation\n"); + return; + } + + max_pad = iface->multi_pad ? iface->max_pad : 1; + + for(i = 0; i < max_pad; i++) { + status = iface->multi_pad ? iface->status(device_data, i) : PAD_CONNECT_READY; + RARCH_LOG("pad %d: status = %d\n", i, status); + if(status == PAD_CONNECT_READY) { + found_slot = (slot == SLOT_AUTO) ? pad_connection_find_vacant_pad(joyconn) : slot; + if(found_slot < 0) { + continue; + } + connection = device_data; + if(iface->multi_pad) { + RARCH_LOG("pad_connection_pad_register: multi-pad detected, initializing pad %d\n", i); + connection = iface->pad_init(device_data, i, &joyconn[found_slot]); + } + + joyconn[found_slot].iface = iface; + joyconn[found_slot].data = handle; + joyconn[found_slot].connection = connection; + joyconn[found_slot].input_driver = input_driver; + joyconn[found_slot].connected = true; + + RARCH_LOG("connecting pad to slot %d\n", found_slot); + input_pad_connect(found_slot, input_driver); + } + } +} + +int32_t pad_connection_pad_init_entry(joypad_connection_t *joyconn, joypad_connection_entry_t *entry, void *data, hid_driver_t *driver) { + joypad_connection_t *conn = NULL; + int pad = pad_connection_find_vacant_pad(joyconn); + + if(pad < 0) { + return -1; + } + + conn = &joyconn[pad]; + if(!conn) { + return -1; + } + + if(entry) { + conn->iface = entry->iface; + conn->data = data; + conn->connection = conn->iface->init(data, pad, driver); + conn->connected = true; + } else { + /* We failed to find a matching pad, set up one without an interface */ + RARCH_DBG("Pad was not matched. Setting up without an interface.\n"); + conn->iface = NULL; + conn->data = data; + conn->connected = true; + } + + return pad; +} + int32_t pad_connection_pad_init(joypad_connection_t *joyconn, const char *name, uint16_t vid, uint16_t pid, void *data, hid_driver_t *driver) { joypad_connection_entry_t *entry = NULL; - joypad_connection_t *s = NULL; - int pad = -1; if(pad_map[0].vid == 0) { init_pad_map(); } - entry = find_connection_entry(vid, pid, name); - pad = pad_connection_find_vacant_pad(joyconn); + entry = find_connection_entry(vid, pid, name); - if (pad == -1) - return -1; - - s = &joyconn[pad]; - - if (s) - { - if(entry) { - RARCH_DBG("Pad was matched to \"%s\". Setting up an interface.\n", entry->name); - s->iface = entry->iface; - s->data = data; - s->connection = s->iface->init(data, pad, driver); - s->connected = true; - } else { - /* We failed to find a matching pad, - * set up one without an interface */ - RARCH_DBG("Pad was not matched. Setting up without an interface.\n"); - s->iface = NULL; - s->data = data; - s->connected = true; - } - } - - return pad; + return pad_connection_pad_init_entry(joyconn, entry, data, driver); } void pad_connection_pad_deinit(joypad_connection_t *joyconn, uint32_t pad) @@ -212,6 +329,7 @@ void pad_connection_pad_deinit(joypad_connection_t *joyconn, uint32_t pad) if (joyconn->iface) { + joyconn->iface->set_rumble(joyconn->connection, RETRO_RUMBLE_STRONG, 0); joyconn->iface->set_rumble(joyconn->connection, RETRO_RUMBLE_WEAK, 0); diff --git a/input/connect/joypad_connection.h b/input/connect/joypad_connection.h index 45b9808b4b..8149205132 100644 --- a/input/connect/joypad_connection.h +++ b/input/connect/joypad_connection.h @@ -58,11 +58,19 @@ struct joypad_connection { struct pad_connection_interface *iface; + input_device_driver_t *input_driver; void* data; void* connection; bool connected; }; +#define PAD_CONNECT_OFFLINE 0x00 /* the pad is offline and cannot be used */ +#define PAD_CONNECT_READY 0x01 /* the pad is ready but is not bound to a RA slot */ +#define PAD_CONNECT_BOUND 0x02 /* the pad is offline and is bound to a RA slot */ +#define PAD_CONNECT_IN_USE 0x03 /* the pad is ready and is bound to a RA slot */ + +#define SLOT_AUTO -1 + typedef struct pad_connection_interface { void* (*init)(void *data, uint32_t slot, hid_driver_t *driver); @@ -74,6 +82,14 @@ typedef struct pad_connection_interface int16_t (*get_axis)(void *data, unsigned axis); const char* (*get_name)(void *data); int32_t (*button)(void *data, uint16_t joykey); + /* all fields/methods below this point are only required for multi-pad devices */ + bool multi_pad; /* does the device provide multiple pads? */ + int8_t max_pad; /* number of pads this device can provide */ + void* (*pad_init)(void *data, int pad_index, joypad_connection_t *joyconn); + void (*pad_deinit)(void *pad_data); + /* pad_index is a number from 0 to max_pad-1 */ + int8_t (*status)(void *data, int pad_index); /* returns a PAD_CONNECT_* state */ + joypad_connection_t* (*joypad)(void *device_data, int pad_index); } pad_connection_interface_t; typedef struct joypad_connection_entry { @@ -130,5 +146,8 @@ const char* pad_connection_get_name(joypad_connection_t *joyconn, unsigned idx); joypad_connection_entry_t *find_connection_entry(int16_t vid, int16_t pid, const char *name); - +int32_t pad_connection_pad_init_entry(joypad_connection_t *joyconn, joypad_connection_entry_t *entry, void *data, hid_driver_t *driver); +void pad_connection_pad_register(joypad_connection_t *joyconn, pad_connection_interface_t *iface, void *pad_data, void *handle, input_device_driver_t *input_driver, int slot); +void pad_connection_pad_deregister(joypad_connection_t *joyconn, pad_connection_interface_t *iface, void *pad_data); +void pad_connection_pad_refresh(joypad_connection_t *joyconn, pad_connection_interface_t *iface, void *device_data, void *handle, input_device_driver_t *input_driver); #endif diff --git a/input/drivers_hid/wiiu_hid.c b/input/drivers_hid/wiiu_hid.c index ae94ee7214..7bc1c3dcfd 100644 --- a/input/drivers_hid/wiiu_hid.c +++ b/input/drivers_hid/wiiu_hid.c @@ -16,6 +16,7 @@ #include "../include/wiiu/hid.h" #include +#include /* TODO/FIXME - static globals */ static wiiu_event_list events; @@ -367,20 +368,48 @@ static void log_device(HIDDevice *device) RARCH_LOG(" max_packet_size_tx: %d\n", device->max_packet_size_tx); } +static uint8_t try_init_driver_multi(wiiu_adapter_t *adapter, joypad_connection_entry_t *entry) { + adapter->pad_driver_data = entry->iface->init(adapter, -1, &wiiu_hid); + if(!adapter->pad_driver_data) { + return ADAPTER_STATE_DONE; + } + + pad_connection_pad_register(joypad_state.pads, adapter->pad_driver, adapter->pad_driver_data, adapter, &hidpad_driver, SLOT_AUTO); + return ADAPTER_STATE_READY; +} static uint8_t try_init_driver(wiiu_adapter_t *adapter) { - RARCH_LOG("Trying to find pad driver for vid 0x%04x pid 0x%04x\n", adapter->vendor_id, adapter->product_id); - int32_t pad = pad_connection_pad_init(joypad_state.pads, &adapter->device_name[0], adapter->vendor_id, adapter->product_id, adapter, &wiiu_hid); - if(pad >= 0) { - RARCH_LOG("Attached to pad %d\n", pad); - joypad_state.pad_drivers[pad] = &hidpad_driver; - adapter->pad = pad; - input_pad_connect(pad, &hidpad_driver); - return ADAPTER_STATE_READY; + joypad_connection_entry_t *entry; + int slot; + + entry = find_connection_entry(adapter->vendor_id, adapter->product_id, adapter->device_name); + if(!entry) { + RARCH_LOG("Failed to find entry for vid: 0x%x, pid: 0x%x, name: %s\n", adapter->vendor_id, adapter->product_id, adapter->device_name); + return ADAPTER_STATE_DONE; } - RARCH_LOG("Failed to find pad driver\n"); - return ADAPTER_STATE_DONE; + + adapter->pad_driver = entry->iface; + + if(entry->iface->multi_pad) { + return try_init_driver_multi(adapter, entry); + } + slot = pad_connection_find_vacant_pad(joypad_state.pads); + if(slot < 0) { + RARCH_LOG("try_init_driver: no slot available\n"); + return ADAPTER_STATE_DONE; + } + + adapter->pad_driver_data = entry->iface->init(adapter, slot, &wiiu_hid); + if(!adapter->pad_driver_data) { + RARCH_LOG("try_init_driver: pad init failed\n"); + return ADAPTER_STATE_DONE; + } + + RARCH_LOG("driver initialized, registering pad\n"); + pad_connection_pad_register(joypad_state.pads, adapter->pad_driver, adapter->pad_driver_data, adapter, &hidpad_driver, slot); + + return ADAPTER_STATE_READY; } static void synchronized_process_adapters(wiiu_hid_t *hid) @@ -401,25 +430,32 @@ static void synchronized_process_adapters(wiiu_hid_t *hid) adapter->state = try_init_driver(adapter); break; case ADAPTER_STATE_READY: + RARCH_LOG("ADAPTER_STATE_READY"); + if(adapter->pad_driver && adapter->pad_driver->multi_pad) { + pad_connection_pad_refresh(joypad_state.pads, adapter->pad_driver, adapter->pad_driver_data, adapter, &hidpad_driver); + } + break; case ADAPTER_STATE_READING: + RARCH_LOG("ADAPTER_STATE_READING"); + break; case ADAPTER_STATE_DONE: + RARCH_LOG("ADAPTER_STATE_DONE"); break; case ADAPTER_STATE_GC: - { - const char *pad_name = joypad_state.pads[adapter->pad].iface->get_name(joypad_state.pads[adapter->pad].connection); - /* remove from the list */ - if (!prev) - adapters.list = adapter->next; - else - prev->next = adapter->next; - - input_autoconfigure_disconnect(adapter->pad, pad_name); - pad_connection_pad_deinit(&joypad_state.pads[adapter->pad], adapter->pad); - /* adapter is no longer valid after this point */ - delete_adapter(adapter); - /* signal not to update prev ptr since adapter is now invalid */ - keep_prev = true; - } + { + RARCH_LOG("ADAPTER_STATE_GC"); + /* remove from the list */ + if (!prev) + adapters.list = adapter->next; + else + prev->next = adapter->next; + + pad_connection_pad_deregister(joypad_state.pads, adapter->pad_driver, adapter->pad_driver_data); + /* adapter is no longer valid after this point */ + delete_adapter(adapter); + /* signal not to update prev ptr since adapter is now invalid */ + keep_prev = true; + } break; default: @@ -554,9 +590,7 @@ static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error, if (error == 0) { - joypad_state.pads[adapter->pad].iface->packet_handler( - joypad_state.pads[adapter->pad].connection, buffer, buffer_size - ); + adapter->pad_driver->packet_handler(adapter->pad_driver_data, buffer, buffer_size); } } } @@ -568,8 +602,7 @@ static void report_hid_error(const char *msg, wiiu_adapter_t *adapter, int32_t e int16_t hid_error_code = error & 0xffff; int16_t error_category = (error >> 16) & 0xffff; - const char *device = (adapter && adapter->pad >= 0) ? - joypad_state.pads[adapter->pad].iface->get_name(joypad_state.pads[adapter->pad].connection) : "unknown"; + const char *device = string_is_empty(adapter->device_name) ? "unknown" : adapter->device_name; switch(hid_error_code) { @@ -648,6 +681,7 @@ static void wiiu_hid_polling_thread_cleanup(OSThread *thread, void *stack) RARCH_LOG("[hid]: shutting down adapter..\n"); adapter = adapters.list; adapters.list = adapter->next; + pad_connection_pad_deregister(joypad_state.pads, adapter->pad_driver, adapter->pad_driver_data); delete_adapter(adapter); } } @@ -705,7 +739,7 @@ static void wiiu_poll_adapters(wiiu_hid_t *hid) wiiu_poll_adapter(it); if (it->state == ADAPTER_STATE_DONE) { - + RARCH_LOG("poll_adapters: read done, ready for garbage collection"); it->state = ADAPTER_STATE_GC; } } @@ -818,13 +852,10 @@ static void delete_adapter(wiiu_adapter_t *adapter) free(adapter->tx_buffer); adapter->tx_buffer = NULL; } - if(adapter->pad >= 0 && - joypad_state.pads[adapter->pad].iface && - joypad_state.pads[adapter->pad].connection) { - joypad_state.pads[adapter->pad].iface->deinit(joypad_state.pads[adapter->pad].connection); - joypad_state.pads[adapter->pad].connection = NULL; - joypad_state.pads[adapter->pad].iface = NULL; - } + if(adapter->pad_driver && adapter->pad_driver_data) { + adapter->pad_driver->deinit(adapter->pad_driver_data); + adapter->pad_driver_data = NULL; + } free(adapter); } diff --git a/input/drivers_joypad/wiiu/kpad_driver.c b/input/drivers_joypad/wiiu/kpad_driver.c index 2f07f56fa5..a7fd8c02c7 100644 --- a/input/drivers_joypad/wiiu/kpad_driver.c +++ b/input/drivers_joypad/wiiu/kpad_driver.c @@ -158,7 +158,7 @@ static void kpad_register(unsigned channel, uint8_t device_type) } joypad_state.kpad.wiimotes[channel].type = device_type; - joypad_state.pad_drivers[slot] = &kpad_driver; + joypad_state.pads[slot].input_driver = &kpad_driver; input_pad_connect(slot, &kpad_driver); } } diff --git a/input/drivers_joypad/wiiu/wpad_driver.c b/input/drivers_joypad/wiiu/wpad_driver.c index 8f1b0b316b..4e30022a15 100644 --- a/input/drivers_joypad/wiiu/wpad_driver.c +++ b/input/drivers_joypad/wiiu/wpad_driver.c @@ -85,7 +85,7 @@ static void wpad_register(unsigned channel) return; joypad_state.pads[slot].connected = true; - joypad_state.pad_drivers[slot] = &wpad_driver; + joypad_state.pads[slot].input_driver = &wpad_driver; input_pad_connect(slot, &wpad_driver); joypad_state.wpad.channel_slot_map[channel] = slot; } diff --git a/input/drivers_joypad/wiiu_joypad.c b/input/drivers_joypad/wiiu_joypad.c index 60c720ac7b..9628e0d6fa 100644 --- a/input/drivers_joypad/wiiu_joypad.c +++ b/input/drivers_joypad/wiiu_joypad.c @@ -40,8 +40,8 @@ static bool wiiu_joypad_query_pad(unsigned pad) { return ready && pad < MAX_USERS && - joypad_state.pad_drivers[pad] && - joypad_state.pad_drivers[pad]->query_pad(pad); + joypad_state.pads[pad].input_driver && + joypad_state.pads[pad].input_driver->query_pad(pad); } static void wiiu_joypad_destroy(void) @@ -59,21 +59,21 @@ static int32_t wiiu_joypad_button(unsigned port, uint16_t joykey) return 0; if (port >= DEFAULT_MAX_PADS) return 0; - return (joypad_state.pad_drivers[port]->button(port, joykey)); + return (joypad_state.pads[port].input_driver->button(port, joykey)); } static void wiiu_joypad_get_buttons(unsigned port, input_bits_t *state) { if (!wiiu_joypad_query_pad(port)) return; - joypad_state.pad_drivers[port]->get_buttons(port, state); + joypad_state.pads[port].input_driver->get_buttons(port, state); } static int16_t wiiu_joypad_axis(unsigned port, uint32_t joyaxis) { if (!wiiu_joypad_query_pad(port)) return 0; - return joypad_state.pad_drivers[port]->axis(port, joyaxis); + return joypad_state.pads[port].input_driver->axis(port, joyaxis); } static int16_t wiiu_joypad_state( @@ -99,11 +99,11 @@ static int16_t wiiu_joypad_state( ? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis; if ( (uint16_t)joykey != NO_BTN - && (joypad_state.pad_drivers[port]->button(port_idx, (uint16_t)joykey)) + && (joypad_state.pads[port].input_driver->button(port_idx, (uint16_t)joykey)) ) ret |= ( 1 << i); else if (joyaxis != AXIS_NONE && - ((float)abs(joypad_state.pad_drivers[port]->axis(port_idx, joyaxis)) + ((float)abs(joypad_state.pads[port].input_driver->axis(port_idx, joyaxis)) / 0x8000) > joypad_info->axis_threshold) ret |= (1 << i); } @@ -123,7 +123,7 @@ static const char* wiiu_joypad_name(unsigned pad) if (!wiiu_joypad_query_pad(pad)) return "N/A"; - return joypad_state.pad_drivers[pad]->name(pad); + return joypad_state.pads[pad].input_driver->name(pad); } input_device_driver_t wiiu_joypad = diff --git a/input/include/wiiu/hid.h b/input/include/wiiu/hid.h index fc8142028c..92c82a4344 100644 --- a/input/include/wiiu/hid.h +++ b/input/include/wiiu/hid.h @@ -51,7 +51,8 @@ struct wiiu_hid { */ struct wiiu_adapter { wiiu_adapter_t *next; - int pad; + pad_connection_interface_t *pad_driver; + void *pad_driver_data; wiiu_hid_t *hid; uint16_t vendor_id; uint16_t product_id; diff --git a/input/include/wiiu/input.h b/input/include/wiiu/input.h index 6bb20f06ae..e07ebc2508 100644 --- a/input/include/wiiu/input.h +++ b/input/include/wiiu/input.h @@ -94,7 +94,6 @@ typedef struct wiiu_hidpad { typedef struct wiiu_joypad { joypad_connection_t pads[MAX_USERS]; - input_device_driver_t *pad_drivers[MAX_USERS]; int max_slot; wiiu_kpad_t kpad; diff --git a/input/input_autodetect_builtin.c b/input/input_autodetect_builtin.c index 7636821d77..2276886b9f 100644 --- a/input/input_autodetect_builtin.c +++ b/input/input_autodetect_builtin.c @@ -304,6 +304,28 @@ DECL_AXIS_EX(r_x_minus, -2, "C-stick left") \ DECL_AXIS_EX(r_y_plus, +3, "C-stick up") \ DECL_AXIS_EX(r_y_minus, -3, "C-stick down") +#define WIIUINPUT_WAVEBIRD_DEFAULT_BINDS \ +DECL_BTN_EX(a, 8, "A") \ +DECL_BTN_EX(b, 0, "B") \ +DECL_BTN_EX(x, 9, "X") \ +DECL_BTN_EX(y, 1, "Y") \ +DECL_BTN_EX(left, 6, "D-Pad Left") \ +DECL_BTN_EX(right, 7, "D-Pad Right") \ +DECL_BTN_EX(down, 5, "D-Pad Down") \ +DECL_BTN_EX(up, 4, "D-Pad Up") \ +DECL_BTN_EX(start, 3, "Start/Pause") \ +DECL_BTN_EX(select, 2, "Z") \ +DECL_BTN_EX(r, 10, "R Trigger") \ +DECL_BTN_EX(l, 11, "L Trigger") \ +DECL_AXIS_EX(l_x_plus, +0, "Analog right") \ +DECL_AXIS_EX(l_x_minus, -0, "Analog left") \ +DECL_AXIS_EX(l_y_plus, +1, "Analog up") \ +DECL_AXIS_EX(l_y_minus, -1, "Analog down") \ +DECL_AXIS_EX(r_x_plus, +2, "C-stick right") \ +DECL_AXIS_EX(r_x_minus, -2, "C-stick left") \ +DECL_AXIS_EX(r_y_plus, +3, "C-stick up") \ +DECL_AXIS_EX(r_y_minus, -3, "C-stick down") + #define WIIUINPUT_DS3_DEFAULT_BINDS \ DECL_BTN_EX(menu_toggle, 16, "Playstation") \ DECL_BTN_EX(select, 2, "Select") \ @@ -743,7 +765,8 @@ const char* const input_builtin_autoconfs[] = DECL_AUTOCONF_DEVICE(PAD_NAME_NUNCHUK, "wiiu", WIIUINPUT_NUNCHUK_DEFAULT_BINDS), DECL_AUTOCONF_DEVICE(PAD_NAME_CLASSIC, "wiiu", WIIUINPUT_CLASSIC_CONTROLLER_DEFAULT_BINDS), DECL_AUTOCONF_DEVICE(PAD_NAME_HID, "wiiu", WIIUINPUT_GAMEPAD_DEFAULT_BINDS), - DECL_AUTOCONF_DEVICE("Wii U GC Controller Adapter", "wiiu", WIIUINPUT_GAMECUBE_DEFAULT_BINDS), + DECL_AUTOCONF_DEVICE("GameCube controller", "wiiu", WIIUINPUT_GAMECUBE_DEFAULT_BINDS), + DECL_AUTOCONF_DEVICE("WaveBird controller", "wiiu", WIIUINPUT_WAVEBIRD_DEFAULT_BINDS), DECL_AUTOCONF_DEVICE("PLAYSTATION(R)3 Controller", "wiiu", WIIUINPUT_DS3_DEFAULT_BINDS), #endif #ifdef __PS3__ From c832828ddb03032cf73719f550b1c4784de22c01 Mon Sep 17 00:00:00 2001 From: Nathan Strong Date: Mon, 4 Oct 2021 00:01:46 +0000 Subject: [PATCH 05/10] Figured out the cause of crash == DETAILS cause of crash: trying to deference init when it's null the reason it was going into deregister: the HID/VID lookup was failing because it wasn't getting initialized first cause of 2nd crash: the "end of pad list" method looked for an entry with a magic value, so we add an end marker --- input/connect/joypad_connection.c | 8 +++++++- input/drivers_joypad/wiiu_joypad.c | 1 + input/include/wiiu/input.h | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/input/connect/joypad_connection.c b/input/connect/joypad_connection.c index 1b6ad4c750..520a05eb6b 100644 --- a/input/connect/joypad_connection.c +++ b/input/connect/joypad_connection.c @@ -143,10 +143,15 @@ void init_pad_map() { pad_map[12].pid = PID_HORI_MINI_WIRED_PS4; } + joypad_connection_entry_t *find_connection_entry(int16_t vid, int16_t pid, const char *name) { unsigned i; const bool has_name = !string_is_empty(name); + if(pad_map[0].vid == 0) { + init_pad_map(); + } + for(i = 0; pad_map[i].name != NULL; i++) { const char *name_match = has_name ? strstr(pad_map[i].name, name) : NULL; /* The Wii Pro Controller and Wii U pro controller have the same VID/PID, so we have to use the @@ -169,9 +174,10 @@ void pad_connection_pad_deregister(joypad_connection_t *joyconn, pad_connection_ int i; RARCH_LOG("pad_connection_pad_deregister\n"); + RARCH_LOG("joyconn: 0x%08lx iface: 0x%08lx pad_data: 0x%08lx\n", (unsigned long)joyconn, (unsigned long)iface, (unsigned long)pad_data); for(i = 0; !joypad_is_end_of_list(&joyconn[i]); i++) { RARCH_LOG("joyconn[i].connected = %d, joyconn[i].iface == iface = %d\n", joyconn[i].connected, joyconn[i].iface == iface); - if(joyconn[i].connected && joyconn[i].iface == iface) { + if(joyconn[i].connected && joyconn[i].iface == iface && iface != NULL) { if(iface->set_rumble) { RARCH_LOG("set_rumble"); iface->set_rumble(joyconn[i].connection, RETRO_RUMBLE_STRONG, 0); diff --git a/input/drivers_joypad/wiiu_joypad.c b/input/drivers_joypad/wiiu_joypad.c index 9628e0d6fa..43f0b4000a 100644 --- a/input/drivers_joypad/wiiu_joypad.c +++ b/input/drivers_joypad/wiiu_joypad.c @@ -25,6 +25,7 @@ wiiu_joypad_t joypad_state = {0}; static void *wiiu_joypad_init(void *data) { memset(&joypad_state, 0, sizeof(wiiu_joypad_t)); + joypad_state.pads[MAX_USERS].data = (void *)0xdeadbeef; joypad_state.max_slot = MAX_USERS; input_hid_init_first(); diff --git a/input/include/wiiu/input.h b/input/include/wiiu/input.h index e07ebc2508..e0c36d2b9e 100644 --- a/input/include/wiiu/input.h +++ b/input/include/wiiu/input.h @@ -93,7 +93,7 @@ typedef struct wiiu_hidpad { } wiiu_hidpad_t; typedef struct wiiu_joypad { - joypad_connection_t pads[MAX_USERS]; + joypad_connection_t pads[MAX_USERS+1]; int max_slot; wiiu_kpad_t kpad; From 2715b4c9c0b799f2ac6d9a6fdad817e6806849f4 Mon Sep 17 00:00:00 2001 From: Nathan Strong Date: Tue, 5 Oct 2021 02:25:52 +0000 Subject: [PATCH 06/10] get gamecube adapter working --- input/connect/joypad_connection.c | 6 +++++- input/drivers_hid/wiiu_hid.c | 8 +------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/input/connect/joypad_connection.c b/input/connect/joypad_connection.c index 520a05eb6b..077d099e97 100644 --- a/input/connect/joypad_connection.c +++ b/input/connect/joypad_connection.c @@ -220,6 +220,7 @@ void pad_connection_pad_refresh(joypad_connection_t *joyconn, pad_connection_int switch(state) { /* The pad slot is bound to a joypad that's no longer connected */ case PAD_CONNECT_BOUND: + RARCH_LOG("PAD_CONNECT_BOUND (0x%02x)\n", state); joypad = iface->joypad(device_data, i); slot = joypad_to_slot(joyconn, joypad); input_autoconfigure_disconnect(slot, iface->get_name(joypad->connection)); @@ -236,10 +237,14 @@ void pad_connection_pad_refresh(joypad_connection_t *joyconn, pad_connection_int joypad->data = handle; joypad->iface = iface; joypad->input_driver = input_driver; + joypad->connected = true; input_pad_connect(slot, input_driver); } break; default: + if(state > 0x03) { + RARCH_LOG("Unrecognized state: 0x%02x", state); + } break; } } @@ -260,7 +265,6 @@ void pad_connection_pad_register(joypad_connection_t *joyconn, pad_connection_in for(i = 0; i < max_pad; i++) { status = iface->multi_pad ? iface->status(device_data, i) : PAD_CONNECT_READY; - RARCH_LOG("pad %d: status = %d\n", i, status); if(status == PAD_CONNECT_READY) { found_slot = (slot == SLOT_AUTO) ? pad_connection_find_vacant_pad(joyconn) : slot; if(found_slot < 0) { diff --git a/input/drivers_hid/wiiu_hid.c b/input/drivers_hid/wiiu_hid.c index 7bc1c3dcfd..3efc2ac0c6 100644 --- a/input/drivers_hid/wiiu_hid.c +++ b/input/drivers_hid/wiiu_hid.c @@ -44,7 +44,6 @@ static joypad_connection_t *get_pad(wiiu_hid_t *hid, unsigned slot) } result = &joypad_state.pads[slot]; if (!result->connected || !result->iface || !result->connection) { - RARCH_LOG("Pad not ready (connected: %d, iface: %08lx, connection: %08lx)\n", result->connected, (unsigned long)result->iface, (unsigned long)result->connection); return NULL; } return result; @@ -430,16 +429,11 @@ static void synchronized_process_adapters(wiiu_hid_t *hid) adapter->state = try_init_driver(adapter); break; case ADAPTER_STATE_READY: - RARCH_LOG("ADAPTER_STATE_READY"); + case ADAPTER_STATE_READING: if(adapter->pad_driver && adapter->pad_driver->multi_pad) { pad_connection_pad_refresh(joypad_state.pads, adapter->pad_driver, adapter->pad_driver_data, adapter, &hidpad_driver); } - break; - case ADAPTER_STATE_READING: - RARCH_LOG("ADAPTER_STATE_READING"); - break; case ADAPTER_STATE_DONE: - RARCH_LOG("ADAPTER_STATE_DONE"); break; case ADAPTER_STATE_GC: { From e02e345a288c5c0bfbd38a28d61b209ecbfb4297 Mon Sep 17 00:00:00 2001 From: Nathan Strong Date: Tue, 5 Oct 2021 15:42:25 +0000 Subject: [PATCH 07/10] Make GCA driver compatible with other HID drivers == DETAILS Use a little trickery to ensure the GCA driver continues working with other HID implementation. I've expanded the joypad implementation to support multi-pad devices. However, this requires changes to each HID implementation to actually function. I've made the necessary changes for WIIU, but I don't have the means of making the change in the other HID implementations. So, I've built in a backwards-compatibilty mode for the driver. The trick is to have an identifier byte at the top of both data structs that the driver returns. We can then use that byte to determine which of the structs has been passed to the pad functions and act accordingly. In the GCA case, for non-wiiu platforms, it will simply expose port 1 of the GCA and the other 3 ports do nothing. --- input/connect/connect_wiiugca.c | 35 +++++++++++++++++++++++++++------ input/input_types.h | 2 +- retroarch.c | 2 +- 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/input/connect/connect_wiiugca.c b/input/connect/connect_wiiugca.c index 784bbc5d15..2e8bd45615 100644 --- a/input/connect/connect_wiiugca.c +++ b/input/connect/connect_wiiugca.c @@ -24,6 +24,9 @@ #define GCA_MAX_PAD 4 +#define GCA_TYPE_DEVICE 0x00 +#define GCA_TYPE_PAD 0x01 + #define GCA_PORT_INITIALIZING 0x00 #define GCA_PORT_POWERED 0x04 #define GCA_PORT_CONNECTED 0x10 @@ -34,6 +37,7 @@ typedef struct hidpad_wiiugca_data gca_device_data_t; struct hidpad_wiiugca_pad_data { + uint8_t datatype; gca_device_data_t *device_data; joypad_connection_t *joypad; int pad_index; @@ -44,6 +48,7 @@ struct hidpad_wiiugca_pad_data struct hidpad_wiiugca_data { + uint8_t datatype; void *handle; hid_driver_t *driver; char connected[GCA_MAX_PAD]; @@ -76,6 +81,7 @@ static void* hidpad_wiiugca_init(void *data, uint32_t slot, hid_driver_t *driver device->handle = data; for(i = 0; i < GCA_MAX_PAD; i++) { + device->pad_data[i].datatype = GCA_TYPE_PAD; device->pad_data[i].device_data = device; device->pad_data[i].joypad = NULL; device->pad_data[i].pad_index = i; @@ -99,9 +105,13 @@ static void hidpad_wiiugca_deinit(void *device_data) static void hidpad_wiiugca_get_buttons(void *pad_data, input_bits_t *state) { gca_pad_data_t *pad = (gca_pad_data_t *)pad_data; - if (pad) - { - BITS_COPY16_PTR(state, pad->buttons); + if (pad) { + if(pad->datatype == GCA_TYPE_PAD) { + BITS_COPY16_PTR(state, pad->buttons); + } else { + gca_device_data_t *device = (gca_device_data_t *)pad_data; + BITS_COPY16_PTR(state, device->pad_data[0].buttons); + } } else { @@ -119,7 +129,12 @@ static int16_t hidpad_wiiugca_get_axis(void *pad_data, unsigned axis) if (!pad || axis_data.axis >= 4) return 0; - return gamepad_get_axis_value(pad->analog, &axis_data); + if(pad->datatype == GCA_TYPE_PAD) + return gamepad_get_axis_value(pad->analog, &axis_data); + else { + gca_device_data_t *device = (gca_device_data_t *)pad_data; + return gamepad_get_axis_value(device->pad_data[0].analog, &axis_data); + } } static void update_button_state(gca_pad_data_t *pad) { @@ -227,7 +242,7 @@ static void hidpad_wiiugca_set_rumble(void *data, const char *hidpad_wiiugca_get_name(void *pad_data) { gca_pad_data_t *pad = (gca_pad_data_t *)pad_data; - if(!pad) { + if(!pad || pad->datatype != GCA_TYPE_PAD) { return DEVICE_NAME; } @@ -246,7 +261,15 @@ const char *hidpad_wiiugca_get_name(void *pad_data) static int32_t hidpad_wiiugca_button(void *pad_data, uint16_t joykey) { gca_pad_data_t *pad = (gca_pad_data_t *)pad_data; - if (!pad || !pad->device_data || joykey > 31 || pad->joypad == NULL) + + if(!pad) return 0; + + if(pad->datatype != GCA_TYPE_PAD) { + gca_device_data_t *device = (gca_device_data_t *)pad_data; + pad = &device->pad_data[0]; + } + + if (!pad->device_data || joykey > 31 || pad->joypad == NULL) return 0; return pad->buttons & (1 << joykey); diff --git a/input/input_types.h b/input/input_types.h index 141ea1830a..235bae2626 100644 --- a/input/input_types.h +++ b/input/input_types.h @@ -107,5 +107,5 @@ typedef struct rarch_joypad_info rarch_joypad_info_t; typedef struct input_driver input_driver_t; typedef struct input_keyboard_ctx_wait input_keyboard_ctx_wait_t; typedef struct turbo_buttons turbo_buttons_t; - +typedef struct joypad_connection joypad_connection_t; #endif /* __INPUT_TYPES__H */ diff --git a/retroarch.c b/retroarch.c index 25e106f68b..9f53e99ad7 100644 --- a/retroarch.c +++ b/retroarch.c @@ -15437,7 +15437,7 @@ const char* config_get_joypad_driver_options(void) void *hid_driver_get_data(void) { struct rarch_state *p_rarch = &rarch_st; - return p_rarch->hid_data; + return (void *)p_rarch->hid_data; } /* This is only to be called after we've invoked free() on the From 002c9a30c0b2f50e906e8246f765b574ecffbd1a Mon Sep 17 00:00:00 2001 From: Nathan Strong Date: Tue, 5 Oct 2021 17:43:03 +0000 Subject: [PATCH 08/10] Implement button() for most HID drivers == DETAILS The HID drivers in `input/connect/` were missing an implementation for button(), so I added it. The only exception is the wii driver, which is really complicated and more than I wanted to try to tackle-- especially since WIIU has its own wiimote drivers. --- input/connect/connect_nesusb.c | 10 +++++- input/connect/connect_ps2adapter.c | 10 +++++- input/connect/connect_ps4.c | 48 ++++++++++++++++++++++++- input/connect/connect_ps4_hori_mini.c | 10 +++++- input/connect/connect_psxadapter.c | 10 +++++- input/connect/connect_retrode.c | 10 +++++- input/connect/connect_snesusb.c | 10 +++++- input/connect/connect_wii.c | 2 ++ input/connect/connect_wiiupro.c | 52 ++++++++++++++++++++++++++- 9 files changed, 154 insertions(+), 8 deletions(-) diff --git a/input/connect/connect_nesusb.c b/input/connect/connect_nesusb.c index 38493c4556..ccb8031d9a 100644 --- a/input/connect/connect_nesusb.c +++ b/input/connect/connect_nesusb.c @@ -139,6 +139,14 @@ const char * hidpad_nesusb_get_name(void *data) return "Generic NES USB Controller"; } +static int32_t hidpad_nesusb_button(void *data, uint16_t joykey) +{ + struct hidpad_nesusb_data *pad = (struct hidpad_nesusb_data*)data; + if (!pad || joykey > 31) + return 0; + return pad->buttons & (1 << joykey); +} + pad_connection_interface_t pad_connection_nesusb = { hidpad_nesusb_init, hidpad_nesusb_deinit, @@ -147,6 +155,6 @@ pad_connection_interface_t pad_connection_nesusb = { hidpad_nesusb_get_buttons, hidpad_nesusb_get_axis, hidpad_nesusb_get_name, - NULL, /* button */ + hidpad_nesusb_button, false, }; diff --git a/input/connect/connect_ps2adapter.c b/input/connect/connect_ps2adapter.c index 74b1cd47be..1dbc079b6a 100644 --- a/input/connect/connect_ps2adapter.c +++ b/input/connect/connect_ps2adapter.c @@ -174,6 +174,14 @@ const char * hidpad_ps2adapter_get_name(void *data) return "PS2/PSX Controller Adapter"; } +static int32_t hidpad_ps2adapter_button(void *data, uint16_t joykey) +{ + struct hidpad_ps2adapter_data *pad = (struct hidpad_ps2adapter_data*)data; + if (!pad || joykey > 31) + return 0; + return pad->buttons & (1 << joykey); +} + pad_connection_interface_t pad_connection_ps2adapter = { hidpad_ps2adapter_init, hidpad_ps2adapter_deinit, @@ -182,6 +190,6 @@ pad_connection_interface_t pad_connection_ps2adapter = { hidpad_ps2adapter_get_buttons, hidpad_ps2adapter_get_axis, hidpad_ps2adapter_get_name, - NULL, + hidpad_ps2adapter_button, false, }; diff --git a/input/connect/connect_ps4.c b/input/connect/connect_ps4.c index 33e9ccc782..a0a236c662 100644 --- a/input/connect/connect_ps4.c +++ b/input/connect/connect_ps4.c @@ -285,6 +285,52 @@ static void hidpad_ps4_set_rumble(void *data, #endif } +static int32_t hidpad_ps4_button(void *data, uint16_t joykey) +{ + struct hidpad_ps4_data *device = (struct hidpad_ps4_data*)data; + struct ps4 *rpt = device ? + (struct ps4*)&device->data : NULL; + if (!device || !rpt || joykey > 31) + return 0; + + switch(joykey) { + case RETRO_DEVICE_ID_JOYPAD_R3: + return rpt->btn.r3; + case RETRO_DEVICE_ID_JOYPAD_L3: + return rpt->btn.l3; + case RETRO_DEVICE_ID_JOYPAD_START: + return rpt->btn.options; + case RETRO_DEVICE_ID_JOYPAD_SELECT: + return rpt->btn.share; + case RETRO_DEVICE_ID_JOYPAD_R2: + return rpt->btn.r2; + case RETRO_DEVICE_ID_JOYPAD_L2: + return rpt->btn.l2; + case RETRO_DEVICE_ID_JOYPAD_R: + return rpt->btn.r1; + case RETRO_DEVICE_ID_JOYPAD_L: + return rpt->btn.l1; + case RETRO_DEVICE_ID_JOYPAD_X: + return rpt->btn.triangle; + case RETRO_DEVICE_ID_JOYPAD_A: + return rpt->btn.circle; + case RETRO_DEVICE_ID_JOYPAD_B: + return rpt->btn.cross; + case RETRO_DEVICE_ID_JOYPAD_Y: + return rpt->btn.square; + case RETRO_DEVICE_ID_JOYPAD_LEFT: + case RETRO_DEVICE_ID_JOYPAD_RIGHT: + case RETRO_DEVICE_ID_JOYPAD_DOWN: + case RETRO_DEVICE_ID_JOYPAD_UP: + return hidpad_ps4_check_dpad(rpt, joykey); + case RARCH_MENU_TOGGLE: + return rpt->btn.ps; + default: + return 0; + } +} + + pad_connection_interface_t pad_connection_ps4 = { hidpad_ps4_init, hidpad_ps4_deinit, @@ -293,6 +339,6 @@ pad_connection_interface_t pad_connection_ps4 = { hidpad_ps4_get_buttons, hidpad_ps4_get_axis, NULL, /* get_name */ - NULL, /* button */ + hidpad_ps4_button, false }; diff --git a/input/connect/connect_ps4_hori_mini.c b/input/connect/connect_ps4_hori_mini.c index ee38f5d73a..31499687da 100644 --- a/input/connect/connect_ps4_hori_mini.c +++ b/input/connect/connect_ps4_hori_mini.c @@ -178,6 +178,14 @@ const char * hidpad_ps4_hori_mini_get_name(void *data) return "HORI mini wired PS4"; } +static int32_t hidpad_ps4_hori_mini_button(void *data, uint16_t joykey) +{ + struct hidpad_ps4_hori_mini_data *pad = (struct hidpad_ps4_hori_mini_data*)data; + if (!pad || joykey > 31) + return 0; + return pad->buttons & (1 << joykey); +} + pad_connection_interface_t pad_connection_ps4_hori_mini = { hidpad_ps4_hori_mini_init, hidpad_ps4_hori_mini_deinit, @@ -186,6 +194,6 @@ pad_connection_interface_t pad_connection_ps4_hori_mini = { hidpad_ps4_hori_mini_get_buttons, hidpad_ps4_hori_mini_get_axis, hidpad_ps4_hori_mini_get_name, - NULL, /* button */ + hidpad_ps4_hori_mini_button, /* button */ false }; diff --git a/input/connect/connect_psxadapter.c b/input/connect/connect_psxadapter.c index 89ec500e84..094ed4c16a 100644 --- a/input/connect/connect_psxadapter.c +++ b/input/connect/connect_psxadapter.c @@ -183,6 +183,14 @@ const char * hidpad_psxadapter_get_name(void *data) return "PSX to PS3 Controller Adapter"; } +static int32_t hidpad_psxadapter_button(void *data, uint16_t joykey) +{ + struct hidpad_psxadapter_data *pad = (struct hidpad_psxadapter_data*)data; + if (!pad || joykey > 31) + return 0; + return pad->buttons & (1 << joykey); +} + pad_connection_interface_t pad_connection_psxadapter = { hidpad_psxadapter_init, hidpad_psxadapter_deinit, @@ -191,6 +199,6 @@ pad_connection_interface_t pad_connection_psxadapter = { hidpad_psxadapter_get_buttons, hidpad_psxadapter_get_axis, hidpad_psxadapter_get_name, - NULL, /* button */ + hidpad_psxadapter_button, false }; diff --git a/input/connect/connect_retrode.c b/input/connect/connect_retrode.c index eaf5bd8d51..648bf18a01 100644 --- a/input/connect/connect_retrode.c +++ b/input/connect/connect_retrode.c @@ -189,6 +189,14 @@ const char * hidpad_retrode_get_name(void *data) return "Retrode"; } +static int32_t hidpad_retrode_button(void *data, uint16_t joykey) +{ + struct hidpad_retrode_data *pad = (struct hidpad_retrode_data*)data; + if (!pad || joykey > 31) + return 0; + return pad->buttons & (1 << joykey); +} + pad_connection_interface_t pad_connection_retrode = { hidpad_retrode_init, hidpad_retrode_deinit, @@ -197,6 +205,6 @@ pad_connection_interface_t pad_connection_retrode = { hidpad_retrode_get_buttons, hidpad_retrode_get_axis, hidpad_retrode_get_name, - NULL, /* button */ + hidpad_retrode_button, false, }; diff --git a/input/connect/connect_snesusb.c b/input/connect/connect_snesusb.c index 7a452abe41..39fb9a9340 100644 --- a/input/connect/connect_snesusb.c +++ b/input/connect/connect_snesusb.c @@ -140,6 +140,14 @@ const char * hidpad_snesusb_get_name(void *data) return "Generic SNES USB Controller"; } +static int32_t hidpad_snesusb_button(void *data, uint16_t joykey) +{ + struct hidpad_snesusb_data *pad = (struct hidpad_snesusb_data*)data; + if (!pad || joykey > 31) + return 0; + return pad->buttons & (1 << joykey); +} + pad_connection_interface_t pad_connection_snesusb = { hidpad_snesusb_init, hidpad_snesusb_deinit, @@ -148,6 +156,6 @@ pad_connection_interface_t pad_connection_snesusb = { hidpad_snesusb_get_buttons, hidpad_snesusb_get_axis, hidpad_snesusb_get_name, - NULL, /* button */ + hidpad_snesusb_button, false }; diff --git a/input/connect/connect_wii.c b/input/connect/connect_wii.c index c3d5a5a783..1c7029a56f 100644 --- a/input/connect/connect_wii.c +++ b/input/connect/connect_wii.c @@ -722,6 +722,8 @@ static void hidpad_wii_set_rumble(void *data, (void)strength; } +/* TODO: implement hidpad_wii_button(). */ + pad_connection_interface_t pad_connection_wii = { hidpad_wii_init, hidpad_wii_deinit, diff --git a/input/connect/connect_wiiupro.c b/input/connect/connect_wiiupro.c index ff26bb5064..51ee3f3ad1 100644 --- a/input/connect/connect_wiiupro.c +++ b/input/connect/connect_wiiupro.c @@ -248,6 +248,56 @@ static void hidpad_wiiupro_set_rumble(void *data, /* TODO */ } +static int32_t hidpad_wiiupro_button(void *data, uint16_t joykey) +{ + struct hidpad_wiiupro_data *device = (struct hidpad_wiiupro_data*)data; + struct wiiupro *rpt = device ? + (struct wiiupro*)&device->data : NULL; + + if (!device || !rpt) + return 0; + + switch(joykey) { + case RETRO_DEVICE_ID_JOYPAD_R3: + return rpt->btn.r3; + case RETRO_DEVICE_ID_JOYPAD_L3: + return rpt->btn.l3; + case RETRO_DEVICE_ID_JOYPAD_START: + return rpt->btn.plus; + case RETRO_DEVICE_ID_JOYPAD_SELECT: + return rpt->btn.minus; + case RETRO_DEVICE_ID_JOYPAD_R2: + return rpt->btn.zr; + case RETRO_DEVICE_ID_JOYPAD_L2: + return rpt->btn.zl; + case RETRO_DEVICE_ID_JOYPAD_R: + return rpt->btn.r; + case RETRO_DEVICE_ID_JOYPAD_L: + return rpt->btn.l; + case RETRO_DEVICE_ID_JOYPAD_X: + return rpt->btn.x; + case RETRO_DEVICE_ID_JOYPAD_A: + return rpt->btn.a; + case RETRO_DEVICE_ID_JOYPAD_B: + return rpt->btn.b; + case RETRO_DEVICE_ID_JOYPAD_Y: + return rpt->btn.y; + case RETRO_DEVICE_ID_JOYPAD_LEFT: + return rpt->btn.left; + case RETRO_DEVICE_ID_JOYPAD_RIGHT: + return rpt->btn.right; + case RETRO_DEVICE_ID_JOYPAD_DOWN: + return rpt->btn.down; + case RETRO_DEVICE_ID_JOYPAD_UP: + return rpt->btn.up; + case RARCH_MENU_TOGGLE: + return rpt->btn.home; + default: + return 0; + } + +} + pad_connection_interface_t pad_connection_wiiupro = { hidpad_wiiupro_init, hidpad_wiiupro_deinit, @@ -256,6 +306,6 @@ pad_connection_interface_t pad_connection_wiiupro = { hidpad_wiiupro_get_buttons, hidpad_wiiupro_get_axis, NULL, /* get_name */ - NULL, /* button */ + hidpad_wiiupro_button, false }; From 3e91e3fbc94d43165681cbcd060d50fd212644ad Mon Sep 17 00:00:00 2001 From: Nathan Strong Date: Tue, 5 Oct 2021 18:15:19 +0000 Subject: [PATCH 09/10] fix up non-wiiu side of ifdefs for ds3 --- input/connect/connect_ps3.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/input/connect/connect_ps3.c b/input/connect/connect_ps3.c index 009c8c5b90..217a37fcaa 100644 --- a/input/connect/connect_ps3.c +++ b/input/connect/connect_ps3.c @@ -93,7 +93,7 @@ static int32_t ds3_send_control_packet(void *data, uint32_t slot, hid_driver_t * #if defined(WIIU) result = driver->set_report(data, HID_REPORT_OUTPUT, DS3_RUMBLE_REPORT_ID, packet_buffer+PACKET_OFFSET, 64-PACKET_OFFSET); #else - result = driver->send_control(data, packet_buffer+PACKET_OFFSET, 64-PACKET_OFFSET); + driver->send_control(data, packet_buffer+PACKET_OFFSET, 64-PACKET_OFFSET); #endif /* WIIU */ return result; } @@ -102,7 +102,8 @@ static int32_t ds3_send_activation_packet(void *data, uint32_t slot, hid_driver_ #ifdef WIIU return driver->set_report(data, HID_REPORT_FEATURE, DS3_ACTIVATION_REPORT_ID, ds3_activation_packet, sizeof(ds3_activation_packet)); #else - return driver->send_control(data, ds3_activation_packet, sizeof(ds3_activation_packet)); + driver->send_control(data, ds3_activation_packet, sizeof(ds3_activation_packet)); + return 0; #endif } From e8ec65ecf71e348397483c3a37e0b56aa696d279 Mon Sep 17 00:00:00 2001 From: Nathan Strong Date: Tue, 5 Oct 2021 19:05:12 +0000 Subject: [PATCH 10/10] squelch format warning --- input/connect/connect_ps3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/input/connect/connect_ps3.c b/input/connect/connect_ps3.c index 217a37fcaa..68af2e76b5 100644 --- a/input/connect/connect_ps3.c +++ b/input/connect/connect_ps3.c @@ -175,8 +175,8 @@ static void ds3_packet_handler(void *data, uint8_t *packet, uint16_t size) if (size > sizeof(instance->data)) { - RARCH_ERR("[ds3]: Expecting packet to be %d but was %d\n", - sizeof(instance->data), size); + RARCH_ERR("[ds3]: Expecting packet to be %ld but was %d\n", + (long)sizeof(instance->data), size); return; }