1
0
mirror of https://github.com/libretro/RetroArch synced 2024-07-08 12:15:49 +00:00

Finish up the OSX DS3 driver

== DETAILS
Put the finishing touches on getting the DS3 to work on Mac OSX.

Basically, there's some differences in the HID interface bewtween
wiiu and osx where OSX expects the first byte of the report to be
the report ID, while wiiu expects that byte to be trimmed off.

I was able to put this behavior in the respective HID
implementations, which eliminated the confusing packet offset
ifdefs.

And, I was able to get the LEDs working again.
This commit is contained in:
Nathan Strong 2021-10-16 14:45:20 -07:00
parent 729c219f1a
commit 81c6d3809a
5 changed files with 101 additions and 101 deletions

View File

@ -23,6 +23,8 @@
#include "../input_defines.h"
#include "verbosity.h"
#define DS3_ACTIVATION_REPORT_ID 0xf4
#define SIXAXIS_REPORT_0xF2_SIZE 17
#define SIXAXIS_REPORT_0xF5_SIZE 8
@ -36,7 +38,6 @@ typedef struct ds3_instance
int16_t analog_state[3][2];
uint16_t motors[2];
uint8_t data[64];
uint8_t led_state[4];
} ds3_instance_t;
struct __attribute__((__packed__)) sixaxis_led {
@ -48,7 +49,6 @@ struct __attribute__((__packed__)) sixaxis_led {
};
struct __attribute__((__packed__)) sixaxis_rumble {
uint8_t padding;
uint8_t right_duration; /* Right motor duration (0xff means forever) */
uint8_t right_motor_on; /* Right (small) motor on/off, only supports values of 0 or 1 (off/on) */
uint8_t left_duration; /* Left motor duration (0xff means forever) */
@ -57,33 +57,54 @@ struct __attribute__((__packed__)) sixaxis_rumble {
struct __attribute__((__packed__)) sixaxis_output_report {
uint8_t report_id;
uint8_t padding1;
struct sixaxis_rumble rumble;
uint8_t padding[4];
uint8_t padding2[4];
uint8_t leds_bitmap; /* bitmap of enabled LEDs: LED_1 = 0x02, LED_2 = 0x04, ... */
struct sixaxis_led led[4]; /* LEDx at (4 - x) */
struct sixaxis_led _reserved; /* LED5, not actually soldered */
uint8_t unknown[13];
};
struct __attribute__((__packed__)) sixaxis_activation_report {
uint8_t report_id;
uint8_t unknown[4];
};
union sixaxis_activation_report_f4 {
struct sixaxis_activation_report data;
uint8_t buf[5];
};
union sixaxis_output_report_01 {
struct sixaxis_output_report data;
uint8_t buf[36];
uint8_t buf[49];
};
static const union sixaxis_output_report_01 default_report = {
.buf = {
0x01,
0x01, 0xff, 0x00, 0xff, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0xff, 0x27, 0x10, 0x00, 0x32,
0x00, 0x00, 0x00, 0x00, 0x00
0x01, /* report ID */
0x00, /* padding */
0xff, 0x00, /* right rumble */
0xff, 0x00, /* left rumble */
0x00, 0x00, 0x00, 0x00, /* padding */
0x00, /* LED bitmap */
0xff, 0x27, 0x10, 0x00, 0x32, /* LED 1 config */
0xff, 0x27, 0x10, 0x00, 0x32, /* LED 2 config */
0xff, 0x27, 0x10, 0x00, 0x32, /* LED 3 config */
0xff, 0x27, 0x10, 0x00, 0x32, /* LED 4 config */
0x00, 0x00, 0x00, 0x00, 0x00, /* LED 5 config (unusable/unsoldered) */
0x00, 0x00, 0x00, 0x00, 0x00, /* unknown */
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00
}
};
static const union sixaxis_activation_report_f4 ds3_activation_packet = {
.buf = { 0xF4, 0x42, 0x0c, 0x00, 0x00 }
};
/* forward declarations */
static void set_leds_from_id(ds3_instance_t *instance);
static int ds3_set_operational(ds3_instance_t *instance);
static int ds3_send_output_report(ds3_instance_t *instance);
static void ds3_update_pad_state(ds3_instance_t *instance);
@ -99,16 +120,20 @@ static void *ds3_init(void *handle, uint32_t slot, hid_driver_t *driver) {
instance->handle = handle;
instance->hid_driver = driver;
instance->slot = slot;
set_leds_from_id(instance);
if(instance->hid_driver->set_protocol) {
instance->hid_driver->set_protocol(instance->handle, 1);
}
if((ret = ds3_send_output_report(instance)) < 0) {
RARCH_LOG("Failed to send output report\n");
goto error;
}
if((ret = ds3_set_operational(instance)) < 0) {
RARCH_LOG("Failed to set operational mode\n");
goto error;
}
if((ret = ds3_send_output_report(instance)) < 0) {
RARCH_LOG("Failed to send output report\n");
goto error;
}
return instance;
error:
@ -201,36 +226,9 @@ static int32_t ds3_button(void *device_data, uint16_t joykey) {
return device->buttons & (1 << joykey);
}
static void set_leds_from_id(ds3_instance_t *instance)
{
/* for pads 0-3, we just light up the appropriate LED. */
/* for higher pads, we sum up the numbers on the LEDs */
/* themselves, so e.g. pad 5 is 4 + 1, pad 6 is 4 + 2, */
/* and so on. We max out at 10 because 4+3+2+1 = 10 */
static const uint8_t sixaxis_leds[10][4] = {
{ 0x01, 0x00, 0x00, 0x00 },
{ 0x00, 0x01, 0x00, 0x00 },
{ 0x00, 0x00, 0x01, 0x00 },
{ 0x00, 0x00, 0x00, 0x01 },
{ 0x01, 0x00, 0x00, 0x01 },
{ 0x00, 0x01, 0x00, 0x01 },
{ 0x00, 0x00, 0x01, 0x01 },
{ 0x01, 0x00, 0x01, 0x01 },
{ 0x00, 0x01, 0x01, 0x01 },
{ 0x01, 0x01, 0x01, 0x01 }
};
int id = instance->slot;
if (id < 0)
return;
id %= 10;
memcpy(instance->led_state, sixaxis_leds[id], sizeof(sixaxis_leds[id]));
}
static int ds3_set_operational(ds3_instance_t *instance) {
const int buf_size = SIXAXIS_REPORT_0xF2_SIZE;
uint8_t *buf = (uint8_t *)malloc(buf_size);
int ret;
@ -238,40 +236,48 @@ static int ds3_set_operational(ds3_instance_t *instance) {
return -1;
}
ret = instance->hid_driver->get_report(instance->handle, HID_REPORT_FEATURE, 0xf2, buf, SIXAXIS_REPORT_0xF2_SIZE);
ret = instance->hid_driver->set_report(instance->handle, HID_REPORT_FEATURE, ds3_activation_packet.data.report_id, ds3_activation_packet.buf, sizeof(ds3_activation_packet));
if(ret < 0) {
RARCH_LOG("Failed to set operational mode step 1\n");
goto out;
RARCH_LOG("Failed to send activation packet\n");
}
ret = instance->hid_driver->get_report(instance->handle, HID_REPORT_FEATURE, 0xf5, buf, SIXAXIS_REPORT_0xF5_SIZE);
if(ret < 0) {
RARCH_LOG("Failed to set operational mode step 2\n");
goto out;
}
ret = instance->hid_driver->set_report(instance->handle, HID_REPORT_OUTPUT, buf[0], buf, 1);
if(ret < 0) {
RARCH_LOG("Failed to set operational mode step 3, ignoring\n");
ret = 0;
}
out:
free(buf);
return ret;
}
static uint8_t get_leds(unsigned slot) {
unsigned pad_number = slot+1;
switch(pad_number) {
case 1:
case 2:
case 3:
case 4:
return 1 << pad_number;
case 5:
return (1 << 1) | (1 << 4);
case 6:
return (1 << 2) | (1 << 4);
case 7:
return (1 << 3) | (1 << 4);
case 8:
return (1 << 3) | (1 << 1) | (1 << 4);
case 9:
return (1 << 2) | (1 << 3) | (1 << 4);
case 10:
default:
return (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4);
}
}
static int ds3_send_output_report(ds3_instance_t *instance) {
struct sixaxis_output_report report = {0};
int n;
uint8_t *packet = (uint8_t *)&report;
/* Initialize the report with default values */
memcpy(&report, &default_report, sizeof(struct sixaxis_output_report));
report.leds_bitmap |= instance->led_state[0] << 1;
report.leds_bitmap |= instance->led_state[1] << 2;
report.leds_bitmap |= instance->led_state[2] << 3;
report.leds_bitmap |= instance->led_state[3] << 4;
report.leds_bitmap = get_leds(instance->slot);
return instance->hid_driver->set_report(instance->handle, HID_REPORT_OUTPUT, report.report_id, (uint8_t *)&report, sizeof(report));
return instance->hid_driver->set_report(instance->handle, HID_REPORT_OUTPUT, report.report_id, packet, sizeof(report));
}
static void ds3_update_pad_state(ds3_instance_t *instance)

View File

@ -189,12 +189,17 @@ static int joypad_to_slot(joypad_connection_t *haystack,
return -1;
}
void release_joypad(joypad_connection_t *joypad) {
}
void legacy_pad_connection_pad_deregister(joypad_connection_t *pad_list, pad_connection_interface_t *iface, void *pad_data) {
int i;
for(i = 0; !joypad_is_end_of_list(&pad_list[i]); i++)
{
if(pad_list[i].connection == pad_data) {
input_autoconfigure_disconnect(i, iface->get_name(pad_data));
memset(&pad_list[i], 0, sizeof(joypad_connection_t));
return;
}
}
@ -219,6 +224,7 @@ void pad_connection_pad_deregister(joypad_connection_t *joyconn,
{
input_autoconfigure_disconnect(slot, iface->get_name(joyconn[slot].connection));
iface->pad_deinit(joyconn[slot].connection);
memset(&joyconn[slot], 0, sizeof(joypad_connection_t));
}
}
}

View File

@ -1096,7 +1096,7 @@ static void iohidmanager_hid_poll(void *data)
(void)data;
}
static int32_t iohidmanager_set_report(void *handle, uint8_t report_type, uint8_t report_id, void *data_buf, uint32_t size)
static int32_t iohidmanager_set_report(void *handle, uint8_t report_type, uint8_t report_id, uint8_t *data_buf, size_t size)
{
struct iohidmanager_hid_adapter *adapter =
(struct iohidmanager_hid_adapter*)handle;
@ -1104,7 +1104,7 @@ static int32_t iohidmanager_set_report(void *handle, uint8_t report_type, uint8_
int retval = -1;
if (adapter) {
retval = IOHIDDeviceSetReport(adapter->handle, translate_hid_report_type(report_type), report_type, data_buf + 1, size - 1);
retval = IOHIDDeviceSetReport(adapter->handle, translate_hid_report_type(report_type), report_type, data_buf, size);
}
return retval;
@ -1119,7 +1119,7 @@ static int32_t iohidmanager_get_report(void *handle, uint8_t report_type, uint8_
if (adapter) {
CFIndex length = size;
retval = IOHIDDeviceGetReport(adapter->handle, translate_hid_report_type(report_type), report_id, data_buf+1, &length);
retval = IOHIDDeviceGetReport(adapter->handle, translate_hid_report_type(report_type), report_id, data_buf, &length);
}
return retval;
@ -1141,6 +1141,6 @@ hid_driver_t iohidmanager_hid = {
iohidmanager_set_report,
iohidmanager_get_report,
NULL, /* set_idle */
NULL, /* set_protocol */
NULL, /* set protocol */
NULL /* read */
};

View File

@ -135,7 +135,7 @@ static bool wiiu_hid_joypad_rumble(void *data, unsigned slot,
static void *wiiu_hid_init(void)
{
RARCH_LOG("[hid]: initializing HID subsystem\n");
RARCH_LOG("[hid]: initializing\n");
wiiu_hid_t *hid = new_hid();
HIDClient *client = new_hidclient();
@ -150,7 +150,6 @@ static void *wiiu_hid_init(void)
HIDAddClient(client, wiiu_attach_callback);
hid->client = client;
RARCH_LOG("[hid]: init success\n");
return hid;
error:
@ -221,13 +220,22 @@ static void wiiu_hid_send_control(void *data, uint8_t *buf, size_t size)
}
}
static void _fixup_report_buffer(uint8_t **buffer, uint8_t report_id, size_t *length) {
if((*buffer)[0] == report_id) {
*buffer = (*buffer)+ 1;
*length = *length - 1;
}
}
static int32_t wiiu_hid_set_report(void *data, uint8_t report_type,
uint8_t report_id, void *report_data, uint32_t report_length)
uint8_t report_id, uint8_t *report_data, size_t report_length)
{
wiiu_adapter_t *adapter = (wiiu_adapter_t *)data;
if (!adapter || report_length > adapter->tx_size)
return -1;
_fixup_report_buffer(&report_data, report_id, &report_length);
memset(adapter->tx_buffer, 0, adapter->tx_size);
memcpy(adapter->tx_buffer, report_data, report_length);
@ -239,14 +247,16 @@ static int32_t wiiu_hid_set_report(void *data, uint8_t report_type,
NULL, NULL);
}
static int32_t wiiu_hid_get_report(void *handle, uint8_t report_type, uint8_t report_id, void *data_buf, size_t size)
static int32_t wiiu_hid_get_report(void *handle, uint8_t report_type, uint8_t report_id, uint8_t *report_data, size_t report_length)
{
wiiu_adapter_t *adapter = (wiiu_adapter_t *)handle;
if (!adapter || size > adapter->tx_size)
if (!adapter || report_length > adapter->tx_size)
return -1;
_fixup_report_buffer(&report_data, report_id, &report_length);
memset(adapter->tx_buffer, 0, adapter->tx_size);
memcpy(adapter->tx_buffer, data_buf, size);
memcpy(adapter->tx_buffer, report_data, report_length);
return HIDGetReport(adapter->handle,
report_type,
@ -422,7 +432,6 @@ static uint8_t try_init_driver(wiiu_adapter_t *adapter)
return ADAPTER_STATE_DONE;
}
RARCH_LOG("driver initialized, registering pad\n");
pad_connection_pad_register(joypad_state.pads, adapter->pad_driver, adapter->pad_driver_data, adapter, &hidpad_driver, slot);
return ADAPTER_STATE_READY;
@ -454,7 +463,6 @@ static void synchronized_process_adapters(wiiu_hid_t *hid)
break;
case ADAPTER_STATE_GC:
{
RARCH_LOG("ADAPTER_STATE_GC");
/* remove from the list */
if (!prev)
adapters.list = adapter->next;
@ -524,13 +532,8 @@ static int32_t wiiu_attach_callback(HIDClient *client,
if (attach)
{
RARCH_LOG("[hid]: Device attach event generated.\n");
log_device(device);
}
else
{
RARCH_LOG("[hid]: Device detach event generated.\n");
}
if (device)
event = new_attach_event(device);
@ -788,36 +791,30 @@ static OSThread *new_thread(void)
static void wiiu_hid_init_lists(void)
{
RARCH_LOG("[hid]: Initializing events list\n");
memset(&events, 0, sizeof(events));
OSFastMutex_Init(&(events.lock), "attach_events");
RARCH_LOG("[hid]: Initializing adapters list\n");
memset(&adapters, 0, sizeof(adapters));
OSFastMutex_Init(&(adapters.lock), "adapters");
}
static wiiu_hid_t *new_hid(void)
{
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);
}
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);
}
@ -927,15 +924,6 @@ void *alloc_zeroed(size_t alignment, size_t size)
return result;
}
/*
void (*send_control)(void *handle, uint8_t *buf, size_t size);
int32_t (*set_report)(void *handle, uint8_t, uint8_t, void *data, uint32_t size);
int32_t (*get_report)(void *handle, uint8_t report_type, uint8_t report_id, void *buffer, size_t length);
int32_t (*set_idle)(void *handle, uint8_t amount);
int32_t (*set_protocol)(void *handle, uint8_t protocol);
int32_t (*read)(void *handle, void *buf, size_t size);
*/
hid_driver_t wiiu_hid = {
wiiu_hid_init,
wiiu_hid_joypad_query,

View File

@ -50,8 +50,8 @@ struct hid_driver
const char *(*name)(void *handle, unsigned pad);
const char *ident;
void (*send_control)(void *handle, uint8_t *buf, size_t size);
int32_t (*set_report)(void *handle, uint8_t, uint8_t, void *data, uint32_t size);
int32_t (*get_report)(void *handle, uint8_t report_type, uint8_t report_id, void *buffer, size_t length);
int32_t (*set_report)(void *handle, uint8_t report_type, uint8_t report_id, uint8_t *data, size_t length);
int32_t (*get_report)(void *handle, uint8_t report_type, uint8_t report_id, uint8_t *data, size_t length);
int32_t (*set_idle)(void *handle, uint8_t amount);
int32_t (*set_protocol)(void *handle, uint8_t protocol);
int32_t (*read)(void *handle, void *buf, size_t size);