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 | */ |
54 | struct 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 | */ |
131 | char * 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 | */ |
150 | char * 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 | */ |
169 | int 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 | */ |
188 | int 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 | */ |
209 | int 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 | */ |
266 | int 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 | */ |
291 | int 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 | */ |
314 | int 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 | |
328 | int num_of_joys = 0; |
329 | struct usbjoy *joys[4]; |
330 | |
e5ab6faf |
331 | void 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 |
349 | void 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 |
358 | int 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 |
407 | int 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 |
430 | void 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 | |