Fix up HID device driver initialization

== DETAILS
Turns out the cause of the crash was a bad cast, resulting in a
function call to nowhere.

Also, I think the DSI exception handler only works on the primary core;
when this was happening in the background thread, I got a black
screen error instead.

Next up: finishing up the GCA driver.
This commit is contained in:
gblues 2018-03-24 22:35:22 -07:00
parent dc6f4c23ed
commit 180d6a28bf
7 changed files with 113 additions and 52 deletions

View File

@ -21,7 +21,7 @@ struct ds3_instance {
void *handle;
};
static void *ds3_init(hid_driver_instance_t *hid_driver)
static void *ds3_init(void *handle)
{
return NULL;
}

View File

@ -21,7 +21,7 @@ struct ds4_instance {
void *handle;
};
static void *ds4_init(hid_driver_instance_t *hid_driver)
static void *ds4_init(void *handle)
{
return NULL;
}

View File

@ -27,7 +27,7 @@ static uint8_t activation_packet[] = { 0x13 };
#define GCA_PORT_CONNECTED 0x14
typedef struct wiiu_gca_instance {
hid_driver_instance_t *driver;
void *handle;
bool online;
uint8_t device_state[37];
joypad_connection_t *pads[4];
@ -39,17 +39,29 @@ static void unregister_pad(wiiu_gca_instance_t *instance, int slot);
extern pad_connection_interface_t wiiu_gca_pad_connection;
static void *wiiu_gca_init(hid_driver_instance_t *driver)
static void *wiiu_gca_init(void *handle)
{
RARCH_LOG("[gca]: allocating driver instance...\n");
wiiu_gca_instance_t *instance = calloc(1, sizeof(wiiu_gca_instance_t));
if(instance == NULL) goto error;
RARCH_LOG("[gca]: zeroing memory...\n");
memset(instance, 0, sizeof(wiiu_gca_instance_t));
instance->driver = driver;
instance->handle = handle;
driver->os_driver->send_control(driver->os_driver_data, activation_packet, sizeof(activation_packet));
driver->os_driver->read(driver->os_driver_data, instance->device_state, sizeof(instance->device_state));
RARCH_LOG("[gca]: sending activation packet to device...\n");
hid_instance.os_driver->send_control(handle, activation_packet, sizeof(activation_packet));
RARCH_LOG("[gca]: reading initial state packet...\n");
hid_instance.os_driver->read(handle, instance->device_state, sizeof(instance->device_state));
instance->online = true;
RARCH_LOG("[gca]: init done\n");
return instance;
error:
RARCH_ERR("[gca]: init failed\n");
if(instance)
free(instance);
return NULL;
}
static void wiiu_gca_free(void *data) {
@ -110,15 +122,15 @@ static joypad_connection_t *register_pad(wiiu_gca_instance_t *instance) {
if(!instance || !instance->online)
return NULL;
slot = pad_connection_find_vacant_pad(instance->driver->pad_list);
slot = pad_connection_find_vacant_pad(hid_instance.pad_list);
if(slot < 0)
return NULL;
result = &(instance->driver->pad_list[slot]);
result = &(hid_instance.pad_list[slot]);
result->iface = &wiiu_gca_pad_connection;
result->data = result->iface->init(instance, slot, instance->driver->os_driver);
result->data = result->iface->init(instance, slot, hid_instance.os_driver);
result->connected = true;
input_pad_connect(slot, instance->driver->pad_driver);
input_pad_connect(slot, hid_instance.pad_driver);
return result;
}

View File

@ -20,9 +20,10 @@
#include "../../input_driver.h"
#include "../../connect/joypad_connection.h"
#include "../../include/hid_driver.h"
#include "../../../verbosity.h"
typedef struct hid_device {
void *(*init)(hid_driver_instance_t *driver);
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);

View File

@ -108,10 +108,8 @@ static int16_t hidpad_axis(unsigned pad, uint32_t axis)
static void hidpad_poll(void)
{
#if 0
if (ready)
hid_driver->poll(hid_data);
#endif
hid_instance.os_driver->poll(hid_instance.os_driver_data);
}
static const char *hidpad_name(unsigned pad)

View File

@ -134,7 +134,11 @@ static void wiiu_hid_free(const void *data)
static void wiiu_hid_poll(void *data)
{
(void)data;
wiiu_hid_t *hid = (wiiu_hid_t *)data;
if(hid == NULL)
return;
synchronized_process_adapters(hid);
}
static void wiiu_hid_send_control(void *data, uint8_t *buf, size_t size)
@ -310,6 +314,46 @@ static void log_device(HIDDevice *device)
}
static uint8_t try_init_driver(wiiu_adapter_t *adapter)
{
adapter->driver_handle = adapter->driver->init(adapter);
if(adapter->driver_handle == NULL) {
RARCH_ERR("[hid]: Failed to initialize driver: %s\n",
adapter->driver->name);
return ADAPTER_STATE_DONE;
}
return ADAPTER_STATE_READY;
}
static void synchronized_process_adapters(wiiu_hid_t *hid)
{
wiiu_adapter_t *adapter = NULL;
OSFastMutex_Lock(&(adapters.lock));
for(adapter = adapters.list; adapter != NULL; adapter = adapter->next)
{
switch(adapter->state)
{
case ADAPTER_STATE_DONE:
break;
case ADAPTER_STATE_NEW:
adapter->state = try_init_driver(adapter);
break;
case ADAPTER_STATE_READY:
case ADAPTER_STATE_READING:
#if 0
adapter->driver->poll();
#endif
break;
default:
RARCH_ERR("[hid]: Invalid adapter state: %d\n", adapter->state);
break;
}
}
OSFastMutex_Unlock(&(adapters.lock));
}
static void synchronized_add_event(wiiu_attach_event *event)
{
OSFastMutex_Lock(&(events.lock));
@ -413,12 +457,7 @@ static void wiiu_hid_attach(wiiu_hid_t *hid, wiiu_attach_event *event)
adapter->hid = hid;
adapter->driver = event->driver;
adapter->driver_handle = adapter->driver->init(hid->driver);
if(adapter->driver_handle == NULL) {
RARCH_ERR("[hid]: Failed to initialize driver: %s\n",
adapter->driver->name);
}
adapter->state = ADAPTER_STATE_NEW;
RARCH_LOG("[hid]: adding to adapter list\n");
synchronized_add_to_adapters_list(adapter);
@ -434,13 +473,11 @@ error:
void wiiu_start_read_loop(wiiu_adapter_t *adapter)
{
adapter->state = ADAPTER_STATE_READING;
#if 0
RARCH_LOG("HIDRead(0x%08x, 0x%08x, %d, 0x%08x, 0x%08x)\n",
adapter->handle, adapter->rx_buffer, adapter->rx_size,
wiiu_hid_read_loop_callback, adapter);
#endif
HIDRead(adapter->handle, adapter->rx_buffer, adapter->rx_size, wiiu_hid_read_loop_callback, adapter);
HIDRead(adapter->handle,
adapter->rx_buffer,
adapter->rx_size,
wiiu_hid_read_loop_callback,
adapter);
}
/**
@ -493,32 +530,42 @@ static void log_buffer(uint8_t *data, uint32_t len)
static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error,
uint8_t *buffer, uint32_t buffer_size, void *userdata)
{
wiiu_adapter_t *adapter = (wiiu_adapter_t *)userdata;
if(!adapter)
{
RARCH_ERR("read_loop_callback: bad userdata\n");
return;
}
wiiu_adapter_t *adapter = (wiiu_adapter_t *)userdata;
if(!adapter)
{
RARCH_ERR("read_loop_callback: bad userdata\n");
return;
}
if(adapter->hid->polling_thread_quit)
{
RARCH_LOG("Shutting down read loop for device: %s\n",
if(adapter->hid->polling_thread_quit)
{
RARCH_LOG("Shutting down read loop for device: %s\n",
adapter->driver->name);
adapter->state = ADAPTER_STATE_DONE;
return;
}
adapter->state = ADAPTER_STATE_DONE;
}
if(error)
{
RARCH_ERR("Read failed with error 0x%08x\n", error);
adapter->state = ADAPTER_STATE_DONE;
return;
}
if(adapter->state == ADAPTER_STATE_READY ||
adapter->state == ADAPTER_STATE_READING) {
adapter->driver->handle_packet(adapter->driver_handle, buffer, buffer_size);
adapter->state = ADAPTER_STATE_READING;
adapter->state = ADAPTER_STATE_READING;
HIDRead(adapter->handle, adapter->rx_buffer, adapter->rx_size,
if(error)
{
int16_t r1 = (error & 0x0000FFFF);
int16_t r2 = ((error & 0xFFFF0000) >> 16);
RARCH_ERR("[hid]: read failed: %08x (%d:%d)\n", error, r2, r1);
} else {
#if 0
adapter->driver->handle_packet(adapter->driver_handle, buffer, buffer_size);
#endif
}
}
/* this can also get set if something goes wrong in initialization */
if(adapter->state == ADAPTER_STATE_DONE)
return;
HIDRead(adapter->handle, adapter->rx_buffer, adapter->rx_size,
wiiu_hid_read_loop_callback, adapter);
}

View File

@ -24,8 +24,10 @@
#define DEVICE_USED 1
#define ADAPTER_STATE_NEW 0
#define ADAPTER_STATE_READING 1
#define ADAPTER_STATE_DONE 2
#define ADAPTER_STATE_READY 1
#define ADAPTER_STATE_READING 2
#define ADAPTER_STATE_DONE 3
static void *alloc_zeroed(size_t alignment, size_t size);
static OSThread *new_thread(void);
@ -47,6 +49,7 @@ static wiiu_attach_event *synchronized_get_events_list(void);
static void wiiu_handle_attach_events(wiiu_hid_t *hid, wiiu_attach_event *list);
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_process_adapters(wiiu_hid_t *hid);
static void synchronized_add_to_adapters_list(wiiu_adapter_t *adapter);
static wiiu_adapter_t *synchronized_remove_from_adapters_list(uint32_t handle);
static void synchronized_add_event(wiiu_attach_event *event);