extracted OSS code to sndout_oss_*, BTN->PBTN, refactoring
[picodrive.git] / platform / linux / usbjoy.c
CommitLineData
cc68a136 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
626f7c37 37/* This is a try to support analog joys. Untested. */
38#define DEAD_ZONE (8*1024)
cc68a136 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;
16b0afd0 60#ifdef __GP2X__
cc68a136 61 static char insmod_done = 0;
cc68a136 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 }
16b0afd0 69#endif
cc68a136 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);
16b0afd0 76 if (fd == -1) {
77 sprintf (path, "/dev/js%d", joynumber-1);
78 fd = open(path, O_RDONLY, 0);
79 }
80 if (fd != -1) {
cc68a136 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) {
626f7c37 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;
cc68a136 224 }
225 else if (events[i].number == 1) {
626f7c37 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;
cc68a136 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
cc68a136 324/*********************************************************************/
325
e5ab6faf 326#include "../common/common.h"
cc68a136 327
328int num_of_joys = 0;
329struct usbjoy *joys[4];
330
e5ab6faf 331void usbjoy_init (void)
332{
cc68a136 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
e5ab6faf 349void usbjoy_update (void)
350{
cc68a136 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
e5ab6faf 358int usbjoy_check (int joyno)
359{
cc68a136 360 /* Check Joystick */
361 int q, joyExKey = 0;
362 struct usbjoy *joy = joys[joyno];
363
364 if (joy != NULL) {
e5ab6faf 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; }
cc68a136 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) {
e5ab6faf 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;
cc68a136 379 }
380 } else {
381 switch (q) {
e5ab6faf 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;
cc68a136 386 }
387 }
388
389 switch (q) {
e5ab6faf 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/*
cc68a136 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;
e5ab6faf 399*/
cc68a136 400 }
401 }
402 }
403 }
404 return joyExKey;
405}
406
e5ab6faf 407int usbjoy_check2 (int joyno)
408{
cc68a136 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
e5ab6faf 430void usbjoy_deinit (void)
431{
cc68a136 432 int i;
433 for (i=0; i<num_of_joys; i++) {
434 joy_close (joys[i]);
626f7c37 435 joys[i] = NULL;
cc68a136 436 }
437 num_of_joys = 0;
438}
439