mirror of
https://github.com/libretro/RetroArch
synced 2025-04-16 08:43:10 +00:00
More work on Dual Shock 3 driver
== DETAILS - update to not try starting the read loop until after the device is successfully initialized - add new HID wrapper macros needed by ds3 driver - add some debug logging to help with troubleshooting - add button map for DS3 == TESTING Tested with local build. DS3 init is not working.
This commit is contained in:
parent
9bc5a15c2d
commit
af08e5015a
@ -22,33 +22,158 @@
|
|||||||
typedef struct ds3_instance {
|
typedef struct ds3_instance {
|
||||||
void *handle;
|
void *handle;
|
||||||
joypad_connection_t *pad;
|
joypad_connection_t *pad;
|
||||||
|
int slot;
|
||||||
|
bool led_set;
|
||||||
|
uint32_t buttons;
|
||||||
|
uint16_t motors[2];
|
||||||
|
uint8_t data[64];
|
||||||
} ds3_instance_t;
|
} ds3_instance_t;
|
||||||
|
|
||||||
static uint8_t activation_packet[] = {
|
static uint8_t activation_packet[] = {
|
||||||
|
#if defined(IOS)
|
||||||
|
0x53, 0xF4,
|
||||||
|
#elif defined(HAVE_WIIUSB_HID)
|
||||||
|
0x02,
|
||||||
|
#endif
|
||||||
0x42, 0x0c, 0x00, 0x00
|
0x42, 0x0c, 0x00, 0x00
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(WIIU)
|
||||||
|
#define PACKET_OFFSET 2
|
||||||
|
#elif defined(HAVE_WIIUSB_HID)
|
||||||
|
#define PACKET_OFFSET 1
|
||||||
|
#else
|
||||||
|
#define PACKET_OFFSET 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LED_OFFSET 11
|
||||||
|
#define MOTOR1_OFFSET 4
|
||||||
|
#define MOTOR2_OFFSET 6
|
||||||
|
|
||||||
|
static uint8_t control_packet[] = {
|
||||||
|
0x52, 0x01,
|
||||||
|
0x00, 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,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
static int control_packet_size = sizeof(control_packet);
|
||||||
|
|
||||||
extern pad_connection_interface_t ds3_pad_connection;
|
extern pad_connection_interface_t ds3_pad_connection;
|
||||||
|
|
||||||
|
static void print_error(const char *fmt, int32_t errcode)
|
||||||
|
{
|
||||||
|
int16_t err1, err2;
|
||||||
|
|
||||||
|
err1 = errcode & 0x0000ffff;
|
||||||
|
err2 = ((errcode & 0xffff0000) >> 16);
|
||||||
|
|
||||||
|
RARCH_ERR(fmt, err1, err2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t send_activation_packet(ds3_instance_t *instance)
|
||||||
|
{
|
||||||
|
uint32_t result;
|
||||||
|
#if defined(WIIU)
|
||||||
|
result = HID_SET_REPORT(instance->handle,
|
||||||
|
HID_REPORT_FEATURE,
|
||||||
|
DS3_ACTIVATION_REPORT_ID,
|
||||||
|
activation_packet,
|
||||||
|
sizeof(activation_packet));
|
||||||
|
#else
|
||||||
|
HID_SEND_CONTROL(instance->handle,
|
||||||
|
activation_packet, sizeof(activation_packet));
|
||||||
|
#endif
|
||||||
|
if(result)
|
||||||
|
print_error("[ds3]: activation packet failed (%d:%d)\n", result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t set_protocol(ds3_instance_t *instance, int protocol)
|
||||||
|
{
|
||||||
|
uint32_t result = 0;
|
||||||
|
#if defined(WIIU)
|
||||||
|
result = HID_SET_PROTOCOL(1);
|
||||||
|
if(result)
|
||||||
|
print_error("[ds3]: set protocol failed (%d:%d)\n", result);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t send_control_packet(ds3_instance_t *instance)
|
||||||
|
{
|
||||||
|
uint8_t packet_buffer[control_packet_size];
|
||||||
|
uint32_t result = 0;
|
||||||
|
memcpy(packet_buffer, control_packet, control_packet_size);
|
||||||
|
|
||||||
|
packet_buffer[LED_OFFSET] = 0;
|
||||||
|
if(instance->pad) {
|
||||||
|
packet_buffer[LED_OFFSET] = 1 << ((instance->slot % 4) + 1);
|
||||||
|
}
|
||||||
|
packet_buffer[MOTOR1_OFFSET] = instance->motors[1] >> 8;
|
||||||
|
packet_buffer[MOTOR2_OFFSET] = instance->motors[0] >> 8;
|
||||||
|
|
||||||
|
#if defined(HAVE_WIIUSB_HID)
|
||||||
|
packet_buffer[1] = 0x03;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(WIIU)
|
||||||
|
result = HID_SET_REPORT(instance->handle,
|
||||||
|
HID_REPORT_OUTPUT,
|
||||||
|
DS3_RUMBLE_REPORT_ID,
|
||||||
|
packet_buffer+PACKET_OFFSET,
|
||||||
|
control_packet_size-PACKET_OFFSET);
|
||||||
|
if(result)
|
||||||
|
print_error("[ds3]: send control packet failed: (%d:%d)\n", result);
|
||||||
|
#else
|
||||||
|
HID_SEND_CONTROL(instance->handle,
|
||||||
|
packet_buffer+PACKET_OFFSET,
|
||||||
|
control_packet_size-PACKET_OFFSET);
|
||||||
|
#endif /* WIIU */
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static void *ds3_init(void *handle)
|
static void *ds3_init(void *handle)
|
||||||
{
|
{
|
||||||
ds3_instance_t *instance;
|
ds3_instance_t *instance;
|
||||||
|
int errors = 0;
|
||||||
|
RARCH_LOG("[ds3]: init\n");
|
||||||
instance = (ds3_instance_t *)calloc(1, sizeof(ds3_instance_t));
|
instance = (ds3_instance_t *)calloc(1, sizeof(ds3_instance_t));
|
||||||
if(!instance)
|
if(!instance)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
instance->handle = handle;
|
instance->handle = handle;
|
||||||
|
|
||||||
/* TODO: do whatever is needed so that the read loop doesn't bomb out */
|
RARCH_LOG("[ds3]: sending activation packet\n");
|
||||||
|
if(send_activation_packet(instance))
|
||||||
|
errors++;
|
||||||
|
RARCH_LOG("[ds3]: setting protocol\n");
|
||||||
|
if(set_protocol(instance, 1))
|
||||||
|
errors++;
|
||||||
|
RARCH_LOG("[ds3]: sending control packet\n");
|
||||||
|
if(send_control_packet(instance))
|
||||||
|
errors++;
|
||||||
|
|
||||||
|
if(errors)
|
||||||
|
goto error;
|
||||||
|
|
||||||
instance->pad = hid_pad_register(instance, &ds3_pad_connection);
|
instance->pad = hid_pad_register(instance, &ds3_pad_connection);
|
||||||
if(!instance->pad)
|
if(!instance->pad)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
RARCH_LOG("[ds3]: init complete.\n");
|
||||||
return instance;
|
return instance;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
RARCH_ERR("[ds3]: init failed.\n");
|
||||||
if(instance)
|
if(instance)
|
||||||
free(instance);
|
free(instance);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -62,9 +187,14 @@ static void ds3_free(void *data)
|
|||||||
free(instance);
|
free(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ds3_handle_packet(void *data, uint8_t *buffer, size_t size)
|
static void ds3_handle_packet(void *data, uint8_t *packet, size_t size)
|
||||||
{
|
{
|
||||||
ds3_instance_t *instance = (ds3_instance_t *)data;
|
ds3_instance_t *instance = (ds3_instance_t *)data;
|
||||||
|
|
||||||
|
if(!instance || !instance->pad)
|
||||||
|
return;
|
||||||
|
|
||||||
|
instance->pad->iface->packet_handler(data, packet, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ds3_detect(uint16_t vendor_id, uint16_t product_id)
|
static bool ds3_detect(uint16_t vendor_id, uint16_t product_id)
|
||||||
@ -86,6 +216,9 @@ hid_device_t ds3_hid_device = {
|
|||||||
|
|
||||||
static void *ds3_pad_init(void *data, uint32_t slot, hid_driver_t *driver)
|
static void *ds3_pad_init(void *data, uint32_t slot, hid_driver_t *driver)
|
||||||
{
|
{
|
||||||
|
ds3_instance_t *pad = (ds3_instance_t *)data;
|
||||||
|
pad->slot = slot;
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,11 +230,38 @@ static void ds3_pad_deinit(void *data)
|
|||||||
static void ds3_get_buttons(void *data, retro_bits_t *state)
|
static void ds3_get_buttons(void *data, retro_bits_t *state)
|
||||||
{
|
{
|
||||||
ds3_instance_t *pad = (ds3_instance_t *)data;
|
ds3_instance_t *pad = (ds3_instance_t *)data;
|
||||||
|
|
||||||
|
if(pad)
|
||||||
|
{
|
||||||
|
BITS_COPY16_PTR(state, pad->buttons);
|
||||||
|
|
||||||
|
if(pad->buttons & 0x10000)
|
||||||
|
BIT256_SET_PTR(state, RARCH_MENU_TOGGLE);
|
||||||
|
} else {
|
||||||
|
BIT256_CLEAR_ALL_PTR(state);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ds3_packet_handler(void *data, uint8_t *packet, uint16_t size)
|
static void ds3_packet_handler(void *data, uint8_t *packet, uint16_t size)
|
||||||
{
|
{
|
||||||
ds3_instance_t *pad = (ds3_instance_t *)data;
|
ds3_instance_t *instance = (ds3_instance_t *)data;
|
||||||
|
RARCH_LOG_BUFFER(packet, size);
|
||||||
|
|
||||||
|
if(!instance->led_set)
|
||||||
|
{
|
||||||
|
send_activation_packet(instance);
|
||||||
|
instance->led_set = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(size > control_packet_size)
|
||||||
|
{
|
||||||
|
RARCH_ERR("[ds3]: Expecting packet to be %d but was %d\n",
|
||||||
|
control_packet_size, size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(instance->data, packet, size);
|
||||||
|
instance->buttons = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ds3_set_rumble(void *data, enum retro_rumble_effect effect, uint16_t strength)
|
static void ds3_set_rumble(void *data, enum retro_rumble_effect effect, uint16_t strength)
|
||||||
|
@ -46,7 +46,10 @@ joypad_connection_t *hid_pad_register(void *pad_handle, pad_connection_interface
|
|||||||
|
|
||||||
slot = pad_connection_find_vacant_pad(hid_instance.pad_list);
|
slot = pad_connection_find_vacant_pad(hid_instance.pad_list);
|
||||||
if(slot < 0)
|
if(slot < 0)
|
||||||
|
{
|
||||||
|
RARCH_ERR("[hid]: failed to find a vacant pad.\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
result = &(hid_instance.pad_list[slot]);
|
result = &(hid_instance.pad_list[slot]);
|
||||||
result->iface = iface;
|
result->iface = iface;
|
||||||
|
@ -60,6 +60,12 @@ struct hid_driver
|
|||||||
hid_instance.os_driver_data, pad, axis)
|
hid_instance.os_driver_data, pad, axis)
|
||||||
#define HID_PAD_NAME(pad) \
|
#define HID_PAD_NAME(pad) \
|
||||||
hid_instance.os_driver->name(hid_instance.os_driver_data, pad)
|
hid_instance.os_driver->name(hid_instance.os_driver_data, pad)
|
||||||
|
#define HID_SET_PROTOCOL(protocol) \
|
||||||
|
hid_instance.os_driver->set_protocol(hid_instance.os_driver_data, protocol)
|
||||||
|
#define HID_SET_REPORT(pad, rpttype, rptid, data, len) \
|
||||||
|
hid_instance.os_driver->set_report(pad, rpttype, rptid, data, len)
|
||||||
|
#define HID_SEND_CONTROL(pad, data, len) \
|
||||||
|
hid_instance.os_driver->send_control(pad, data, len)
|
||||||
#define HID_POLL() hid_instance.os_driver->poll( \
|
#define HID_POLL() hid_instance.os_driver->poll( \
|
||||||
hid_instance.os_driver_data)
|
hid_instance.os_driver_data)
|
||||||
#define HID_MAX_SLOT() hid_instance.max_slot
|
#define HID_MAX_SLOT() hid_instance.max_slot
|
||||||
|
@ -635,6 +635,7 @@ const char* const input_builtin_autoconfs[] =
|
|||||||
DECL_AUTOCONF_DEVICE(PAD_NAME_CLASSIC, "wiiu", WIIUINPUT_CLASSIC_CONTROLLER_DEFAULT_BINDS),
|
DECL_AUTOCONF_DEVICE(PAD_NAME_CLASSIC, "wiiu", WIIUINPUT_CLASSIC_CONTROLLER_DEFAULT_BINDS),
|
||||||
DECL_AUTOCONF_DEVICE(PAD_NAME_HID, "wiiu", WIIUINPUT_GAMEPAD_DEFAULT_BINDS),
|
DECL_AUTOCONF_DEVICE(PAD_NAME_HID, "wiiu", WIIUINPUT_GAMEPAD_DEFAULT_BINDS),
|
||||||
DECL_AUTOCONF_DEVICE("GameCube Controller", "wiiu", WIIUINPUT_GAMECUBE_DEFAULT_BINDS),
|
DECL_AUTOCONF_DEVICE("GameCube Controller", "wiiu", WIIUINPUT_GAMECUBE_DEFAULT_BINDS),
|
||||||
|
DECL_AUTOCONF_DEVICE("Sony DualShock 3", "wiiu", PS3INPUT_DEFAULT_BINDS),
|
||||||
#endif
|
#endif
|
||||||
#ifdef __CELLOS_LV2__
|
#ifdef __CELLOS_LV2__
|
||||||
DECL_AUTOCONF_DEVICE("SixAxis Controller", "ps3", PS3INPUT_DEFAULT_BINDS),
|
DECL_AUTOCONF_DEVICE("SixAxis Controller", "ps3", PS3INPUT_DEFAULT_BINDS),
|
||||||
|
@ -458,7 +458,6 @@ static void wiiu_hid_attach(wiiu_hid_t *hid, wiiu_attach_event *event)
|
|||||||
adapter->state = ADAPTER_STATE_NEW;
|
adapter->state = ADAPTER_STATE_NEW;
|
||||||
|
|
||||||
synchronized_add_to_adapters_list(adapter);
|
synchronized_add_to_adapters_list(adapter);
|
||||||
wiiu_start_read_loop(adapter);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -580,6 +579,21 @@ static void wiiu_handle_attach_events(wiiu_hid_t *hid, wiiu_attach_event *list)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wiiu_handle_ready_adapters(wiiu_hid_t *hid)
|
||||||
|
{
|
||||||
|
wiiu_adapter_t *it;
|
||||||
|
OSFastMutex_Lock(&(adapters.lock));
|
||||||
|
|
||||||
|
for(it = adapters.list; it != NULL; it = it->next)
|
||||||
|
{
|
||||||
|
if(it->state == ADAPTER_STATE_READY)
|
||||||
|
wiiu_start_read_loop(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
OSFastMutex_Unlock(&(adapters.lock));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static int wiiu_hid_polling_thread(int argc, const char **argv)
|
static int wiiu_hid_polling_thread(int argc, const char **argv)
|
||||||
{
|
{
|
||||||
wiiu_hid_t *hid = (wiiu_hid_t *)argv;
|
wiiu_hid_t *hid = (wiiu_hid_t *)argv;
|
||||||
@ -590,6 +604,7 @@ static int wiiu_hid_polling_thread(int argc, const char **argv)
|
|||||||
while(!hid->polling_thread_quit)
|
while(!hid->polling_thread_quit)
|
||||||
{
|
{
|
||||||
wiiu_handle_attach_events(hid, synchronized_get_events_list());
|
wiiu_handle_attach_events(hid, synchronized_get_events_list());
|
||||||
|
wiiu_handle_ready_adapters(hid);
|
||||||
usleep(10000);
|
usleep(10000);
|
||||||
i += 10000;
|
i += 10000;
|
||||||
if(i >= (1000 * 1000 * 3))
|
if(i >= (1000 * 1000 * 3))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user