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/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_nesusb.c b/input/connect/connect_nesusb.c index cc557cee46..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,4 +155,6 @@ pad_connection_interface_t pad_connection_nesusb = { hidpad_nesusb_get_buttons, hidpad_nesusb_get_axis, hidpad_nesusb_get_name, + hidpad_nesusb_button, + false, }; diff --git a/input/connect/connect_ps2adapter.c b/input/connect/connect_ps2adapter.c index 6a324b9491..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,4 +190,6 @@ pad_connection_interface_t pad_connection_ps2adapter = { hidpad_ps2adapter_get_buttons, hidpad_ps2adapter_get_axis, hidpad_ps2adapter_get_name, + hidpad_ps2adapter_button, + false, }; diff --git a/input/connect/connect_ps3.c b/input/connect/connect_ps3.c index 5ea88264ad..68af2e76b5 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 + 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 + driver->send_control(data, ds3_activation_packet, sizeof(ds3_activation_packet)); + return 0; + #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 %ld but was %d\n", + (long)sizeof(instance->data), size); + return; + } -#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,43 @@ 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, + false, +}; \ No newline at end of file diff --git a/input/connect/connect_ps4.c b/input/connect/connect_ps4.c index 5f9ae933b6..a0a236c662 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 { @@ -286,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,5 +338,7 @@ pad_connection_interface_t pad_connection_ps4 = { hidpad_ps4_set_rumble, hidpad_ps4_get_buttons, hidpad_ps4_get_axis, - NULL, + NULL, /* get_name */ + hidpad_ps4_button, + false }; diff --git a/input/connect/connect_ps4_hori_mini.c b/input/connect/connect_ps4_hori_mini.c index cd4e529622..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,4 +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, + hidpad_ps4_hori_mini_button, /* button */ + false }; diff --git a/input/connect/connect_psxadapter.c b/input/connect/connect_psxadapter.c index 27332a149f..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,4 +199,6 @@ pad_connection_interface_t pad_connection_psxadapter = { hidpad_psxadapter_get_buttons, hidpad_psxadapter_get_axis, hidpad_psxadapter_get_name, + hidpad_psxadapter_button, + false }; diff --git a/input/connect/connect_retrode.c b/input/connect/connect_retrode.c index 58fc31f504..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,4 +205,6 @@ pad_connection_interface_t pad_connection_retrode = { hidpad_retrode_get_buttons, hidpad_retrode_get_axis, hidpad_retrode_get_name, + hidpad_retrode_button, + false, }; diff --git a/input/connect/connect_snesusb.c b/input/connect/connect_snesusb.c index 13bf4a0d14..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,4 +156,6 @@ pad_connection_interface_t pad_connection_snesusb = { hidpad_snesusb_get_buttons, hidpad_snesusb_get_axis, hidpad_snesusb_get_name, + hidpad_snesusb_button, + false }; diff --git a/input/connect/connect_wii.c b/input/connect/connect_wii.c index 974e9c61ad..1c7029a56f 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 @@ -723,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, @@ -730,5 +731,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 012d29e6d0..2e8bd45615 100644 --- a/input/connect/connect_wiiugca.c +++ b/input/connect/connect_wiiugca.c @@ -21,17 +21,45 @@ #include #include "joypad_connection.h" #include "../input_defines.h" -#include "../common/hid/hid_device_driver.h" + +#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 +#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 +{ + uint8_t datatype; + 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; + uint8_t datatype; + void *handle; hid_driver_t *driver; + 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 +67,79 @@ 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].datatype = GCA_TYPE_PAD; + 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) { + 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 + { + 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; + 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 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 +155,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,11 +239,86 @@ 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 || pad->datatype != GCA_TYPE_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 *pad_data, uint16_t joykey) { + gca_pad_data_t *pad = (gca_pad_data_t *)pad_data; + + 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); +} + +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 = { @@ -157,4 +329,11 @@ pad_connection_interface_t pad_connection_wiiugca = { hidpad_wiiugca_get_buttons, 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 01e20252c5..51ee3f3ad1 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 { @@ -249,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,5 +305,7 @@ pad_connection_interface_t pad_connection_wiiupro = { hidpad_wiiupro_set_rumble, hidpad_wiiupro_get_buttons, hidpad_wiiupro_get_axis, - NULL, + NULL, /* get_name */ + hidpad_wiiupro_button, + false }; diff --git a/input/connect/joypad_connection.c b/input/connect/joypad_connection.c index 6174c7f45b..077d099e97 100644 --- a/input/connect/joypad_connection.c +++ b/input/connect/joypad_connection.c @@ -18,12 +18,33 @@ #include #include +#include "../tasks/tasks_internal.h" #include "../input_driver.h" #include "../../verbosity.h" #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 +114,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,66 +141,197 @@ 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; +} - if (s) - { - unsigned i; - - const bool has_name = !string_is_empty(name); - for (i = 0; name && pad_map[i].name; i++) +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 + * descriptor string to differentiate them. */ + if(pad_map[i].vid == VID_NINTENDO && pad_map[i].pid == PID_NINTENDO_PRO) { - const char *name_match = has_name ? strstr(pad_map[i].name, name) : NULL; + if(!string_is_equal(pad_map[i].name, name)) + continue; + } - /* 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_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_DBG("Pad was not matched. Setting up without an interface.\n"); - s->iface = NULL; - s->data = data; - s->connected = true; + if(name_match || (pad_map[i].vid == vid && pad_map[i].pid == pid)) { + return &pad_map[i]; } } + 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"); + 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 && iface != NULL) { + 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: + 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)); + + 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; + joypad->connected = true; + input_pad_connect(slot, input_driver); + } + break; + default: + if(state > 0x03) { + RARCH_LOG("Unrecognized state: 0x%02x", state); + } + 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; + 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; + + if(pad_map[0].vid == 0) { + init_pad_map(); + } + + entry = find_connection_entry(vid, pid, name); + + return pad_connection_pad_init_entry(joyconn, entry, data, driver); +} + void pad_connection_pad_deinit(joypad_connection_t *joyconn, uint32_t pad) { if (!joyconn || !joyconn->connected) @@ -222,6 +339,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 f68eadb5cd..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); @@ -73,9 +81,24 @@ 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); + /* 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 { + 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 +145,9 @@ 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); +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 256562a988..3efc2ac0c6 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; @@ -31,17 +32,20 @@ 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) { 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; } @@ -363,16 +367,47 @@ 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) { - 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; + 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; } + 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; } @@ -386,35 +421,43 @@ 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: + 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); + } + case ADAPTER_STATE_DONE: + break; + case ADAPTER_STATE_GC: + { + RARCH_LOG("ADAPTER_STATE_GC"); + /* remove from the list */ + if (!prev) + adapters.list = adapter->next; + else + prev->next = adapter->next; - /* 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; + 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: + RARCH_ERR("[hid]: Invalid adapter state: %d\n", adapter->state); + break; + } + prev = keep_prev ? prev : adapter; + keep_prev = false; } OSFastMutex_Unlock(&(adapters.lock)); } @@ -509,9 +552,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); @@ -540,8 +584,7 @@ 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); + adapter->pad_driver->packet_handler(adapter->pad_driver_data, buffer, buffer_size); } } } @@ -553,7 +596,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->driver) ? adapter->driver->name : "unknown"; + const char *device = string_is_empty(adapter->device_name) ? "unknown" : adapter->device_name; switch(hid_error_code) { @@ -632,6 +675,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); } } @@ -688,8 +732,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) { + RARCH_LOG("poll_adapters: read done, ready for garbage collection"); it->state = ADAPTER_STATE_GC; + } } OSFastMutex_Unlock(&(adapters.lock)); @@ -775,8 +821,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; @@ -797,29 +846,40 @@ 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_driver && adapter->pad_driver_data) { + adapter->pad_driver->deinit(adapter->pad_driver_data); + adapter->pad_driver_data = NULL; } free(adapter); } +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 +890,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..9504acc66e 100644 --- a/input/drivers_joypad/wiiu/hidpad_driver.c +++ b/input/drivers_joypad/wiiu/hidpad_driver.c @@ -16,66 +16,52 @@ #include "../../include/wiiu/input.h" -/* TODO/FIXME - static global variables */ -static bool hidpad_ready = false; - -static bool init_hid_driver(void) -{ - return hid_init(&hid_instance, &wiiu_hid, &hidpad_driver, MAX_USERS); -} - static void hidpad_poll(void) { - if (hidpad_ready) - HID_POLL(); + 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; - - hid_deinit(&hid_instance); + joypad_state.hid.ready = false; } 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( @@ -99,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); } @@ -116,7 +102,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 +115,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/kpad_driver.c b/input/drivers_joypad/wiiu/kpad_driver.c index 86e8bec846..a7fd8c02c7 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.pads[slot].input_driver = &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..4e30022a15 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.pads[slot].input_driver = &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 18eb5db822..43f0b4000a 100644 --- a/input/drivers_joypad/wiiu_joypad.c +++ b/input/drivers_joypad/wiiu_joypad.c @@ -16,48 +16,42 @@ #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); - hid_instance.pad_list = pad_connection_init(MAX_USERS); - hid_instance.max_slot = MAX_USERS; + 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(); 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.pads[pad].input_driver && + joypad_state.pads[pad].input_driver->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) @@ -66,21 +60,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.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; - wiiu_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 wiiu_pad_drivers[port]->axis(port, joyaxis); + return joypad_state.pads[port].input_driver->axis(port, joyaxis); } static int16_t wiiu_joypad_state( @@ -106,11 +100,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.pads[port].input_driver->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.pads[port].input_driver->axis(port_idx, joyaxis)) / 0x8000) > joypad_info->axis_threshold) ret |= (1 << i); } @@ -122,9 +116,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) @@ -132,14 +124,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.pads[pad].input_driver->name(pad); } input_device_driver_t wiiu_joypad = @@ -157,8 +142,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/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..92c82a4344 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,9 +51,11 @@ struct wiiu_hid { */ struct wiiu_adapter { wiiu_adapter_t *next; - hid_device_t *driver; - void *driver_handle; + pad_connection_interface_t *pad_driver; + void *pad_driver_data; 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 +63,7 @@ struct wiiu_adapter { int32_t tx_size; uint32_t handle; uint8_t interface_index; + char device_name[32]; bool connected; }; @@ -72,7 +74,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 +83,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..e0c36d2b9e 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,45 @@ struct _wiiu_pad_functions { void (*connect)(unsigned pad, input_device_driver_t *driver); }; +typedef struct _wiimote_state { + uint64_t button_state; + int16_t analog_state[3][2]; + uint8_t type; +} wiimote_state; + +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+1]; + 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..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,8 +765,9 @@ 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("Sony DualShock 3", "wiiu", WIIUINPUT_DS3_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__ DECL_AUTOCONF_DEVICE("SixAxis Controller", "ps3", PS3INPUT_DEFAULT_BINDS), diff --git a/input/input_driver.c b/input/input_driver.c index c13eba5f01..f9eabff8aa 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) + &wiiu_hid, #endif &null_hid, NULL, @@ -3294,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 d372ebc22e..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); @@ -1037,6 +1028,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 diff --git a/input/input_types.h b/input/input_types.h index 4712d90cbe..235bae2626 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; - +typedef struct joypad_connection joypad_connection_t; #endif /* __INPUT_TYPES__H */ diff --git a/retroarch.c b/retroarch.c index 84159e8875..fbe7d52921 100644 --- a/retroarch.c +++ b/retroarch.c @@ -15434,10 +15434,10 @@ 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; + return (void *)p_rarch->hid_data; } /* This is only to be called after we've invoked free() on the