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:
gblues 2018-04-02 23:16:49 -07:00
parent 9bc5a15c2d
commit af08e5015a
5 changed files with 190 additions and 5 deletions

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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),

View File

@ -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))