diff --git a/input/connect/connect_retrode.c b/input/connect/connect_retrode.c index 69d59a2d9b..b84a37d24b 100644 --- a/input/connect/connect_retrode.c +++ b/input/connect/connect_retrode.c @@ -23,75 +23,107 @@ #include "../input_defines.h" -/* store device for each port */ -static struct hidpad_retrode_data* port_device[4]; +#define RETRODE_MAX_PAD 4 -struct hidpad_retrode_data +#define RETRODE_TYPE_DEVICE 0x00 +#define RETRODE_TYPE_PAD 0x01 + +typedef struct hidpad_retrode_pad_data retrode_pad_data_t; +typedef struct hidpad_retrode_data retrode_device_data_t; + +struct hidpad_retrode_pad_data { - struct pad_connection* connection; - uint32_t slot; + uint8_t datatype; + retrode_device_data_t *device_data; + joypad_connection_t *joypad; + int pad_index; uint32_t buttons; - int port_count; uint8_t data[64]; }; +struct hidpad_retrode_data +{ + uint8_t datatype; + void *handle; + hid_driver_t *driver; + retrode_pad_data_t pad_data[RETRODE_MAX_PAD]; + uint8_t data[64]; +}; + +const char *RETRODE_PAD = "Retrode pad"; +const char *RETRODE_DEVICE_NAME = "Retrode adapter"; + static void* hidpad_retrode_init(void *data, uint32_t slot, hid_driver_t *driver) { - struct pad_connection* connection = (struct pad_connection*)data; - struct hidpad_retrode_data* device = (struct hidpad_retrode_data*) - calloc(1, sizeof(struct hidpad_retrode_data)); + int i; + retrode_device_data_t * device = (retrode_device_data_t *)calloc(1, sizeof(retrode_device_data_t)); if (!device) return NULL; - if (!connection) + if (!data) { free(device); return NULL; } - device->connection = connection; - device->slot = slot; + device->handle = data; - port_device[device->port_count] = device; - device->port_count++; + for (i = 0; i < RETRODE_MAX_PAD; i++) + { + device->pad_data[i].datatype = RETRODE_TYPE_PAD; + device->pad_data[i].device_data = device; + device->pad_data[i].joypad = NULL; + device->pad_data[i].pad_index = i; + } + + device->driver = driver; return device; } static void hidpad_retrode_deinit(void *data) { - struct hidpad_retrode_data *device = (struct hidpad_retrode_data*)data; + retrode_device_data_t *device = (retrode_device_data_t *)data; if (device) free(device); - - port_device[0] = NULL; - port_device[1] = NULL; - port_device[2] = NULL; - port_device[3] = NULL; } -static void hidpad_retrode_get_buttons(void *data, input_bits_t *state) +static void hidpad_retrode_get_buttons(void *pad_data, input_bits_t *state) { - struct hidpad_retrode_data *device = (struct hidpad_retrode_data*)data; - if (device) + retrode_pad_data_t *pad = (retrode_pad_data_t *)pad_data; + if (pad) { - BITS_COPY16_PTR(state, device->buttons); + if(pad->datatype == RETRODE_TYPE_PAD) + { + BITS_COPY16_PTR(state, pad->buttons); + } + else + { + retrode_device_data_t *device = (retrode_device_data_t *)pad_data; + BITS_COPY16_PTR(state, device->pad_data[0].buttons); + } } else - BIT256_CLEAR_ALL_PTR(state); + { + BIT256_CLEAR_ALL_PTR(state); + } } -static int16_t hidpad_retrode_get_axis(void *data, unsigned axis) +static int16_t hidpad_retrode_get_axis(void *pad_data, unsigned axis) { int val; - struct hidpad_retrode_data *device = (struct hidpad_retrode_data*)data; + retrode_pad_data_t *pad = (retrode_pad_data_t *)pad_data; + retrode_device_data_t *device = (retrode_device_data_t *)pad_data; - if (!device || axis >= 2) + if (!pad || axis >= 2) return 0; - val = device->data[2 + axis]; + if(pad->datatype == RETRODE_TYPE_PAD) + val = pad->data[2 + axis]; + else + val = device->pad_data[0].data[2 + axis]; /* map Retrode values to a known gamepad (VID=0x0079, PID=0x0011) */ if (val == 0x9C) @@ -108,9 +140,10 @@ static int16_t hidpad_retrode_get_axis(void *data, unsigned axis) return 0; } -static void hidpad_retrode_packet_handler(void *data, uint8_t *packet, uint16_t size) +static void retrode_update_button_state(retrode_pad_data_t *pad) { uint32_t i, pressed_keys; + static const uint32_t button_mapping[8] = { RETRO_DEVICE_ID_JOYPAD_B, @@ -122,12 +155,33 @@ static void hidpad_retrode_packet_handler(void *data, uint8_t *packet, uint16_t RETRO_DEVICE_ID_JOYPAD_L, RETRO_DEVICE_ID_JOYPAD_R }; - struct hidpad_retrode_data *device = (struct hidpad_retrode_data*)data; - struct hidpad_retrode_data *device1234; + + if (!pad) + return; + + pressed_keys = pad->data[4]; + pad->buttons = 0; + + for (i = 0; i < 8; i ++) + if (button_mapping[i] != NO_BTN) + pad->buttons |= (pressed_keys & (1 << i)) ? (1 << button_mapping[i]) : 0; +} + +static void hidpad_retrode_pad_packet_handler(retrode_pad_data_t *pad, uint8_t *packet, size_t size) +{ + memcpy(pad->data, packet, size); + retrode_update_button_state(pad); +} + +static void hidpad_retrode_packet_handler(void *device_data, uint8_t *packet, uint16_t size) +{ + retrode_device_data_t *device = (retrode_device_data_t *)device_data; if (!device) return; + memcpy(device->data, packet, size); + /* * packet[1] contains Retrode port number * 1 = left SNES @@ -136,40 +190,7 @@ static void hidpad_retrode_packet_handler(void *data, uint8_t *packet, uint16_t * 4 = right Genesis/MD */ - /* for port 1 only */ - /* - if (packet[1] != 1) - return; - - memcpy(device->data, packet, size); - - device->buttons = 0; - - pressed_keys = device->data[4]; - - for (i = 0; i < 8; i ++) - if (button_mapping[i] != NO_BTN) - device->buttons |= (pressed_keys & (1 << i)) ? (1 << button_mapping[i]) : 0; - */ - - /* - * find instance which handles specific port - * (wiiusb_hid_read_cb calls first instance only, so need to delegate) - */ - device1234 = port_device[packet[1] - 1]; - - if (!device1234) - return; - - memcpy(device1234->data, packet, size); - - device1234->buttons = 0; - - pressed_keys = device1234->data[4]; - - for (i = 0; i < 8; i ++) - if (button_mapping[i] != NO_BTN) - device1234->buttons |= (pressed_keys & (1 << i)) ? (1 << button_mapping[i]) : 0; + hidpad_retrode_pad_packet_handler(&device->pad_data[packet[1] - 1], &device->data[0], size); } static void hidpad_retrode_set_rumble(void *data, @@ -180,19 +201,79 @@ static void hidpad_retrode_set_rumble(void *data, (void)strength; } -const char * hidpad_retrode_get_name(void *data) +const char * hidpad_retrode_get_name(void *pad_data) { - (void)data; - /* For now we return a single static name */ - return "Retrode"; + /* this could be improved by marking it as pad/mouse */ + retrode_pad_data_t *pad = (retrode_pad_data_t *)pad_data; + if(!pad || pad->datatype != RETRODE_TYPE_PAD) + return RETRODE_DEVICE_NAME; + + return RETRODE_PAD; } -static int32_t hidpad_retrode_button(void *data, uint16_t joykey) +static int32_t hidpad_retrode_button(void *pad_data, uint16_t joykey) { - struct hidpad_retrode_data *pad = (struct hidpad_retrode_data*)data; - if (!pad || joykey > 31) + retrode_pad_data_t *pad = (retrode_pad_data_t *)pad_data; + + if (!pad) return 0; - return pad->buttons & (1 << joykey); + + if (pad->datatype != RETRODE_TYPE_PAD) + { + retrode_device_data_t *device = (retrode_device_data_t *)pad_data; + pad = &device->pad_data[0]; + } + + if (!pad->device_data || joykey > 31 || !pad->joypad) + return 0; + + return pad->buttons & (1 << joykey); +} + +static void *hidpad_retrode_pad_init(void *device_data, int pad_index, joypad_connection_t *joypad) +{ + retrode_device_data_t *device = (retrode_device_data_t *)device_data; + + if(!device || pad_index < 0 || pad_index >= RETRODE_MAX_PAD || !joypad || device->pad_data[pad_index].joypad) + return NULL; + + device->pad_data[pad_index].joypad = joypad; + return &device->pad_data[pad_index]; +} + +static void hidpad_retrode_pad_deinit(void *pad_data) +{ + retrode_pad_data_t *pad = (retrode_pad_data_t *)pad_data; + + if(!pad) + return; + + pad->joypad = NULL; +} + +static int8_t hidpad_retrode_status(void *device_data, int pad_index) +{ + retrode_device_data_t *device = (retrode_device_data_t *)device_data; + int8_t result = 0; + + if(!device || pad_index < 0 || pad_index >= RETRODE_MAX_PAD) + return 0; + + result |= PAD_CONNECT_READY; + + if (device->pad_data[pad_index].joypad) + result |= PAD_CONNECT_BOUND; + + return result; +} + +static joypad_connection_t *hidpad_retrode_joypad(void *device_data, int pad_index) +{ + retrode_device_data_t *device = (retrode_device_data_t *)device_data; + + if(!device || pad_index < 0 || pad_index >= RETRODE_MAX_PAD) + return 0; + return device->pad_data[pad_index].joypad; } pad_connection_interface_t pad_connection_retrode = { @@ -204,5 +285,10 @@ pad_connection_interface_t pad_connection_retrode = { hidpad_retrode_get_axis, hidpad_retrode_get_name, hidpad_retrode_button, - false, + true, + RETRODE_MAX_PAD, + hidpad_retrode_pad_init, + hidpad_retrode_pad_deinit, + hidpad_retrode_status, + hidpad_retrode_joypad, };