diff --git a/Makefile.griffin b/Makefile.griffin index f94037d4e0..ea4cb3df36 100644 --- a/Makefile.griffin +++ b/Makefile.griffin @@ -105,6 +105,7 @@ endif HAVE_ZLIB := 1 HAVE_RPNG := 1 HAVE_OVERLAY := 1 + HAVE_LIBSICKSAXIS := 0 else ifeq ($(platform), psp1) CC = psp-gcc$(EXE_EXT) CXX = psp-g++$(EXE_EXT) @@ -140,6 +141,10 @@ ifeq ($(HAVE_LIBRETRO_MANAGEMENT), 1) CFLAGS += -DHAVE_LIBRETRO_MANAGEMENT endif +ifeq ($(HAVE_LIBSICKSAXIS), 1) +CFLAGS += -DHAVE_LIBSICKSAXIS +endif + ifeq ($(HAVE_RPNG), 1) CFLAGS += -DWANT_RPNG endif diff --git a/driver.h b/driver.h index a8aed837d4..951ef0ebf6 100644 --- a/driver.h +++ b/driver.h @@ -301,6 +301,9 @@ enum input_devices DEVICE_WIIMOTE, DEVICE_NUNCHUK, DEVICE_CLASSIC, +#ifdef HAVE_LIBSICKSAXIS + DEVICE_SIXAXIS, +#endif #endif #elif defined(_XBOX) DEVICE_XBOX_PAD = 0, diff --git a/griffin/griffin.c b/griffin/griffin.c index d2559174ab..f8e5f43b75 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -295,6 +295,9 @@ INPUT #elif defined(SN_TARGET_PSP2) || defined(PSP) #include "../psp/psp_input.c" #elif defined(GEKKO) +#ifdef HAVE_LIBSICKSAXIS +#include "../gx/sicksaxis.c" +#endif #include "../gx/gx_input.c" #elif defined(_XBOX) #include "../xdk/xdk_xinput_input.c" diff --git a/gx/gx_input.c b/gx/gx_input.c index 2a3ad83f91..2f8cbf814f 100644 --- a/gx/gx_input.c +++ b/gx/gx_input.c @@ -38,6 +38,7 @@ #define MAX_PADS 4 + typedef struct gx_input { uint64_t pad_state[MAX_PADS]; @@ -97,14 +98,42 @@ const struct platform_bind platform_keys[] = { #endif }; + extern const rarch_joypad_driver_t gx_joypad; static bool g_menu; #ifdef HW_RVL static bool g_quit; + +static void power_callback(void) +{ + g_quit = true; +} + +#ifdef HAVE_LIBSICKSAXIS +volatile int lol = 0; +struct ss_device dev[MAX_PADS]; + +int change_cb(int result, void *usrdata) +{ + (*(volatile int*)usrdata)++; + return result; +} + +void removal_cb(void *usrdata) +{ + RARCH_LOG("Device %d disconnected\n", (int)usrdata); +} #endif +#endif + +static void reset_cb(void) +{ + g_menu = true; +} + static bool gx_menu_input_state(uint64_t joykey, uint64_t state) { switch (joykey) @@ -223,20 +252,17 @@ static int16_t gx_input_state(void *data, const struct retro_keybind **binds, static void gx_input_free_input(void *data) { + unsigned i; (void)data; -} + (void)i; +#ifdef HAVE_LIBSICKSAXIS + for (i = 0; i < MAX_PADS; i++) + ss_close(&dev[i]); -static void reset_callback(void) -{ - g_menu = true; -} - -#ifdef HW_RVL -static void power_callback(void) -{ - g_quit = true; -} + USB_Deinitialize(); #endif +} + static void gx_input_set_keybinds(void *data, unsigned device, unsigned port, unsigned id, unsigned keybind_action) @@ -255,6 +281,60 @@ static void gx_input_set_keybinds(void *data, unsigned device, unsigned port, switch (device) { #ifdef HW_RVL +#ifdef HAVE_LIBSICKSAXIS + case DEVICE_SIXAXIS: + g_settings.input.device[port] = device; + strlcpy(g_settings.input.device_names[port], "DualShock3/Sixaxis", sizeof(g_settings.input.device_names[port])); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_B].def_joykey = (RETRO_DEVICE_ID_JOYPAD_B); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_Y].def_joykey = (RETRO_DEVICE_ID_JOYPAD_Y); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_SELECT].def_joykey = (RETRO_DEVICE_ID_JOYPAD_SELECT); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_START].def_joykey = (RETRO_DEVICE_ID_JOYPAD_START); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_UP].def_joykey = (RETRO_DEVICE_ID_JOYPAD_UP); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_DOWN].def_joykey = (RETRO_DEVICE_ID_JOYPAD_DOWN); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_LEFT].def_joykey = (RETRO_DEVICE_ID_JOYPAD_LEFT); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_RIGHT].def_joykey = (RETRO_DEVICE_ID_JOYPAD_RIGHT); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_A].def_joykey = (RETRO_DEVICE_ID_JOYPAD_A); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_X].def_joykey = (RETRO_DEVICE_ID_JOYPAD_X); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_L].def_joykey = (RETRO_DEVICE_ID_JOYPAD_L); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_R].def_joykey = (RETRO_DEVICE_ID_JOYPAD_R); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_L2].def_joykey = (RETRO_DEVICE_ID_JOYPAD_L2); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_R2].def_joykey = (RETRO_DEVICE_ID_JOYPAD_R2); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_L3].def_joykey = (RETRO_DEVICE_ID_JOYPAD_L3); + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_R3].def_joykey = (RETRO_DEVICE_ID_JOYPAD_R3); + g_settings.input.binds[port][RARCH_ANALOG_LEFT_X_PLUS].def_joykey = NO_BTN; + g_settings.input.binds[port][RARCH_ANALOG_LEFT_X_MINUS].def_joykey = NO_BTN; + g_settings.input.binds[port][RARCH_ANALOG_LEFT_Y_PLUS].def_joykey = NO_BTN; + g_settings.input.binds[port][RARCH_ANALOG_LEFT_Y_MINUS].def_joykey = NO_BTN; + g_settings.input.binds[port][RARCH_ANALOG_RIGHT_X_PLUS].def_joykey = NO_BTN; + g_settings.input.binds[port][RARCH_ANALOG_RIGHT_X_MINUS].def_joykey = NO_BTN; + g_settings.input.binds[port][RARCH_ANALOG_RIGHT_Y_PLUS].def_joykey = NO_BTN; + g_settings.input.binds[port][RARCH_ANALOG_RIGHT_Y_MINUS].def_joykey = NO_BTN; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_B].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_Y].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_SELECT].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_START].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_UP].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_DOWN].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_LEFT].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_RIGHT].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_A].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_X].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_L].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_R].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_L2].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_R2].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_L3].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RETRO_DEVICE_ID_JOYPAD_R3].def_joyaxis = AXIS_NONE; + g_settings.input.binds[port][RARCH_ANALOG_LEFT_X_PLUS].def_joyaxis = AXIS_POS(0); + g_settings.input.binds[port][RARCH_ANALOG_LEFT_X_MINUS].def_joyaxis = AXIS_NEG(0); + g_settings.input.binds[port][RARCH_ANALOG_LEFT_Y_PLUS].def_joyaxis = AXIS_POS(1); + g_settings.input.binds[port][RARCH_ANALOG_LEFT_Y_MINUS].def_joyaxis = AXIS_NEG(1); + g_settings.input.binds[port][RARCH_ANALOG_RIGHT_X_PLUS].def_joyaxis = AXIS_POS(2); + g_settings.input.binds[port][RARCH_ANALOG_RIGHT_X_MINUS].def_joyaxis = AXIS_NEG(2); + g_settings.input.binds[port][RARCH_ANALOG_RIGHT_Y_PLUS].def_joyaxis = AXIS_POS(3); + g_settings.input.binds[port][RARCH_ANALOG_RIGHT_Y_MINUS].def_joyaxis = AXIS_NEG(3); + break; +#endif case DEVICE_WIIMOTE: g_settings.input.device[port] = device; strlcpy(g_settings.input.device_names[port], "Wiimote", sizeof(g_settings.input.device_names[port])); @@ -499,19 +579,30 @@ static void gx_input_set_keybinds(void *data, unsigned device, unsigned port, static void *gx_input_init(void) { + unsigned i; gx_input_t *gx = (gx_input_t*)calloc(1, sizeof(*gx)); if (!gx) return NULL; PAD_Init(); +#ifdef HAVE_LIBSICKSAXIS + USB_Initialize(); +#endif #ifdef HW_RVL WPAD_Init(); #endif - SYS_SetResetCallback(reset_callback); + SYS_SetResetCallback(reset_cb); #ifdef HW_RVL SYS_SetPowerCallback(power_callback); #endif + (void)i; +#ifdef HAVE_LIBSICKSAXIS + ss_init(); + for (i = 0; i < MAX_PADS; i++) + ss_initialize(&dev[i]); +#endif + return gx; } @@ -580,6 +671,44 @@ static void gx_input_poll(void *data) #ifdef HW_RVL uint32_t ptype = 0; uint32_t connected = WPAD_Probe(port, &ptype); + +#ifdef HAVE_LIBSICKSAXIS + USB_DeviceChangeNotifyAsync(USB_CLASS_HID, change_cb, (void*)&lol); + + if (ss_is_connected(&dev[port])) + { + *state_cur |= (dev[port].pad.buttons.PS) ? (1ULL << RARCH_MENU_TOGGLE) : 0; + *state_cur |= (dev[port].pad.buttons.cross) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_B) : 0; + *state_cur |= (dev[port].pad.buttons.square) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_Y) : 0; + *state_cur |= (dev[port].pad.buttons.select) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_SELECT) : 0; + *state_cur |= (dev[port].pad.buttons.start) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_START) : 0; + *state_cur |= (dev[port].pad.buttons.up) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_UP) : 0; + *state_cur |= (dev[port].pad.buttons.down) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_DOWN) : 0; + *state_cur |= (dev[port].pad.buttons.left) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_LEFT) : 0; + *state_cur |= (dev[port].pad.buttons.right) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_RIGHT) : 0; + *state_cur |= (dev[port].pad.buttons.circle) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_A) : 0; + *state_cur |= (dev[port].pad.buttons.triangle) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_X) : 0; + *state_cur |= (dev[port].pad.buttons.L1) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_L) : 0; + *state_cur |= (dev[port].pad.buttons.R1) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_R) : 0; + *state_cur |= (dev[port].pad.buttons.L2) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_L2) : 0; + *state_cur |= (dev[port].pad.buttons.R2) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_R2) : 0; + *state_cur |= (dev[port].pad.buttons.L3) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_L3) : 0; + *state_cur |= (dev[port].pad.buttons.R3) ? (1ULL << RETRO_DEVICE_ID_JOYPAD_R3) : 0; + } + else + { + if (ss_open(&dev[port]) > 0) + { + ss_start_reading(&dev[port]); + ss_set_removal_cb(&dev[port], removal_cb, (void*)1); + if (g_settings.input.autodetect_enable) + { + if (strcmp(g_settings.input.device_names[port], "DualShock3/Sixaxis") != 0) + gx_input_set_keybinds(NULL, DEVICE_SIXAXIS, port, 0, (1ULL << KEYBINDS_ACTION_SET_DEFAULT_BINDS)); + } + } + } +#endif if (connected == WPAD_ERR_NONE) { diff --git a/gx/sicksaxis.c b/gx/sicksaxis.c new file mode 100644 index 0000000000..d57b9c07a3 --- /dev/null +++ b/gx/sicksaxis.c @@ -0,0 +1,346 @@ +#include "sicksaxis.h" +#include +#include +#include + +static uint8_t ATTRIBUTE_ALIGN(32) _ss_attributes_payload[] = +{ + 0x52, + 0x00, 0x00, 0x00, 0x00, //Rumble + 0xff, 0x80, //Gyro + 0x00, 0x00, + 0x00, //* LED_1 = 0x02, LED_2 = 0x04, ... */ + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_4 */ + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_3 */ + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_2 */ + 0xff, 0x27, 0x10, 0x00, 0x32, /* LED_1 */ +}; + +static const uint8_t _ss_led_pattern[] = {0x0, 0x02, 0x04, 0x08, 0x10, 0x12, 0x14, 0x18}; + +static int _ss_heap_id = -1; +static int _ss_inited = 0; +static int _ss_dev_number = 1; +static int _ss_dev_id_list[SS_MAX_DEV] = {0}; + +static int _ss_dev_id_list_exists(int id); +static int _ss_dev_id_list_add(int id); +static int _ss_dev_id_list_remove(int id); +static int _ss_removal_cb(int result, void *usrdata); +static int _ss_read_cb(int result, void *usrdata); +static int _ss_operational_cb(int result, void *usrdata); +static int _ss_read(struct ss_device *dev); +static int _ss_set_operational(struct ss_device *dev); +static int _ss_build_attributes_payload(struct ss_device *dev); +static int _ss_send_attributes_payload(struct ss_device *dev); + +int ss_init() +{ + if (!_ss_inited) { + _ss_heap_id = iosCreateHeap(SS_HEAP_SIZE); + _ss_inited = 1; + } + return 1; +} + + +int ss_initialize(struct ss_device *dev) +{ + dev->device_id = -1; + dev->fd = -1; + dev->connected = 0; + dev->enabled = 0; + dev->reading = 0; + dev->removal_callback = NULL; + dev->removal_usrdata = NULL; + dev->read_callback = NULL; + dev->read_usrdata = NULL; + memset(&dev->pad, 0x0, sizeof(struct SS_GAMEPAD)); + memset(&dev->attributes, 0x0, sizeof(struct SS_ATTRIBUTES)); + return 1; +} + +int ss_open(struct ss_device *dev) +{ + if (!_ss_inited) return -1; + if (dev->connected) ss_close(dev); + + usb_device_entry dev_entry[8]; + unsigned char dev_count; + if (USB_GetDeviceList(dev_entry, 8, USB_CLASS_HID, &dev_count) < 0) { + return -2; + } + + int i; + for (i = 0; i < dev_count; ++i) { + + if ((dev_entry[i].vid == SS_VENDOR_ID) && (dev_entry[i].pid == SS_PRODUCT_ID)) { + + if (!_ss_dev_id_list_exists(dev_entry[i].device_id)) { + if (USB_OpenDevice(dev_entry[i].device_id, SS_VENDOR_ID, SS_PRODUCT_ID, &dev->fd) < 0) { + return -3; + } + + dev->device_id = dev_entry[i].device_id; + dev->connected = 1; + dev->enabled = 0; + dev->reading = 0; + + _ss_set_operational(dev); + ss_set_led(dev, _ss_dev_number); + + _ss_dev_id_list_add(dev_entry[i].device_id); + _ss_dev_number++; + + USB_DeviceRemovalNotifyAsync(dev->fd, &_ss_removal_cb, dev); + return 1; + } + } + } + return -4; +} + +int ss_close(struct ss_device *dev) +{ + if (dev && dev->fd > 0) { + USB_CloseDevice(&dev->fd); + } + return 1; +} + +int ss_is_connected(struct ss_device *dev) +{ + return dev->connected; +} + +int ss_set_read_cb(struct ss_device *dev,ss_usb_callback cb, void *usrdata) +{ + dev->read_callback = cb; + dev->read_usrdata = usrdata; + return 1; +} + +int ss_set_removal_cb(struct ss_device *dev, ss_usb_callback cb, void *usrdata) +{ + dev->removal_callback = cb; + dev->removal_usrdata = usrdata; + return 1; +} + +int ss_start_reading(struct ss_device *dev) +{ + if (dev) { + dev->reading = 1; + if (dev->enabled) { + _ss_read(dev); + } + return 1; + } + return 0; +} + + +int ss_stop_reading(struct ss_device *dev) +{ + if (dev) { + dev->reading = 0; + return 1; + } + return 0; +} + +static int _ss_build_attributes_payload(struct ss_device *dev) +{ + _ss_attributes_payload[1] = dev->attributes.rumble.duration_right; + _ss_attributes_payload[2] = dev->attributes.rumble.power_right; + _ss_attributes_payload[3] = dev->attributes.rumble.duration_left; + _ss_attributes_payload[4] = dev->attributes.rumble.power_left; + _ss_attributes_payload[9] = _ss_led_pattern[dev->attributes.led]; + return 1; +} + +static int _ss_send_attributes_payload(struct ss_device *dev) +{ + if (!dev->connected) return 0; + _ss_build_attributes_payload(dev); + return USB_WriteCtrlMsgAsync(dev->fd, + USB_REQTYPE_INTERFACE_SET, + USB_REQ_SETREPORT, + (USB_REPTYPE_OUTPUT<<8) | 0x01, + 0x0, + sizeof(_ss_attributes_payload), + _ss_attributes_payload, + NULL, NULL); +} + +inline int ss_set_led(struct ss_device *dev, int led) +{ + dev->attributes.led = led; + return _ss_send_attributes_payload(dev); +} + +inline int ss_set_rumble(struct ss_device *dev, uint8_t duration_right, uint8_t power_right, uint8_t duration_left, uint8_t power_left) +{ + dev->attributes.rumble.duration_right = duration_right; + dev->attributes.rumble.power_right = power_right; + dev->attributes.rumble.duration_left = duration_left; + dev->attributes.rumble.power_left = power_left; + return _ss_send_attributes_payload(dev); +} + +int ss_get_bd_address(struct ss_device *dev, uint8_t *mac) +{ + uint8_t ATTRIBUTE_ALIGN(32) msg[17]; + int ret = USB_WriteCtrlMsgAsync(dev->fd, + USB_REQTYPE_INTERFACE_GET, + USB_REQ_GETREPORT, + (USB_REPTYPE_FEATURE<<8) | 0xf2, + 0, + sizeof(msg), + msg, + NULL, NULL); + + mac[0] = msg[4]; + mac[1] = msg[5]; + mac[2] = msg[6]; + mac[3] = msg[7]; + mac[4] = msg[8]; + mac[5] = msg[9]; + return ret; +} + +int ss_get_mac(struct ss_device *dev, uint8_t *mac) +{ + uint8_t ATTRIBUTE_ALIGN(32) msg[8]; + int ret = USB_WriteCtrlMsgAsync(dev->fd, + USB_REQTYPE_INTERFACE_GET, + USB_REQ_GETREPORT, + (USB_REPTYPE_FEATURE<<8) | 0xf5, + 0, + sizeof(msg), + msg, + NULL, NULL); + + mac[0] = msg[2]; + mac[1] = msg[3]; + mac[2] = msg[4]; + mac[3] = msg[5]; + mac[4] = msg[6]; + mac[5] = msg[7]; + return ret; +} + +int ss_set_mac(struct ss_device *dev, const uint8_t *mac) +{ + uint8_t ATTRIBUTE_ALIGN(32) msg[] = {0x01, 0x00, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]}; + int ret = USB_WriteCtrlMsgAsync(dev->fd, + USB_REQTYPE_INTERFACE_SET, + USB_REQ_SETREPORT, + (USB_REPTYPE_FEATURE<<8) | 0xf5, + 0, + sizeof(msg), + msg, + NULL, NULL); + return ret; +} + + +static int _ss_read(struct ss_device *dev) +{ + return USB_WriteCtrlMsgAsync( + dev->fd, + USB_REQTYPE_INTERFACE_GET, + USB_REQ_GETREPORT, + (USB_REPTYPE_INPUT<<8) | 0x01, + 0x0, + SS_PAYLOAD_SIZE, + &dev->pad, + &_ss_read_cb, + dev); +} + +static int _ss_removal_cb(int result, void *usrdata) +{ + struct ss_device *dev = (struct ss_device*)usrdata; + if (dev->device_id > 0) { + _ss_dev_id_list_remove(dev->device_id); + _ss_dev_number--; + if (dev->removal_callback) + dev->removal_callback(dev->removal_usrdata); + ss_initialize(dev); + return 1; + } + return 0; +} + +static int _ss_set_operational(struct ss_device *dev) +{ + uint8_t ATTRIBUTE_ALIGN(32) buf[17]; + return USB_WriteCtrlMsgAsync( + dev->fd, + USB_REQTYPE_INTERFACE_GET, + USB_REQ_GETREPORT, + (USB_REPTYPE_FEATURE<<8) | 0xf2, + 0x0, + 17, + buf, + &_ss_operational_cb, + dev); +} + +static int _ss_read_cb(int result, void *usrdata) +{ + if (usrdata) { + struct ss_device *dev = (struct ss_device*)usrdata; + if (dev->reading) { + _ss_read(dev); + if (dev->read_callback) + dev->read_callback(dev->read_usrdata); + } + } + return 1; +} + +static int _ss_operational_cb(int result, void *usrdata) +{ + struct ss_device *dev = (struct ss_device*)usrdata; + dev->enabled = 1; + if (dev->reading) { + _ss_read(dev); + } + return 1; +} + + +static int _ss_dev_id_list_exists(int id) +{ + int i; + for (i = 0; i < SS_MAX_DEV; ++i) { + if (_ss_dev_id_list[i] == id) return 1; + } + return 0; +} + +static int _ss_dev_id_list_add(int id) +{ + int i; + for (i = 0; i < SS_MAX_DEV; ++i) { + if (_ss_dev_id_list[i] == 0) { + _ss_dev_id_list[i] = id; + return 1; + } + } + return 0; +} + +static int _ss_dev_id_list_remove(int id) +{ + int i; + for (i = 0; i < SS_MAX_DEV; ++i) { + if (_ss_dev_id_list[i] == id) { + _ss_dev_id_list[i] = 0; + return 1; + } + } + return 0; +} diff --git a/gx/sicksaxis.h b/gx/sicksaxis.h new file mode 100644 index 0000000000..c514aed5c3 --- /dev/null +++ b/gx/sicksaxis.h @@ -0,0 +1,143 @@ +#ifndef _SICKSAXIS_H_ +#define _SICKSAXIS_H_ + +#include + + +#define SS_HEAP_SIZE 4096 +#define SS_MAX_DEV 8 +#define SS_VENDOR_ID 0x054C +#define SS_PRODUCT_ID 0x0268 +#define SS_PAYLOAD_SIZE 49 + +struct SS_BUTTONS +{ + uint8_t left : 1; + uint8_t down : 1; + uint8_t right : 1; + uint8_t up : 1; + uint8_t start : 1; + uint8_t R3 : 1; + uint8_t L3 : 1; + uint8_t select : 1; + + uint8_t square : 1; + uint8_t cross : 1; + uint8_t circle : 1; + uint8_t triangle : 1; + uint8_t R1 : 1; + uint8_t L1 : 1; + uint8_t R2 : 1; + uint8_t L2 : 1; + + uint8_t not_used : 7; + uint8_t PS : 1; +}; + +struct SS_ANALOG +{ + uint8_t x; + uint8_t y; +}; + +struct SS_DPAD_SENSITIVE +{ + uint8_t up; + uint8_t right; + uint8_t down; + uint8_t left; +}; + +struct SS_SHOULDER_SENSITIVE +{ + uint8_t L2; + uint8_t R2; + uint8_t L1; + uint8_t R1; +}; + +struct SS_BUTTON_SENSITIVE +{ + uint8_t triangle; + uint8_t circle; + uint8_t cross; + uint8_t square; +}; + +struct SS_MOTION +{ + uint16_t acc_x; + uint16_t acc_y; + uint16_t acc_z; + uint16_t z_gyro; +}; + +struct SS_GAMEPAD +{ + uint8_t hid_data; + uint8_t unk0; + struct SS_BUTTONS buttons; + uint8_t unk1; + struct SS_ANALOG left_analog; + struct SS_ANALOG right_analog; + uint32_t unk2; + struct SS_DPAD_SENSITIVE dpad_sens; + struct SS_SHOULDER_SENSITIVE shoulder_sens; + struct SS_BUTTON_SENSITIVE button_sens; + uint16_t unk3; + uint8_t unk4; + uint8_t status; + uint8_t power_rating; + uint8_t comm_status; + uint32_t unk5; + uint32_t unk6; + uint8_t unk7; + struct SS_MOTION motion; +}__attribute__((packed)); + +struct SS_ATTRIBUTE_RUMBLE +{ + uint8_t duration_right; + uint8_t power_right; + uint8_t duration_left; + uint8_t power_left; +}; + +struct SS_ATTRIBUTES +{ + struct SS_ATTRIBUTE_RUMBLE rumble; + int led; +}; + +typedef void (*ss_usb_callback)(void *usrdata); + +struct ss_device { + struct SS_GAMEPAD pad; + struct SS_ATTRIBUTES attributes; + int device_id, fd; + int connected, enabled, reading; + ss_usb_callback read_callback; + ss_usb_callback removal_callback; + void *read_usrdata, *removal_usrdata; +}__attribute__((aligned(32))); + + +int ss_init(); +int ss_initialize(struct ss_device *dev); +int ss_open(struct ss_device *dev); +int ss_close(struct ss_device *dev); +int ss_is_connected(struct ss_device *dev); + +int ss_set_read_cb(struct ss_device *dev, ss_usb_callback cb, void *usrdata); +int ss_set_removal_cb(struct ss_device *dev, ss_usb_callback cb, void *usrdata); + +int ss_start_reading(struct ss_device *dev); +int ss_stop_reading(struct ss_device *dev); +int ss_set_led(struct ss_device *dev, int led); +int ss_set_rumble(struct ss_device *dev, uint8_t duration_right, uint8_t power_right, uint8_t duration_left, uint8_t power_left); +int ss_get_bd_address(struct ss_device *dev, uint8_t *mac); +int ss_get_paired_mac(struct ss_device *dev, uint8_t *mac); +int ss_set_paired_mac(struct ss_device *dev, const uint8_t *mac); + + +#endif