d92e8f66462fbb63179328e67b1f1f7a42d0a481
[libpicofe.git] / 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 #ifdef __GP2X__
61         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.
64         if (!insmod_done) {
65                 system ("insmod input");
66                 system ("insmod joydev"); // Loads joydev module
67                 insmod_done = 1;
68         }
69 #endif
70
71         if (joynumber == 0) {
72         }
73         else if (joynumber > 0) {
74                 sprintf (path, "/dev/input/js%d", joynumber-1);
75                 fd = open(path, O_RDONLY, 0);
76                 if (fd == -1) {
77                         sprintf (path, "/dev/js%d", joynumber-1);
78                         fd = open(path, O_RDONLY, 0);
79                 }
80                 if (fd != -1) {
81                         joy = (struct usbjoy *) malloc(sizeof(*joy));
82                         if (joy == NULL) { close(fd); return NULL; }
83                         memset(joy, 0, sizeof(*joy));
84
85                         // Set the joystick to non-blocking read mode
86                         fcntl(fd, F_SETFL, O_NONBLOCK);
87
88                         // notaz: maybe we should flush init events now.
89                         // My pad returns axis as active when I plug it in, which is kind of annoying.
90                         while (read(fd, &event, sizeof(event)) > 0);
91
92                         // Joystick's file descriptor
93                         joy->fd = fd;
94
95                         // Joystick's name
96                         ioctl(joy->fd, JSIOCGNAME(128*sizeof(char)), joy->name);
97
98                         // Joystick's device
99                         strcpy(joy->device, path);
100
101                         // Joystick's buttons
102                         ioctl(joy->fd, JSIOCGBUTTONS, &joy->numbuttons);
103
104                         // Joystick's axes
105                         ioctl(joy->fd, JSIOCGAXES, &joy->numaxes);
106
107                         // Joystick's type (derived from name)
108                         if (strncasecmp(joy->name, "logitech", strlen("logitech")) == 0)
109                              joy->type = JOY_TYPE_LOGITECH;
110                         else joy->type = JOY_TYPE_GENERIC;
111                 } else {
112                         // printf ("ERROR: No Joystick found\n");
113                 }
114         }
115         return joy;
116 }
117
118 /*
119   Function: joy_name
120
121   Returns Joystick's name.
122
123   Parameters:
124
125   joy - Selected joystick.
126
127   Returns:
128
129   Joystick's name or NULL if <usbjoy> struct is empty.
130 */
131 char * joy_name (struct usbjoy * joy) {
132   if (joy != NULL)  return joy->name;
133   else return NULL;
134 }
135
136
137 /*
138   Function: joy_device
139
140   Returns Joystick's device.
141
142   Parameters:
143
144   joy - Selected joystick.
145
146   Returns:
147
148   Joystick's device or NULL if <usbjoy> struct is empty.
149 */
150 char * joy_device (struct usbjoy * joy) {
151   if (joy != NULL)  return joy->device;
152   else return NULL;
153 }
154
155
156 /*
157   Function: joy_buttons
158
159   Returns Joystick's buttons number.
160
161   Parameters:
162
163   joy - Selected joystick.
164
165   Returns:
166
167   Joystick's buttons or 0 if <usbjoy> struct is empty.
168 */
169 int joy_buttons (struct usbjoy * joy) {
170   if (joy != NULL) return joy->numbuttons;
171   else return 0;
172 }
173
174
175 /*
176   Function: joy_axes
177
178   Returns Joystick's axes number.
179
180   Parameters:
181
182   joy - Selected joystick.
183
184   Returns:
185
186   Joystick's axes or 0 if <usbjoy> struct is empty.
187 */
188 int joy_axes (struct usbjoy * joy) {
189   if (joy != NULL) return joy->numaxes;
190   else return 0;
191 }
192
193
194 /*
195   Function: joy_update
196
197   Updates Joystick's internal information (<statebuttons> and <stateaxes> fields).
198
199   Parameters:
200
201   joy - Selected joystick.
202
203   Returns:
204
205   0 - No events registered (no need to update).
206   1 - Events registered (a button or axe has been pushed).
207   -1 - Error: <usbjoy> struct is empty.
208 */
209 int joy_update (struct usbjoy * joy) {
210   struct js_event events[0xff];
211   int i, len;
212   int event = 0;
213   if (joy != NULL) {
214     if ((len=read(joy->fd, events, (sizeof events))) >0) {
215       len /= sizeof(events[0]);
216       for ( i=0; i<len; ++i ) {
217         switch (events[i].type & ~JS_EVENT_INIT) {
218         case JS_EVENT_AXIS:
219           if (events[i].number == 0) {
220             joy->stateaxes[JOYLEFT] = joy->stateaxes[JOYRIGHT] = 0;
221             if      (events[i].value < -DEAD_ZONE) joy->stateaxes[JOYLEFT] = 1;
222             else if (events[i].value >  DEAD_ZONE) joy->stateaxes[JOYRIGHT] = 1;
223             joy->axevals[0] = events[i].value;
224           }
225           else if (events[i].number == 1) {
226             joy->stateaxes[JOYUP] = joy->stateaxes[JOYDOWN] = 0;
227             if      (events[i].value < -DEAD_ZONE) joy->stateaxes[JOYUP] = 1;
228             else if (events[i].value >  DEAD_ZONE) joy->stateaxes[JOYDOWN] = 1;
229             joy->axevals[1] = events[i].value;
230           }
231           event = 1;
232           break;
233         case JS_EVENT_BUTTON:
234           joy->statebuttons[events[i].number] = events[i].value;
235           event = 1;
236           break;
237         default:
238           break;
239         }
240       }
241     }
242   }
243   else {
244     event = -1;
245   }
246   return event;
247 }
248
249
250 /*
251   Function: joy_getbutton
252
253   Returns Joystick's button information.
254
255   Parameters:
256
257   button - Button which value you want to know (from 0 to 31).
258   joy - Selected joystick.
259
260   Returns:
261
262   0 - Button NOT pushed.
263   1 - Button pushed.
264   -1 - Error: <usbjoy> struct is empty.
265 */
266 int joy_getbutton (int button, struct usbjoy * joy) {
267   if (joy != NULL) {
268     if (button < joy_buttons(joy)) return joy->statebuttons[button];
269     else return 0;
270   }
271   else return -1;
272 }
273
274
275 /*
276   Function: joy_getaxe
277
278   Returns Joystick's axes information.
279
280   Parameters:
281
282   axe - Axe which value you want to know (see <Axes values>).
283   joy - Selected joystick.
284
285   Returns:
286
287   0 - Direction NOT pushed.
288   1 - Direction pushed.
289   -1 - Error: <usbjoy> struct is empty.
290 */
291 int joy_getaxe (int axe, struct usbjoy * joy) {
292   if (joy != NULL) {
293     if (axe < 4) return joy->stateaxes[axe];
294     else return 0;
295   }
296   else return -1;
297 }
298
299
300 /*
301   Function: joy_close
302
303   Closes selected joystick's file descriptor and detroys it's fields.
304
305   Parameters:
306
307   joy - Selected joystick.
308
309   Returns:
310
311   0 - Joystick successfully closed.
312   -1 - Error: <usbjoy> struct is empty.
313 */
314 int joy_close (struct usbjoy * joy) {
315   if (joy != NULL) {
316     close (joy->fd);
317     free (joy);
318     return 0;
319   }
320   else return -1;
321 }
322
323
324 /*********************************************************************/
325 /* GP2X USB Joystick Handling -GnoStiC                               */
326 /*********************************************************************/
327
328 #include "gp2x.h"
329
330 int num_of_joys = 0;
331 struct usbjoy *joys[4];
332
333 void gp2x_usbjoy_init (void) {
334         /* Open available joysticks -GnoStiC */
335         int i, n = 0;
336
337         printf("\n");
338         for (i = 0; i < 4; i++) {
339                 joys[n] = joy_open(i+1);
340                 if (joys[n] && joy_buttons(joys[n]) > 0) {
341                         printf ("+-Joystick %d: \"%s\", buttons = %i\n", i+1, joy_name(joys[n]), joy_buttons(joys[n]));
342                         n++;
343                 }
344         }
345         num_of_joys = n;
346
347         printf("Found %d Joystick(s)\n",num_of_joys);
348 }
349
350 void gp2x_usbjoy_update (void) {
351         /* Update Joystick Event Cache */
352         int q, foo;
353         for (q=0; q < num_of_joys; q++) {
354                 foo = joy_update (joys[q]);
355         }
356 }
357
358 int gp2x_usbjoy_check (int joyno) {
359         /* Check Joystick */
360         int q, joyExKey = 0;
361         struct usbjoy *joy = joys[joyno];
362
363         if (joy != NULL) {
364                 if (joy_getaxe(JOYUP, joy))    { joyExKey |= GP2X_UP; }
365                 if (joy_getaxe(JOYDOWN, joy))  { joyExKey |= GP2X_DOWN; }
366                 if (joy_getaxe(JOYLEFT, joy))  { joyExKey |= GP2X_LEFT; }
367                 if (joy_getaxe(JOYRIGHT, joy)) { joyExKey |= GP2X_RIGHT; }
368
369                 /* loop through joy buttons to check if they are pushed */
370                 for (q=0; q<joy_buttons (joy); q++) {
371                         if (joy_getbutton (q, joy)) {
372                                 if (joy->type == JOY_TYPE_LOGITECH) {
373                                         switch (q) {
374                                                 case 0: joyExKey |= GP2X_A; break;
375                                                 case 1: joyExKey |= GP2X_X; break;
376                                                 case 2: joyExKey |= GP2X_B; break;
377                                                 case 3: joyExKey |= GP2X_Y; break;
378                                         }
379                                 } else {
380                                         switch (q) {
381                                                 case 0: joyExKey |= GP2X_Y; break;
382                                                 case 1: joyExKey |= GP2X_B; break;
383                                                 case 2: joyExKey |= GP2X_X; break;
384                                                 case 3: joyExKey |= GP2X_A; break;
385                                         }
386                                 }
387
388                                 switch (q) {
389                                         case  4: joyExKey |= GP2X_L; break;
390                                         case  5: joyExKey |= GP2X_R; break;
391                                         case  6: joyExKey |= GP2X_L; break; /* left shoulder button 2 */
392                                         case  7: joyExKey |= GP2X_R; break; /* right shoulder button 2 */
393                                         case  8: joyExKey |= GP2X_SELECT;break;
394                                         case  9: joyExKey |= GP2X_START; break;
395                                         case 10: joyExKey |= GP2X_PUSH;  break;
396                                         case 11: joyExKey |= GP2X_PUSH;  break;
397                                 }
398                         }
399                 }
400         }
401         return joyExKey;
402 }
403
404 int gp2x_usbjoy_check2 (int joyno) {
405         /* Check Joystick, don't map to gp2x joy */
406         int q, to, joyExKey = 0;
407         struct usbjoy *joy = joys[joyno];
408
409         if (joy != NULL) {
410                 if (joy_getaxe(JOYUP, joy))    { joyExKey |= 1 << 0; }
411                 if (joy_getaxe(JOYDOWN, joy))  { joyExKey |= 1 << 1; }
412                 if (joy_getaxe(JOYLEFT, joy))  { joyExKey |= 1 << 2; }
413                 if (joy_getaxe(JOYRIGHT, joy)) { joyExKey |= 1 << 3; }
414
415                 /* loop through joy buttons to check if they are pushed */
416                 to = joy->numbuttons;
417                 if (to > 32-4) to = 32-4;
418                 for (q=0; q < to; q++)
419                         if (joy->statebuttons[q]) joyExKey |= 1 << (q+4);
420         }
421         return joyExKey;
422 }
423
424
425
426 void gp2x_usbjoy_deinit (void) {
427         int i;
428         for (i=0; i<num_of_joys; i++) {
429                 joy_close (joys[i]);
430                 joys[i] = NULL;
431         }
432         num_of_joys = 0;
433 }
434