Fix the blocking call to HIDRead()

== DETAILS

TIL that the "max_packet_size_*" fields in the HIDDevice struct
are actually requirements, not maximums.

The reason HIDRead() was blocking was because the HIDWrite() that
sent the activation command was silently failing.

The reason HIDWrite() was silently failing was because I was using too
small of a buffer for the device.

In this case: the Wii U GC adapter, which has a "max" tx packet size of 5.

"max" is misleading. You actually have to write all 5 bytes.

Which means: copying the 1-byte buffer to the 5-byte buffer, and writing
the 5-byte buffer via HIDWrite().

So, in summary:

- Use correct semantics for HIDWrite() so that HIDRead() can work.
- Update the OSThread struct to reflect the current knowledge over at
  WUT. It's unlikely this was actually causing a problem, but never
  hurts to be more correct.

== TESTING
I temporarily enabled the call to log_buffer() and confirmed that the
GC adapter's state is successfully being read.
This commit is contained in:
gblues 2018-01-05 23:12:42 -08:00
parent 74942551ff
commit 560a5f0a4f
3 changed files with 35 additions and 15 deletions

View File

@ -227,7 +227,7 @@ typedef struct OSThread
//! Queue of threads waiting for a thread to be suspended.
OSThreadQueue suspendQueue;
uint32_t unknown4[0x2A];
uint32_t unknown4[0x2B];
} OSThread;
#pragma pack(pop)

View File

@ -138,6 +138,8 @@ struct wiiu_adapter {
uint8_t state;
uint8_t *rx_buffer;
int32_t rx_size;
uint8_t *tx_buffer;
int32_t tx_size;
int32_t slot;
uint32_t handle;
uint8_t interface_index;

View File

@ -77,7 +77,7 @@ 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");
RARCH_LOG("[hid]: initializing HID subsystem\n");
wiiu_hid_t *hid = new_hid();
HIDClient *client = new_hidclient();
@ -135,10 +135,28 @@ static void wiiu_hid_poll(void *data)
static void wiiu_hid_send_control(void *data, uint8_t *buf, size_t size)
{
wiiu_adapter_t *adapter = (wiiu_adapter_t *)data;
if (!adapter)
return;
int32_t result;
HIDWrite(adapter->handle, buf, size, NULL, NULL);
if (!adapter) {
RARCH_ERR("[hid]: send_control: bad adapter.\n");
return;
}
memset(adapter->tx_buffer, 0, adapter->tx_size);
memcpy(adapter->tx_buffer, buf, size);
// From testing, HIDWrite returns an error that looks like it's two
// int16_t's bitmasked together. For example, one error I saw when trying
// to write a single byte was 0xffe2ff97, which works out to -30 and -105.
// I have no idea what these mean.
result = HIDWrite(adapter->handle, adapter->tx_buffer, adapter->tx_size, NULL, NULL);
if(result < 0) {
int16_t r1, r2;
r1 = (result & 0x0000FFFF);
r2 = ((result & 0xFFFF0000) >> 16);
RARCH_LOG("[hid]: write failed: %08x (%d:%d)\n", result, r2, r1);
}
}
static int32_t wiiu_hid_set_report(void *data, uint8_t report_type,
@ -356,12 +374,9 @@ static void wiiu_hid_attach(wiiu_hid_t *hid, wiiu_attach_event *event)
RARCH_LOG("[hid]: adding to adapter list\n");
synchronized_add_to_adapters_list(adapter);
#if 0
/* this is breaking again. Not sure why. But disabling it now so the
* startup/shutdown times aren't affected by the blocking call. */
RARCH_LOG("[hid]: starting read loop\n");
wiiu_start_read_loop(adapter);
#endif
return;
error:
@ -429,10 +444,11 @@ static void log_buffer(uint8_t *data, uint32_t len)
static void wiiu_hid_do_read(wiiu_adapter_t *adapter,
uint8_t *data, uint32_t length)
{
/* log_buffer(data, length);
* do_sampling()
* do other stuff?
*/
#if 0
log_buffer(data, length);
#endif
// TODO: get this data to the connect_xxx driver somehow.
}
static void wiiu_hid_read_loop_callback(uint32_t handle, int32_t error,
@ -593,7 +609,7 @@ static void delete_hidclient(HIDClient *client)
static wiiu_adapter_t *new_adapter(wiiu_attach_event *event)
{
wiiu_adapter_t *adapter = alloc_zeroed(64, sizeof(wiiu_adapter_t));
wiiu_adapter_t *adapter = alloc_zeroed(32, sizeof(wiiu_adapter_t));
if (!adapter)
return NULL;
@ -601,7 +617,9 @@ static wiiu_adapter_t *new_adapter(wiiu_attach_event *event)
adapter->handle = event->handle;
adapter->interface_index = event->interface_index;
adapter->rx_size = event->max_packet_size_rx;
adapter->rx_buffer = alloc_zeroed(64, adapter->rx_size);
adapter->rx_buffer = alloc_zeroed(32, adapter->rx_size);
adapter->tx_size = event->max_packet_size_tx;
adapter->tx_buffer = alloc_zeroed(32, adapter->tx_size);
return adapter;
}