Only call HIDSetup/HidTeardown once

== DETAILS
I did a minimalist edit of the HID thread that stripped out all
HID* syscalls, and this stopped the crashing. I then re-added just
the HIDSetup() and HIDTeardown() calls, and the crash came back.

This smells like an OS bug. To work around it, I've put the
HIDSetup() and HIDTeardown() calls into the app init/shutdown
section, so they only get called once in the application lifetime
and not each time the input driver is initialized.
This commit is contained in:
gblues 2017-12-06 22:33:14 -08:00 committed by twinaphex
parent d0368124e6
commit 1beba28d02
5 changed files with 100 additions and 91 deletions

View File

@ -49,7 +49,7 @@
#include "system/memory.h"
#include "system/exception_handler.h"
#include <sys/iosupport.h>
#include <wiiu/syshid.h>
#include <wiiu/os/foreground.h>
#include <wiiu/gx2/event.h>
#include <wiiu/procui.h>
@ -641,9 +641,16 @@ void _start(int argc, char **argv)
memoryInitialize();
__init();
fsdev_init();
#ifdef HAVE_HID
HIDSetup();
#endif
main(argc, argv);
#ifdef HAVE_HID
HIDTeardown();
#endif
fsdev_exit();
/* TODO: fix elf2rpl so it doesn't error with "Could not find matching symbol

View File

@ -24,6 +24,8 @@
#include "../input_defines.h"
#include "../input_driver.h"
#include "../connect/joypad_connection.h"
#include "../../verbosity.h"
#define POLL_THREAD_SLEEP 10000
<<<<<<< HEAD
@ -37,9 +39,18 @@ typedef struct wiiu_hid_user wiiu_hid_user_t;
struct wiiu_hid_user
{
wiiu_hid_user_t *next;
uint8_t *buffer;
uint32_t transfersize;
uint8_t *send_control_buffer;
uint8_t *send_control_type;
uint32_t handle;
uint32_t physical_device_inst;
uint16_t vid;
uint16_t pid;
uint8_t interface_index;
uint8_t sub_class;
uint8_t protocol;
uint16_t max_packet_size_rx;
uint16_t max_packet_size_tx;
};
typedef struct wiiu_hid
@ -53,6 +64,7 @@ typedef struct wiiu_hid
} wiiu_hid_t;
>>>>>>> Start implementing HID polling thread
<<<<<<< HEAD
#define DEVICE_UNUSED 0
#define DEVICE_USED 1
@ -96,6 +108,9 @@ static OSFastMutex *new_fastmutex(const char *name);
static void delete_fastmutex(OSFastMutex *mutex);
static int32_t wiiu_attach_callback(HIDClient *client, HIDDevice *device, uint32_t attach);
=======
//static int32_t wiiu_attach_callback(HIDClient *client, HIDDevice *device, uint32_t attach);
>>>>>>> Only call HIDSetup/HidTeardown once
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);
@ -106,7 +121,10 @@ static void enqueue_device(void);
=======
>>>>>>> Start implementing HID polling thread
static void enqueue_device(void);
//HIDClient *new_hidclient(void);
//void delete_hidclient(HIDClient *client);
wiiu_hid_t *new_hid(void);
void delete_hid(wiiu_hid_t *hid);
/**
* HID driver entrypoints registered with hid_driver_t
@ -119,7 +137,7 @@ static bool wiiu_hid_joypad_query(void *data, unsigned pad)
static const char *wiiu_hid_joypad_name(void *data, unsigned pad)
{
return NULL;
return NULL;
}
static uint64_t wiiu_hid_joypad_get_buttons(void *data, unsigned port)
@ -161,32 +179,30 @@ static int16_t wiiu_hid_joypad_axis(void *data, unsigned port, uint32_t joyaxis)
static void *wiiu_hid_init(void)
{
wiiu_hid_t *hid = new_wiiu_hid_t();
HIDClient *client = new_hidclient();
wiiu_hid_t *hid = new_hid();
// HIDClient *client = new_hidclient();
if(!hid || !client)
// if(!hid || !client)
if(!hid)
goto error;
start_polling_thread(hid);
if(hid->polling_thread == NULL)
goto error;
HIDAddClient(client, wiiu_attach_callback);
hid->client = client;
// HIDAddClient(client, wiiu_attach_callback);
// hid->client = client;
return hid;
error:
if(hid) {
stop_polling_thread(hid);
delete_wiiu_hid_t(hid);
}
if(client)
delete_hidclient(client);
if(pad_list_mutex) {
delete_fastmutex(pad_list_mutex);
pad_list_mutex = NULL;
delete_hid(hid);
}
// if(client) {
// delete_hidclient(client);
// }
return NULL;
}
@ -197,6 +213,7 @@ static void wiiu_hid_free(void *data)
if (hid) {
stop_polling_thread(hid);
<<<<<<< HEAD
delete_wiiu_hid_t(hid);
}
}
@ -212,6 +229,9 @@ static void free_pad_list(void) {
top = pad_list;
pad_list = top->next;
delete_wiiu_hid_user_t(top);
=======
delete_hid(hid);
>>>>>>> Only call HIDSetup/HidTeardown once
}
}
@ -234,14 +254,14 @@ static void wiiu_hid_poll(void *data)
static void start_polling_thread(wiiu_hid_t *hid) {
OSThreadAttributes attributes = OS_THREAD_ATTRIB_AFFINITY_CPU2 |
OS_THREAD_ATTRIB_DETACHED |
OS_THREAD_ATTRIB_STACK_USAGE;
int32_t stack_size = 0x8000;
// wild-ass guess. the patcher thread used 28 for the network threads (10 for BOTW).
int32_t priority = 19;
int32_t priority = 10;
OSThread *thread = memalign(8, sizeof(OSThread));
void *stack = memalign(32, stack_size);
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
=======
@ -257,6 +277,9 @@ static void start_polling_thread(wiiu_hid_t *hid) {
>>>>>>> Start implementing HID polling thread
=======
>>>>>>> More progress on the HID driver
=======
if(!thread || !stack)
>>>>>>> Only call HIDSetup/HidTeardown once
goto error;
if(!OSCreateThread(thread, wiiu_hid_polling_thread, 1, (char *)hid, stack, stack_size, priority, attributes))
@ -268,6 +291,7 @@ static void start_polling_thread(wiiu_hid_t *hid) {
error:
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
if(pad_list_mutex)
delete_fastmutex(pad_list_mutex);
@ -277,6 +301,8 @@ static void start_polling_thread(wiiu_hid_t *hid) {
if(pad_list_mutex)
delete_fastmutex(pad_list_mutex);
>>>>>>> More progress on the HID driver
=======
>>>>>>> Only call HIDSetup/HidTeardown once
if(stack)
free(stack);
if(thread)
@ -298,6 +324,7 @@ static void stop_polling_thread(wiiu_hid_t *hid) {
free(hid->polling_thread_stack);
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
=======
>>>>>>> More progress on the HID driver
@ -310,6 +337,8 @@ static void stop_polling_thread(wiiu_hid_t *hid) {
>>>>>>> Start implementing HID polling thread
=======
>>>>>>> More progress on the HID driver
=======
>>>>>>> Only call HIDSetup/HidTeardown once
}
/**
@ -331,6 +360,7 @@ static void wiiu_hid_do_poll(wiiu_hid_t *hid) {
usleep(POLL_THREAD_SLEEP);
}
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
=======
@ -357,19 +387,21 @@ int32_t wiiu_detach_device(HIDClient *client, HIDDevice *device) {
>>>>>>> Start implementing HID polling thread
=======
>>>>>>> More progress on the HID driver
=======
>>>>>>> Only call HIDSetup/HidTeardown once
/**
* Callbacks
*/
/*
int32_t wiiu_attach_callback(HIDClient *client, HIDDevice *device, uint32_t attach) {
int32_t result = DEVICE_UNUSED;
switch(attach) {
case HID_DEVICE_ATTACH:
result = wiiu_attach_device(client, device);
RARCH_LOG("Device attached\n");
break;
case HID_DEVICE_DETACH:
result = wiiu_detach_device(client, device);
RARCH_LOG("Device detached\n");
break;
default:
// Undefined behavior, bail out
@ -378,91 +410,41 @@ int32_t wiiu_attach_callback(HIDClient *client, HIDDevice *device, uint32_t atta
return result;
}
static void wiiu_read_callback(uint32_t handle, int32_t errno, unsigned char *buffer, uint32_t transferred, void *usr) {
}
static void wiiu_write_callback(uint32_t handle, int32_t errno, unsigned char *buffer, uint32_t transferred, void *usr) {
}
*/
/**
* Allocation/deallocation
* Allocation
*/
static wiiu_hid_t *new_wiiu_hid_t(void) {
wiiu_hid_t *hid = (wiiu_hid_t*)calloc(1, sizeof(wiiu_hid_t));
if(!hid)
goto error;
memset(hid, 0, sizeof(wiiu_hid_t));
wiiu_hid_t *new_hid(void) {
wiiu_hid_t *hid = calloc(1, sizeof(wiiu_hid_t));
if(hid)
memset(hid, 0, sizeof(wiiu_hid_t));
return hid;
error:
if(hid)
delete_wiiu_hid_t(hid);
return NULL;
}
static void delete_wiiu_hid_t(wiiu_hid_t *hid) {
if(!hid)
return;
void delete_hid(wiiu_hid_t *hid) {
if(hid) {
if(hid->polling_thread_stack)
free(hid->polling_thread_stack);
if(hid->client) {
HIDDelClient(hid->client);
delete_hidclient(hid->client);
hid->client = NULL;
free(hid);
}
free(hid);
}
static HIDClient *new_hidclient(void) {
HIDClient *client = calloc(1, sizeof(HIDClient));
if(client != NULL) {
/*
HIDClient *new_hidclient(void) {
HIDClient *client = memalign(32, sizeof(HIDClient));
if(client)
memset(client, 0, sizeof(HIDClient));
}
return client;
}
static OSFastMutex *new_fastmutex(const char *name) {
OSFastMutex *mutex = calloc(1, sizeof(OSFastMutex));
if(mutex != NULL) {
memset(mutex, 0, sizeof(OSFastMutex));
}
OSFastMutex_Init(mutex, name);
return mutex;
}
static void delete_hidclient(HIDClient *client) {
void delete_hidclient(HIDClient *client) {
if(client)
free(client);
}
static wiiu_hid_user_t *new_wiiu_hid_user_t(void) {
wiiu_hid_user_t *user = calloc(1, sizeof(wiiu_hid_user_t));
if(user != NULL) {
memset(user, 0, sizeof(wiiu_hid_user_t));
}
return user;
}
static void delete_wiiu_hid_user_t(wiiu_hid_user_t *user) {
if(user) {
free(user);
}
}
static void delete_fastmutex(OSFastMutex *mutex) {
if(mutex)
free(mutex);
}
*/
hid_driver_t wiiu_hid = {
wiiu_hid_init,
wiiu_hid_joypad_query,
@ -473,5 +455,5 @@ hid_driver_t wiiu_hid = {
wiiu_hid_poll,
wiiu_hid_joypad_rumble,
wiiu_hid_joypad_name,
"wiiu",
"wiiu_usb",
};

View File

@ -43,6 +43,8 @@
#define GAMEPAD_OFFSET 0
static const hid_driver_t *hid_driver = NULL;
static uint64_t pad_state[MAX_PADS];
static uint8_t pad_type[MAX_PADS-1] = {WIIUINPUT_TYPE_NONE, WIIUINPUT_TYPE_NONE, WIIUINPUT_TYPE_NONE, WIIUINPUT_TYPE_NONE};
@ -299,6 +301,7 @@ static void wiiu_joypad_poll(void)
static bool wiiu_joypad_init(void* data)
{
hid_driver = input_hid_init_first();
wiiu_joypad_autodetect_add(0);
wiiu_joypad_poll();
@ -315,6 +318,11 @@ static bool wiiu_joypad_query_pad(unsigned pad)
static void wiiu_joypad_destroy(void)
{
if(hid_driver) {
hid_driver->free(hid_driver_get_data());
hid_driver_reset_data();
hid_driver = NULL;
}
wiiu_pad_inited = false;
}

View File

@ -176,7 +176,10 @@ static input_device_driver_t *joypad_drivers[] = {
#ifdef DJGPP
&dos_joypad,
#endif
#ifdef HAVE_HID
// Selecting the HID gamepad driver disables the Wii U gamepad. So while
// we want the HID code to be compiled & linked, we don't want the driver
// to be selectable in the UI.
#if defined(HAVE_HID) && !defined(WIIU)
&hid_joypad,
#endif
&null_joypad,
@ -1829,6 +1832,14 @@ const void *hid_driver_get_data(void)
return hid_data;
}
// This is only to be called after we've invoked free() on the
// HID driver; the memory will have already been freed, so we need to
// reset the pointer.
void hid_driver_reset_data(void)
{
hid_data = NULL;
}
/**
* hid_driver_find_ident:
* @idx : index of driver to get handle to.

View File

@ -647,6 +647,7 @@ const char* config_get_hid_driver_options(void);
const hid_driver_t *input_hid_init_first(void);
const void *hid_driver_get_data(void);
void hid_driver_reset_data(void);
#endif
/** Line complete callback.