de1178a44898f293f5be1673ae21305162171780
[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
38 /*
39   Function: joy_open
40
41   Opens a USB joystick and fills its information.
42
43   Parameters:
44
45   joynumber - Joystick's identifier (0 reserved for GP2X's builtin Joystick).
46
47   Returns:
48
49   Filled usbjoy structure.
50
51 */
52 struct usbjoy *joy_open(int joynumber)
53 {
54         int fd;
55         char path [128];
56         struct usbjoy * joy = NULL;
57         struct js_event event;
58         static char insmod_done = 0;
59
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.
62         if (!insmod_done) {
63                 system ("insmod input");
64                 system ("insmod joydev"); // Loads joydev module
65                 insmod_done = 1;
66         }
67
68         if (joynumber == 0) {
69         }
70         else if (joynumber > 0) {
71                 sprintf (path, "/dev/input/js%d", joynumber-1);
72                 fd = open(path, O_RDONLY, 0);
73                 if (fd > 0) {
74                         joy = (struct usbjoy *) malloc(sizeof(*joy));
75                         if (joy == NULL) { close(fd); return NULL; }
76                         memset(joy, 0, sizeof(*joy));
77
78                         // Set the joystick to non-blocking read mode
79                         fcntl(fd, F_SETFL, O_NONBLOCK);
80
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);
84
85                         // Joystick's file descriptor
86                         joy->fd = fd;
87
88                         // Joystick's name
89                         ioctl(joy->fd, JSIOCGNAME(128*sizeof(char)), joy->name);
90
91                         // Joystick's device
92                         strcpy(joy->device, path);
93
94                         // Joystick's buttons
95                         ioctl(joy->fd, JSIOCGBUTTONS, &joy->numbuttons);
96
97                         // Joystick's axes
98                         ioctl(joy->fd, JSIOCGAXES, &joy->numaxes);
99
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;
104                 } else {
105                         // printf ("ERROR: No Joystick found\n");
106                 }
107         }
108         return joy;
109 }
110
111 /*
112   Function: joy_name
113
114   Returns Joystick's name.
115
116   Parameters:
117
118   joy - Selected joystick.
119
120   Returns:
121
122   Joystick's name or NULL if <usbjoy> struct is empty.
123 */
124 char * joy_name (struct usbjoy * joy) {
125   if (joy != NULL)  return joy->name;
126   else return NULL;
127 }
128
129
130 /*
131   Function: joy_device
132
133   Returns Joystick's device.
134
135   Parameters:
136
137   joy - Selected joystick.
138
139   Returns:
140
141   Joystick's device or NULL if <usbjoy> struct is empty.
142 */
143 char * joy_device (struct usbjoy * joy) {
144   if (joy != NULL)  return joy->device;
145   else return NULL;
146 }
147
148
149 /*
150   Function: joy_buttons
151
152   Returns Joystick's buttons number.
153
154   Parameters:
155
156   joy - Selected joystick.
157
158   Returns:
159
160   Joystick's buttons or 0 if <usbjoy> struct is empty.
161 */
162 int joy_buttons (struct usbjoy * joy) {
163   if (joy != NULL) return joy->numbuttons;
164   else return 0;
165 }
166
167
168 /*
169   Function: joy_axes
170
171   Returns Joystick's axes number.
172
173   Parameters:
174
175   joy - Selected joystick.
176
177   Returns:
178
179   Joystick's axes or 0 if <usbjoy> struct is empty.
180 */
181 int joy_axes (struct usbjoy * joy) {
182   if (joy != NULL) return joy->numaxes;
183   else return 0;
184 }
185
186
187 /*
188   Function: joy_update
189
190   Updates Joystick's internal information (<statebuttons> and <stateaxes> fields).
191
192   Parameters:
193
194   joy - Selected joystick.
195
196   Returns:
197
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.
201 */
202 int joy_update (struct usbjoy * joy) {
203   struct js_event events[0xff];
204   int i, len;
205   int event = 0;
206   if (joy != NULL) {
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) {
211         case JS_EVENT_AXIS:
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;
216           }
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;
221           }
222           event = 1;
223           break;
224         case JS_EVENT_BUTTON:
225           joy->statebuttons[events[i].number] = events[i].value;
226           event = 1;
227           break;
228         default:
229           break;
230         }
231       }
232     }
233   }
234   else {
235     event = -1;
236   }
237   return event;
238 }
239
240
241 /*
242   Function: joy_getbutton
243
244   Returns Joystick's button information.
245
246   Parameters:
247
248   button - Button which value you want to know (from 0 to 31).
249   joy - Selected joystick.
250
251   Returns:
252
253   0 - Button NOT pushed.
254   1 - Button pushed.
255   -1 - Error: <usbjoy> struct is empty.
256 */
257 int joy_getbutton (int button, struct usbjoy * joy) {
258   if (joy != NULL) {
259     if (button < joy_buttons(joy)) return joy->statebuttons[button];
260     else return 0;
261   }
262   else return -1;
263 }
264
265
266 /*
267   Function: joy_getaxe
268
269   Returns Joystick's axes information.
270
271   Parameters:
272
273   axe - Axe which value you want to know (see <Axes values>).
274   joy - Selected joystick.
275
276   Returns:
277
278   0 - Direction NOT pushed.
279   1 - Direction pushed.
280   -1 - Error: <usbjoy> struct is empty.
281 */
282 int joy_getaxe (int axe, struct usbjoy * joy) {
283   if (joy != NULL) {
284     if (axe < 4) return joy->stateaxes[axe];
285     else return 0;
286   }
287   else return -1;
288 }
289
290
291 /*
292   Function: joy_close
293
294   Closes selected joystick's file descriptor and detroys it's fields.
295
296   Parameters:
297
298   joy - Selected joystick.
299
300   Returns:
301
302   0 - Joystick successfully closed.
303   -1 - Error: <usbjoy> struct is empty.
304 */
305 int joy_close (struct usbjoy * joy) {
306   if (joy != NULL) {
307     close (joy->fd);
308     free (joy);
309     return 0;
310   }
311   else return -1;
312 }
313
314
315 /*********************************************************************/
316 /* GP2X USB Joystick Handling -GnoStiC                               */
317 /*********************************************************************/
318
319 #include "minimal.h"
320
321 int num_of_joys = 0;
322 struct usbjoy *joys[4];
323
324 void gp2x_usbjoy_init (void) {
325         /* Open available joysticks -GnoStiC */
326         int i, n = 0;
327
328         printf("\n");
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]));
333                         n++;
334                 }
335         }
336         num_of_joys = n;
337
338         printf("Found %d Joystick(s)\n",num_of_joys);
339 }
340
341 void gp2x_usbjoy_update (void) {
342         /* Update Joystick Event Cache */
343         int q, foo;
344         for (q=0; q < num_of_joys; q++) {
345                 foo = joy_update (joys[q]);
346         }
347 }
348
349 int gp2x_usbjoy_check (int joyno) {
350         /* Check Joystick */
351         int q, joyExKey = 0;
352         struct usbjoy *joy = joys[joyno];
353
354         if (joy != NULL) {
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; }
359
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) {
364                                         switch (q) {
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;
369                                         }
370                                 } else {
371                                         switch (q) {
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;
376                                         }
377                                 }
378
379                                 switch (q) {
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;
388                                 }
389                         }
390                 }
391         }
392         return joyExKey;
393 }
394
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];
399
400         if (joy != NULL) {
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; }
405
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);
411         }
412         return joyExKey;
413 }
414
415
416
417 void gp2x_usbjoy_deinit (void) {
418         int i;
419         for (i=0; i<num_of_joys; i++) {
420                 joy_close (joys[i]);
421         }
422         num_of_joys = 0;
423 }
424