1 /* Title: USB Joystick library
3 Written by Puck2099 (puck2099@gmail.com), (c) 2006.
4 <http://www.gp32wip.com>
6 If you use this library or a part of it, please, let it know.
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24 #include <stdio.h> /* For the definition of NULL */
25 #include <sys/types.h> // For Device open
27 #include <sys/ioctl.h>
29 #include <unistd.h> // For Device read
32 #include <limits.h> /* For the definition of PATH_MAX */
33 #include <linux/joystick.h>
37 /* This is a try to support analog joys. Untested. */
38 #define DEAD_ZONE (8*1024)
43 Opens a USB joystick and fills its information.
47 joynumber - Joystick's identifier (0 reserved for GP2X's builtin Joystick).
51 Filled usbjoy structure.
54 struct usbjoy *joy_open(int joynumber)
58 struct usbjoy * joy = NULL;
59 struct js_event event;
60 static char insmod_done = 0;
62 // notaz: on my system I get unresolved input_* symbols, so have to 'insmod input' too
63 // also we should insmod only once, not on every joy_open() call.
65 system ("insmod input");
66 system ("insmod joydev"); // Loads joydev module
72 else if (joynumber > 0) {
73 sprintf (path, "/dev/input/js%d", joynumber-1);
74 fd = open(path, O_RDONLY, 0);
76 joy = (struct usbjoy *) malloc(sizeof(*joy));
77 if (joy == NULL) { close(fd); return NULL; }
78 memset(joy, 0, sizeof(*joy));
80 // Set the joystick to non-blocking read mode
81 fcntl(fd, F_SETFL, O_NONBLOCK);
83 // notaz: maybe we should flush init events now.
84 // My pad returns axis as active when I plug it in, which is kind of annoying.
85 while (read(fd, &event, sizeof(event)) > 0);
87 // Joystick's file descriptor
91 ioctl(joy->fd, JSIOCGNAME(128*sizeof(char)), joy->name);
94 strcpy(joy->device, path);
97 ioctl(joy->fd, JSIOCGBUTTONS, &joy->numbuttons);
100 ioctl(joy->fd, JSIOCGAXES, &joy->numaxes);
102 // Joystick's type (derived from name)
103 if (strncasecmp(joy->name, "logitech", strlen("logitech")) == 0)
104 joy->type = JOY_TYPE_LOGITECH;
105 else joy->type = JOY_TYPE_GENERIC;
107 // printf ("ERROR: No Joystick found\n");
116 Returns Joystick's name.
120 joy - Selected joystick.
124 Joystick's name or NULL if <usbjoy> struct is empty.
126 char * joy_name (struct usbjoy * joy) {
127 if (joy != NULL) return joy->name;
135 Returns Joystick's device.
139 joy - Selected joystick.
143 Joystick's device or NULL if <usbjoy> struct is empty.
145 char * joy_device (struct usbjoy * joy) {
146 if (joy != NULL) return joy->device;
152 Function: joy_buttons
154 Returns Joystick's buttons number.
158 joy - Selected joystick.
162 Joystick's buttons or 0 if <usbjoy> struct is empty.
164 int joy_buttons (struct usbjoy * joy) {
165 if (joy != NULL) return joy->numbuttons;
173 Returns Joystick's axes number.
177 joy - Selected joystick.
181 Joystick's axes or 0 if <usbjoy> struct is empty.
183 int joy_axes (struct usbjoy * joy) {
184 if (joy != NULL) return joy->numaxes;
192 Updates Joystick's internal information (<statebuttons> and <stateaxes> fields).
196 joy - Selected joystick.
200 0 - No events registered (no need to update).
201 1 - Events registered (a button or axe has been pushed).
202 -1 - Error: <usbjoy> struct is empty.
204 int joy_update (struct usbjoy * joy) {
205 struct js_event events[0xff];
209 if ((len=read(joy->fd, events, (sizeof events))) >0) {
210 len /= sizeof(events[0]);
211 for ( i=0; i<len; ++i ) {
212 switch (events[i].type & ~JS_EVENT_INIT) {
214 if (events[i].number == 0) {
215 joy->stateaxes[JOYLEFT] = joy->stateaxes[JOYRIGHT] = 0;
216 if (events[i].value < -DEAD_ZONE) joy->stateaxes[JOYLEFT] = 1;
217 else if (events[i].value > DEAD_ZONE) joy->stateaxes[JOYRIGHT] = 1;
218 joy->axevals[0] = events[i].value;
220 else if (events[i].number == 1) {
221 joy->stateaxes[JOYUP] = joy->stateaxes[JOYDOWN] = 0;
222 if (events[i].value < -DEAD_ZONE) joy->stateaxes[JOYUP] = 1;
223 else if (events[i].value > DEAD_ZONE) joy->stateaxes[JOYDOWN] = 1;
224 joy->axevals[1] = events[i].value;
228 case JS_EVENT_BUTTON:
229 joy->statebuttons[events[i].number] = events[i].value;
246 Function: joy_getbutton
248 Returns Joystick's button information.
252 button - Button which value you want to know (from 0 to 31).
253 joy - Selected joystick.
257 0 - Button NOT pushed.
259 -1 - Error: <usbjoy> struct is empty.
261 int joy_getbutton (int button, struct usbjoy * joy) {
263 if (button < joy_buttons(joy)) return joy->statebuttons[button];
273 Returns Joystick's axes information.
277 axe - Axe which value you want to know (see <Axes values>).
278 joy - Selected joystick.
282 0 - Direction NOT pushed.
283 1 - Direction pushed.
284 -1 - Error: <usbjoy> struct is empty.
286 int joy_getaxe (int axe, struct usbjoy * joy) {
288 if (axe < 4) return joy->stateaxes[axe];
298 Closes selected joystick's file descriptor and detroys it's fields.
302 joy - Selected joystick.
306 0 - Joystick successfully closed.
307 -1 - Error: <usbjoy> struct is empty.
309 int joy_close (struct usbjoy * joy) {
319 /*********************************************************************/
320 /* GP2X USB Joystick Handling -GnoStiC */
321 /*********************************************************************/
326 struct usbjoy *joys[4];
328 void gp2x_usbjoy_init (void) {
329 /* Open available joysticks -GnoStiC */
333 for (i = 0; i < 4; i++) {
334 joys[n] = joy_open(i+1);
335 if (joys[n] && joy_buttons(joys[n]) > 0) {
336 printf ("+-Joystick %d: \"%s\", buttons = %i\n", i+1, joy_name(joys[n]), joy_buttons(joys[n]));
342 printf("Found %d Joystick(s)\n",num_of_joys);
345 void gp2x_usbjoy_update (void) {
346 /* Update Joystick Event Cache */
348 for (q=0; q < num_of_joys; q++) {
349 foo = joy_update (joys[q]);
353 int gp2x_usbjoy_check (int joyno) {
356 struct usbjoy *joy = joys[joyno];
359 if (joy_getaxe(JOYUP, joy)) { joyExKey |= GP2X_UP; }
360 if (joy_getaxe(JOYDOWN, joy)) { joyExKey |= GP2X_DOWN; }
361 if (joy_getaxe(JOYLEFT, joy)) { joyExKey |= GP2X_LEFT; }
362 if (joy_getaxe(JOYRIGHT, joy)) { joyExKey |= GP2X_RIGHT; }
364 /* loop through joy buttons to check if they are pushed */
365 for (q=0; q<joy_buttons (joy); q++) {
366 if (joy_getbutton (q, joy)) {
367 if (joy->type == JOY_TYPE_LOGITECH) {
369 case 0: joyExKey |= GP2X_A; break;
370 case 1: joyExKey |= GP2X_X; break;
371 case 2: joyExKey |= GP2X_B; break;
372 case 3: joyExKey |= GP2X_Y; break;
376 case 0: joyExKey |= GP2X_Y; break;
377 case 1: joyExKey |= GP2X_B; break;
378 case 2: joyExKey |= GP2X_X; break;
379 case 3: joyExKey |= GP2X_A; break;
384 case 4: joyExKey |= GP2X_L; break;
385 case 5: joyExKey |= GP2X_R; break;
386 case 6: joyExKey |= GP2X_L; break; /* left shoulder button 2 */
387 case 7: joyExKey |= GP2X_R; break; /* right shoulder button 2 */
388 case 8: joyExKey |= GP2X_SELECT;break;
389 case 9: joyExKey |= GP2X_START; break;
390 case 10: joyExKey |= GP2X_PUSH; break;
391 case 11: joyExKey |= GP2X_PUSH; break;
399 int gp2x_usbjoy_check2 (int joyno) {
400 /* Check Joystick, don't map to gp2x joy */
401 int q, to, joyExKey = 0;
402 struct usbjoy *joy = joys[joyno];
405 if (joy_getaxe(JOYUP, joy)) { joyExKey |= 1 << 0; }
406 if (joy_getaxe(JOYDOWN, joy)) { joyExKey |= 1 << 1; }
407 if (joy_getaxe(JOYLEFT, joy)) { joyExKey |= 1 << 2; }
408 if (joy_getaxe(JOYRIGHT, joy)) { joyExKey |= 1 << 3; }
410 /* loop through joy buttons to check if they are pushed */
411 to = joy->numbuttons;
412 if (to > 32-4) to = 32-4;
413 for (q=0; q < to; q++)
414 if (joy->statebuttons[q]) joyExKey |= 1 << (q+4);
421 void gp2x_usbjoy_deinit (void) {
423 for (i=0; i<num_of_joys; i++) {