HID worker thread is now operational

== DETAILS
After wasting some cycles trying to isolate a crash, I went back to
basics.

I enabled the network logging, and put in a bunch of logging lines,
and noticed that the HID thread wasn't actually starting.

I did quite a bit of experimenting, working with different
memory alignments, and finally got it working.

== TESTING
As you can see, I put a log output inside the worker thread. When
I run the build, I can see the TICK messages. I can also see that
the thread shuts down as expected.

Also! The HID callback works as expected too! I have the GC
adapter, and when I register the HID callback it fires and I get the
following data:

    [INFO] USB device attach event
    [INFO]                 handle: 2058729
    [INFO]   physical_device_inst: 0
    [INFO]                    vid: 0x7e05
    [INFO]                    pid: 0x3703
    [INFO]        interface_index: 0
    [INFO]              sub_class: 0
    [INFO]               protocol: 0
    [INFO]     max_packet_size_rx: 37
    [INFO]     max_packet_size_tx: 5

Note that these are raw dumps of the data passed to the method,
so e.g. the VID/PID might be byte-swapped from how they're usually
represented.

Have not done the stress test to try to reproduce the crash.
This commit is contained in:
gblues 2017-12-09 00:18:04 -08:00 committed by twinaphex
parent 192f5875b9
commit e98b006715

View File

@ -24,64 +24,9 @@
#include "../input_driver.h"
#include "../../verbosity.h"
<<<<<<< HEAD
#define POLL_THREAD_SLEEP 10000
<<<<<<< HEAD
=======
#define DEVICE_UNUSED 0
#define DEVICE_USED 1
typedef struct wiiu_hid_user wiiu_hid_user_t;
struct wiiu_hid_user
{
wiiu_hid_user_t *next;
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
{
HIDClient *client;
OSThread *polling_thread;
// memory accounting; keep a pointer to the stack buffer so we can clean up later.
void *polling_thread_stack;
// setting this to true tells the polling thread to quit
volatile bool polling_thread_quit;
} wiiu_hid_t;
>>>>>>> Start implementing HID polling thread
<<<<<<< HEAD
#define DEVICE_UNUSED 0
#define DEVICE_USED 1
typedef struct wiiu_hid_user wiiu_hid_user_t;
<<<<<<< HEAD
struct wiiu_hid_user
{
wiiu_hid_user_t *next;
uint8_t *buffer;
uint32_t transfersize;
uint32_t handle;
};
=======
#define DEVICE_UNUSED 0
#define DEVICE_USED 1
#define ALIGN_POINTER sizeof(void *)
>>>>>>> Simplify, add logging, revert some of the changes
typedef struct wiiu_hid
{
HIDClient *client;
@ -90,57 +35,17 @@ typedef struct wiiu_hid
volatile bool polling_thread_quit;
} wiiu_hid_t;
<<<<<<< HEAD
=======
>>>>>>> More progress on the HID driver
/*
* The attach/detach callback has no access to the wiiu_hid_t object. Therefore, we need a
* global place to handle device data.
*/
static wiiu_hid_user_t *pad_list = NULL;
static OSFastMutex *pad_list_mutex;
static wiiu_hid_t *new_wiiu_hid_t(void);
static void delete_wiiu_hid_t(wiiu_hid_t *hid);
static wiiu_hid_user_t *new_wiiu_hid_user_t(void);
static void delete_wiiu_hid_user_t(wiiu_hid_user_t *user);
=======
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);
>>>>>>> Simplify, add logging, revert some of the changes
static HIDClient *new_hidclient(void);
<<<<<<< HEAD
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);
static void wiiu_hid_do_poll(wiiu_hid_t *hid);
<<<<<<< HEAD
static void enqueue_device(void);
=======
>>>>>>> Start implementing HID polling thread
//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
*/
=======
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);
>>>>>>> Simplify, add logging, revert some of the changes
static bool wiiu_hid_joypad_query(void *data, unsigned pad)
{
@ -149,7 +54,6 @@ static bool wiiu_hid_joypad_query(void *data, unsigned pad)
static const char *wiiu_hid_joypad_name(void *data, unsigned pad)
{
/* TODO/FIXME - implement properly */
if (pad >= MAX_USERS)
return NULL;
@ -195,48 +99,26 @@ static int16_t wiiu_hid_joypad_axis(void *data, unsigned port, uint32_t joyaxis)
static void *wiiu_hid_init(void)
{
<<<<<<< HEAD
wiiu_hid_t *hid = new_hid();
// HIDClient *client = new_hidclient();
// 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;
return hid;
error:
if(hid) {
stop_polling_thread(hid);
delete_hid(hid);
}
// if(client) {
// delete_hidclient(client);
// }
return NULL;
=======
HIDSetup();
RARCH_LOG("[hid]: wiiu_hid: init\n");
// HIDSetup();
wiiu_hid_t *hid = new_hid();
HIDClient *client = new_hidclient();
if(!hid || !client) {
goto error;
}
RARCH_LOG("[hid]: hid: 0x%x\n", hid);
RARCH_LOG("[hid]: client: 0x%x\n", client);
start_polling_thread(hid);
if(!hid->polling_thread)
goto error;
RARCH_LOG("[hid]: Registering HIDClient\n");
HIDAddClient(client, wiiu_attach_callback);
hid->client = client;
RARCH_LOG("[hid]: init success");
return hid;
error:
@ -245,47 +127,10 @@ static void *wiiu_hid_init(void)
delete_hid(hid);
delete_hidclient(client);
return NULL;
>>>>>>> Simplify, add logging, revert some of the changes
}
static void wiiu_hid_free(void *data)
{
<<<<<<< HEAD
wiiu_hid_t *hid = (wiiu_hid_t*)data;
if (hid) {
stop_polling_thread(hid);
<<<<<<< HEAD
delete_wiiu_hid_t(hid);
}
}
<<<<<<< HEAD
<<<<<<< HEAD
=======
>>>>>>> More progress on the HID driver
static void free_pad_list(void) {
wiiu_hid_user_t *top;
while(pad_list != NULL) {
top = pad_list;
pad_list = top->next;
delete_wiiu_hid_user_t(top);
=======
delete_hid(hid);
>>>>>>> Only call HIDSetup/HidTeardown once
}
}
<<<<<<< HEAD
=======
>>>>>>> Start implementing HID polling thread
=======
>>>>>>> More progress on the HID driver
/**
* This is a no-op because polling is done with a worker thread.
*/
=======
wiiu_hid_t *hid = (wiiu_hid_t*)data;
if (hid) {
@ -293,10 +138,9 @@ static void free_pad_list(void) {
delete_hidclient(hid->client);
delete_hid(hid);
}
HIDTeardown();
//HIDTeardown();
}
>>>>>>> Simplify, add logging, revert some of the changes
static void wiiu_hid_poll(void *data)
{
(void)data;
@ -304,73 +148,37 @@ static void wiiu_hid_poll(void *data)
static void start_polling_thread(wiiu_hid_t *hid) {
RARCH_LOG("[hid]: starting polling thread.\n");
OSThreadAttributes attributes = OS_THREAD_ATTRIB_AFFINITY_CPU2 |
OS_THREAD_ATTRIB_STACK_USAGE;
OSThreadAttributes attributes = OS_THREAD_ATTRIB_AFFINITY_CPU2;
BOOL result;
int32_t stack_size = 0x8000;
int32_t priority = 10;
OSThread *thread = memalign(ALIGN_POINTER, sizeof(OSThread));
void *stack = memalign(ALIGN_POINTER, stack_size);
OSThread *thread = new_thread();
void *stack = alloc_zeroed(16, stack_size);
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
=======
>>>>>>> More progress on the HID driver
if(pad_list_mutex == NULL) {
pad_list_mutex = new_fastmutex("pad_list");
}
if(!thread || !stack || !pad_list_mutex)
<<<<<<< HEAD
=======
if(!thread || !stack)
>>>>>>> Start implementing HID polling thread
=======
>>>>>>> More progress on the HID driver
=======
if(!thread || !stack)
>>>>>>> Only call HIDSetup/HidTeardown once
goto error;
=======
if(!thread || !stack) {
RARCH_LOG("[hid]: allocation failed, aborting thread start.\n");
goto error;
}
RARCH_LOG("[hid]: thread = %x; stack = %x\n", thread, stack);
>>>>>>> Simplify, add logging, revert some of the changes
RARCH_LOG("[hid]: thread: 0x%x; stack: 0x%x\n", thread, stack);
if(!OSCreateThread(thread, wiiu_hid_polling_thread, 1, (char *)hid, stack, stack_size, priority, attributes)) {
if(!OSCreateThread(thread,
wiiu_hid_polling_thread,
1, (char *)hid,
stack+stack_size, stack_size,
priority,
attributes)) {
RARCH_LOG("[hid]: OSCreateThread failed.\n");
goto error;
}
hid->polling_thread = thread;
hid->polling_thread_stack = stack;
OSResumeThread(thread);
return;
error:
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
if(pad_list_mutex)
delete_fastmutex(pad_list_mutex);
=======
>>>>>>> Start implementing HID polling thread
=======
if(pad_list_mutex)
delete_fastmutex(pad_list_mutex);
>>>>>>> More progress on the HID driver
=======
>>>>>>> Only call HIDSetup/HidTeardown once
if(stack)
free(stack);
=======
>>>>>>> Simplify, add logging, revert some of the changes
if(thread)
free(thread);
if(stack)
@ -391,28 +199,8 @@ static void stop_polling_thread(wiiu_hid_t *hid) {
OSJoinThread(hid->polling_thread, &thread_result);
free(hid->polling_thread);
free(hid->polling_thread_stack);
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
=======
>>>>>>> More progress on the HID driver
// with the thread stopped, we don't need the mutex.
delete_fastmutex(pad_list_mutex);
pad_list_mutex = NULL;
free_pad_list();
<<<<<<< HEAD
=======
>>>>>>> Start implementing HID polling thread
=======
>>>>>>> More progress on the HID driver
=======
>>>>>>> Only call HIDSetup/HidTeardown once
=======
hid->polling_thread = NULL;
hid->polling_thread_stack = NULL;
>>>>>>> Simplify, add logging, revert some of the changes
}
void log_device(HIDDevice *device) {
@ -420,60 +208,6 @@ void log_device(HIDDevice *device) {
RARCH_LOG("NULL device.\n");
}
<<<<<<< HEAD
return 0;
}
/**
* Only call this from the polling thread.
*/
static void wiiu_hid_do_poll(wiiu_hid_t *hid) {
usleep(POLL_THREAD_SLEEP);
}
<<<<<<< HEAD
<<<<<<< HEAD
<<<<<<< HEAD
=======
>>>>>>> More progress on the HID driver
int32_t wiiu_attach_device(HIDClient *client, HIDDevice *device) {
wiiu_hid_user_t *adapter = new_wiiu_hid_user_t();
if(!adapter)
goto error;
error:
if(adapter) {
delete_wiiu_hid_user_t(adapter);
}
return DEVICE_UNUSED;
}
int32_t wiiu_detach_device(HIDClient *client, HIDDevice *device) {
return DEVICE_UNUSED;
}
<<<<<<< HEAD
=======
>>>>>>> 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:
RARCH_LOG("Device attached\n");
break;
case HID_DEVICE_DETACH:
RARCH_LOG("Device detached\n");
=======
RARCH_LOG(" handle: %d\n", device->handle);
RARCH_LOG(" physical_device_inst: %d\n", device->physical_device_inst);
RARCH_LOG(" vid: 0x%x\n", device->vid);
@ -492,7 +226,6 @@ static int32_t wiiu_attach_callback(HIDClient *client, HIDDevice *device, uint32
break;
case HID_DEVICE_DETACH:
RARCH_LOG("USB device detach event\n");
>>>>>>> Simplify, add logging, revert some of the changes
break;
default:
break;
@ -501,60 +234,49 @@ static int32_t wiiu_attach_callback(HIDClient *client, HIDDevice *device, uint32
return DEVICE_UNUSED;
}
<<<<<<< HEAD
*/
/**
* Allocation
*/
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;
=======
static int wiiu_hid_polling_thread(int argc, const char **argv) {
wiiu_hid_t *hid = (wiiu_hid_t *)argv;
int i = 0;
RARCH_LOG("[hid]: polling thread is starting\n");
while(!hid->polling_thread_quit) {
usleep(10000);
i += 10000;
if(i >= (1000 * 1000 * 3)) {
RARCH_LOG("[hid]: thread: TICK!\n");
i = 0;
}
}
RARCH_LOG("[hid]: polling thread is stopping\n");
return 0;
}
static OSThread *new_thread(void) {
OSThread *t = alloc_zeroed(8, sizeof(OSThread));
t->tag = OS_THREAD_TAG;
return t;
}
static wiiu_hid_t *new_hid(void) {
return alloc_zeroed(2, sizeof(wiiu_hid_t));
>>>>>>> Simplify, add logging, revert some of the changes
RARCH_LOG("[hid]: new_hid()\n");
return alloc_zeroed(4, sizeof(wiiu_hid_t));
}
static void delete_hid(wiiu_hid_t *hid) {
RARCH_LOG("[hid]: delete_hid()\n");
if(hid)
free(hid);
}
<<<<<<< HEAD
/*
HIDClient *new_hidclient(void) {
HIDClient *client = memalign(32, sizeof(HIDClient));
if(client)
memset(client, 0, sizeof(HIDClient));
return client;
}
void delete_hidclient(HIDClient *client) {
if(client)
free(client);
}
*/
=======
static HIDClient *new_hidclient(void) {
RARCH_LOG("[hid]: new_hidclient()\n");
return alloc_zeroed(32, sizeof(HIDClient));
}
static void delete_hidclient(HIDClient *client) {
RARCH_LOG("[hid]: delete_hidclient()\n");
if(client)
free(client);
}
@ -569,7 +291,6 @@ void *alloc_zeroed(size_t alignment, size_t size) {
}
>>>>>>> Simplify, add logging, revert some of the changes
hid_driver_t wiiu_hid = {
wiiu_hid_init,
wiiu_hid_joypad_query,
@ -580,5 +301,5 @@ hid_driver_t wiiu_hid = {
wiiu_hid_poll,
wiiu_hid_joypad_rumble,
wiiu_hid_joypad_name,
"wiiu_usb",
"wiiu",
};