📄 sdl_sysjoystick.c
字号:
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2006 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Sam Lantinga slouken@libsdl.org*/#include "SDL_config.h"#ifdef SDL_JOYSTICK_LINUX/* This is the system specific header for the SDL joystick API */#include <sys/stat.h>#include <unistd.h>#include <fcntl.h>#include <sys/ioctl.h>#include <limits.h> /* For the definition of PATH_MAX */#include <linux/joystick.h>#if SDL_INPUT_LINUXEV#include <linux/input.h>#endif#include "SDL_joystick.h"#include "../SDL_sysjoystick.h"#include "../SDL_joystick_c.h"/* Special joystick configurations */static struct { const char *name; int naxes; int nhats; int nballs;} special_joysticks[] = { { "MadCatz Panther XL", 3, 2, 1 }, /* We don't handle rudder (axis 8) */ { "SideWinder Precision Pro", 4, 1, 0 }, { "SideWinder 3D Pro", 4, 1, 0 }, { "Microsoft SideWinder 3D Pro", 4, 1, 0 }, { "Microsoft SideWinder Precision Pro", 4, 1, 0 }, { "Microsoft SideWinder Dual Strike USB version 1.0", 2, 1, 0 }, { "WingMan Interceptor", 3, 3, 0 }, { "WingMan Extreme Digital 3D", 4, 1, 0 }, { "Microsoft SideWinder Precision 2 Joystick", 4, 1, 0 }, { "Logitech Inc. WingMan Extreme Digital 3D", 4, 1, 0 }, { "Saitek Saitek X45", 6, 1, 0 }};#ifndef NO_LOGICAL_JOYSTICKS/* Some USB HIDs show up as a single joystick even though they actually control 2 or more joysticks.*//* This code handles the MP-8800 (Quad) and MP-8866 (Dual), which can be identified by their transparent blue design. It's quite trivial to add other joysticks with similar quirky behavior. -id*/struct joystick_logical_mapping { int njoy; int nthing;};/* {logical joy, logical axis}, {logical joy, logical hat}, {logical joy, logical ball}, {logical joy, logical button}*/static struct joystick_logical_mapping mp88xx_1_logical_axismap[] = { {0,0},{0,1},{0,2},{0,3},{0,4},{0,5}};static struct joystick_logical_mapping mp88xx_1_logical_buttonmap[] = { {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}};static struct joystick_logical_mapping mp88xx_2_logical_axismap[] = { {0,0},{0,1},{0,2},{1,0},{1,1},{0,3}, {1,2},{1,3},{0,4},{0,5},{1,4},{1,5}};static struct joystick_logical_mapping mp88xx_2_logical_buttonmap[] = { {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}, {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11}};static struct joystick_logical_mapping mp88xx_3_logical_axismap[] = { {0,0},{0,1},{0,2},{1,0},{1,1},{0,3}, {1,2},{1,3},{2,0},{2,1},{2,2},{2,3}, {0,4},{0,5},{1,4},{1,5},{2,4},{2,5}};static struct joystick_logical_mapping mp88xx_3_logical_buttonmap[] = { {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}, {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11}, {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11}};static struct joystick_logical_mapping mp88xx_4_logical_axismap[] = { {0,0},{0,1},{0,2},{1,0},{1,1},{0,3}, {1,2},{1,3},{2,0},{2,1},{2,2},{2,3}, {3,0},{3,1},{3,2},{3,3},{0,4},{0,5}, {1,4},{1,5},{2,4},{2,5},{3,4},{3,5}};static struct joystick_logical_mapping mp88xx_4_logical_buttonmap[] = { {0,0},{0,1},{0,2},{0,3},{0,4},{0,5},{0,6},{0,7},{0,8},{0,9},{0,10},{0,11}, {1,0},{1,1},{1,2},{1,3},{1,4},{1,5},{1,6},{1,7},{1,8},{1,9},{1,10},{1,11}, {2,0},{2,1},{2,2},{2,3},{2,4},{2,5},{2,6},{2,7},{2,8},{2,9},{2,10},{2,11}, {3,0},{3,1},{3,2},{3,3},{3,4},{3,5},{3,6},{3,7},{3,8},{3,9},{3,10},{3,11}};struct joystick_logical_layout { int naxes; int nhats; int nballs; int nbuttons;};static struct joystick_logical_layout mp88xx_1_logical_layout[] = { {6, 0, 0, 12}};static struct joystick_logical_layout mp88xx_2_logical_layout[] = { {6, 0, 0, 12}, {6, 0, 0, 12}};static struct joystick_logical_layout mp88xx_3_logical_layout[] = { {6, 0, 0, 12}, {6, 0, 0, 12}, {6, 0, 0, 12}};static struct joystick_logical_layout mp88xx_4_logical_layout[] = { {6, 0, 0, 12}, {6, 0, 0, 12}, {6, 0, 0, 12}, {6, 0, 0, 12}};/* This array sets up a means of mapping a single physical joystick to multiple logical joysticks. (djm) njoys the number of logical joysticks layouts an array of layout structures, one to describe each logical joystick axes, hats, balls, buttons arrays that map a physical thingy to a logical thingy */struct joystick_logicalmap { const char *name; int nbuttons; int njoys; struct joystick_logical_layout *layout; struct joystick_logical_mapping *axismap; struct joystick_logical_mapping *hatmap; struct joystick_logical_mapping *ballmap; struct joystick_logical_mapping *buttonmap;};static struct joystick_logicalmap joystick_logicalmap[] = { { "WiseGroup.,Ltd MP-8866 Dual USB Joypad", 12, 1, mp88xx_1_logical_layout, mp88xx_1_logical_axismap, NULL, NULL, mp88xx_1_logical_buttonmap }, { "WiseGroup.,Ltd MP-8866 Dual USB Joypad", 24, 2, mp88xx_2_logical_layout, mp88xx_2_logical_axismap, NULL, NULL, mp88xx_2_logical_buttonmap }, { "WiseGroup.,Ltd MP-8800 Quad USB Joypad", 12, 1, mp88xx_1_logical_layout, mp88xx_1_logical_axismap, NULL, NULL, mp88xx_1_logical_buttonmap }, { "WiseGroup.,Ltd MP-8800 Quad USB Joypad", 24, 2, mp88xx_2_logical_layout, mp88xx_2_logical_axismap, NULL, NULL, mp88xx_2_logical_buttonmap }, { "WiseGroup.,Ltd MP-8800 Quad USB Joypad", 36, 3, mp88xx_3_logical_layout, mp88xx_3_logical_axismap, NULL, NULL, mp88xx_3_logical_buttonmap }, { "WiseGroup.,Ltd MP-8800 Quad USB Joypad", 48, 4, mp88xx_4_logical_layout, mp88xx_4_logical_axismap, NULL, NULL, mp88xx_4_logical_buttonmap }};/* find the head of a linked list, given a point in it */#define SDL_joylist_head(i, start)\ for(i = start; SDL_joylist[i].fname == NULL;) i = SDL_joylist[i].prev;#define SDL_logical_joydecl(d) d#else#define SDL_logical_joydecl(d)#endif /* USE_LOGICAL_JOYSTICKS *//* The maximum number of joysticks we'll detect */#define MAX_JOYSTICKS 32/* A list of available joysticks */static struct{ char* fname;#ifndef NO_LOGICAL_JOYSTICKS SDL_Joystick* joy; struct joystick_logicalmap* map; int prev; int next; int logicalno;#endif /* USE_LOGICAL_JOYSTICKS */} SDL_joylist[MAX_JOYSTICKS];/* The private structure used to keep track of a joystick */struct joystick_hwdata { int fd; /* The current linux joystick driver maps hats to two axes */ struct hwdata_hat { int axis[2]; } *hats; /* The current linux joystick driver maps balls to two axes */ struct hwdata_ball { int axis[2]; } *balls; /* Support for the Linux 2.4 unified input interface */#if SDL_INPUT_LINUXEV SDL_bool is_hid; Uint8 key_map[KEY_MAX-BTN_MISC]; Uint8 abs_map[ABS_MAX]; struct axis_correct { int used; int coef[3]; } abs_correct[ABS_MAX];#endif};#ifndef NO_LOGICAL_JOYSTICKSstatic int CountLogicalJoysticks(int max){ register int i, j, k, ret, prev; const char* name; int nbuttons, fd; unsigned char n; ret = 0; for(i = 0; i < max; i++) { name = SDL_SYS_JoystickName(i); fd = open(SDL_joylist[i].fname, O_RDONLY, 0); if ( fd >= 0 ) { if ( ioctl(fd, JSIOCGBUTTONS, &n) < 0 ) { nbuttons = -1; } else { nbuttons = n; } close(fd); } else { nbuttons=-1; } if (name) { for(j = 0; j < SDL_arraysize(joystick_logicalmap); j++) { if (!SDL_strcmp(name, joystick_logicalmap[j].name) && (nbuttons==-1 || nbuttons==joystick_logicalmap[j].nbuttons)) { prev = i; SDL_joylist[prev].map = &(joystick_logicalmap[j]); for(k = 1; k < joystick_logicalmap[j].njoys; k++) { SDL_joylist[prev].next = max + ret; SDL_joylist[max+ret].prev = prev; prev = max + ret; SDL_joylist[prev].logicalno = k; SDL_joylist[prev].map = &(joystick_logicalmap[j]); ret++; } break; } } } } return ret;}static void LogicalSuffix(int logicalno, char* namebuf, int len){ register int slen; const static char suffixs[] = "01020304050607080910111213141516171819" "20212223242526272829303132"; const char* suffix; slen = SDL_strlen(namebuf); suffix = NULL; if (logicalno*2<sizeof(suffixs)) suffix = suffixs + (logicalno*2); if (slen + 4 < len && suffix) { namebuf[slen++] = ' '; namebuf[slen++] = '#'; namebuf[slen++] = suffix[0]; namebuf[slen++] = suffix[1]; namebuf[slen++] = 0; }}#endif /* USE_LOGICAL_JOYSTICKS */#if SDL_INPUT_LINUXEV#define test_bit(nr, addr) \ (((1UL << ((nr) & 31)) & (((const unsigned int *) addr)[(nr) >> 5])) != 0)static int EV_IsJoystick(int fd){ unsigned long evbit[40]; unsigned long keybit[40]; unsigned long absbit[40]; if ( (ioctl(fd, EVIOCGBIT(0, sizeof(evbit)), evbit) < 0) || (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(keybit)), keybit) < 0) || (ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(absbit)), absbit) < 0) ) { return(0); } if (!(test_bit(EV_KEY, evbit) && test_bit(EV_ABS, evbit) && test_bit(ABS_X, absbit) && test_bit(ABS_Y, absbit) && (test_bit(BTN_TRIGGER, keybit) || test_bit(BTN_A, keybit) || test_bit(BTN_1, keybit)))) return 0; return(1);}#endif /* SDL_INPUT_LINUXEV *//* Function to scan the system for joysticks */int SDL_SYS_JoystickInit(void){ /* The base path of the joystick devices */ const char *joydev_pattern[] = {#if SDL_INPUT_LINUXEV
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -