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; |
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 | */ |
126 | char * 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 | */ |
145 | char * 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 | */ |
164 | int 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 | */ |
183 | int 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 | */ |
204 | int 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) { |
626f7c37 |
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; |
cc68a136 |
219 | } |
220 | else if (events[i].number == 1) { |
626f7c37 |
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; |
cc68a136 |
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 | */ |
261 | int 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 | */ |
286 | int 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 | */ |
309 | int 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 "gp2x.h" |
324 | |
325 | int num_of_joys = 0; |
326 | struct usbjoy *joys[4]; |
327 | |
328 | void 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 | |
345 | void 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 | |
353 | int 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 | |
399 | int 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 | |
421 | void gp2x_usbjoy_deinit (void) { |
422 | int i; |
423 | for (i=0; i<num_of_joys; i++) { |
424 | joy_close (joys[i]); |
626f7c37 |
425 | joys[i] = NULL; |
cc68a136 |
426 | } |
427 | num_of_joys = 0; |
428 | } |
429 | |