Some simplifications in Windows input drivers

This commit is contained in:
twinaphex 2015-01-11 01:29:19 +01:00
parent 89902c3339
commit 10c042f1dc
5 changed files with 238 additions and 160 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -30,8 +30,9 @@
#include <stddef.h>
#include <string.h>
// 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)