Start fleshing out wiiu_hid driver

== DETAILS

- Added entrypoints into `input/connect/joypad_connection.c` to allow
  a max value to be passed in, instead of using single macro value
- Created a hand-off between the HID attach handler and the worker thread
- Created a pad initializer in `wiiu_hid.c` leveraging the new functionality
  added to `joypad_connection.c`

== TESTING
Compiles cleanly. At best, doesn't do anything. Might crash--not ready
to test quite yet.
This commit is contained in:
gblues 2017-12-10 22:31:00 -08:00 committed by twinaphex
parent e98b006715
commit 5804233ca8
4 changed files with 278 additions and 44 deletions

View File

@ -24,13 +24,18 @@
#include "joypad_connection.h"
int pad_connection_find_vacant_pad(joypad_connection_t *joyconn)
{
return pad_connection_find_vacant_pad_max(joyconn, MAX_USERS);
}
int pad_connection_find_vacant_pad_max(joypad_connection_t *joyconn, unsigned max)
{
unsigned i;
if (!joyconn)
return -1;
for (i = 0; i < MAX_USERS; i++)
for (i = 0; i < max; i++)
{
joypad_connection_t *conn = &joyconn[i];
@ -66,6 +71,16 @@ int32_t pad_connection_pad_init(joypad_connection_t *joyconn,
const char* name, uint16_t vid, uint16_t pid,
void *data, send_control_t ptr)
{
int pad = pad_connection_find_vacant_pad(joyconn);
return pad_connection_pad_init_with_slot(joyconn, name,
vid, pid, data, ptr, pad);
}
int32_t pad_connection_pad_init_with_slot(joypad_connection_t *joyconn,
const char *name, uint16_t vid, uint16_t pid,
void *data, send_control_t ptr, int slot)
{
static const struct
{
const char* name;
@ -88,12 +103,11 @@ int32_t pad_connection_pad_init(joypad_connection_t *joyconn,
{ 0, 0}
};
joypad_connection_t *s = NULL;
int pad = pad_connection_find_vacant_pad(joyconn);
if (pad == -1)
if (slot == -1)
return -1;
s = &joyconn[pad];
s = &joyconn[slot];
if (s)
{
@ -119,7 +133,7 @@ int32_t pad_connection_pad_init(joypad_connection_t *joyconn,
if (name_match || (pad_map[i].vid == vid && pad_map[i].pid == pid))
{
s->iface = pad_map[i].iface;
s->data = s->iface->init(data, pad, ptr);
s->data = s->iface->init(data, slot, ptr);
s->connected = true;
#if 0
RARCH_LOG("%s found \n", pad_map[i].name);
@ -144,7 +158,7 @@ int32_t pad_connection_pad_init(joypad_connection_t *joyconn,
}
}
return pad;
return slot;
}
void pad_connection_pad_deinit(joypad_connection_t *joyconn, uint32_t pad)

View File

@ -59,6 +59,9 @@ extern pad_connection_interface_t pad_connection_psxadapter;
int32_t pad_connection_pad_init(joypad_connection_t *joyconn,
const char* name, uint16_t vid, uint16_t pid,
void *data, send_control_t ptr);
int32_t pad_connection_pad_init_with_slot(joypad_connection_t *joyconn,
const char* name, uint16_t vid, uint16_t pid,
void *data, send_control_t ptr, int slot);
joypad_connection_t *pad_connection_init(unsigned pads);
@ -83,6 +86,7 @@ bool pad_connection_has_interface(joypad_connection_t *joyconn,
unsigned idx);
int pad_connection_find_vacant_pad(joypad_connection_t *joyconn);
int pad_connection_find_vacant_pad_max(joypad_connection_t *joyconn, unsigned max);
bool pad_connection_rumble(joypad_connection_t *s,
unsigned pad, enum retro_rumble_effect effect, uint16_t strength);

View File

@ -20,32 +20,9 @@
#include <wiiu/os.h>
#include <wiiu/syshid.h>
#include "../input_defines.h"
#include "../input_driver.h"
#include "../../verbosity.h"
#include "wiiu_hid.h"
#define DEVICE_UNUSED 0
#define DEVICE_USED 1
typedef struct wiiu_hid
{
HIDClient *client;
OSThread *polling_thread;
void *polling_thread_stack;
volatile bool polling_thread_quit;
} wiiu_hid_t;
void *alloc_zeroed(size_t alignment, size_t size);
static OSThread *new_thread(void);
static wiiu_hid_t *new_hid(void);
static void delete_hid(wiiu_hid_t *hid);
static void delete_hidclient(HIDClient *client);
static HIDClient *new_hidclient(void);
static void start_polling_thread(wiiu_hid_t *hid);
static void stop_polling_thread(wiiu_hid_t *hid);
static int wiiu_hid_polling_thread(int argc, const char **argv);
static int32_t wiiu_attach_callback(HIDClient *client, HIDDevice *device, uint32_t attach);
static wiiu_event_list events;
static bool wiiu_hid_joypad_query(void *data, unsigned pad)
{
@ -100,16 +77,17 @@ static int16_t wiiu_hid_joypad_axis(void *data, unsigned port, uint32_t joyaxis)
static void *wiiu_hid_init(void)
{
RARCH_LOG("[hid]: wiiu_hid: init\n");
// HIDSetup();
wiiu_hid_t *hid = new_hid();
HIDClient *client = new_hidclient();
if(!hid || !client) {
joypad_connection_t *connections = pad_connection_init(MAX_HID_PADS);
if(!hid || !client || !connections) {
goto error;
}
RARCH_LOG("[hid]: hid: 0x%x\n", hid);
RARCH_LOG("[hid]: client: 0x%x\n", client);
hid->connections = connections;
wiiu_hid_init_event_list();
start_polling_thread(hid);
if(!hid->polling_thread)
goto error;
@ -118,11 +96,13 @@ static void *wiiu_hid_init(void)
HIDAddClient(client, wiiu_attach_callback);
hid->client = client;
RARCH_LOG("[hid]: init success");
RARCH_LOG("[hid]: init success\n");
return hid;
error:
RARCH_LOG("[hid]: initialization failed. cleaning up.\n");
if(connections)
free(connections);
stop_polling_thread(hid);
delete_hid(hid);
delete_hidclient(client);
@ -137,8 +117,15 @@ static void wiiu_hid_free(void *data)
stop_polling_thread(hid);
delete_hidclient(hid->client);
delete_hid(hid);
if(events.list) {
wiiu_attach_event *event;
while( (event = events.list) != NULL) {
events.list = event->next;
delete_attach_event(event);
}
memset(&events, 0, sizeof(events));
}
}
//HIDTeardown();
}
static void wiiu_hid_poll(void *data)
@ -146,6 +133,15 @@ static void wiiu_hid_poll(void *data)
(void)data;
}
static void wiiu_hid_device_send_control(void *data,
uint8_t *buffer,
size_t buffer_size) {
struct wiiu_adapter *adapter = (struct wiiu_adapter *)data;
if(!adapter)
return;
}
static void start_polling_thread(wiiu_hid_t *hid) {
RARCH_LOG("[hid]: starting polling thread.\n");
OSThreadAttributes attributes = OS_THREAD_ATTRIB_AFFINITY_CPU2;
@ -203,7 +199,7 @@ static void stop_polling_thread(wiiu_hid_t *hid) {
hid->polling_thread_stack = NULL;
}
void log_device(HIDDevice *device) {
static void log_device(HIDDevice *device) {
if(!device) {
RARCH_LOG("NULL device.\n");
}
@ -219,20 +215,105 @@ void log_device(HIDDevice *device) {
RARCH_LOG(" max_packet_size_tx: %d\n", device->max_packet_size_tx);
}
static void synchronized_add_event(wiiu_attach_event *event) {
OSFastMutex_Lock(&(events.lock));
event->next = events.list;
events.list = event;
OSFastMutex_Unlock(&(events.lock));
}
static wiiu_attach_event *synchronized_get_events_list(void) {
wiiu_attach_event *list;
OSFastMutex_Lock(&(events.lock));
list = events.list;
events.list = NULL;
OSFastMutex_Unlock(&(events.lock));
return list;
}
static void synchronized_add_to_adapters_list(struct wiiu_adapter *adapter) {
}
static int32_t wiiu_attach_callback(HIDClient *client, HIDDevice *device, uint32_t attach) {
wiiu_attach_event *event;
log_device(device);
switch(attach) {
case HID_DEVICE_ATTACH:
RARCH_LOG("USB device attach event\n");
break;
case HID_DEVICE_DETACH:
RARCH_LOG("USB device detach event\n");
break;
event = new_attach_event(device);
if(!event)
goto error;
event->type = attach;
synchronized_add_event(event);
return DEVICE_USED;
default:
break;
}
log_device(device);
return DEVICE_UNUSED;
error:
delete_attach_event(event);
return DEVICE_UNUSED;
}
static int32_t wiiu_hid_pad_init(joypad_connection_t *joyconn,
const char *name, uint16_t vid, uint16_t pid, void *data,
send_control_t ptr) {
int pad = pad_connection_find_vacant_pad_max(joyconn, MAX_HID_PADS);
return pad_connection_pad_init_with_slot(joyconn, name, vid, pid,
data, ptr, pad);
}
static void wiiu_hid_detach(wiiu_hid_t *hid, wiiu_attach_event *event) {
}
static void wiiu_hid_attach(wiiu_hid_t *hid, wiiu_attach_event *event) {
struct wiiu_adapter *adapter = new_adapter();
if(!adapter) {
RARCH_ERR("[hid]: Failed to allocate adapter.\n");
goto error;
}
adapter->hid = hid;
adapter->handle = event->handle;
adapter->slot = wiiu_hid_pad_init(hid->connections,
"hid", event->vendor_id, event->product_id, adapter,
&wiiu_hid_device_send_control);
if(adapter->slot < 0) {
RARCH_ERR("[hid]: No available slots.\n");
goto error;
}
if(!pad_connection_has_interface(hid->connections, adapter->slot)) {
RARCH_ERR("[hid]: Interface not found for HID device with vid=0x%04x pid=0x%04x\n",
event->vendor_id, event->product_id);
goto error;
}
synchronized_add_to_adapters_list(adapter);
return;
error:
delete_adapter(adapter);
}
static void wiiu_handle_attach_events(wiiu_hid_t *hid, wiiu_attach_event *list) {
wiiu_attach_event *event;
if(!hid || !list)
return;
for(event = list; event != NULL; event = event->next) {
if(event->type == HID_DEVICE_ATTACH) {
wiiu_hid_attach(hid, event);
} else {
wiiu_hid_detach(hid, event);
}
}
}
static int wiiu_hid_polling_thread(int argc, const char **argv) {
@ -240,6 +321,7 @@ static int wiiu_hid_polling_thread(int argc, const char **argv) {
int i = 0;
RARCH_LOG("[hid]: polling thread is starting\n");
while(!hid->polling_thread_quit) {
wiiu_handle_attach_events(hid, synchronized_get_events_list());
usleep(10000);
i += 10000;
if(i >= (1000 * 1000 * 3)) {
@ -259,6 +341,12 @@ static OSThread *new_thread(void) {
return t;
}
static void wiiu_hid_init_event_list(void) {
RARCH_LOG("[hid]: Initializing events list\n");
memset(&events, 0, sizeof(events));
OSFastMutex_Init(&(events.lock), "attach_events");
}
static wiiu_hid_t *new_hid(void) {
RARCH_LOG("[hid]: new_hid()\n");
return alloc_zeroed(4, sizeof(wiiu_hid_t));
@ -281,6 +369,42 @@ static void delete_hidclient(HIDClient *client) {
free(client);
}
static struct wiiu_adapter *new_adapter(void) {
RARCH_LOG("[hid]: new_adapter()\n");
return alloc_zeroed(4, sizeof(struct wiiu_adapter));
}
static void delete_adapter(struct wiiu_adapter *adapter) {
RARCH_LOG("[hid]: delete_adapter()\n");
if(adapter)
free(adapter);
}
static wiiu_attach_event *new_attach_event(HIDDevice *device) {
if(!device)
return NULL;
wiiu_attach_event *event = alloc_zeroed(4, sizeof(wiiu_attach_event));
if(!event)
return NULL;
event->handle = device->handle;
event->vendor_id = device->vid;
event->product_id = device->vid;
event->interface_index = device->interface_index;
event->is_keyboard = (device->sub_class == 1 && device->protocol == 1);
event->is_mouse = (device->sub_class == 1 && device->protocol == 2);
event->max_packet_size_rx = device->max_packet_size_rx;
event->max_packet_size_tx = device->max_packet_size_tx;
return event;
}
static void delete_attach_event(wiiu_attach_event *event) {
if(event)
free(event);
}
void *alloc_zeroed(size_t alignment, size_t size) {
void *result = memalign(alignment, size);
if(result) {

View File

@ -0,0 +1,92 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2013-2014 - Jason Fetters
* Copyright (C) 2011-2017 - Daniel De Matteis
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __WIIU_HID__H
#define __WIIU_HID__H
#include "../connect/joypad_connection.h"
#include "../input_defines.h"
#include "../input_driver.h"
#include "../../verbosity.h"
#define DEVICE_UNUSED 0
#define DEVICE_USED 1
#define MAX_HID_PADS 5
typedef struct wiiu_hid
{
HIDClient *client;
joypad_connection_t *connections;
OSThread *polling_thread;
void *polling_thread_stack;
volatile bool polling_thread_quit;
} wiiu_hid_t;
struct wiiu_adapter {
wiiu_hid_t *hid;
int32_t slot;
uint32_t handle;
};
typedef struct wiiu_attach wiiu_attach_event;
struct wiiu_attach {
wiiu_attach_event *next;
uint32_t type;
uint32_t handle;
uint16_t vendor_id;
uint16_t product_id;
uint8_t interface_index;
uint8_t is_keyboard;
uint8_t is_mouse;
uint16_t max_packet_size_rx;
uint16_t max_packet_size_tx;
};
typedef struct _wiiu_event_list wiiu_event_list;
struct _wiiu_event_list {
OSFastMutex lock;
wiiu_attach_event *list;
};
static void *alloc_zeroed(size_t alignment, size_t size);
static OSThread *new_thread(void);
static wiiu_hid_t *new_hid(void);
static void delete_hid(wiiu_hid_t *hid);
static void delete_hidclient(HIDClient *client);
static HIDClient *new_hidclient(void);
static struct wiiu_adapter *new_adapter(void);
static void delete_adapter(struct wiiu_adapter *adapter);
static wiiu_attach_event *new_attach_event(HIDDevice *device);
static void delete_attach_event(wiiu_attach_event *);
static void wiiu_hid_init_event_list(void);
static void start_polling_thread(wiiu_hid_t *hid);
static void stop_polling_thread(wiiu_hid_t *hid);
static int wiiu_hid_polling_thread(int argc, const char **argv);
static int32_t wiiu_attach_callback(HIDClient *client, HIDDevice *device, uint32_t attach);
static wiiu_attach_event *synchronized_get_events_list(void);
static void wiiu_handle_attach_events(wiiu_hid_t *hid, wiiu_attach_event *list);
static int32_t wiiu_hid_pad_init(joypad_connection_t *joyconn,
const char *name, uint16_t vid, uint16_t pid, void *data,
send_control_t ptr);
static void wiiu_hid_attach(wiiu_hid_t *hid, wiiu_attach_event *event);
static void wiiu_hid_detach(wiiu_hid_t *hid, wiiu_attach_event *event);
static void synchronized_add_to_adapters_list(struct wiiu_adapter *adapter);
static void synchronized_add_event(wiiu_attach_event *event);
#endif // __WIIU_HID__H