Unify the HID driver architecture

== DETAILS
When I first implemented the Wii U HID architecture, I ended up
having to design my own implementation because, at the time, I did
not have a way to read the HID device string to allow the existing
code to successfully detect the gamepad.

After spending some time experimenting, I've figured out how to
do this. And that means I can better align the HID driver with other
platforms.

change summary:

- create a single state structure for all three sub-types of wiiu pads
  (kpad, wpad, and hid)
- eliminate confusing duplicate pad lists
- eliminate confusing duplicate HID pad drivers (ds3, gamecube
  adapter, etc)
- ensure the ds3 driver still works
This commit is contained in:
Nathan Strong 2021-10-01 00:02:11 -07:00
parent 9edb449471
commit 5da1cd08ff
25 changed files with 411 additions and 1665 deletions

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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
};

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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
};

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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
};

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#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
};

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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));
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 */

View File

@ -21,148 +21,205 @@
#include <boolean.h>
#include "joypad_connection.h"
#include "../input_defines.h"
#include "../common/hid/hid_device_driver.h"
struct hidpad_ps3_data
{
struct pad_connection* connection;
hid_driver_t *driver;
uint32_t slot;
uint32_t buttons;
uint16_t motors[2];
uint8_t data[512];
bool have_led;
};
/*
* TODO: give these more meaningful names.
*/
#include "verbosity.h"
#define DS3_ACTIVATION_REPORT_ID 0xf4
#define DS3_RUMBLE_REPORT_ID 0x01
static void hidpad_ps3_send_control(struct hidpad_ps3_data* device)
{
/* TODO: Can this be modified to turn off motion tracking? */
static uint8_t report_buffer[] = {
0x52, 0x01,
0x00, 0xFF, 0x00, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
typedef struct ds3_instance {
hid_driver_t *hid_driver;
void *handle;
int slot;
bool led_set;
uint32_t buttons;
int16_t analog_state[3][2];
uint16_t motors[2];
uint8_t data[64];
} ds3_instance_t;
/* Turn on the appropriate LED */
report_buffer[11] = 1 << ((device->slot % 4) + 1);
/* Set rumble state */
report_buffer[4] = device->motors[1] >> 8;
report_buffer[6] = device->motors[0] >> 8;
#ifdef HAVE_WIIUSB_HID
report_buffer[1] = 0x03; /* send control message type */
device->driver->send_control(device->connection, &report_buffer[1], sizeof(report_buffer)-1);
#elif defined(WIIU)
device->driver->set_report(device->connection,
HID_REPORT_OUTPUT,
DS3_RUMBLE_REPORT_ID,
report_buffer+2,
sizeof(report_buffer) - (2*sizeof(uint8_t)));
#else
device->driver->send_control(device->connection, report_buffer, sizeof(report_buffer));
static void ds3_update_pad_state(ds3_instance_t *instance);
static void ds3_update_analog_state(ds3_instance_t *instance);
static uint8_t ds3_activation_packet[] = {
#if defined(IOS)
0x53, 0xF4,
#elif defined(HAVE_WIIUSB_HID)
0x02,
#endif
0x42, 0x0c, 0x00, 0x00
};
#if defined(WIIU)
#define PACKET_OFFSET 2
#elif defined(HAVE_WIIUSB_HID)
#define PACKET_OFFSET 1
#else
#define PACKET_OFFSET 0
#endif
#define LED_OFFSET 11
#define MOTOR1_OFFSET 4
#define MOTOR2_OFFSET 6
static uint8_t ds3_control_packet[] = {
0x52, 0x01,
0x00, 0xff, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00
};
static int32_t ds3_send_control_packet(void *data, uint32_t slot, hid_driver_t *driver) {
int32_t result = 0;
uint8_t packet_buffer[64] = {0};
memcpy(packet_buffer, ds3_control_packet, sizeof(ds3_control_packet));
packet_buffer[LED_OFFSET] = 0;
packet_buffer[LED_OFFSET] = 1 << ((slot % 4) + 1);
packet_buffer[MOTOR1_OFFSET] = 0;
packet_buffer[MOTOR2_OFFSET] = 0;
#if defined(HAVE_WIIUSB_HID)
packet_buffer[1] = 0x03;
#endif
#if defined(WIIU)
result = driver->set_report(data, HID_REPORT_OUTPUT, DS3_RUMBLE_REPORT_ID, packet_buffer+PACKET_OFFSET, 64-PACKET_OFFSET);
#else
result = driver->send_control(data, packet_buffer+PACKET_OFFSET, 64-PACKET_OFFSET);
#endif /* WIIU */
return result;
}
static void* hidpad_ps3_init(void *data, uint32_t slot, hid_driver_t *driver)
static int32_t ds3_send_activation_packet(void *data, uint32_t slot, hid_driver_t *driver) {
#ifdef WIIU
return driver->set_report(data, HID_REPORT_FEATURE, DS3_ACTIVATION_REPORT_ID, ds3_activation_packet, sizeof(ds3_activation_packet));
#else
return driver->send_control(data, ds3_activation_packet, sizeof(ds3_activation_packet));
#endif
}
static void *ds3_pad_init(void *data, uint32_t slot, hid_driver_t *driver)
{
#if defined(HAVE_WIIUSB_HID) || defined(WIIU)
/* Special command to enable Sixaxis, first byte defines the message type */
static uint8_t magic_data[] = {0x02, 0x42, 0x0c, 0x00, 0x00};
#elif defined(IOS)
/* Magic packet to start reports. */
static uint8_t magic_data[] = {0x53, 0xF4, 0x42, 0x03, 0x00, 0x00};
#endif
struct pad_connection* connection = (struct pad_connection*)data;
struct hidpad_ps3_data* device = (struct hidpad_ps3_data*)
calloc(1, sizeof(struct hidpad_ps3_data));
ds3_instance_t *instance = (ds3_instance_t *)calloc(1, sizeof(ds3_instance_t));
int errors = 0;
if (!device)
return NULL;
driver->set_protocol(data, 1);
if (!connection)
if (ds3_send_control_packet(data, slot, driver) < 0)
errors++;
/* Sending activation packet.. */
if (ds3_send_activation_packet(data, slot, driver) < 0)
errors++;
if (errors)
goto error;
instance->hid_driver = driver;
instance->handle = data;
instance->slot = slot;
instance->led_set = true;
return instance;
error:
free(instance);
return NULL;
}
static void ds3_pad_deinit(void *data)
{
ds3_instance_t *pad = (ds3_instance_t *)data;
if (pad)
free(pad);
}
static void ds3_get_buttons(void *data, input_bits_t *state)
{
ds3_instance_t *pad = (ds3_instance_t *)data;
if (pad)
{
free(device);
return NULL;
BITS_COPY16_PTR(state, pad->buttons);
if (pad->buttons & 0x10000)
BIT256_SET_PTR(state, RARCH_MENU_TOGGLE);
}
else
{
BIT256_CLEAR_ALL_PTR(state);
}
}
static void ds3_packet_handler(void *data, uint8_t *packet, uint16_t size)
{
ds3_instance_t *instance = (ds3_instance_t *)data;
if(!instance) {
return;
}
device->connection = connection;
device->slot = slot;
device->driver = driver;
if (!instance->led_set)
{
ds3_send_control_packet(instance->handle, instance->slot, instance->hid_driver);
instance->led_set = true;
}
#if defined(IOS) || defined(HAVE_WIIUSB_HID)
device->driver->send_control(device->connection, magic_data, sizeof(magic_data));
#endif
if (size > sizeof(instance->data))
{
RARCH_ERR("[ds3]: Expecting packet to be %d but was %d\n",
sizeof(instance->data), size);
return;
}
RARCH_LOG_BUFFER(packet, size);
#ifdef WIIU
device->driver->set_protocol(device->connection, 1);
hidpad_ps3_send_control(device);
device->driver->set_report(device->connection,
HID_REPORT_FEATURE,
DS3_ACTIVATION_REPORT_ID,
magic_data+1,
(sizeof(magic_data) - sizeof(uint8_t)));
#endif
#ifndef HAVE_WIIUSB_HID
/* Without this, the digital buttons won't be reported. */
hidpad_ps3_send_control(device);
#endif
return device;
memcpy(instance->data, packet, size);
ds3_update_pad_state(instance);
ds3_update_analog_state(instance);
}
static void hidpad_ps3_deinit(void *data)
const char * ds3_get_name(void *data)
{
struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data;
if (device)
free(device);
(void)data;
/* For now we return a single static name */
return "PLAYSTATION(R)3 Controller";
}
static void hidpad_ps3_get_buttons(void *data, input_bits_t *state)
{
struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data;
if ( device )
{
/* copy 32 bits : needed for PS button? */
BITS_COPY32_PTR(state, device->buttons);
}
else
BIT256_CLEAR_ALL_PTR(state);
}
static void ds3_set_rumble(void *data,
enum retro_rumble_effect effect, uint16_t strength) { }
static int16_t hidpad_ps3_get_axis(void *data, unsigned axis)
static int16_t ds3_get_axis(void *data, unsigned axis)
{
int val;
struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data;
axis_data axis_data;
ds3_instance_t *pad = (ds3_instance_t *)data;
if (!device || axis >= 4)
gamepad_read_axis_data(axis, &axis_data);
if (!pad || axis_data.axis >= 4)
return 0;
val = device->data[7 + axis];
val = (val << 8) - 0x8000;
if (abs(val) > 0x1000)
return val;
return 0;
return gamepad_get_axis_value(pad->analog_state, &axis_data);
}
static void hidpad_ps3_packet_handler(void *data,
uint8_t *packet, uint16_t size)
static int32_t ds3_button(void *data, uint16_t joykey)
{
ds3_instance_t *pad = (ds3_instance_t *)data;
if (!pad || joykey > 31)
return 0;
return pad->buttons & (1 << joykey);
}
static void ds3_update_pad_state(ds3_instance_t *instance)
{
uint32_t i, pressed_keys;
static const uint32_t button_mapping[17] =
{
RETRO_DEVICE_ID_JOYPAD_SELECT,
@ -181,59 +238,42 @@ static void hidpad_ps3_packet_handler(void *data,
RETRO_DEVICE_ID_JOYPAD_A,
RETRO_DEVICE_ID_JOYPAD_B,
RETRO_DEVICE_ID_JOYPAD_Y,
16 /* PS Button */
16 /* PS button */
};
struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data;
if (!device)
return;
instance->buttons = 0;
if (!device->have_led)
pressed_keys = instance->data[2] |
(instance->data[3] << 8) |
((instance->data[4] & 0x01) << 16);
for (i = 0; i < 17; i++)
instance->buttons |= (pressed_keys & (1 << i)) ?
(1 << button_mapping[i]) : 0;
}
static void ds3_update_analog_state(ds3_instance_t *instance)
{
int pad_axis;
int16_t interpolated;
unsigned stick, axis;
for (pad_axis = 0; pad_axis < 4; pad_axis++)
{
hidpad_ps3_send_control(device);
device->have_led = true;
axis = pad_axis % 2 ? 0 : 1;
stick = pad_axis / 2;
interpolated = instance->data[6+pad_axis];
instance->analog_state[stick][axis] = (interpolated - 128) * 256;
}
memcpy(device->data, packet, size);
device->buttons = 0;
pressed_keys = device->data[3] | (device->data[4] << 8) |
((device->data[5] & 1) << 16);
for (i = 0; i < 17; i ++)
device->buttons |= (pressed_keys & (1 << i)) ?
(1 << button_mapping[i]) : 0;
}
static void hidpad_ps3_set_rumble(void *data,
enum retro_rumble_effect effect, uint16_t strength)
{
struct hidpad_ps3_data *device = (struct hidpad_ps3_data*)data;
unsigned idx = (effect == RETRO_RUMBLE_STRONG) ? 0 : 1;
if (!device)
return;
if (device->motors[idx] == strength)
return;
device->motors[idx] = strength;
hidpad_ps3_send_control(device);
}
const char * hidpad_ps3_get_name(void *data)
{
(void)data;
/* For now we return a single static name */
return "PLAYSTATION(R)3 Controller";
}
pad_connection_interface_t pad_connection_ps3 = {
hidpad_ps3_init,
hidpad_ps3_deinit,
hidpad_ps3_packet_handler,
hidpad_ps3_set_rumble,
hidpad_ps3_get_buttons,
hidpad_ps3_get_axis,
hidpad_ps3_get_name,
};
ds3_pad_init,
ds3_pad_deinit,
ds3_packet_handler,
ds3_set_rumble,
ds3_get_buttons,
ds3_get_axis,
ds3_get_name,
ds3_button
};

View File

@ -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
{

View File

@ -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

View File

@ -21,7 +21,6 @@
#include <boolean.h>
#include "joypad_connection.h"
#include "../input_defines.h"
#include "../common/hid/hid_device_driver.h"
struct hidpad_wiiugca_data
{

View File

@ -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
{

View File

@ -183,7 +183,8 @@ int32_t pad_connection_pad_init(joypad_connection_t *joyconn,
if (name_match || (pad_map[i].vid == vid && pad_map[i].pid == pid))
{
RARCH_DBG("Pad was matched to \"%s\". Setting up an interface.\n", name_match);
RARCH_LOG("Pad was matched to \"%s\". Setting up an interface.\n", name_match);
// RARCH_DBG("Pad was matched to \"%s\". Setting up an interface.\n", name_match);
s->iface = pad_map[i].iface;
s->data = data;
s->connection = s->iface->init(data, pad, driver);
@ -205,7 +206,8 @@ int32_t pad_connection_pad_init(joypad_connection_t *joyconn,
* set up one without an interface */
if (!s->connected)
{
RARCH_DBG("Pad was not matched. Setting up without an interface.\n");
RARCH_LOG("Pad was not matched. Setting up without an interface.\n");
// RARCH_DBG("Pad was not matched. Setting up without an interface.\n");
s->iface = NULL;
s->data = data;
s->connected = true;

View File

@ -31,17 +31,21 @@ static bool wiiu_hid_joypad_query(void *data, unsigned slot)
if (!hid)
return false;
return slot < HID_MAX_SLOT();
return slot < joypad_state.max_slot;
}
static joypad_connection_t *get_pad(wiiu_hid_t *hid, unsigned slot)
{
joypad_connection_t *result;
if (!wiiu_hid_joypad_query(hid, slot))
if (!wiiu_hid_joypad_query(hid, slot)) {
RARCH_LOG("wiiu_hid: get_pad: invalid slot: %d", slot);
return NULL;
result = HID_PAD_CONNECTION_PTR(slot);
if (!result || !result->connected || !result->iface || !result->data)
}
result = &joypad_state.pads[slot];
if (!result->connected || !result->iface || !result->connection) {
RARCH_LOG("Pad not ready (connected: %d, iface: %08lx, connection: %08lx)\n", result->connected, (unsigned long)result->iface, (unsigned long)result->connection);
return NULL;
}
return result;
}
@ -49,27 +53,27 @@ static const char *wiiu_hid_joypad_name(void *data, unsigned slot)
{
joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot);
if (!pad)
if (!pad || !pad->iface->get_name)
return NULL;
return pad->iface->get_name(pad->data);
return pad->iface->get_name(pad->connection);
}
static void wiiu_hid_joypad_get_buttons(void *data, unsigned slot, input_bits_t *state)
{
joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot);
if (pad)
pad->iface->get_buttons(pad->data, state);
if (pad && pad->iface->get_buttons)
pad->iface->get_buttons(pad->connection, state);
}
static int16_t wiiu_hid_joypad_button(void *data,
unsigned slot, uint16_t joykey)
{
joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot);
if (!pad)
if (!pad || !pad->iface->button)
return 0;
return pad->iface->button(pad->data, joykey);
return pad->iface->button(pad->connection, joykey);
}
static int16_t wiiu_hid_joypad_axis(void *data, unsigned slot, uint32_t joyaxis)
@ -79,7 +83,7 @@ static int16_t wiiu_hid_joypad_axis(void *data, unsigned slot, uint32_t joyaxis)
if (!pad)
return 0;
return pad->iface->get_axis(pad->data, joyaxis);
return pad->iface->get_axis(pad->connection, joyaxis);
}
static int16_t wiiu_hid_joypad_state(
@ -106,10 +110,10 @@ static int16_t wiiu_hid_joypad_state(
? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis;
if (
(uint16_t)joykey != NO_BTN
&& pad->iface->button(pad->data, (uint16_t)joykey))
&& pad->iface->button && pad->iface->button(pad->connection, (uint16_t)joykey))
ret |= ( 1 << i);
else if (joyaxis != AXIS_NONE &&
((float)abs(pad->iface->get_axis(pad->data, joyaxis))
else if (joyaxis != AXIS_NONE && pad->iface->get_axis &&
((float)abs(pad->iface->get_axis(pad->connection, joyaxis))
/ 0x8000) > joypad_info->axis_threshold)
ret |= (1 << i);
}
@ -122,10 +126,10 @@ static bool wiiu_hid_joypad_rumble(void *data, unsigned slot,
{
joypad_connection_t *pad = get_pad((wiiu_hid_t *)data, slot);
if (!pad)
if (!pad || !pad->iface->set_rumble)
return false;
pad->iface->set_rumble(pad->data, effect, strength);
pad->iface->set_rumble(pad->connection, effect, strength);
return false;
}
@ -366,9 +370,17 @@ static void log_device(HIDDevice *device)
static uint8_t try_init_driver(wiiu_adapter_t *adapter)
{
int32_t pad = pad_connection_pad_init(HID_PAD_CONNECTION_PTR(0), &adapter->device_name[0], adapter->vendor_id, adapter->product_id, adapter, &wiiu_hid);
return (pad >= 0) ? ADAPTER_STATE_READY : ADAPTER_STATE_DONE;
RARCH_LOG("Trying to find pad driver for vid 0x%04x pid 0x%04x\n", adapter->vendor_id, adapter->product_id);
int32_t pad = pad_connection_pad_init(joypad_state.pads, &adapter->device_name[0], adapter->vendor_id, adapter->product_id, adapter, &wiiu_hid);
if(pad >= 0) {
RARCH_LOG("Attached to pad %d\n", pad);
joypad_state.pad_drivers[pad] = &hidpad_driver;
adapter->pad = pad;
input_pad_connect(pad, &hidpad_driver);
return ADAPTER_STATE_READY;
}
RARCH_LOG("Failed to find pad driver\n");
return ADAPTER_STATE_DONE;
}
static void synchronized_process_adapters(wiiu_hid_t *hid)
@ -381,35 +393,41 @@ static void synchronized_process_adapters(wiiu_hid_t *hid)
for (adapter = adapters.list; adapter != NULL; adapter = adapter_next)
{
adapter_next = adapter->next;
adapter_next = adapter->next;
switch(adapter->state)
{
case ADAPTER_STATE_NEW:
adapter->state = try_init_driver(adapter);
break;
case ADAPTER_STATE_READY:
case ADAPTER_STATE_READING:
case ADAPTER_STATE_DONE:
break;
case ADAPTER_STATE_GC:
/* remove from the list */
if (!prev)
adapters.list = adapter->next;
else
prev->next = adapter->next;
switch(adapter->state)
{
case ADAPTER_STATE_NEW:
adapter->state = try_init_driver(adapter);
break;
case ADAPTER_STATE_READY:
case ADAPTER_STATE_READING:
case ADAPTER_STATE_DONE:
break;
case ADAPTER_STATE_GC:
{
const char *pad_name = joypad_state.pads[adapter->pad].iface->get_name(joypad_state.pads[adapter->pad].connection);
/* remove from the list */
if (!prev)
adapters.list = adapter->next;
else
prev->next = adapter->next;
input_autoconfigure_disconnect(adapter->pad, pad_name);
pad_connection_pad_deinit(&joypad_state.pads[adapter->pad], adapter->pad);
/* adapter is no longer valid after this point */
delete_adapter(adapter);
/* signal not to update prev ptr since adapter is now invalid */
keep_prev = true;
}
break;
/* adapter is no longer valid after this point */
delete_adapter(adapter);
/* signal not to update prev ptr since adapter is now invalid */
keep_prev = true;
break;
default:
RARCH_ERR("[hid]: Invalid adapter state: %d\n", adapter->state);
break;
}
prev = keep_prev ? prev : adapter;
keep_prev = false;
default:
RARCH_ERR("[hid]: Invalid adapter state: %d\n", adapter->state);
break;
}
prev = keep_prev ? prev : adapter;
keep_prev = false;
}
OSFastMutex_Unlock(&(adapters.lock));
}
@ -536,8 +554,9 @@ static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error,
if (error == 0)
{
adapter->driver->handle_packet(adapter->driver_handle,
buffer, buffer_size);
joypad_state.pads[adapter->pad].iface->packet_handler(
joypad_state.pads[adapter->pad].connection, buffer, buffer_size
);
}
}
}
@ -549,7 +568,8 @@ static void report_hid_error(const char *msg, wiiu_adapter_t *adapter, int32_t e
int16_t hid_error_code = error & 0xffff;
int16_t error_category = (error >> 16) & 0xffff;
const char *device = (adapter && adapter->driver) ? adapter->driver->name : "unknown";
const char *device = (adapter && adapter->pad >= 0) ?
joypad_state.pads[adapter->pad].iface->get_name(joypad_state.pads[adapter->pad].connection) : "unknown";
switch(hid_error_code)
{
@ -684,8 +704,10 @@ static void wiiu_poll_adapters(wiiu_hid_t *hid)
if (it->state == ADAPTER_STATE_READY)
wiiu_poll_adapter(it);
if (it->state == ADAPTER_STATE_DONE)
if (it->state == ADAPTER_STATE_DONE) {
it->state = ADAPTER_STATE_GC;
}
}
OSFastMutex_Unlock(&(adapters.lock));
@ -796,31 +818,17 @@ static void delete_adapter(wiiu_adapter_t *adapter)
free(adapter->tx_buffer);
adapter->tx_buffer = NULL;
}
if (adapter->driver && adapter->driver_handle) {
adapter->driver->free(adapter->driver_handle);
adapter->driver_handle = NULL;
adapter->driver = NULL;
}
if(adapter->pad >= 0 &&
joypad_state.pads[adapter->pad].iface &&
joypad_state.pads[adapter->pad].connection) {
joypad_state.pads[adapter->pad].iface->deinit(joypad_state.pads[adapter->pad].connection);
joypad_state.pads[adapter->pad].connection = NULL;
joypad_state.pads[adapter->pad].iface = NULL;
}
free(adapter);
}
static void get_descriptor_string_ascii(wiiu_adapter_t *adapter, uint8_t *buffer, size_t buffer_size) {
int32_t result = HIDGetDescriptor(adapter->handle, 3, 2, 0, adapter->rx_buffer, adapter->rx_size, NULL, NULL);
memset(buffer, 0, buffer_size);
uint8_t *top;
if(result > 0) {
top = buffer;
for(int i = 2; i < result; i += 2) {
top[0] = adapter->rx_buffer[i];
top++;
}
} else {
RARCH_ERR("Failed to read descriptor string (0x%08x). Will attempt match by VID/PID\n", result);
}
}
static void get_device_name(HIDDevice *device, wiiu_attach_event *event)
{
int32_t result;

View File

@ -16,69 +16,28 @@
#include "../../include/wiiu/input.h"
static hidpad_driver_t instance;
/* TODO/FIXME - static global variables */
static bool hidpad_ready = false;
static bool init_pad_list(unsigned slots)
{
if (slots > MAX_USERS)
return false;
if (instance.pad_list)
return true;
instance.pad_list = pad_connection_init(slots);
if (!instance.pad_list)
return false;
instance.max_slot = slots;
return true;
}
static bool init_hid_driver(void)
{
return init_pad_list(MAX_USERS);
}
static void hidpad_poll(void)
{
if (hidpad_ready)
if (joypad_state.hid.ready)
wiiu_hid.poll(hid_driver_get_data());
}
static void *hidpad_init(void *data)
{
if(!init_hid_driver())
{
RARCH_ERR("Failed to initialize HID driver.\n");
return NULL;
}
hidpad_poll();
hidpad_ready = true;
joypad_state.hid.ready = true;
return (void*)-1;
}
static bool hidpad_query_pad(unsigned port)
{
return hidpad_ready && port < MAX_USERS;
return joypad_state.hid.ready && port < MAX_USERS;
}
static void hidpad_destroy(void)
{
hidpad_ready = false;
if(instance.pad_list) {
pad_connection_destroy(instance.pad_list);
instance.pad_list = NULL;
}
/* Wiping instance data.. */
memset(&instance, 0, sizeof(instance));
joypad_state.hid.ready = false;
}
static int32_t hidpad_button(unsigned port, uint16_t joykey)
@ -126,11 +85,11 @@ static int16_t hidpad_state(
? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis;
if (
(uint16_t)joykey != NO_BTN
&& HID_BUTTON(port_idx, (uint16_t)joykey)
&& wiiu_hid.button(hid_driver_get_data(), port_idx, (uint16_t)joykey)
)
ret |= ( 1 << i);
else if (joyaxis != AXIS_NONE &&
((float)abs(HID_AXIS(port_idx, joyaxis))
((float)abs(wiiu_hid.axis(hid_driver_get_data(), port_idx, joyaxis))
/ 0x8000) > joypad_info->axis_threshold)
ret |= (1 << i);
}

View File

@ -29,34 +29,12 @@
static void kpad_poll(void);
static void kpad_deregister(unsigned channel);
typedef struct _wiimote_state wiimote_state;
struct _wiimote_state
{
uint64_t button_state;
int16_t analog_state[3][2];
uint8_t type;
};
/* static global variables */
static bool kpad_ready = false;
static int channel_slot_map[] = { -1, -1, -1, -1 };
static int poll_failures[WIIU_WIIMOTE_CHANNELS] = { 0, 0, 0, 0 };
static wiimote_state
wiimotes[WIIU_WIIMOTE_CHANNELS] = {
{ 0, {{0,0},{0,0},{0,0}}, WIIMOTE_TYPE_NONE },
{ 0, {{0,0},{0,0},{0,0}}, WIIMOTE_TYPE_NONE },
{ 0, {{0,0},{0,0},{0,0}}, WIIMOTE_TYPE_NONE },
{ 0, {{0,0},{0,0},{0,0}}, WIIMOTE_TYPE_NONE },
};
static int to_wiimote_channel(unsigned pad)
{
unsigned i;
for (i = 0; i < WIIU_WIIMOTE_CHANNELS; i++)
if (channel_slot_map[i] == pad)
if (joypad_state.kpad.channel_slot_map[i] == pad)
return i;
return -1;
@ -64,11 +42,11 @@ static int to_wiimote_channel(unsigned pad)
static int get_slot_for_channel(unsigned channel)
{
int slot = pad_connection_find_vacant_pad(hid_instance.pad_list);
int slot = pad_connection_find_vacant_pad(joypad_state.pads);
if (slot >= 0)
{
channel_slot_map[channel] = slot;
hid_instance.pad_list[slot].connected = true;
joypad_state.kpad.channel_slot_map[channel] = slot;
joypad_state.pads[slot].connected = true;
}
return slot;
@ -76,20 +54,26 @@ static int get_slot_for_channel(unsigned channel)
static void *kpad_init(void *data)
{
memset(&joypad_state.kpad, 0, sizeof(joypad_state.kpad));
for(int i = 0; i < WIIU_WIIMOTE_CHANNELS; i++) {
joypad_state.kpad.channel_slot_map[i] = -1;
}
kpad_poll();
kpad_ready = true;
joypad_state.kpad.ready = true;
return (void*)-1;
}
static bool kpad_query_pad(unsigned pad)
{
return kpad_ready && pad < MAX_USERS;
return joypad_state.kpad.ready && pad < MAX_USERS;
}
static void kpad_destroy(void)
{
kpad_ready = false;
joypad_state.kpad.ready = false;
}
static int32_t kpad_button(unsigned port, uint16_t joykey)
@ -101,7 +85,7 @@ static int32_t kpad_button(unsigned port, uint16_t joykey)
channel = to_wiimote_channel(port);
if (channel < 0)
return 0;
return (wiimotes[channel].button_state
return (joypad_state.kpad.wiimotes[channel].button_state
& (UINT64_C(1) << joykey));
}
@ -112,7 +96,7 @@ static void kpad_get_buttons(unsigned port, input_bits_t *state)
if (!kpad_query_pad(port) || channel < 0)
BIT256_CLEAR_ALL_PTR(state);
else
BITS_COPY16_PTR(state, wiimotes[channel].button_state);
BITS_COPY16_PTR(state, joypad_state.kpad.wiimotes[channel].button_state);
}
static int16_t kpad_axis(unsigned port, uint32_t axis)
@ -125,7 +109,7 @@ static int16_t kpad_axis(unsigned port, uint32_t axis)
pad_functions.read_axis_data(axis, &data);
return pad_functions.get_axis_value(data.axis,
wiimotes[channel].analog_state,
joypad_state.kpad.wiimotes[channel].analog_state,
data.is_negative);
}
@ -160,7 +144,7 @@ static int16_t kpad_state(
static void kpad_register(unsigned channel, uint8_t device_type)
{
if (wiimotes[channel].type != device_type)
if (joypad_state.kpad.wiimotes[channel].type != device_type)
{
int slot;
@ -173,7 +157,8 @@ static void kpad_register(unsigned channel, uint8_t device_type)
return;
}
wiimotes[channel].type = device_type;
joypad_state.kpad.wiimotes[channel].type = device_type;
joypad_state.pad_drivers[slot] = &kpad_driver;
input_pad_connect(slot, &kpad_driver);
}
}
@ -184,32 +169,32 @@ static void kpad_poll_one_channel(unsigned channel, KPADData *kpad)
switch(kpad->device_type)
{
case WIIMOTE_TYPE_PRO:
wiimotes[channel].button_state = kpad->classic.btns_h
joypad_state.kpad.wiimotes[channel].button_state = kpad->classic.btns_h
& ~WIIU_PRO_BUTTON_MASK;
pad_functions.set_axis_value(wiimotes[channel].analog_state,
pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state,
WIIU_READ_STICK(kpad->classic.lstick_x),
WIIU_READ_STICK(kpad->classic.lstick_y),
WIIU_READ_STICK(kpad->classic.rstick_x),
WIIU_READ_STICK(kpad->classic.rstick_y), 0, 0);
break;
case WIIMOTE_TYPE_CLASSIC:
wiimotes[channel].button_state = kpad->classic.btns_h
joypad_state.kpad.wiimotes[channel].button_state = kpad->classic.btns_h
& ~CLASSIC_BUTTON_MASK;
pad_functions.set_axis_value(wiimotes[channel].analog_state,
pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state,
WIIU_READ_STICK(kpad->classic.lstick_x),
WIIU_READ_STICK(kpad->classic.lstick_y),
WIIU_READ_STICK(kpad->classic.rstick_x),
WIIU_READ_STICK(kpad->classic.rstick_y), 0, 0);
break;
case WIIMOTE_TYPE_NUNCHUK:
wiimotes[channel].button_state = kpad->btns_h;
pad_functions.set_axis_value(wiimotes[channel].analog_state,
joypad_state.kpad.wiimotes[channel].button_state = kpad->btns_h;
pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state,
WIIU_READ_STICK(kpad->nunchuck.stick_x),
WIIU_READ_STICK(kpad->nunchuck.stick_y), 0, 0, 0, 0);
break;
case WIIMOTE_TYPE_WIIPLUS:
wiimotes[channel].button_state = kpad->btns_h;
pad_functions.set_axis_value(wiimotes[channel].analog_state,
joypad_state.kpad.wiimotes[channel].button_state = kpad->btns_h;
pad_functions.set_axis_value(joypad_state.kpad.wiimotes[channel].analog_state,
0, 0, 0, 0, 0, 0);
break;
}
@ -217,14 +202,15 @@ static void kpad_poll_one_channel(unsigned channel, KPADData *kpad)
static void kpad_deregister(unsigned channel)
{
int slot = channel_slot_map[channel];
int slot = joypad_state.kpad.channel_slot_map[channel];
if (slot >= 0)
{
input_autoconfigure_disconnect(slot, kpad_driver.name(slot));
wiimotes[channel].type = WIIMOTE_TYPE_NONE;
hid_instance.pad_list[slot].connected = false;
channel_slot_map[channel] = -1;
joypad_state.kpad.wiimotes[channel].type = WIIMOTE_TYPE_NONE;
joypad_state.pads[slot].connected = false;
joypad_state.kpad.channel_slot_map[channel] = -1;
}
}
@ -244,12 +230,12 @@ static void kpad_poll(void)
/* pad disconnects properly. */
if (result == 0)
{
poll_failures[channel]++;
if (poll_failures[channel] > 5)
joypad_state.kpad.poll_failures[channel]++;
if (joypad_state.kpad.poll_failures[channel] > 5)
kpad_deregister(channel);
continue;
}
poll_failures[channel] = 0;
joypad_state.kpad.poll_failures[channel] = 0;
/* Several reads when a device is connected or an attachment added give */
/* bogus results, try to weed them out */
@ -267,7 +253,7 @@ static const char *kpad_name(unsigned pad)
if (channel < 0)
return "unknown";
switch(wiimotes[channel].type)
switch(joypad_state.kpad.wiimotes[channel].type)
{
case WIIMOTE_TYPE_PRO:
return PAD_NAME_WIIU_PRO;
@ -280,7 +266,7 @@ static const char *kpad_name(unsigned pad)
case WIIMOTE_TYPE_NONE:
default:
#ifdef DEBUG
RARCH_LOG("[kpad]: Unknown pad type %d\n", wiimotes[pad].type);
RARCH_LOG("[kpad]: Unknown pad type %d\n", joypad_state.kpad.wiimotes[pad].type);
#endif
break;
}

View File

@ -27,24 +27,13 @@
#define WPAD_INVALID_CHANNEL -1
typedef struct _drc_state drc_state;
struct _drc_state
{
uint64_t button_state;
int16_t analog_state[3][2];
};
/* TODO/FIXME - static global variables */
static drc_state gamepads[WIIU_GAMEPAD_CHANNELS] = { 0 };
static int channel_slot_map[WIIU_GAMEPAD_CHANNELS] = { WPAD_INVALID_CHANNEL, WPAD_INVALID_CHANNEL };
static VPADChan to_gamepad_channel(unsigned pad)
{
unsigned i;
for (i = 0; i < WIIU_GAMEPAD_CHANNELS; i++)
{
if (channel_slot_map[i] == pad)
if (joypad_state.wpad.channel_slot_map[i] == pad)
return i;
}
@ -59,23 +48,23 @@ static void wpad_deregister(unsigned channel)
return;
/* See if Gamepad is already disconnected */
if (channel_slot_map[channel] == WPAD_INVALID_CHANNEL)
if (joypad_state.wpad.channel_slot_map[channel] == WPAD_INVALID_CHANNEL)
return;
/* Sanity check, about to use as unsigned */
if (channel_slot_map[channel] < 0)
if (joypad_state.wpad.channel_slot_map[channel] < 0)
{
channel_slot_map[channel] = WPAD_INVALID_CHANNEL;
joypad_state.wpad.channel_slot_map[channel] = WPAD_INVALID_CHANNEL;
return;
}
slot = (unsigned)channel_slot_map[channel];
slot = (unsigned)joypad_state.wpad.channel_slot_map[channel];
if (slot >= MAX_USERS)
return;
input_autoconfigure_disconnect(slot, wpad_driver.ident);
hid_instance.pad_list[slot].connected = false;
channel_slot_map[channel] = WPAD_INVALID_CHANNEL;
joypad_state.pads[slot].connected = false;
joypad_state.wpad.channel_slot_map[channel] = WPAD_INVALID_CHANNEL;
}
static void wpad_register(unsigned channel)
@ -87,17 +76,18 @@ static void wpad_register(unsigned channel)
/* Check if gamepad is already handled
Other checks not needed here - about to overwrite
channel_slot_map entry*/
if (channel_slot_map[channel] != WPAD_INVALID_CHANNEL)
joypad_state.wpad.channel_slot_map entry*/
if (joypad_state.wpad.channel_slot_map[channel] != WPAD_INVALID_CHANNEL)
return;
slot = pad_connection_find_vacant_pad(hid_instance.pad_list);
slot = pad_connection_find_vacant_pad(joypad_state.pads);
if(slot < 0)
return;
hid_instance.pad_list[slot].connected = true;
joypad_state.pads[slot].connected = true;
joypad_state.pad_drivers[slot] = &wpad_driver;
input_pad_connect(slot, &wpad_driver);
channel_slot_map[channel] = slot;
joypad_state.wpad.channel_slot_map[channel] = slot;
}
static void update_button_state(uint64_t *state, uint32_t held_buttons)
@ -255,9 +245,9 @@ static void wpad_poll(void)
if (error == VPAD_READ_SUCCESS)
{
update_button_state(&gamepads[channel].button_state, vpad.hold);
update_analog_state(gamepads[channel].analog_state, &vpad);
update_touch_state(gamepads[channel].analog_state, &gamepads[channel].button_state, &vpad, channel);
update_button_state(&joypad_state.wpad.pads[channel].button_state, vpad.hold);
update_analog_state(joypad_state.wpad.pads[channel].analog_state, &vpad);
update_touch_state(joypad_state.wpad.pads[channel].analog_state, &joypad_state.wpad.pads[channel].button_state, &vpad, channel);
check_panic_button(vpad.hold);
}
}
@ -265,6 +255,10 @@ static void wpad_poll(void)
static void *wpad_init(void *data)
{
memset(&joypad_state.wpad, 0, sizeof(joypad_state.wpad));
for(int i = 0; i < WIIU_GAMEPAD_CHANNELS; i++) {
joypad_state.wpad.channel_slot_map[i] = WPAD_INVALID_CHANNEL;
}
wpad_poll();
return (void*)-1;
}
@ -285,7 +279,7 @@ static int32_t wpad_button(unsigned port, uint16_t joykey)
channel = to_gamepad_channel(port);
if (channel < 0)
return 0;
return (gamepads[channel].button_state & (UINT64_C(1) << joykey));
return (joypad_state.wpad.pads[channel].button_state & (UINT64_C(1) << joykey));
}
static void wpad_get_buttons(unsigned port, input_bits_t *state)
@ -305,7 +299,7 @@ static void wpad_get_buttons(unsigned port, input_bits_t *state)
return;
}
BITS_COPY32_PTR(state, gamepads[channel].button_state);
BITS_COPY32_PTR(state, joypad_state.wpad.pads[channel].button_state);
}
static int16_t wpad_axis(unsigned port, uint32_t axis)
@ -322,7 +316,7 @@ static int16_t wpad_axis(unsigned port, uint32_t axis)
pad_functions.read_axis_data(axis, &data);
return pad_functions.get_axis_value(data.axis,
gamepads[channel].analog_state, data.is_negative);
joypad_state.wpad.pads[channel].analog_state, data.is_negative);
}
static int16_t wpad_state(

View File

@ -16,46 +16,41 @@
#include "../include/wiiu/input.h"
#include "wiiu_dbg.h"
extern pad_connection_listener_t wiiu_pad_connection_listener;
/* TODO/FIXME - static globals */
static input_device_driver_t *wiiu_pad_drivers[MAX_USERS];
static bool wiiu_joypad_ready = false;
static bool ready = false;
wiiu_joypad_t joypad_state = {0};
static void *wiiu_joypad_init(void *data)
{
set_connection_listener(&wiiu_pad_connection_listener);
memset(&joypad_state, 0, sizeof(wiiu_joypad_t));
joypad_state.max_slot = MAX_USERS;
input_hid_init_first();
wpad_driver.init(data);
kpad_driver.init(data);
#ifdef WIIU_HID
hidpad_driver.init(data);
#endif
ready = true;
wiiu_joypad_ready = true;
return (void*)-1;
return (void *)-1;
}
static bool wiiu_joypad_query_pad(unsigned pad)
{
return wiiu_joypad_ready &&
return ready &&
pad < MAX_USERS &&
wiiu_pad_drivers[pad] &&
wiiu_pad_drivers[pad]->query_pad(pad);
joypad_state.pad_drivers[pad] &&
joypad_state.pad_drivers[pad]->query_pad(pad);
}
static void wiiu_joypad_destroy(void)
{
wiiu_joypad_ready = false;
ready = false;
wpad_driver.destroy();
kpad_driver.destroy();
#ifdef WIIU_HID
hidpad_driver.destroy();
#endif
}
static int32_t wiiu_joypad_button(unsigned port, uint16_t joykey)
@ -64,21 +59,21 @@ static int32_t wiiu_joypad_button(unsigned port, uint16_t joykey)
return 0;
if (port >= DEFAULT_MAX_PADS)
return 0;
return (wiiu_pad_drivers[port]->button(port, joykey));
return (joypad_state.pad_drivers[port]->button(port, joykey));
}
static void wiiu_joypad_get_buttons(unsigned port, input_bits_t *state)
{
if (!wiiu_joypad_query_pad(port))
return;
wiiu_pad_drivers[port]->get_buttons(port, state);
joypad_state.pad_drivers[port]->get_buttons(port, state);
}
static int16_t wiiu_joypad_axis(unsigned port, uint32_t joyaxis)
{
if (!wiiu_joypad_query_pad(port))
return 0;
return wiiu_pad_drivers[port]->axis(port, joyaxis);
return joypad_state.pad_drivers[port]->axis(port, joyaxis);
}
static int16_t wiiu_joypad_state(
@ -104,11 +99,11 @@ static int16_t wiiu_joypad_state(
? binds[i].joyaxis : joypad_info->auto_binds[i].joyaxis;
if (
(uint16_t)joykey != NO_BTN
&& (wiiu_pad_drivers[port]->button(port_idx, (uint16_t)joykey))
&& (joypad_state.pad_drivers[port]->button(port_idx, (uint16_t)joykey))
)
ret |= ( 1 << i);
else if (joyaxis != AXIS_NONE &&
((float)abs(wiiu_pad_drivers[port]->axis(port_idx, joyaxis))
((float)abs(joypad_state.pad_drivers[port]->axis(port_idx, joyaxis))
/ 0x8000) > joypad_info->axis_threshold)
ret |= (1 << i);
}
@ -120,9 +115,7 @@ static void wiiu_joypad_poll(void)
{
wpad_driver.poll();
kpad_driver.poll();
#ifdef WIIU_HID
hidpad_driver.poll();
#endif
}
static const char* wiiu_joypad_name(unsigned pad)
@ -130,14 +123,7 @@ static const char* wiiu_joypad_name(unsigned pad)
if (!wiiu_joypad_query_pad(pad))
return "N/A";
return wiiu_pad_drivers[pad]->name(pad);
}
static void wiiu_joypad_connection_listener(unsigned pad,
input_device_driver_t *driver)
{
if (pad < MAX_USERS)
wiiu_pad_drivers[pad] = driver;
return joypad_state.pad_drivers[pad]->name(pad);
}
input_device_driver_t wiiu_joypad =
@ -155,8 +141,3 @@ input_device_driver_t wiiu_joypad =
wiiu_joypad_name,
"wiiu",
};
pad_connection_listener_t wiiu_pad_connection_listener =
{
wiiu_joypad_connection_listener
};

View File

@ -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;

View File

@ -19,7 +19,6 @@
#include "hid_types.h"
#include "input.h"
#include "../../common/hid/hid_device_driver.h"
#define DEVICE_UNUSED 0
#define DEVICE_USED 1
@ -52,8 +51,7 @@ struct wiiu_hid {
*/
struct wiiu_adapter {
wiiu_adapter_t *next;
hid_device_t *driver;
void *driver_handle;
int pad;
wiiu_hid_t *hid;
uint16_t vendor_id;
uint16_t product_id;
@ -64,7 +62,7 @@ struct wiiu_adapter {
int32_t tx_size;
uint32_t handle;
uint8_t interface_index;
uint8_t device_name[32];
char device_name[32];
bool connected;
};

View File

@ -63,14 +63,46 @@ struct _wiiu_pad_functions {
void (*connect)(unsigned pad, input_device_driver_t *driver);
};
struct hidpad_driver_t {
input_device_driver_t *pad_driver;
joypad_connection_t *pad_list;
unsigned max_slot;
};
typedef struct _wiimote_state {
uint64_t button_state;
int16_t analog_state[3][2];
uint8_t type;
} wiimote_state;
typedef struct hidpad_driver_t hidpad_driver_t;
typedef struct _drc_state
{
uint64_t button_state;
int16_t analog_state[3][2];
} drc_state;
typedef struct wiiu_kpad {
bool ready;
int channel_slot_map[WIIU_WIIMOTE_CHANNELS];
int poll_failures[WIIU_WIIMOTE_CHANNELS];
wiimote_state wiimotes[WIIU_WIIMOTE_CHANNELS];
} wiiu_kpad_t;
typedef struct wiiu_wpad {
drc_state pads[WIIU_GAMEPAD_CHANNELS];
int channel_slot_map[WIIU_GAMEPAD_CHANNELS];
bool ready;
} wiiu_wpad_t;
typedef struct wiiu_hidpad {
bool ready;
} wiiu_hidpad_t;
typedef struct wiiu_joypad {
joypad_connection_t pads[MAX_USERS];
input_device_driver_t *pad_drivers[MAX_USERS];
int max_slot;
wiiu_kpad_t kpad;
wiiu_wpad_t wpad;
wiiu_hidpad_t hid;
} wiiu_joypad_t;
extern wiiu_joypad_t joypad_state;
extern wiiu_pad_functions_t pad_functions;
extern input_device_driver_t wiiu_joypad;
extern input_device_driver_t wpad_driver;

View File

@ -744,7 +744,7 @@ const char* const input_builtin_autoconfs[] =
DECL_AUTOCONF_DEVICE(PAD_NAME_CLASSIC, "wiiu", WIIUINPUT_CLASSIC_CONTROLLER_DEFAULT_BINDS),
DECL_AUTOCONF_DEVICE(PAD_NAME_HID, "wiiu", WIIUINPUT_GAMEPAD_DEFAULT_BINDS),
DECL_AUTOCONF_DEVICE("GameCube Controller", "wiiu", WIIUINPUT_GAMECUBE_DEFAULT_BINDS),
DECL_AUTOCONF_DEVICE("Sony DualShock 3", "wiiu", WIIUINPUT_DS3_DEFAULT_BINDS),
DECL_AUTOCONF_DEVICE("PLAYSTATION(R)3 Controller", "wiiu", WIIUINPUT_DS3_DEFAULT_BINDS),
#endif
#ifdef __PS3__
DECL_AUTOCONF_DEVICE("SixAxis Controller", "ps3", PS3INPUT_DEFAULT_BINDS),

View File

@ -306,7 +306,7 @@ hid_driver_t *hid_drivers[] = {
#ifdef HW_RVL
&wiiusb_hid,
#endif
#if defined(WIIU) && defined(WIIU_HID)
#if defined(WIIU)
&wiiu_hid,
#endif
&null_hid,
@ -3297,23 +3297,14 @@ void input_overlay_init(void)
}
#endif
void set_connection_listener(pad_connection_listener_t *listener)
{
input_driver_st.pad_connection_listener = listener;
}
void input_pad_connect(unsigned port, input_device_driver_t *driver)
{
input_driver_state_t *input_st = &input_driver_st;
if (port >= MAX_USERS || !driver)
{
RARCH_ERR("[Input]: input_pad_connect: bad parameters\n");
return;
}
if (input_st->pad_connection_listener)
input_st->pad_connection_listener->connected(port, driver);
input_autoconfigure_connect(driver->name(port), NULL, driver->ident,
port, 0, 0);
}

View File

@ -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);

View File

@ -106,9 +106,6 @@ typedef struct input_keyboard_line input_keyboard_line_t;
typedef struct rarch_joypad_info rarch_joypad_info_t;
typedef struct input_driver input_driver_t;
typedef struct input_keyboard_ctx_wait input_keyboard_ctx_wait_t;
typedef struct joypad_connection joypad_connection_t;
typedef struct pad_connection_listener_interface pad_connection_listener_t;
typedef struct turbo_buttons turbo_buttons_t;
#endif /* __INPUT_TYPES__H */

View File

@ -15434,7 +15434,7 @@ const char* config_get_joypad_driver_options(void)
}
#ifdef HAVE_HID
const void *hid_driver_get_data(void)
void *hid_driver_get_data(void)
{
struct rarch_state *p_rarch = &rarch_st;
return p_rarch->hid_data;