arm_linux.S for cache ops and random fixes
[libpicofe.git] / gp2x / usbjoy.c
CommitLineData
720ee7f6 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
576fc637 37/* This is a try to support analog joys. Untested. */
38#define DEAD_ZONE (8*1024)
720ee7f6 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;
095a240b 60#ifdef __GP2X__
720ee7f6 61 static char insmod_done = 0;
720ee7f6 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 }
095a240b 69#endif
720ee7f6 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);
095a240b 76 if (fd == -1) {
77 sprintf (path, "/dev/js%d", joynumber-1);
78 fd = open(path, O_RDONLY, 0);
79 }
80 if (fd != -1) {
720ee7f6 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*/
131char * 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*/
150char * 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*/
169int 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*/
188int 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*/
209int 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) {
576fc637 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;
720ee7f6 224 }
225 else if (events[i].number == 1) {
576fc637 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;
720ee7f6 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*/
266int 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*/
291int 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*/
314int 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
330int num_of_joys = 0;
331struct usbjoy *joys[4];
332
333void 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
350void 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
358int 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
404int 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
426void gp2x_usbjoy_deinit (void) {
427 int i;
428 for (i=0; i<num_of_joys; i++) {
429 joy_close (joys[i]);
576fc637 430 joys[i] = NULL;
720ee7f6 431 }
432 num_of_joys = 0;
433}
434