mirror of
https://github.com/libretro/RetroArch.git
synced 2025-02-12 04:31:19 +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 {
|
||||
void *handle;
|
||||
joypad_connection_t *pad;
|
||||
int slot;
|
||||
bool led_set;
|
||||
uint32_t buttons;
|
||||
uint16_t motors[2];
|
||||
uint8_t data[64];
|
||||
} ds3_instance_t;
|
||||
|
||||
static uint8_t activation_packet[] = {
|
||||
#if defined(IOS)
|
||||
0x53, 0xF4,
|
||||
#elif defined(HAVE_WIIUSB_HID)
|
||||
0x02,
|
||||
#endif
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
ds3_instance_t *instance;
|
||||
|
||||
int errors = 0;
|
||||
RARCH_LOG("[ds3]: init\n");
|
||||
instance = (ds3_instance_t *)calloc(1, sizeof(ds3_instance_t));
|
||||
if(!instance)
|
||||
goto error;
|
||||
|
||||
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);
|
||||
if(!instance->pad)
|
||||
goto error;
|
||||
|
||||
RARCH_LOG("[ds3]: init complete.\n");
|
||||
return instance;
|
||||
|
||||
error:
|
||||
RARCH_ERR("[ds3]: init failed.\n");
|
||||
if(instance)
|
||||
free(instance);
|
||||
return NULL;
|
||||
@ -62,9 +187,14 @@ static void ds3_free(void *data)
|
||||
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;
|
||||
|
||||
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)
|
||||
@ -86,6 +216,9 @@ hid_device_t ds3_hid_device = {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -97,11 +230,38 @@ static void ds3_pad_deinit(void *data)
|
||||
static void ds3_get_buttons(void *data, retro_bits_t *state)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
|
@ -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);
|
||||
if(slot < 0)
|
||||
{
|
||||
RARCH_ERR("[hid]: failed to find a vacant pad.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = &(hid_instance.pad_list[slot]);
|
||||
result->iface = iface;
|
||||
|
@ -60,6 +60,12 @@ struct hid_driver
|
||||
hid_instance.os_driver_data, pad, axis)
|
||||
#define HID_PAD_NAME(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( \
|
||||
hid_instance.os_driver_data)
|
||||
#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_HID, "wiiu", WIIUINPUT_GAMEPAD_DEFAULT_BINDS),
|
||||
DECL_AUTOCONF_DEVICE("GameCube Controller", "wiiu", WIIUINPUT_GAMECUBE_DEFAULT_BINDS),
|
||||
DECL_AUTOCONF_DEVICE("Sony DualShock 3", "wiiu", PS3INPUT_DEFAULT_BINDS),
|
||||
#endif
|
||||
#ifdef __CELLOS_LV2__
|
||||
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;
|
||||
|
||||
synchronized_add_to_adapters_list(adapter);
|
||||
wiiu_start_read_loop(adapter);
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
wiiu_handle_attach_events(hid, synchronized_get_events_list());
|
||||
wiiu_handle_ready_adapters(hid);
|
||||
usleep(10000);
|
||||
i += 10000;
|
||||
if(i >= (1000 * 1000 * 3))
|
||||
|
Loading…
x
Reference in New Issue
Block a user