usbjoy fix
[fceu.git] / drivers / gp2x / usbjoy.c
1 /* Title: USB Joystick library
2    Version 0.2
3    Written by Puck2099 (puck2099@gmail.com), (c) 2006.
4    <http://www.gp32wip.com>
5
6    If you use this library or a part of it, please, let it know.
7
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.
12
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.
17
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
21 */
22
23 #include <stdlib.h>
24 #include <stdio.h>              /* For the definition of NULL */
25 #include <sys/types.h>          // For Device open
26 #include <sys/stat.h>
27 #include <sys/ioctl.h>
28 #include <fcntl.h>
29 #include <unistd.h>             // For Device read
30
31 #include <string.h>
32 #include <limits.h>             /* For the definition of PATH_MAX */
33 #include <linux/joystick.h>
34
35 #include "usbjoy.h"
36
37 /* This is a try to support analog joys. Untested. */
38 #define DEAD_ZONE (8*1024)
39
40 /*
41   Function: joy_open
42
43   Opens a USB joystick and fills its information.
44
45   Parameters:
46
47   joynumber - Joystick's identifier (0 reserved for GP2X's builtin Joystick).
48
49   Returns:
50
51   Filled usbjoy structure.
52
53 */
54 struct usbjoy *joy_open(int joynumber)
55 {
56         int fd;
57         char path [128];
58         struct usbjoy * joy = NULL;
59         struct js_event event;
60         static char insmod_done = 0;
61
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.
64         if (!insmod_done) {
65                 system ("insmod input");
66                 system ("insmod joydev"); // Loads joydev module
67                 insmod_done = 1;
68         }
69
70         if (joynumber == 0) {
71         }
72         else if (joynumber > 0) {
73                 sprintf (path, "/dev/input/js%d", joynumber-1);
74                 fd = open(path, O_RDONLY, 0);
75                 if (fd > 0) {
76                         joy = (struct usbjoy *) malloc(sizeof(*joy));
77                         if (joy == NULL) { close(fd); return NULL; }
78                         memset(joy, 0, sizeof(*joy));
79
80                         // Set the joystick to non-blocking read mode
81                         fcntl(fd, F_SETFL, O_NONBLOCK);
82
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);
86
87                         // Joystick's file descriptor
88                         joy->fd = fd;
89
90                         // Joystick's name
91                         ioctl(joy->fd, JSIOCGNAME(128*sizeof(char)), joy->name);
92
93                         // Joystick's device
94                         strcpy(joy->device, path);
95
96                         // Joystick's buttons
97                         ioctl(joy->fd, JSIOCGBUTTONS, &joy->numbuttons);
98
99                         // Joystick's axes
100                         ioctl(joy->fd, JSIOCGAXES, &joy->numaxes);
101
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;
106                 } else {
107                         // printf ("ERROR: No Joystick found\n");
108                 }
109         }
110         return joy;
111 }
112
113 /*
114   Function: joy_name
115
116   Returns Joystick's name.
117
118   Parameters:
119
120   joy - Selected joystick.
121
122   Returns:
123
124   Joystick's name or NULL if <usbjoy> struct is empty.
125 */
126 char * joy_name (struct usbjoy * joy) {
127   if (joy != NULL)  return joy->name;
128   else return NULL;
129 }
130
131
132 /*
133   Function: joy_device
134
135   Returns Joystick's device.
136
137   Parameters:
138
139   joy - Selected joystick.
140
141   Returns:
142
143   Joystick's device or NULL if <usbjoy> struct is empty.
144 */
145 char * joy_device (struct usbjoy * joy) {
146   if (joy != NULL)  return joy->device;
147   else return NULL;
148 }
149
150
151 /*
152   Function: joy_buttons
153
154   Returns Joystick's buttons number.
155
156   Parameters:
157
158   joy - Selected joystick.
159
160   Returns:
161
162   Joystick's buttons or 0 if <usbjoy> struct is empty.
163 */
164 int joy_buttons (struct usbjoy * joy) {
165   if (joy != NULL) return joy->numbuttons;
166   else return 0;
167 }
168
169
170 /*
171   Function: joy_axes
172
173   Returns Joystick's axes number.
174
175   Parameters:
176
177   joy - Selected joystick.
178
179   Returns:
180
181   Joystick's axes or 0 if <usbjoy> struct is empty.
182 */
183 int joy_axes (struct usbjoy * joy) {
184   if (joy != NULL) return joy->numaxes;
185   else return 0;
186 }
187
188
189 /*
190   Function: joy_update
191
192   Updates Joystick's internal information (<statebuttons> and <stateaxes> fields).
193
194   Parameters:
195
196   joy - Selected joystick.
197
198   Returns:
199
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.
203 */
204 int joy_update (struct usbjoy * joy) {
205   struct js_event events[0xff];
206   int i, len;
207   int event = 0;
208   if (joy != NULL) {
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) {
213         case JS_EVENT_AXIS:
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;
219           }
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;
225           }
226           event = 1;
227           break;
228         case JS_EVENT_BUTTON:
229           joy->statebuttons[events[i].number] = events[i].value;
230           event = 1;
231           break;
232         default:
233           break;
234         }
235       }
236     }
237   }
238   else {
239     event = -1;
240   }
241   return event;
242 }
243
244
245 /*
246   Function: joy_getbutton
247
248   Returns Joystick's button information.
249
250   Parameters:
251
252   button - Button which value you want to know (from 0 to 31).
253   joy - Selected joystick.
254
255   Returns:
256
257   0 - Button NOT pushed.
258   1 - Button pushed.
259   -1 - Error: <usbjoy> struct is empty.
260 */
261 int joy_getbutton (int button, struct usbjoy * joy) {
262   if (joy != NULL) {
263     if (button < joy_buttons(joy)) return joy->statebuttons[button];
264     else return 0;
265   }
266   else return -1;
267 }
268
269
270 /*
271   Function: joy_getaxe
272
273   Returns Joystick's axes information.
274
275   Parameters:
276
277   axe - Axe which value you want to know (see <Axes values>).
278   joy - Selected joystick.
279
280   Returns:
281
282   0 - Direction NOT pushed.
283   1 - Direction pushed.
284   -1 - Error: <usbjoy> struct is empty.
285 */
286 int joy_getaxe (int axe, struct usbjoy * joy) {
287   if (joy != NULL) {
288     if (axe < 4) return joy->stateaxes[axe];
289     else return 0;
290   }
291   else return -1;
292 }
293
294
295 /*
296   Function: joy_close
297
298   Closes selected joystick's file descriptor and detroys it's fields.
299
300   Parameters:
301
302   joy - Selected joystick.
303
304   Returns:
305
306   0 - Joystick successfully closed.
307   -1 - Error: <usbjoy> struct is empty.
308 */
309 int joy_close (struct usbjoy * joy) {
310   if (joy != NULL) {
311     close (joy->fd);
312     free (joy);
313     return 0;
314   }
315   else return -1;
316 }
317
318
319 /*********************************************************************/
320 /* GP2X USB Joystick Handling -GnoStiC                               */
321 /*********************************************************************/
322
323 #include "minimal.h"
324
325 int num_of_joys = 0;
326 struct usbjoy *joys[4];
327
328 void gp2x_usbjoy_init (void) {
329         /* Open available joysticks -GnoStiC */
330         int i, n = 0;
331
332         printf("\n");
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]));
337                         n++;
338                 }
339         }
340         num_of_joys = n;
341
342         printf("Found %d Joystick(s)\n",num_of_joys);
343 }
344
345 void gp2x_usbjoy_update (void) {
346         /* Update Joystick Event Cache */
347         int q, foo;
348         for (q=0; q < num_of_joys; q++) {
349                 foo = joy_update (joys[q]);
350         }
351 }
352
353 int gp2x_usbjoy_check (int joyno) {
354         /* Check Joystick */
355         int q, joyExKey = 0;
356         struct usbjoy *joy = joys[joyno];
357
358         if (joy != NULL) {
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; }
363
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) {
368                                         switch (q) {
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;
373                                         }
374                                 } else {
375                                         switch (q) {
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;
380                                         }
381                                 }
382
383                                 switch (q) {
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;
392                                 }
393                         }
394                 }
395         }
396         return joyExKey;
397 }
398
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];
403
404         if (joy != NULL) {
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; }
409
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);
415         }
416         return joyExKey;
417 }
418
419
420
421 void gp2x_usbjoy_deinit (void) {
422         int i;
423         for (i=0; i<num_of_joys; i++) {
424                 joy_close (joys[i]);
425                 joys[i] = NULL;
426         }
427         num_of_joys = 0;
428 }
429