usbjoy fix
[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
3ee0ae39 37/* This is a try to support analog joys. Untested. */
38#define DEAD_ZONE (8*1024)
b2b95d2e 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*/
54struct 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*/
126char * 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*/
145char * 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*/
164int 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*/
183int 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*/
204int 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) {
3ee0ae39 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;
b2b95d2e 219 }
220 else if (events[i].number == 1) {
3ee0ae39 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;
b2b95d2e 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*/
261int 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*/
286int 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*/
309int 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
325int num_of_joys = 0;
326struct usbjoy *joys[4];
327
328void 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
345void 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
353int 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
399int 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
421void gp2x_usbjoy_deinit (void) {
422 int i;
423 for (i=0; i<num_of_joys; i++) {
424 joy_close (joys[i]);
3ee0ae39 425 joys[i] = NULL;
b2b95d2e 426 }
427 num_of_joys = 0;
428}
429