From c130d15677ac6d2d2f225ac1f318fb42fc7a1d6f Mon Sep 17 00:00:00 2001 From: marschap Date: Sun, 9 Apr 2006 11:05:52 +0000 Subject: [PATCH] update joystick driver to API 0.5 and do some cleanup --- LCDd.conf | 13 +- docs/lcdproc-user/drivers/joy.docbook | 55 +++++-- server/drivers/joy.c | 204 +++++++++++++++----------- server/drivers/joy.h | 2 +- 4 files changed, 170 insertions(+), 104 deletions(-) diff --git a/LCDd.conf b/LCDd.conf index 0b66fcb..b22994e 100644 --- a/LCDd.conf +++ b/LCDd.conf @@ -452,11 +452,15 @@ Size=16x2 # Select the input device to use [default: /dev/js0] Device=/dev/js0 -# Modify the axis mapa [default: EFGHIJKLMNOPQRST] -#AxisMap=EFGHIJKLMNOPQRST +# set the axis map +Map_Axis1- = Left +Map_Axis1+ = Right +Map_Axis2- = Up +Map_Axis2+ = Down -# Modify the button map [default: BDACEFGHIJKLMNOP] -#ButtonMap=BDACEFGHIJKLMNOP +# set the button map +Map_Button1 = Enter +Map_Button2 = Escape @@ -486,7 +490,6 @@ Device=/dev/ttyS1 # Keyname Function # Normal context Menu context # ------- -------------- ------------ -# # PauseKey Pause/Continue Enter/select # BackKey Back(Go to previous screen) Up/Left # ForwardKey Forward(Go to next screen) Down/Right diff --git a/docs/lcdproc-user/drivers/joy.docbook b/docs/lcdproc-user/drivers/joy.docbook index 8136811..219a9e0 100644 --- a/docs/lcdproc-user/drivers/joy.docbook +++ b/docs/lcdproc-user/drivers/joy.docbook @@ -25,22 +25,57 @@ This section covers the joystick input driver for LCDd. - AxisMap= - MAP-LIST + Map_AxisNUM-= + KEY - - Modify the axis mapa [default: EFGHIJKLMNOPQRST] - + + Map_AxisNUM+= + KEY + + + + Set the axis map. + + + + NUM is an integer starting with 1 + that represents each axis with the appendices + and + - determining the direction. + The exact numbering of the axes depends on the hardware used. + + + + KEY can be one of the keys that LCDd recognizes + (Left, Right, Up, + Down, Enter or Escape) + or any other string that a client can parse. + + - ButtonMap= - MAP-LIST + Map_ButtonNUM= + KEY - - Modify the button map [default: BDACEFGHIJKLMNOP] - + + + Set the button map. + + + + NUM is an integer starting with 1 + that represents each button. The exact numbering of the buttons depends on the + hardware used. + + + + KEY can be one of the keys that LCDd recognizes + (Left, Right, Up, + Down, Enter or Escape) + or any other string that a client can parse. + + diff --git a/server/drivers/joy.c b/server/drivers/joy.c index 3471ff9..b91a44b 100644 --- a/server/drivers/joy.c +++ b/server/drivers/joy.c @@ -43,21 +43,21 @@ #define JOY_DEFAULT_AXISMAP "EFGHIJKLMNOPQRST" #define JOY_DEFAULT_BUTTONMAP "BDACEFGHIJKLMNOP" -int fd = -1; -struct js_event js; -char axes = 2; -char buttons = 2; -int jsversion = 0x000801; -char jsname[JOY_NAMELENGTH] = "Unknown"; +typedef struct driver_private_data { + char device[256]; + int fd; -int *axis = NULL; -int *button = NULL; + char axes; + char buttons; + int jsversion; + char jsname[JOY_NAMELENGTH]; + + char **axismap; + char **buttonmap; +} PrivateData; -// Configured for a Gravis Gamepad (2 axis, 4 button) -char axismap[JOY_MAPSIZE+1] = JOY_DEFAULT_AXISMAP; -char buttonmap[JOY_MAPSIZE+1] = JOY_DEFAULT_BUTTONMAP; // Vars for the server core MODULE_EXPORT char *api_version = API_VERSION; @@ -72,54 +72,92 @@ MODULE_EXPORT char *symbol_prefix = "joy_"; MODULE_EXPORT int joy_init (Driver *drvthis) { - char device[256]; + PrivateData *p; + int i; - /* Read config file */ + /* Allocate and store private data */ + p = (PrivateData *) calloc(1, sizeof(PrivateData)); + if (p == NULL) + return -1; + if (drvthis->store_private_ptr(drvthis, p)) + return -1; + + /* initialize private data */ + p->fd = -1; + p->axes = 2; + p->buttons = 2; + p->jsversion = 0; + strcpy(p->jsname, "Unknown"); + p->axismap = NULL; + p->buttonmap = NULL; + + + /* Read config file (1st part) */ /* What device should be used */ - strncpy(device, drvthis->config_get_string(drvthis->name, "Device", 0, - JOY_DEFAULT_DEVICE), sizeof(device)); - device[sizeof(device)-1] = '\0'; - report(RPT_INFO, "%s: using Device %s", drvthis->name, device); + strncpy(p->device, drvthis->config_get_string(drvthis->name, "Device", 0, + JOY_DEFAULT_DEVICE), sizeof(p->device)); + p->device[sizeof(p->device)-1] = '\0'; + report(RPT_INFO, "%s: using Device %s", drvthis->name, p->device); - /* How does the axis map look like */ - strncpy(axismap, drvthis->config_get_string(drvthis->name, "AxisMap", 0, - JOY_DEFAULT_AXISMAP), sizeof(axismap)); - axismap[sizeof(axismap)-1] = '\0'; - - /* How does the button map look like */ - strncpy(buttonmap, drvthis->config_get_string(drvthis->name, "ButtonMap", 0, - JOY_DEFAULT_BUTTONMAP), sizeof(buttonmap)); - buttonmap[sizeof(buttonmap)-1] = '\0'; - - /* End of config file parsing */ + /* End of config file parsing (1st part) */ - if ((fd = open(device, O_RDONLY)) < 0) { + if ((p->fd = open(p->device, O_RDONLY)) < 0) { report(RPT_ERR, "%s: open(%s) failed (%s)", - drvthis->name, device, strerror(errno)); + drvthis->name, p->device, strerror(errno)); return -1; } - fcntl(fd, F_SETFL, O_NONBLOCK); - ioctl(fd, JSIOCGVERSION, &jsversion); - ioctl(fd, JSIOCGAXES, &axes); - ioctl(fd, JSIOCGBUTTONS, &buttons); - ioctl(fd, JSIOCGNAME(JOY_NAMELENGTH), jsname); + /* init joystick, get values for buttons, exes, name, ... */ + fcntl(p->fd, F_SETFL, O_NONBLOCK); + ioctl(p->fd, JSIOCGVERSION, &p->jsversion); + ioctl(p->fd, JSIOCGAXES, &p->axes); + ioctl(p->fd, JSIOCGBUTTONS, &p->buttons); + ioctl(p->fd, JSIOCGNAME(JOY_NAMELENGTH), p->jsname); report(RPT_NOTICE, "%s: Joystick (%s) has %d axes and %d buttons. Driver version is %d.%d.%d", - drvthis->name, jsname, axes, buttons, - jsversion >> 16, (jsversion >> 8) & 0xff, jsversion & 0xff); + drvthis->name, p->jsname, p->axes, p->buttons, + p->jsversion >> 16, (p->jsversion >> 8) & 0xff, p->jsversion & 0xff); - if ((axis = calloc(axes, sizeof (int))) == NULL) { - report(RPT_ERR, "%s: could not allocate memory for axes", drvthis->name); + if ((p->axismap = calloc(2 * p->axes, sizeof(char *))) == NULL) { + report(RPT_ERR, "%s: cannot allocate memory for axes", drvthis->name); return -1; } - if ((button = calloc(buttons, sizeof (char))) == NULL) { - report(RPT_ERR, "%s: could not allocate memory for buttons", drvthis->name); + if ((p->buttonmap = calloc(p->buttons, sizeof(char *))) == NULL) { + report(RPT_ERR, "%s: cannot allocate memory for buttons", drvthis->name); return -1; } + /* Read config file (2nd part) */ + + for (i = 0; i < p->axes; i++) { + char mapkey[50]; + char *mapval; + + snprintf(mapkey, sizeof(mapkey), "Map_Axis%d-", i+1); + mapval = drvthis->config_get_string(drvthis->name, mapkey, 0, NULL); + if (mapval != NULL) + p->axismap[2*i] = strdup(mapval); + + snprintf(mapkey, sizeof(mapkey), "Map_Axis%d+", i+1); + mapval = drvthis->config_get_string(drvthis->name, mapkey, 0, NULL); + if (mapval != NULL) + p->axismap[2*i + 1] = strdup(mapval); + } + + for (i = 0; i < p->buttons; i++) { + char mapkey[50]; + char *mapval; + + snprintf(mapkey, sizeof(mapkey), "Map_Button%d", i+1); + mapval = drvthis->config_get_string(drvthis->name, mapkey, 0, NULL); + if (mapval != NULL) + p->buttonmap[i] = strdup(mapval); + } + + /* End of config file parsing (2nd part) */ + report(RPT_DEBUG, "%s: init() done", drvthis->name); return 0; @@ -128,69 +166,59 @@ joy_init (Driver *drvthis) MODULE_EXPORT void joy_close (Driver *drvthis) { - if (fd >= 0) - close(fd); + PrivateData *p = drvthis->private_data; + + if (p != NULL) { + if (p->fd >= 0) + close(p->fd); - // Why do I have so much trouble getting memory freed without segfaults?? - // Use gdb and find out :) In preliminary testing, this seemed to work... - - if (axis != NULL) - free(axis); - if (button != NULL) - free(button); + if (p->axismap != NULL) + free(p->axismap); + if (p->buttonmap != NULL) + free(p->buttonmap); + free(p); + } + drvthis->store_private_ptr(drvthis, NULL); } ////////////////////////////////////////////////////////////////////// // Tries to read a character from an input device... // -// Return 0 for "nothing available". +// Return NULL0 for "nothing available". // -MODULE_EXPORT char -joy_getkey (Driver *drvthis) +MODULE_EXPORT const char * +joy_get_key (Driver *drvthis) { - int i; + PrivateData *p = drvthis->private_data; + struct js_event js; int err; - if ((err = read(fd, &js, sizeof(struct js_event))) <= 0) { - return 0; - } else - if (err != sizeof(struct js_event)) { - report(RPT_ERR, "%s: error reading joystick input", drvthis->name); - return 0; - } + if ((err = read(p->fd, &js, sizeof(struct js_event))) <= 0) { + return NULL; + } + if (err != sizeof(struct js_event)) { + report(RPT_ERR, "%s: error reading joystick input", drvthis->name); + return NULL; + } -// if (js.type & JS_EVENT_INIT) return 0; + //if (js.type & JS_EVENT_INIT) + // return NULL; switch (js.type & ~JS_EVENT_INIT) { case JS_EVENT_BUTTON: - button[js.number] = js.value; - break; + /* ignore button release */ + if ((js.value == 0) || (js.number >= p->buttons)) + return NULL; + return p->buttonmap[js.number]; case JS_EVENT_AXIS: - axis[js.number] = js.value; - break; + /* ignore noise */ + if ((js.value > -20000) || (js.value < 20000) + || (js.number >= 2 * p->axes)) + return NULL; + return p->axismap[js.number]; + default: + return NULL; } - - if (buttons) { - //printf("Buttons: "); - for (i = 0; i < buttons; i++) - //printf("%2d:%s ", i, button[i] ? "on " : "off"); - if (button[i]) - return buttonmap[i]; - } - - if (axes) { - //printf("Axes: "); - for (i = 0; i < axes; i++) { - //printf("%2d:%6d ", i, axis[i]); - // Eliminate noise... - if (axis[i] > 20000) - return axismap[(2 * i) + 1]; - if (axis[i] < -20000) - return axismap[(2 * i)]; - } - } - - return 0; } diff --git a/server/drivers/joy.h b/server/drivers/joy.h index 8a68944..e964ea0 100644 --- a/server/drivers/joy.h +++ b/server/drivers/joy.h @@ -6,6 +6,6 @@ MODULE_EXPORT int joy_init (Driver *drvthis); MODULE_EXPORT void joy_close (Driver *drvthis); -MODULE_EXPORT char joy_getkey (Driver *drvthis); +MODULE_EXPORT const char *joy_get_key (Driver *drvthis); #endif