From 10c042f1dc3437cae44e7766dc389b10d3e529f9 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Sun, 11 Jan 2015 01:29:19 +0100 Subject: [PATCH] Some simplifications in Windows input drivers --- input/dinput.c | 176 +++++++++++++++++++++++---------------- input/gx_input.c | 6 +- input/linuxraw_input.c | 62 ++++++++------ input/linuxraw_joypad.c | 40 ++++++--- input/winxinput_joypad.c | 114 ++++++++++++++----------- 5 files changed, 238 insertions(+), 160 deletions(-) diff --git a/input/dinput.c b/input/dinput.c index ca1657da12..a7b972e2e9 100644 --- a/input/dinput.c +++ b/input/dinput.c @@ -72,11 +72,11 @@ static struct dinput_joypad g_pads[MAX_USERS]; static void dinput_destroy_context(void) { - if (g_ctx) - { - IDirectInput8_Release(g_ctx); - g_ctx = NULL; - } + if (!g_ctx) + return; + + IDirectInput8_Release(g_ctx); + g_ctx = NULL; } static bool dinput_init_context(void) @@ -106,13 +106,15 @@ static bool dinput_init_context(void) static void *dinput_init(void) { + struct dinput_input *di = NULL; + if (!dinput_init_context()) { RARCH_ERR("Failed to start DirectInput driver.\n"); return NULL; } - struct dinput_input *di = (struct dinput_input*)calloc(1, sizeof(*di)); + di = (struct dinput_input*)calloc(1, sizeof(*di)); if (!di) return NULL; @@ -217,10 +219,11 @@ static void dinput_poll(void *data) static bool dinput_keyboard_pressed(struct dinput_input *di, unsigned key) { + unsigned sym; if (key >= RETROK_LAST) return false; - unsigned sym = input_translate_rk_to_keysym((enum retro_key)key); + sym = input_translate_rk_to_keysym((enum retro_key)key); return di->state[sym] & 0x80; } @@ -228,10 +231,10 @@ static bool dinput_is_pressed(struct dinput_input *di, const struct retro_keybind *binds, unsigned port, unsigned id) { + const struct retro_keybind *bind = &binds[id]; if (id >= RARCH_BIND_LIST_END) return false; - const struct retro_keybind *bind = &binds[id]; return dinput_keyboard_pressed(di, bind->key) || input_joypad_pressed(di->joypad, port, binds, id); } @@ -240,19 +243,23 @@ static int16_t dinput_pressed_analog(struct dinput_input *di, const struct retro_keybind *binds, unsigned idx, unsigned id) { - unsigned id_minus = 0; - unsigned id_plus = 0; + const struct retro_keybind *bind_minus, *bind_plus; + int16_t pressed_minus = 0, pressed_plus = 0; + unsigned id_minus = 0, id_plus = 0; + input_conv_analog_id_to_bind_id(idx, id, &id_minus, &id_plus); - const struct retro_keybind *bind_minus = &binds[id_minus]; - const struct retro_keybind *bind_plus = &binds[id_plus]; + bind_minus = &binds[id_minus]; + bind_plus = &binds[id_plus]; + if (!bind_minus->valid || !bind_plus->valid) return 0; - int16_t pressed_minus = - dinput_keyboard_pressed(di, bind_minus->key) ? -0x7fff : 0; - int16_t pressed_plus = - dinput_keyboard_pressed(di, bind_plus->key) ? 0x7fff : 0; + if (dinput_keyboard_pressed(di, bind_minus->key)) + pressed_minus = -0x7fff; + if (dinput_keyboard_pressed(di, bind_plus->key)) + pressed_plus = 0x7fff; + return pressed_plus + pressed_minus; } @@ -311,9 +318,12 @@ static int16_t dinput_mouse_state(struct dinput_input *di, unsigned id) static int16_t dinput_pointer_state(struct dinput_input *di, unsigned idx, unsigned id, bool screen) { + bool pointer_down, valid, inside; + int x, y; int16_t res_x = 0, res_y = 0, res_screen_x = 0, res_screen_y = 0; unsigned num = 0; struct pointer_status *check_pos = di->pointer_head.next; + while (check_pos && num < idx) { num++; @@ -322,11 +332,11 @@ static int16_t dinput_pointer_state(struct dinput_input *di, if (!check_pos && idx > 0) /* idx = 0 has mouse fallback. */ return 0; - int x = check_pos ? check_pos->pointer_x : di->mouse_x; - int y = check_pos ? check_pos->pointer_y : di->mouse_y; - bool pointer_down = check_pos ? true : di->mouse_l; + x = check_pos ? check_pos->pointer_x : di->mouse_x; + y = check_pos ? check_pos->pointer_y : di->mouse_y; + pointer_down = check_pos ? true : di->mouse_l; - bool valid = input_translate_coord_viewport(x, y, + valid = input_translate_coord_viewport(x, y, &res_x, &res_y, &res_screen_x, &res_screen_y); if (!valid) @@ -338,7 +348,7 @@ static int16_t dinput_pointer_state(struct dinput_input *di, res_y = res_screen_y; } - bool inside = (res_x >= -0x7fff) && (res_y >= -0x7fff); + inside = (res_x >= -0x7fff) && (res_y >= -0x7fff); if (!inside) return 0; @@ -388,22 +398,25 @@ static int16_t dinput_input_state(void *data, case RETRO_DEVICE_LIGHTGUN: return dinput_lightgun_state(di, id); - - default: - return 0; } + + return 0; } -/* these are defined in later SDKs, thus ifdeffed. */ +/* These are defined in later SDKs, thus ifdeffed. */ + #ifndef WM_POINTERUPDATE #define WM_POINTERUPDATE 0x0245 #endif + #ifndef WM_POINTERDOWN #define WM_POINTERDOWN 0x0246 #endif + #ifndef WM_POINTERUP #define WM_POINTERUP 0x0247 #endif + #ifndef GET_POINTERID_WPARAM #define GET_POINTERID_WPARAM(wParam) (LOWORD(wParam)) #endif @@ -412,6 +425,7 @@ static int16_t dinput_input_state(void *data, void dinput_pointer_store_pos(struct pointer_status *pointer, WPARAM lParam) { POINT point; + point.x = GET_X_LPARAM(lParam); point.y = GET_Y_LPARAM(lParam); ScreenToClient((HWND)driver.video_window, &point); @@ -422,8 +436,11 @@ void dinput_pointer_store_pos(struct pointer_status *pointer, WPARAM lParam) void dinput_add_pointer(struct dinput_input *di, struct pointer_status *new_pointer) { + struct pointer_status *insert_pos = NULL; + new_pointer->next = NULL; - struct pointer_status *insert_pos = &di->pointer_head; + insert_pos = &di->pointer_head; + while (insert_pos->next) insert_pos = insert_pos->next; insert_pos->next = new_pointer; @@ -432,11 +449,13 @@ void dinput_add_pointer(struct dinput_input *di, void dinput_delete_pointer(struct dinput_input *di, int pointer_id) { struct pointer_status *check_pos = &di->pointer_head; + while (check_pos && check_pos->next) { if (check_pos->next->pointer_id == pointer_id) { struct pointer_status *to_delete = check_pos->next; + check_pos->next = check_pos->next->next; free(to_delete); } @@ -448,6 +467,7 @@ struct pointer_status *dinput_find_pointer(struct dinput_input *di, int pointer_id) { struct pointer_status *check_pos = di->pointer_head.next; + while (check_pos) { if (check_pos->pointer_id == pointer_id) @@ -460,9 +480,11 @@ struct pointer_status *dinput_find_pointer(struct dinput_input *di, void dinput_clear_pointers(struct dinput_input *di) { struct pointer_status *pointer = &di->pointer_head; + while (pointer->next) { struct pointer_status *del = pointer->next; + pointer->next = pointer->next->next; free(del); } @@ -475,11 +497,11 @@ bool dinput_handle_message(void *dinput, UINT message, WPARAM wParam, LPARAM lPa { struct dinput_input *di = (struct dinput_input *)dinput; /* WM_POINTERDOWN : Arrives for each new touch event - * with a new ID - add to list. + * with a new ID - add to list. * WM_POINTERUP : Arrives once the pointer is no - * longer down - remove from list. + * longer down - remove from list. * WM_POINTERUPDATE : arrives for both pressed and - * hovering pointers - ignore hovering + * hovering pointers - ignore hovering */ switch (message) @@ -488,6 +510,7 @@ bool dinput_handle_message(void *dinput, UINT message, WPARAM wParam, LPARAM lPa { struct pointer_status *new_pointer = (struct pointer_status *)malloc(sizeof(struct pointer_status)); + if (!new_pointer) { RARCH_ERR("dinput_handle_message: pointer allocation in WM_POINTERDOWN failed.\n"); @@ -555,6 +578,7 @@ static void dinput_free(void *data) static void dinput_grab_mouse(void *data, bool state) { struct dinput_input *di = (struct dinput_input*)data; + IDirectInputDevice8_Unacquire(di->mouse); IDirectInputDevice8_SetCooperativeLevel(di->mouse, (HWND)driver.video_window, @@ -568,12 +592,16 @@ static bool dinput_set_rumble(void *data, unsigned port, enum retro_rumble_effect effect, uint16_t strength) { struct dinput_input *di = (struct dinput_input*)data; + if (!di) + return false; return input_joypad_set_rumble(di->joypad, port, effect, strength); } static const rarch_joypad_driver_t *dinput_get_joypad_driver(void *data) { struct dinput_input *di = (struct dinput_input*)data; + if (!di) + return false; return di->joypad; } @@ -641,9 +669,9 @@ static void dinput_joypad_destroy(void) static BOOL CALLBACK enum_axes_cb( const DIDEVICEOBJECTINSTANCE *inst, void *p) { + DIPROPRANGE range; LPDIRECTINPUTDEVICE8 joypad = (LPDIRECTINPUTDEVICE8)p; - DIPROPRANGE range; memset(&range, 0, sizeof(range)); range.diph.dwSize = sizeof(DIPROPRANGE); range.diph.dwHeaderSize = sizeof(DIPROPHEADER); @@ -657,17 +685,16 @@ static BOOL CALLBACK enum_axes_cb( } static const GUID common_xinput_guids[] = { - {MAKELONG(0x28DE, 0x11FF),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}}, // valve streaming pad - {MAKELONG(0x045E, 0x02A1),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}}, // wired 360 pad - {MAKELONG(0x045E, 0x028E),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}} // wireless 360 pad + {MAKELONG(0x28DE, 0x11FF),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}}, /* Valve streaming pad */ + {MAKELONG(0x045E, 0x02A1),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}}, /* Wired 360 pad */ + {MAKELONG(0x045E, 0x028E),0x0000,0x0000,{0x00,0x00,0x50,0x49,0x44,0x56,0x49,0x44}} /* wireless 360 pad */ }; /* Based on SDL2's implementation. */ static bool guid_is_xinput_device(const GUID* product_guid) { + unsigned i, num_raw_devs = 0; PRAWINPUTDEVICELIST raw_devs = NULL; - unsigned num_raw_devs = 0; - unsigned i; /* Check for well known XInput device GUIDs, * thereby removing the need for the IG_ check. @@ -711,6 +738,7 @@ static bool guid_is_xinput_device(const GUID* product_guid) UINT nameSize = sizeof(devName); rdi.cbSize = sizeof (rdi); + if ((raw_devs[i].dwType == RIM_TYPEHID) && (GetRawInputDeviceInfoA(raw_devs[i].hDevice, RIDI_DEVICEINFO, &rdi, &rdiSize) != ((UINT)-1)) && (MAKELONG(rdi.hid.dwVendorId, rdi.hid.dwProductId) == ((LONG)product_guid->Data1)) && @@ -735,11 +763,15 @@ static unsigned g_last_xinput_pad_idx; static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p) { + bool is_xinput_pad; + LPDIRECTINPUTDEVICE8 *pad = NULL; + (void)p; + if (g_joypad_cnt == MAX_USERS) return DIENUM_STOP; - LPDIRECTINPUTDEVICE8 *pad = &g_pads[g_joypad_cnt].joypad; + pad = &g_pads[g_joypad_cnt].joypad; #ifdef __cplusplus if (FAILED(IDirectInput8_CreateDevice( @@ -754,10 +786,10 @@ static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p) #ifdef HAVE_WINXINPUT #if 0 - bool is_xinput_pad = g_xinput_block_pads + is_xinput_pad = g_xinput_block_pads && name_is_xinput_pad(inst->tszProductName); #endif - bool is_xinput_pad = g_xinput_block_pads + is_xinput_pad = g_xinput_block_pads && guid_is_xinput_device(&inst->guidProduct); if (is_xinput_pad) @@ -796,6 +828,7 @@ enum_iteration_done: static bool dinput_joypad_init(void) { unsigned i; + if (!dinput_init_context()) return false; @@ -816,27 +849,29 @@ static bool dinput_joypad_init(void) static bool dinput_joypad_button(unsigned port_num, uint16_t joykey) { + const struct dinput_joypad *pad = NULL; + if (joykey == NO_BTN) return false; - const struct dinput_joypad *pad = &g_pads[port_num]; + pad = &g_pads[port_num]; if (!pad->joypad) return false; - // Check hat. + /* Check hat. */ if (GET_HAT_DIR(joykey)) { - unsigned hat = GET_HAT(joykey); - + unsigned pov; + unsigned hat = GET_HAT(joykey); unsigned elems = sizeof(pad->joy_state.rgdwPOV) / sizeof(pad->joy_state.rgdwPOV[0]); if (hat >= elems) return false; - unsigned pov = pad->joy_state.rgdwPOV[hat]; + pov = pad->joy_state.rgdwPOV[hat]; - // Magic numbers I'm not sure where originate from. + /* Magic numbers I'm not sure where originate from. */ if (pov < 36000) { switch (GET_HAT_DIR(joykey)) @@ -868,19 +903,19 @@ static bool dinput_joypad_button(unsigned port_num, uint16_t joykey) static int16_t dinput_joypad_axis(unsigned port_num, uint32_t joyaxis) { - if (joyaxis == AXIS_NONE) - return 0; - - const struct dinput_joypad *pad = &g_pads[port_num]; - if (!pad->joypad) - return 0; - + const struct dinput_joypad *pad = NULL; int val = 0; - int axis = -1; bool is_neg = false; bool is_pos = false; + if (joyaxis == AXIS_NONE) + return 0; + + pad = &g_pads[port_num]; + if (!pad->joypad) + return 0; + if (AXIS_NEG_GET(joyaxis) <= 5) { axis = AXIS_NEG_GET(joyaxis); @@ -928,30 +963,31 @@ static void dinput_joypad_poll(void) for (i = 0; i < MAX_USERS; i++) { struct dinput_joypad *pad = &g_pads[i]; + bool polled = g_xinput_pad_indexes[i] < 0; - if (pad->joypad && g_xinput_pad_indexes[i] < 0) + if (!pad || !pad->joypad || !polled) + continue; + + memset(&pad->joy_state, 0, sizeof(pad->joy_state)); + + if (FAILED(IDirectInputDevice8_Poll(pad->joypad))) { - memset(&pad->joy_state, 0, sizeof(pad->joy_state)); - - if (FAILED(IDirectInputDevice8_Poll(pad->joypad))) + if (FAILED(IDirectInputDevice8_Acquire(pad->joypad))) { - if (FAILED(IDirectInputDevice8_Acquire(pad->joypad))) - { - memset(&pad->joy_state, 0, sizeof(DIJOYSTATE2)); - continue; - } - - /* If this fails, something *really* bad must have happened. */ - if (FAILED(IDirectInputDevice8_Poll(pad->joypad))) - { - memset(&pad->joy_state, 0, sizeof(DIJOYSTATE2)); - continue; - } + memset(&pad->joy_state, 0, sizeof(DIJOYSTATE2)); + continue; } - IDirectInputDevice8_GetDeviceState(pad->joypad, - sizeof(DIJOYSTATE2), &pad->joy_state); + /* If this fails, something *really* bad must have happened. */ + if (FAILED(IDirectInputDevice8_Poll(pad->joypad))) + { + memset(&pad->joy_state, 0, sizeof(DIJOYSTATE2)); + continue; + } } + + IDirectInputDevice8_GetDeviceState(pad->joypad, + sizeof(DIJOYSTATE2), &pad->joy_state); } } diff --git a/input/gx_input.c b/input/gx_input.c index 88c3c78fa5..9017510101 100644 --- a/input/gx_input.c +++ b/input/gx_input.c @@ -104,9 +104,9 @@ static uint64_t gx_input_get_capabilities(void *data) static const rarch_joypad_driver_t *gx_input_get_joypad_driver(void *data) { gx_input_t *gx = (gx_input_t*)data; - if (gx) - return gx->joypad; - return NULL; + if (!gx) + return NULL; + return gx->joypad; } input_driver_t input_gx = { diff --git a/input/linuxraw_input.c b/input/linuxraw_input.c index 83f7a4c8e6..1855f07764 100644 --- a/input/linuxraw_input.c +++ b/input/linuxraw_input.c @@ -57,7 +57,10 @@ static void linuxraw_exitGracefully(int sig) static void *linuxraw_input_init(void) { - // only work on terminals + linuxraw_input_t *linuxraw; + struct sigaction sa; + + /* Only work on terminals. */ if (!isatty(0)) return NULL; @@ -67,7 +70,7 @@ static void *linuxraw_input_init(void) return NULL; } - linuxraw_input_t *linuxraw = (linuxraw_input_t*)calloc(1, sizeof(*linuxraw)); + linuxraw = (linuxraw_input_t*)calloc(1, sizeof(*linuxraw)); if (!linuxraw) return NULL; @@ -96,7 +99,6 @@ static void *linuxraw_input_init(void) return NULL; } - struct sigaction sa; sa.sa_handler = linuxraw_exitGracefully; sa.sa_flags = SA_RESTART | SA_RESETHAND; sigemptyset(&sa.sa_mask); @@ -118,6 +120,7 @@ static void *linuxraw_input_init(void) /* We need to disable use of stdin command interface if * stdin is supposed to be used for input. */ driver.stdin_claimed = true; + return linuxraw; } @@ -130,32 +133,37 @@ static bool linuxraw_key_pressed(linuxraw_input_t *linuxraw, int key) static bool linuxraw_is_pressed(linuxraw_input_t *linuxraw, const struct retro_keybind *binds, unsigned id) { - if (id < RARCH_BIND_LIST_END) - { - const struct retro_keybind *bind = &binds[id]; - if (bind) - return bind->valid && linuxraw_key_pressed(linuxraw, binds[id].key); - } - return false; + const struct retro_keybind *bind = &binds[id]; + + if (id >= RARCH_BIND_LIST_END) + return false; + if (!bind) + return false; + + return bind->valid && linuxraw_key_pressed(linuxraw, binds[id].key); } static int16_t linuxraw_analog_pressed(linuxraw_input_t *linuxraw, const struct retro_keybind *binds, unsigned idx, unsigned id) { + int16_t pressed_minus = 0, pressed_plus = 0; unsigned id_minus = 0; unsigned id_plus = 0; input_conv_analog_id_to_bind_id(idx, id, &id_minus, &id_plus); - int16_t pressed_minus = linuxraw_is_pressed(linuxraw, - binds, id_minus) ? -0x7fff : 0; - int16_t pressed_plus = linuxraw_is_pressed(linuxraw, - binds, id_plus) ? 0x7fff : 0; + if (linuxraw_is_pressed(linuxraw, binds, id_minus)) + pressed_minus = -0x7fff; + if (linuxraw_is_pressed(linuxraw, binds, id_plus)) + pressed_plus = 0x7fff; + return pressed_plus + pressed_minus; } static bool linuxraw_bind_button_pressed(void *data, int key) { linuxraw_input_t *linuxraw = (linuxraw_input_t*)data; + if (!linuxraw) + return false; return linuxraw_is_pressed(linuxraw, g_settings.input.binds[0], key) || input_joypad_pressed(linuxraw->joypad, 0, g_settings.input.binds[0], key); } @@ -178,10 +186,9 @@ static int16_t linuxraw_input_state(void *data, if (!ret) ret = input_joypad_analog(linuxraw->joypad, port, idx, id, binds[port]); return ret; - - default: - return 0; } + + return 0; } static void linuxraw_input_free(void *data) @@ -202,31 +209,33 @@ static bool linuxraw_set_rumble(void *data, unsigned port, enum retro_rumble_effect effect, uint16_t strength) { linuxraw_input_t *linuxraw = (linuxraw_input_t*)data; - if (linuxraw) - return input_joypad_set_rumble(linuxraw->joypad, port, effect, strength); - return false; + if (!linuxraw) + return false; + return input_joypad_set_rumble(linuxraw->joypad, port, effect, strength); } static const rarch_joypad_driver_t *linuxraw_get_joypad_driver(void *data) { linuxraw_input_t *linuxraw = (linuxraw_input_t*)data; - if (linuxraw) - return linuxraw->joypad; - return NULL; + if (!linuxraw) + return false; + return linuxraw->joypad; } static void linuxraw_input_poll(void *data) { - linuxraw_input_t *linuxraw = (linuxraw_input_t*)data; uint8_t c; uint16_t t; + linuxraw_input_t *linuxraw = (linuxraw_input_t*)data; while (read(STDIN_FILENO, &c, 1) > 0) { + bool pressed; + if (c == KEY_C && (linuxraw->state[KEY_LEFTCTRL] || linuxraw->state[KEY_RIGHTCTRL])) kill(getpid(), SIGINT); - bool pressed = !(c & 0x80); + pressed = !(c & 0x80); c &= ~0x80; // ignore extended scancodes @@ -242,9 +251,10 @@ static void linuxraw_input_poll(void *data) static uint64_t linuxraw_get_capabilities(void *data) { - (void)data; uint64_t caps = 0; + (void)data; + caps |= (1 << RETRO_DEVICE_JOYPAD); caps |= (1 << RETRO_DEVICE_ANALOG); diff --git a/input/linuxraw_joypad.c b/input/linuxraw_joypad.c index 86c9fd630e..a7d3ddd5d7 100644 --- a/input/linuxraw_joypad.c +++ b/input/linuxraw_joypad.c @@ -48,6 +48,7 @@ static bool g_hotplug; static void poll_pad(struct linuxraw_joypad *pad) { struct js_event event; + while (read(pad->fd, &event, sizeof(event)) == (ssize_t)sizeof(event)) { unsigned type = event.type & ~JS_EVENT_INIT; @@ -120,21 +121,26 @@ static void handle_plugged_pad(void) int i, rc; size_t event_size = sizeof(struct inotify_event) + NAME_MAX + 1; uint8_t *event_buf = (uint8_t*)calloc(1, event_size); + if (!event_buf) return; while ((rc = read(g_notify, event_buf, event_size)) >= 0) { struct inotify_event *event = NULL; - // Can read multiple events in one read() call. + + /* Can read multiple events in one read() call. */ + for (i = 0; i < rc; i += event->len + sizeof(struct inotify_event)) { + unsigned idx; + event = (struct inotify_event*)&event_buf[i]; if (strstr(event->name, "js") != event->name) continue; - unsigned idx = strtoul(event->name + 2, NULL, 0); + idx = strtoul(event->name + 2, NULL, 0); if (idx >= MAX_USERS) continue; @@ -165,9 +171,10 @@ static void handle_plugged_pad(void) // Sometimes, device will be created before acess to it is established. else if (event->mask & (IN_CREATE | IN_ATTRIB)) { + bool ret; char path[PATH_MAX]; snprintf(path, sizeof(path), "/dev/input/%s", event->name); - bool ret = linuxraw_joypad_init_pad(path, &linuxraw_pads[idx]); + ret = linuxraw_joypad_init_pad(path, &linuxraw_pads[idx]); if (*linuxraw_pads[idx].ident && ret) /* TODO - implement VID/PID? */ @@ -207,17 +214,22 @@ static void linuxraw_joypad_setup_notify(void) static bool linuxraw_joypad_init(void) { unsigned i; + g_epoll = epoll_create(MAX_USERS + 1); if (g_epoll < 0) return false; for (i = 0; i < MAX_USERS; i++) { + char path[PATH_MAX]; struct linuxraw_joypad *pad = (struct linuxraw_joypad*)&linuxraw_pads[i]; + + if (!pad) + continue; + pad->fd = -1; pad->ident = g_settings.input.device_names[i]; - char path[PATH_MAX]; snprintf(path, sizeof(path), "/dev/input/js%u", i); /* TODO - implement VID/PID? */ @@ -233,9 +245,10 @@ static bool linuxraw_joypad_init(void) g_notify = inotify_init(); if (g_notify >= 0) { + struct epoll_event event; + linuxraw_joypad_setup_notify(); - struct epoll_event event; event.events = EPOLLIN; event.data.ptr = NULL; epoll_ctl(g_epoll, EPOLL_CTL_ADD, g_notify, &event); @@ -249,6 +262,7 @@ static bool linuxraw_joypad_init(void) static void linuxraw_joypad_destroy(void) { unsigned i; + for (i = 0; i < MAX_USERS; i++) { if (linuxraw_pads[i].fd >= 0) @@ -256,6 +270,7 @@ static void linuxraw_joypad_destroy(void) } memset(linuxraw_pads, 0, sizeof(linuxraw_pads)); + for (i = 0; i < MAX_USERS; i++) linuxraw_pads[i].fd = -1; @@ -273,26 +288,27 @@ static void linuxraw_joypad_destroy(void) static bool linuxraw_joypad_button(unsigned port, uint16_t joykey) { const struct linuxraw_joypad *pad = (const struct linuxraw_joypad*)&linuxraw_pads[port]; - if (pad) - return joykey < NUM_BUTTONS && BIT32_GET(pad->buttons, joykey); - return false; + if (!pad) + return false; + return joykey < NUM_BUTTONS && BIT32_GET(pad->buttons, joykey); } static int16_t linuxraw_joypad_axis(unsigned port, uint32_t joyaxis) { + int16_t val = 0; + const struct linuxraw_joypad *pad = NULL; + if (joyaxis == AXIS_NONE) return 0; - const struct linuxraw_joypad *pad = (const struct linuxraw_joypad*) - &linuxraw_pads[port]; + pad = (const struct linuxraw_joypad*)&linuxraw_pads[port]; - int16_t val = 0; if (AXIS_NEG_GET(joyaxis) < NUM_AXES) { val = pad->axes[AXIS_NEG_GET(joyaxis)]; if (val > 0) val = 0; - // Kernel returns values in range [-0x7fff, 0x7fff]. + /* Kernel returns values in range [-0x7fff, 0x7fff]. */ } else if (AXIS_POS_GET(joyaxis) < NUM_AXES) { diff --git a/input/winxinput_joypad.c b/input/winxinput_joypad.c index 0e3b3cd10b..48d7421c99 100644 --- a/input/winxinput_joypad.c +++ b/input/winxinput_joypad.c @@ -30,8 +30,9 @@ #include #include -// Check the definitions do not already exist. -// Official and mingw xinput headers have different include guards +/* Check if the definitions do not already exist. + * Official and mingw xinput headers have different include guards. + */ #if ((!_XINPUT_H_) && (!__WINE_XINPUT_H)) #define XINPUT_GAMEPAD_DPAD_UP 0x0001 @@ -74,7 +75,7 @@ typedef struct #endif -// Guide constant is not officially documented +/* Guide constant is not officially documented. */ #define XINPUT_GAMEPAD_GUIDE 0x0400 #ifndef ERROR_DEVICE_NOT_CONNECTED @@ -85,25 +86,28 @@ typedef struct #error Cannot compile xinput without dinput. #endif -// Due to 360 pads showing up under both XI and DI, and since we are going -// to have to pass through unhandled joypad numbers to DI, a slightly ugly -// hack is required here. dinput_joypad_init will fill this. -// For each pad index, the appropriate entry will be set to -1 if it is not -// a 360 pad, or the correct XInput user number (0..3 inclusive) if it is. +/* Due to 360 pads showing up under both XInput and DirectInput, + * and since we are going to have to pass through unhandled + * joypad numbers to DirectInput, a slightly ugly + * hack is required here. dinput_joypad_init will fill this. + * + * For each pad index, the appropriate entry will be set to -1 if it is not + * a 360 pad, or the correct XInput user number (0..3 inclusive) if it is. + */ extern int g_xinput_pad_indexes[MAX_USERS]; extern bool g_xinput_block_pads; -// For xinput1_n.dll +/* For xinput1_n.dll */ static HINSTANCE g_winxinput_dll; -// Function pointer, to be assigned with GetProcAddress +/* Function pointer, to be assigned with GetProcAddress */ typedef uint32_t (__stdcall *XInputGetStateEx_t)(uint32_t, XINPUT_STATE*); static XInputGetStateEx_t g_XInputGetStateEx; typedef uint32_t (__stdcall *XInputSetState_t)(uint32_t, XINPUT_VIBRATION*); static XInputSetState_t g_XInputSetState; -// Guide button may or may not be available +/* Guide button may or may not be available */ static bool g_winxinput_guide_button_supported; typedef struct @@ -121,8 +125,9 @@ static inline int pad_index_to_xuser_index(unsigned pad) return g_xinput_pad_indexes[pad]; } -// Generic "XInput" instead of "Xbox 360", because there are -// some other non-xbox third party PC controllers. +/* Generic "XInput" instead of "Xbox 360", because there are + * some other non-xbox third party PC controllers. + */ static const char* const XBOX_CONTROLLER_NAMES[4] = { "XInput Controller (User 1)", @@ -137,26 +142,30 @@ const char* winxinput_joypad_name (unsigned pad) if (xuser < 0) return dinput_joypad.name(pad); - // TODO: Different name if disconnected? + /* TODO: Different name if disconnected? */ return XBOX_CONTROLLER_NAMES[xuser]; } static bool winxinput_joypad_init(void) { unsigned i, autoconf_pad; + XINPUT_STATE dummy_state; + const char *version = "1.4"; + g_winxinput_dll = NULL; - // Find the correct path to load the DLL from. - // Usually this will be from the system directory, - // but occasionally a user may wish to use a third-party - // wrapper DLL (such as x360ce); support these by checking - // the working directory first. + /* Find the correct path to load the DLL from. + * Usually this will be from the system directory, + * but occasionally a user may wish to use a third-party + * wrapper DLL (such as x360ce); support these by checking + * the working directory first. + * + * No need to check for existance as we will be checking LoadLibrary's + * success anyway. + */ - // No need to check for existance as we will be checking LoadLibrary's - // success anyway. - - const char *version = "1.4"; - g_winxinput_dll = LoadLibrary("xinput1_4.dll"); // Using dylib_* complicates building joyconfig. + /* Using dylib_* complicates building joyconfig. */ + g_winxinput_dll = LoadLibrary("xinput1_4.dll"); if (!g_winxinput_dll) { g_winxinput_dll = LoadLibrary("xinput1_3.dll"); @@ -171,22 +180,25 @@ static bool winxinput_joypad_init(void) RARCH_LOG("Found XInput v%s.\n", version); - // If we get here then an xinput DLL is correctly loaded. - // First try to load ordinal 100 (XInputGetStateEx). + /* If we get here then an xinput DLL is correctly loaded. + * First try to load ordinal 100 (XInputGetStateEx). + */ g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, (const char*)100); g_winxinput_guide_button_supported = true; if (!g_XInputGetStateEx) { - // no ordinal 100. (Presumably a wrapper.) Load the ordinary - // XInputGetState, at the cost of losing guide button support. + /* no ordinal 100. (Presumably a wrapper.) Load the ordinary + * XInputGetState, at the cost of losing guide button support. + */ g_winxinput_guide_button_supported = false; g_XInputGetStateEx = (XInputGetStateEx_t) GetProcAddress(g_winxinput_dll, "XInputGetState"); + if (!g_XInputGetStateEx) { RARCH_ERR("Failed to init XInput: DLL is invalid or corrupt.\n"); FreeLibrary(g_winxinput_dll); - return false; // DLL was loaded but did not contain the correct function. + return false; /* DLL was loaded but did not contain the correct function. */ } RARCH_WARN("XInput: No guide button support.\n"); } @@ -196,15 +208,14 @@ static bool winxinput_joypad_init(void) { RARCH_ERR("Failed to init XInput: DLL is invalid or corrupt.\n"); FreeLibrary(g_winxinput_dll); - return false; // DLL was loaded but did not contain the correct function. + return false; /* DLL was loaded but did not contain the correct function. */ } - // Zero out the states + /* Zero out the states. */ for (i = 0; i < 4; ++i) memset(&g_winxinput_states[i], 0, sizeof(winxinput_joypad_state)); - // Do a dummy poll to check which controllers are connected. - XINPUT_STATE dummy_state; + /* Do a dummy poll to check which controllers are connected. */ for (i = 0; i < 4; ++i) { g_winxinput_states[i].connected = !(g_XInputGetStateEx(i, &dummy_state) == ERROR_DEVICE_NOT_CONNECTED); @@ -220,8 +231,8 @@ static bool winxinput_joypad_init(void) g_xinput_block_pads = true; - // We're going to have to be buddies with dinput if we want to be able - // to use XI and non-XI controllers together. + /* We're going to have to be buddies with dinput if we want to be able + * to use XInput and non-XInput controllers together. */ if (!dinput_joypad.init()) { g_xinput_block_pads = false; @@ -262,6 +273,7 @@ static void winxinput_joypad_destroy(void) memset(&g_winxinput_states[i], 0, sizeof(winxinput_joypad_state)); FreeLibrary(g_winxinput_dll); + g_winxinput_dll = NULL; g_XInputGetStateEx = NULL; g_XInputSetState = NULL; @@ -270,9 +282,9 @@ static void winxinput_joypad_destroy(void) g_xinput_block_pads = false; } -// Buttons are provided by XInput as bits of a uint16. -// Map from rarch button index (0..10) to a mask to bitwise-& the buttons against. -// dpad is handled seperately. +/* Buttons are provided by XInput as bits of a uint16. + * Map from rarch button index (0..10) to a mask to bitwise-& the buttons against. + * dpad is handled seperately. */ static const uint16_t button_index_to_bitmap_code[] = { XINPUT_GAMEPAD_A, XINPUT_GAMEPAD_B, @@ -289,17 +301,20 @@ static const uint16_t button_index_to_bitmap_code[] = { static bool winxinput_joypad_button (unsigned port_num, uint16_t joykey) { + uint16_t btn_word; + int xuser; + if (joykey == NO_BTN) return false; - int xuser = pad_index_to_xuser_index(port_num); + xuser = pad_index_to_xuser_index(port_num); if (xuser == -1) return dinput_joypad.button(port_num, joykey); if (!(g_winxinput_states[xuser].connected)) return false; - uint16_t btn_word = g_winxinput_states[xuser].xstate.Gamepad.wButtons; + btn_word = g_winxinput_states[xuser].xstate.Gamepad.wButtons; if (GET_HAT_DIR(joykey)) { @@ -329,10 +344,17 @@ static bool winxinput_joypad_button (unsigned port_num, uint16_t joykey) static int16_t winxinput_joypad_axis (unsigned port_num, uint32_t joyaxis) { + int xuser; + int16_t val = 0; + int axis = -1; + + bool is_neg = false; + bool is_pos = false; + if (joyaxis == AXIS_NONE) return 0; - int xuser = pad_index_to_xuser_index(port_num); + xuser = pad_index_to_xuser_index(port_num); if (xuser == -1) return dinput_joypad.axis(port_num, joyaxis); @@ -340,12 +362,6 @@ static int16_t winxinput_joypad_axis (unsigned port_num, uint32_t joyaxis) if (!(g_winxinput_states[xuser].connected)) return 0; - int16_t val = 0; - int axis = -1; - - bool is_neg = false; - bool is_pos = false; - /* triggers (axes 4,5) cannot be negative */ if (AXIS_NEG_GET(joyaxis) <= 3) { @@ -397,6 +413,7 @@ static int16_t winxinput_joypad_axis (unsigned port_num, uint32_t joyaxis) static void winxinput_joypad_poll(void) { unsigned i; + for (i = 0; i < 4; ++i) { if (g_winxinput_states[i].connected) @@ -404,9 +421,7 @@ static void winxinput_joypad_poll(void) if (g_XInputGetStateEx(i, &(g_winxinput_states[i].xstate)) == ERROR_DEVICE_NOT_CONNECTED) - { g_winxinput_states[i].connected = false; - } } } @@ -417,6 +432,7 @@ static bool winxinput_joypad_rumble(unsigned pad, enum retro_rumble_effect effect, uint16_t strength) { int xuser = pad_index_to_xuser_index(pad); + if (xuser == -1) { if (dinput_joypad.set_rumble)