diff --git a/driver.h b/driver.h index c59948ccb6..181b088939 100644 --- a/driver.h +++ b/driver.h @@ -268,6 +268,11 @@ enum input_devices DEVICE_XBOX_PAD = 0, #elif defined(__CELLOS_LV2__) DEVICE_SIXAXIS = 0, +#elif defined(__BLACKBERRY_QNX__) + DEVICE_NONE, + DEVICE_WIIMOTE, + DEVICE_KEYBOARD, + DEVICE_UNKNOWN, #endif DEVICE_LAST }; diff --git a/gfx/context/bbqnx_ctx.c b/gfx/context/bbqnx_ctx.c index 1b32be974f..cedfafcf35 100644 --- a/gfx/context/bbqnx_ctx.c +++ b/gfx/context/bbqnx_ctx.c @@ -44,7 +44,7 @@ static EGLDisplay g_egl_dpy; static EGLConfig egl_config; static bool g_resize; -static screen_context_t screen_ctx; +screen_context_t screen_ctx; static screen_window_t screen_win; static screen_display_t screen_disp; diff --git a/playbook/qnx_input.c b/playbook/qnx_input.c index 99f4a21b3c..671a3eb9a9 100644 --- a/playbook/qnx_input.c +++ b/playbook/qnx_input.c @@ -18,8 +18,10 @@ #include #include #include +#include #define MAX_TOUCH 16 +#define MAX_PADS 8 struct touches { @@ -32,6 +34,278 @@ static struct touches touch[MAX_TOUCH]; static unsigned touch_count; //Internal helper functions +typedef struct { + // Static device info. +#ifdef HAVE_BB10 + screen_device_t handle; +#endif + int type; + int analogCount; + int buttonCount; + char id[64]; + char vendor[64]; + char product[64]; + + // Current state. + int buttons; + int analog0[3]; + int analog1[3]; +} input_device_t; + +input_device_t devices[MAX_PADS]; + +static unsigned pads_connected; + +static void qnx_input_autodetect_gamepad(input_device_t* controller); + +#ifdef HAVE_BB10 + +const struct platform_bind platform_keys[] = { + { SCREEN_A_GAME_BUTTON, "A button" }, + { SCREEN_B_GAME_BUTTON, "B button" }, + { SCREEN_C_GAME_BUTTON, "C button" }, + { SCREEN_X_GAME_BUTTON, "X button" }, + { SCREEN_Y_GAME_BUTTON, "Y button" }, + { SCREEN_Z_GAME_BUTTON, "Z button" }, + { SCREEN_MENU1_GAME_BUTTON, "Menu1 button" }, + { SCREEN_MENU2_GAME_BUTTON, "Menu2 button" }, + { SCREEN_MENU3_GAME_BUTTON, "Menu3 button" }, + { SCREEN_MENU4_GAME_BUTTON, "Menu4 button" }, + { SCREEN_L1_GAME_BUTTON, "L1 Button" }, + { SCREEN_L2_GAME_BUTTON, "L2 Button" }, + { SCREEN_L3_GAME_BUTTON, "L3 Button" }, + { SCREEN_R1_GAME_BUTTON, "R1 Button" }, + { SCREEN_R2_GAME_BUTTON, "R2 Button" }, + { SCREEN_R3_GAME_BUTTON, "R3 Button" }, + { SCREEN_DPAD_UP_GAME_BUTTON, "D-Pad Up" }, + { SCREEN_DPAD_DOWN_GAME_BUTTON, "D-Pad Down" }, + { SCREEN_DPAD_LEFT_GAME_BUTTON, "D-Pad Left" }, + { SCREEN_DPAD_RIGHT_GAME_BUTTON, "D-Pad Right" }, +}; + +static void process_gamepad_event(screen_event_t screen_event, int type) +{ + screen_device_t device; + screen_get_event_property_pv(screen_event, SCREEN_PROPERTY_DEVICE, (void**)&device); + + input_device_t* controller = NULL; + int i; + for (i = 0; i < MAX_PADS; ++i) + { + if (device == devices[i].handle) + { + controller = &devices[i]; + break; + } + } + + if (!controller) + return; + + // Store the controller's new state. + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_BUTTONS, &controller->buttons); + + if (controller->analogCount > 0) + { + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_ANALOG0, controller->analog0); + } + + if (controller->analogCount == 2) + { + screen_get_event_property_iv(screen_event, SCREEN_PROPERTY_ANALOG1, controller->analog1); + } +} + +static void loadController(input_device_t* controller) +{ + int device; + + // Query libscreen for information about this device. + screen_get_device_property_iv(controller->handle, SCREEN_PROPERTY_TYPE, &controller->type); + screen_get_device_property_cv(controller->handle, SCREEN_PROPERTY_ID_STRING, sizeof(controller->id), controller->id); + screen_get_device_property_cv(controller->handle, SCREEN_PROPERTY_VENDOR, sizeof(controller->id), controller->vendor); + screen_get_device_property_cv(controller->handle, SCREEN_PROPERTY_PRODUCT, sizeof(controller->id), controller->product); + + if (controller->type == SCREEN_EVENT_GAMEPAD || controller->type == SCREEN_EVENT_JOYSTICK) + { + screen_get_device_property_iv(controller->handle, SCREEN_PROPERTY_BUTTON_COUNT, &controller->buttonCount); + + // Check for the existence of analog sticks. + if (!screen_get_device_property_iv(controller->handle, SCREEN_PROPERTY_ANALOG0, controller->analog0)) + { + ++controller->analogCount; + } + + if (!screen_get_device_property_iv(controller->handle, SCREEN_PROPERTY_ANALOG1, controller->analog1)) + { + ++controller->analogCount; + } + } + + //Screen service will map supported controllers, we still might need to adjust. + qnx_input_autodetect_gamepad(controller); + + if (controller->type == SCREEN_EVENT_GAMEPAD) + { + RARCH_LOG("Gamepad Device Connected:\n"); + } + else if (controller->type == SCREEN_EVENT_JOYSTICK) + { + RARCH_LOG("Joystick Device Connected:\n"); + } + else if (controller->type == SCREEN_EVENT_KEYBOARD) + { + RARCH_LOG("Keyboard Device Connected:\n"); + } + + RARCH_LOG("\tID: %s\n", controller->id); + RARCH_LOG("\tVendor: %s\n", controller->vendor); + RARCH_LOG("\tProduct: %s\n", controller->product); + RARCH_LOG("\tButton Count: %d\n", controller->buttonCount); + RARCH_LOG("\tAnalog Count: %d\n", controller->analogCount); +} + +extern screen_context_t screen_ctx; +static void discoverControllers() +{ + // Get an array of all available devices. + int deviceCount; + screen_get_context_property_iv(screen_ctx, SCREEN_PROPERTY_DEVICE_COUNT, &deviceCount); + screen_device_t* devices_found = (screen_device_t*)calloc(deviceCount, sizeof(screen_device_t)); + screen_get_context_property_pv(screen_ctx, SCREEN_PROPERTY_DEVICES, (void**)devices_found); + + // Scan the list for gamepad and joystick devices. + int i; + for (i = 0; i < deviceCount; i++) + { + int type; + screen_get_device_property_iv(devices_found[i], SCREEN_PROPERTY_TYPE, &type); + + if (type == SCREEN_EVENT_GAMEPAD || type == SCREEN_EVENT_JOYSTICK || type == SCREEN_EVENT_KEYBOARD) + { + devices[pads_connected].handle = devices_found[i]; + loadController(&devices[pads_connected]); + + pads_connected++; + if (pads_connected == MAX_PADS) + { + break; + } + } + } + + free(devices_found); +} +#else +void init_playbook_keyboard() +{ + strlcpy(devices[0].id, "0A5C-8502", sizeof(devices[0].id)); + qnx_input_autodetect_gamepad(&devices[0]); + pads_connected = 1; +} +#endif + +static void initController(input_device_t* controller) +{ + // Initialize controller values. +#ifdef HAVE_BB10 + controller->handle = 0; +#endif + controller->type = 0; + controller->analogCount = 0; + controller->buttonCount = 0; + controller->buttons = 0; + controller->analog0[0] = controller->analog0[1] = controller->analog0[2] = 0; + controller->analog1[0] = controller->analog1[1] = controller->analog1[2] = 0; + memset(controller->id, 0, sizeof(controller->id)); +} + +static void qnx_input_autodetect_gamepad(input_device_t* controller) +{ + int device; + + //ID: A-BBBB-CCCC-D.D + //A is the device's index in the array returned by screen_get_context_property_pv() + //BBBB is the device's Vendor ID (in hexadecimal) + //CCCC is the device's Product ID (also in hexadecimal) + //D.D is the device's version number + if (strstr(controller->id, "057E-0306")) + { + device = DEVICE_WIIMOTE; + } + else if (strstr(controller->id, "0A5C-8502")) + { + device = DEVICE_KEYBOARD; + } + else if (controller->id) + { + device = DEVICE_UNKNOWN; + } + else + { + device = DEVICE_NONE; + } + + if (driver.input->set_keybinds) + driver.input->set_keybinds((void*)controller, device, pads_connected, 0, + (1ULL << KEYBINDS_ACTION_SET_DEFAULT_BINDS)); +} + +static void process_keyboard_event(screen_event_t event, int type) +{ + input_device_t* controller = NULL; + int i = 0; + + //Get Keyboard state + int sym = 0; + screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_SYM, &sym); + int modifiers = 0; + screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_MODIFIERS, &modifiers); + int flags = 0; + screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_FLAGS, &flags); + int scan = 0; + screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_SCAN, &scan); + int cap = 0; + screen_get_event_property_iv(event, SCREEN_PROPERTY_KEY_CAP, &cap); + +#ifdef HAVE_BB10 + //Find device that pressed the key + screen_device_t device; + screen_get_event_property_pv(event, SCREEN_PROPERTY_DEVICE, (void**)&device); + + for (i = 0; i < MAX_PADS; ++i) + { + if (device == devices[i].handle) + { + controller = &devices[i]; + break; + } + } + + if (!controller) + return; +#else + controller = &devices[0]; +#endif + + int b; + for (b = 0; b < RARCH_FIRST_CUSTOM_BIND; ++b) + { + if ((unsigned int)g_settings.input.binds[i][b].joykey == (unsigned int)(sym&0xFF)) + { + if (flags & KEY_DOWN) + { + controller->buttons |= 1 << b; + } + else + { + controller->buttons &= ~(1<joykey == NO_BTN) + strlcpy(ret->desc, "No button", sizeof(ret->desc)); + else + { + for (size_t i = 0; i < arr_size; i++) + { + if (platform_keys[i].joykey == ret->joykey) + { + strlcpy(ret->desc, platform_keys[i].desc, sizeof(ret->desc)); + return; + } + } + strlcpy(ret->desc, "Unknown", sizeof(ret->desc)); + } + } +#endif } const input_driver_t input_qnx = { @@ -275,7 +772,7 @@ const input_driver_t input_qnx = { qnx_input_state, qnx_input_key_pressed, qnx_input_free_input, - qnx_set_keybinds, + qnx_input_set_keybinds, "qnx_input", };