ips patches, 0.4 r162 rel?
[fceu.git] / drivers / gp2x / usbjoy.c
CommitLineData
b2b95d2e 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*/
52struct 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*/
124char * 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*/
143char * 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*/
162int 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*/
181int 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*/
202int 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*/
257int 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*/
282int 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*/
305int 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
321int num_of_joys = 0;
322struct usbjoy *joys[4];
323
324void 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
341void 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
349int 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
395int 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
417void 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