linux port fixed; some cleanups
[libpicofe.git] / linux / 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
720ee7f6 324/*********************************************************************/
325
b3972d82 326#include "../common/common.h"
720ee7f6 327
328int num_of_joys = 0;
329struct usbjoy *joys[4];
330
b3972d82 331void usbjoy_init (void)
332{
720ee7f6 333 /* Open available joysticks -GnoStiC */
334 int i, n = 0;
335
336 printf("\n");
337 for (i = 0; i < 4; i++) {
338 joys[n] = joy_open(i+1);
339 if (joys[n] && joy_buttons(joys[n]) > 0) {
340 printf ("+-Joystick %d: \"%s\", buttons = %i\n", i+1, joy_name(joys[n]), joy_buttons(joys[n]));
341 n++;
342 }
343 }
344 num_of_joys = n;
345
346 printf("Found %d Joystick(s)\n",num_of_joys);
347}
348
b3972d82 349void usbjoy_update (void)
350{
720ee7f6 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
b3972d82 358int usbjoy_check (int joyno)
359{
720ee7f6 360 /* Check Joystick */
361 int q, joyExKey = 0;
362 struct usbjoy *joy = joys[joyno];
363
364 if (joy != NULL) {
b3972d82 365 if (joy_getaxe(JOYUP, joy)) { joyExKey |= PBTN_UP; }
366 if (joy_getaxe(JOYDOWN, joy)) { joyExKey |= PBTN_DOWN; }
367 if (joy_getaxe(JOYLEFT, joy)) { joyExKey |= PBTN_LEFT; }
368 if (joy_getaxe(JOYRIGHT, joy)) { joyExKey |= PBTN_RIGHT; }
720ee7f6 369
370 /* loop through joy buttons to check if they are pushed */
371 for (q=0; q<joy_buttons (joy); q++) {
372 if (joy_getbutton (q, joy)) {
373 if (joy->type == JOY_TYPE_LOGITECH) {
374 switch (q) {
b3972d82 375 case 0: joyExKey |= PBTN_WEST; break;
376 case 1: joyExKey |= PBTN_SOUTH; break;
377 case 2: joyExKey |= PBTN_EAST; break;
378 case 3: joyExKey |= PBTN_NORTH; break;
720ee7f6 379 }
380 } else {
381 switch (q) {
b3972d82 382 case 0: joyExKey |= PBTN_NORTH; break;
383 case 1: joyExKey |= PBTN_EAST; break;
384 case 2: joyExKey |= PBTN_SOUTH; break;
385 case 3: joyExKey |= PBTN_WEST; break;
720ee7f6 386 }
387 }
388
389 switch (q) {
b3972d82 390 case 4: joyExKey |= PBTN_L; break;
391 case 5: joyExKey |= PBTN_R; break;
392 case 6: joyExKey |= PBTN_L; break; /* left shoulder button 2 */
393 case 7: joyExKey |= PBTN_R; break; /* right shoulder button 2 */
394/*
720ee7f6 395 case 8: joyExKey |= GP2X_SELECT;break;
396 case 9: joyExKey |= GP2X_START; break;
397 case 10: joyExKey |= GP2X_PUSH; break;
398 case 11: joyExKey |= GP2X_PUSH; break;
b3972d82 399*/
720ee7f6 400 }
401 }
402 }
403 }
404 return joyExKey;
405}
406
b3972d82 407int usbjoy_check2 (int joyno)
408{
720ee7f6 409 /* Check Joystick, don't map to gp2x joy */
410 int q, to, joyExKey = 0;
411 struct usbjoy *joy = joys[joyno];
412
413 if (joy != NULL) {
414 if (joy_getaxe(JOYUP, joy)) { joyExKey |= 1 << 0; }
415 if (joy_getaxe(JOYDOWN, joy)) { joyExKey |= 1 << 1; }
416 if (joy_getaxe(JOYLEFT, joy)) { joyExKey |= 1 << 2; }
417 if (joy_getaxe(JOYRIGHT, joy)) { joyExKey |= 1 << 3; }
418
419 /* loop through joy buttons to check if they are pushed */
420 to = joy->numbuttons;
421 if (to > 32-4) to = 32-4;
422 for (q=0; q < to; q++)
423 if (joy->statebuttons[q]) joyExKey |= 1 << (q+4);
424 }
425 return joyExKey;
426}
427
428
429
b3972d82 430void usbjoy_deinit (void)
431{
720ee7f6 432 int i;
433 for (i=0; i<num_of_joys; i++) {
434 joy_close (joys[i]);
576fc637 435 joys[i] = NULL;
720ee7f6 436 }
437 num_of_joys = 0;
438}
439