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>
41 Opens a USB joystick and fills its information.
45 joynumber - Joystick's identifier (0 reserved for GP2X's builtin Joystick).
49 Filled usbjoy structure.
52 struct usbjoy *joy_open(int joynumber)
56 struct usbjoy * joy = NULL;
57 struct js_event event;
58 static char insmod_done = 0;
60 // notaz: on my system I get unresolved input_* symbols, so have to 'insmod input' too
61 // also we should insmod only once, not on every joy_open() call.
63 system ("insmod input");
64 system ("insmod joydev"); // Loads joydev module
70 else if (joynumber > 0) {
71 sprintf (path, "/dev/input/js%d", joynumber-1);
72 fd = open(path, O_RDONLY, 0);
74 joy = (struct usbjoy *) malloc(sizeof(*joy));
75 if (joy == NULL) { close(fd); return NULL; }
76 memset(joy, 0, sizeof(*joy));
78 // Set the joystick to non-blocking read mode
79 fcntl(fd, F_SETFL, O_NONBLOCK);
81 // notaz: maybe we should flush init events now.
82 // My pad returns axis as active when I plug it in, which is kind of annoying.
83 while (read(fd, &event, sizeof(event)) > 0);
85 // Joystick's file descriptor
89 ioctl(joy->fd, JSIOCGNAME(128*sizeof(char)), joy->name);
92 strcpy(joy->device, path);
95 ioctl(joy->fd, JSIOCGBUTTONS, &joy->numbuttons);
98 ioctl(joy->fd, JSIOCGAXES, &joy->numaxes);
100 // Joystick's type (derived from name)
101 if (strncasecmp(joy->name, "logitech", strlen("logitech")) == 0)
102 joy->type = JOY_TYPE_LOGITECH;
103 else joy->type = JOY_TYPE_GENERIC;
105 // printf ("ERROR: No Joystick found\n");
114 Returns Joystick's name.
118 joy - Selected joystick.
122 Joystick's name or NULL if <usbjoy> struct is empty.
124 char * joy_name (struct usbjoy * joy) {
125 if (joy != NULL) return joy->name;
133 Returns Joystick's device.
137 joy - Selected joystick.
141 Joystick's device or NULL if <usbjoy> struct is empty.
143 char * joy_device (struct usbjoy * joy) {
144 if (joy != NULL) return joy->device;
150 Function: joy_buttons
152 Returns Joystick's buttons number.
156 joy - Selected joystick.
160 Joystick's buttons or 0 if <usbjoy> struct is empty.
162 int joy_buttons (struct usbjoy * joy) {
163 if (joy != NULL) return joy->numbuttons;
171 Returns Joystick's axes number.
175 joy - Selected joystick.
179 Joystick's axes or 0 if <usbjoy> struct is empty.
181 int joy_axes (struct usbjoy * joy) {
182 if (joy != NULL) return joy->numaxes;
190 Updates Joystick's internal information (<statebuttons> and <stateaxes> fields).
194 joy - Selected joystick.
198 0 - No events registered (no need to update).
199 1 - Events registered (a button or axe has been pushed).
200 -1 - Error: <usbjoy> struct is empty.
202 int joy_update (struct usbjoy * joy) {
203 struct js_event events[0xff];
207 if ((len=read(joy->fd, events, (sizeof events))) >0) {
208 len /= sizeof(events[0]);
209 for ( i=0; i<len; ++i ) {
210 switch (events[i].type & ~JS_EVENT_INIT) {
212 if (events[i].number == 0) {
213 if (events[i].value == 0) joy->stateaxes[JOYLEFT] = joy->stateaxes[JOYRIGHT] = 0;
214 else if (events[i].value < 0) joy->stateaxes[JOYLEFT] = 1;
215 else joy->stateaxes[JOYRIGHT] = 1;
217 else if (events[i].number == 1) {
218 if (events[i].value == 0) joy->stateaxes[JOYUP] = joy->stateaxes[JOYDOWN] = 0;
219 else if (events[i].value < 0) joy->stateaxes[JOYUP] = 1;
220 else joy->stateaxes[JOYDOWN] = 1;
224 case JS_EVENT_BUTTON:
225 joy->statebuttons[events[i].number] = events[i].value;
242 Function: joy_getbutton
244 Returns Joystick's button information.
248 button - Button which value you want to know (from 0 to 31).
249 joy - Selected joystick.
253 0 - Button NOT pushed.
255 -1 - Error: <usbjoy> struct is empty.
257 int joy_getbutton (int button, struct usbjoy * joy) {
259 if (button < joy_buttons(joy)) return joy->statebuttons[button];
269 Returns Joystick's axes information.
273 axe - Axe which value you want to know (see <Axes values>).
274 joy - Selected joystick.
278 0 - Direction NOT pushed.
279 1 - Direction pushed.
280 -1 - Error: <usbjoy> struct is empty.
282 int joy_getaxe (int axe, struct usbjoy * joy) {
284 if (axe < 4) return joy->stateaxes[axe];
294 Closes selected joystick's file descriptor and detroys it's fields.
298 joy - Selected joystick.
302 0 - Joystick successfully closed.
303 -1 - Error: <usbjoy> struct is empty.
305 int joy_close (struct usbjoy * joy) {
315 /*********************************************************************/
316 /* GP2X USB Joystick Handling -GnoStiC */
317 /*********************************************************************/
322 struct usbjoy *joys[4];
324 void gp2x_usbjoy_init (void) {
325 /* Open available joysticks -GnoStiC */
329 for (i = 0; i < 4; i++) {
330 joys[n] = joy_open(i+1);
331 if (joys[n] && joy_buttons(joys[n]) > 0) {
332 printf ("+-Joystick %d: \"%s\", buttons = %i\n", i+1, joy_name(joys[n]), joy_buttons(joys[n]));
338 printf("Found %d Joystick(s)\n",num_of_joys);
341 void gp2x_usbjoy_update (void) {
342 /* Update Joystick Event Cache */
344 for (q=0; q < num_of_joys; q++) {
345 foo = joy_update (joys[q]);
349 int gp2x_usbjoy_check (int joyno) {
352 struct usbjoy *joy = joys[joyno];
355 if (joy_getaxe(JOYUP, joy)) { joyExKey |= GP2X_UP; }
356 if (joy_getaxe(JOYDOWN, joy)) { joyExKey |= GP2X_DOWN; }
357 if (joy_getaxe(JOYLEFT, joy)) { joyExKey |= GP2X_LEFT; }
358 if (joy_getaxe(JOYRIGHT, joy)) { joyExKey |= GP2X_RIGHT; }
360 /* loop through joy buttons to check if they are pushed */
361 for (q=0; q<joy_buttons (joy); q++) {
362 if (joy_getbutton (q, joy)) {
363 if (joy->type == JOY_TYPE_LOGITECH) {
365 case 0: joyExKey |= GP2X_A; break;
366 case 1: joyExKey |= GP2X_X; break;
367 case 2: joyExKey |= GP2X_B; break;
368 case 3: joyExKey |= GP2X_Y; break;
372 case 0: joyExKey |= GP2X_Y; break;
373 case 1: joyExKey |= GP2X_B; break;
374 case 2: joyExKey |= GP2X_X; break;
375 case 3: joyExKey |= GP2X_A; break;
380 case 4: joyExKey |= GP2X_L; break;
381 case 5: joyExKey |= GP2X_R; break;
382 case 6: joyExKey |= GP2X_L; break; /* left shoulder button 2 */
383 case 7: joyExKey |= GP2X_R; break; /* right shoulder button 2 */
384 case 8: joyExKey |= GP2X_SELECT;break;
385 case 9: joyExKey |= GP2X_START; break;
386 case 10: joyExKey |= GP2X_PUSH; break;
387 case 11: joyExKey |= GP2X_PUSH; break;
395 int gp2x_usbjoy_check2 (int joyno) {
396 /* Check Joystick, don't map to gp2x joy */
397 int q, to, joyExKey = 0;
398 struct usbjoy *joy = joys[joyno];
401 if (joy_getaxe(JOYUP, joy)) { joyExKey |= 1 << 0; }
402 if (joy_getaxe(JOYDOWN, joy)) { joyExKey |= 1 << 1; }
403 if (joy_getaxe(JOYLEFT, joy)) { joyExKey |= 1 << 2; }
404 if (joy_getaxe(JOYRIGHT, joy)) { joyExKey |= 1 << 3; }
406 /* loop through joy buttons to check if they are pushed */
407 to = joy->numbuttons;
408 if (to > 32-4) to = 32-4;
409 for (q=0; q < to; q++)
410 if (joy->statebuttons[q]) joyExKey |= 1 << (q+4);
417 void gp2x_usbjoy_deinit (void) {
419 for (i=0; i<num_of_joys; i++) {