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 | |
37 | |
38 | /* |
39 | Function: joy_open |
40 | |
41 | Opens a USB joystick and fills its information. |
42 | |
43 | Parameters: |
44 | |
45 | joynumber - Joystick's identifier (0 reserved for GP2X's builtin Joystick). |
46 | |
47 | Returns: |
48 | |
49 | Filled usbjoy structure. |
50 | |
51 | */ |
52 | struct usbjoy *joy_open(int joynumber) |
53 | { |
54 | int fd; |
55 | char path [128]; |
56 | struct usbjoy * joy = NULL; |
57 | struct js_event event; |
58 | static char insmod_done = 0; |
59 | |
60 | // notaz: on my system I get unresolved input_* symbols, so have to 'insmod input' too |
61 | // also we should insmod only once, not on every joy_open() call. |
62 | if (!insmod_done) { |
63 | system ("insmod input"); |
64 | system ("insmod joydev"); // Loads joydev module |
65 | insmod_done = 1; |
66 | } |
67 | |
68 | if (joynumber == 0) { |
69 | } |
70 | else if (joynumber > 0) { |
71 | sprintf (path, "/dev/input/js%d", joynumber-1); |
72 | fd = open(path, O_RDONLY, 0); |
73 | if (fd > 0) { |
74 | joy = (struct usbjoy *) malloc(sizeof(*joy)); |
75 | if (joy == NULL) { close(fd); return NULL; } |
76 | memset(joy, 0, sizeof(*joy)); |
77 | |
78 | // Set the joystick to non-blocking read mode |
79 | fcntl(fd, F_SETFL, O_NONBLOCK); |
80 | |
81 | // notaz: maybe we should flush init events now. |
82 | // My pad returns axis as active when I plug it in, which is kind of annoying. |
83 | while (read(fd, &event, sizeof(event)) > 0); |
84 | |
85 | // Joystick's file descriptor |
86 | joy->fd = fd; |
87 | |
88 | // Joystick's name |
89 | ioctl(joy->fd, JSIOCGNAME(128*sizeof(char)), joy->name); |
90 | |
91 | // Joystick's device |
92 | strcpy(joy->device, path); |
93 | |
94 | // Joystick's buttons |
95 | ioctl(joy->fd, JSIOCGBUTTONS, &joy->numbuttons); |
96 | |
97 | // Joystick's axes |
98 | ioctl(joy->fd, JSIOCGAXES, &joy->numaxes); |
99 | |
100 | // Joystick's type (derived from name) |
101 | if (strncasecmp(joy->name, "logitech", strlen("logitech")) == 0) |
102 | joy->type = JOY_TYPE_LOGITECH; |
103 | else joy->type = JOY_TYPE_GENERIC; |
104 | } else { |
105 | // printf ("ERROR: No Joystick found\n"); |
106 | } |
107 | } |
108 | return joy; |
109 | } |
110 | |
111 | /* |
112 | Function: joy_name |
113 | |
114 | Returns Joystick's name. |
115 | |
116 | Parameters: |
117 | |
118 | joy - Selected joystick. |
119 | |
120 | Returns: |
121 | |
122 | Joystick's name or NULL if <usbjoy> struct is empty. |
123 | */ |
124 | char * joy_name (struct usbjoy * joy) { |
125 | if (joy != NULL) return joy->name; |
126 | else return NULL; |
127 | } |
128 | |
129 | |
130 | /* |
131 | Function: joy_device |
132 | |
133 | Returns Joystick's device. |
134 | |
135 | Parameters: |
136 | |
137 | joy - Selected joystick. |
138 | |
139 | Returns: |
140 | |
141 | Joystick's device or NULL if <usbjoy> struct is empty. |
142 | */ |
143 | char * joy_device (struct usbjoy * joy) { |
144 | if (joy != NULL) return joy->device; |
145 | else return NULL; |
146 | } |
147 | |
148 | |
149 | /* |
150 | Function: joy_buttons |
151 | |
152 | Returns Joystick's buttons number. |
153 | |
154 | Parameters: |
155 | |
156 | joy - Selected joystick. |
157 | |
158 | Returns: |
159 | |
160 | Joystick's buttons or 0 if <usbjoy> struct is empty. |
161 | */ |
162 | int joy_buttons (struct usbjoy * joy) { |
163 | if (joy != NULL) return joy->numbuttons; |
164 | else return 0; |
165 | } |
166 | |
167 | |
168 | /* |
169 | Function: joy_axes |
170 | |
171 | Returns Joystick's axes number. |
172 | |
173 | Parameters: |
174 | |
175 | joy - Selected joystick. |
176 | |
177 | Returns: |
178 | |
179 | Joystick's axes or 0 if <usbjoy> struct is empty. |
180 | */ |
181 | int joy_axes (struct usbjoy * joy) { |
182 | if (joy != NULL) return joy->numaxes; |
183 | else return 0; |
184 | } |
185 | |
186 | |
187 | /* |
188 | Function: joy_update |
189 | |
190 | Updates Joystick's internal information (<statebuttons> and <stateaxes> fields). |
191 | |
192 | Parameters: |
193 | |
194 | joy - Selected joystick. |
195 | |
196 | Returns: |
197 | |
198 | 0 - No events registered (no need to update). |
199 | 1 - Events registered (a button or axe has been pushed). |
200 | -1 - Error: <usbjoy> struct is empty. |
201 | */ |
202 | int joy_update (struct usbjoy * joy) { |
203 | struct js_event events[0xff]; |
204 | int i, len; |
205 | int event = 0; |
206 | if (joy != NULL) { |
207 | if ((len=read(joy->fd, events, (sizeof events))) >0) { |
208 | len /= sizeof(events[0]); |
209 | for ( i=0; i<len; ++i ) { |
210 | switch (events[i].type & ~JS_EVENT_INIT) { |
211 | case JS_EVENT_AXIS: |
212 | if (events[i].number == 0) { |
213 | if (events[i].value == 0) joy->stateaxes[JOYLEFT] = joy->stateaxes[JOYRIGHT] = 0; |
214 | else if (events[i].value < 0) joy->stateaxes[JOYLEFT] = 1; |
215 | else joy->stateaxes[JOYRIGHT] = 1; |
216 | } |
217 | else if (events[i].number == 1) { |
218 | if (events[i].value == 0) joy->stateaxes[JOYUP] = joy->stateaxes[JOYDOWN] = 0; |
219 | else if (events[i].value < 0) joy->stateaxes[JOYUP] = 1; |
220 | else joy->stateaxes[JOYDOWN] = 1; |
221 | } |
222 | event = 1; |
223 | break; |
224 | case JS_EVENT_BUTTON: |
225 | joy->statebuttons[events[i].number] = events[i].value; |
226 | event = 1; |
227 | break; |
228 | default: |
229 | break; |
230 | } |
231 | } |
232 | } |
233 | } |
234 | else { |
235 | event = -1; |
236 | } |
237 | return event; |
238 | } |
239 | |
240 | |
241 | /* |
242 | Function: joy_getbutton |
243 | |
244 | Returns Joystick's button information. |
245 | |
246 | Parameters: |
247 | |
248 | button - Button which value you want to know (from 0 to 31). |
249 | joy - Selected joystick. |
250 | |
251 | Returns: |
252 | |
253 | 0 - Button NOT pushed. |
254 | 1 - Button pushed. |
255 | -1 - Error: <usbjoy> struct is empty. |
256 | */ |
257 | int joy_getbutton (int button, struct usbjoy * joy) { |
258 | if (joy != NULL) { |
259 | if (button < joy_buttons(joy)) return joy->statebuttons[button]; |
260 | else return 0; |
261 | } |
262 | else return -1; |
263 | } |
264 | |
265 | |
266 | /* |
267 | Function: joy_getaxe |
268 | |
269 | Returns Joystick's axes information. |
270 | |
271 | Parameters: |
272 | |
273 | axe - Axe which value you want to know (see <Axes values>). |
274 | joy - Selected joystick. |
275 | |
276 | Returns: |
277 | |
278 | 0 - Direction NOT pushed. |
279 | 1 - Direction pushed. |
280 | -1 - Error: <usbjoy> struct is empty. |
281 | */ |
282 | int joy_getaxe (int axe, struct usbjoy * joy) { |
283 | if (joy != NULL) { |
284 | if (axe < 4) return joy->stateaxes[axe]; |
285 | else return 0; |
286 | } |
287 | else return -1; |
288 | } |
289 | |
290 | |
291 | /* |
292 | Function: joy_close |
293 | |
294 | Closes selected joystick's file descriptor and detroys it's fields. |
295 | |
296 | Parameters: |
297 | |
298 | joy - Selected joystick. |
299 | |
300 | Returns: |
301 | |
302 | 0 - Joystick successfully closed. |
303 | -1 - Error: <usbjoy> struct is empty. |
304 | */ |
305 | int joy_close (struct usbjoy * joy) { |
306 | if (joy != NULL) { |
307 | close (joy->fd); |
308 | free (joy); |
309 | return 0; |
310 | } |
311 | else return -1; |
312 | } |
313 | |
314 | |
315 | /*********************************************************************/ |
316 | /* GP2X USB Joystick Handling -GnoStiC */ |
317 | /*********************************************************************/ |
318 | |
319 | #include "gp2x.h" |
320 | |
321 | int num_of_joys = 0; |
322 | struct usbjoy *joys[4]; |
323 | |
324 | void gp2x_usbjoy_init (void) { |
325 | /* Open available joysticks -GnoStiC */ |
326 | int i, n = 0; |
327 | |
328 | printf("\n"); |
329 | for (i = 0; i < 4; i++) { |
330 | joys[n] = joy_open(i+1); |
331 | if (joys[n] && joy_buttons(joys[n]) > 0) { |
332 | printf ("+-Joystick %d: \"%s\", buttons = %i\n", i+1, joy_name(joys[n]), joy_buttons(joys[n])); |
333 | n++; |
334 | } |
335 | } |
336 | num_of_joys = n; |
337 | |
338 | printf("Found %d Joystick(s)\n",num_of_joys); |
339 | } |
340 | |
341 | void gp2x_usbjoy_update (void) { |
342 | /* Update Joystick Event Cache */ |
343 | int q, foo; |
344 | for (q=0; q < num_of_joys; q++) { |
345 | foo = joy_update (joys[q]); |
346 | } |
347 | } |
348 | |
349 | int gp2x_usbjoy_check (int joyno) { |
350 | /* Check Joystick */ |
351 | int q, joyExKey = 0; |
352 | struct usbjoy *joy = joys[joyno]; |
353 | |
354 | if (joy != NULL) { |
355 | if (joy_getaxe(JOYUP, joy)) { joyExKey |= GP2X_UP; } |
356 | if (joy_getaxe(JOYDOWN, joy)) { joyExKey |= GP2X_DOWN; } |
357 | if (joy_getaxe(JOYLEFT, joy)) { joyExKey |= GP2X_LEFT; } |
358 | if (joy_getaxe(JOYRIGHT, joy)) { joyExKey |= GP2X_RIGHT; } |
359 | |
360 | /* loop through joy buttons to check if they are pushed */ |
361 | for (q=0; q<joy_buttons (joy); q++) { |
362 | if (joy_getbutton (q, joy)) { |
363 | if (joy->type == JOY_TYPE_LOGITECH) { |
364 | switch (q) { |
365 | case 0: joyExKey |= GP2X_A; break; |
366 | case 1: joyExKey |= GP2X_X; break; |
367 | case 2: joyExKey |= GP2X_B; break; |
368 | case 3: joyExKey |= GP2X_Y; break; |
369 | } |
370 | } else { |
371 | switch (q) { |
372 | case 0: joyExKey |= GP2X_Y; break; |
373 | case 1: joyExKey |= GP2X_B; break; |
374 | case 2: joyExKey |= GP2X_X; break; |
375 | case 3: joyExKey |= GP2X_A; break; |
376 | } |
377 | } |
378 | |
379 | switch (q) { |
380 | case 4: joyExKey |= GP2X_L; break; |
381 | case 5: joyExKey |= GP2X_R; break; |
382 | case 6: joyExKey |= GP2X_L; break; /* left shoulder button 2 */ |
383 | case 7: joyExKey |= GP2X_R; break; /* right shoulder button 2 */ |
384 | case 8: joyExKey |= GP2X_SELECT;break; |
385 | case 9: joyExKey |= GP2X_START; break; |
386 | case 10: joyExKey |= GP2X_PUSH; break; |
387 | case 11: joyExKey |= GP2X_PUSH; break; |
388 | } |
389 | } |
390 | } |
391 | } |
392 | return joyExKey; |
393 | } |
394 | |
395 | int gp2x_usbjoy_check2 (int joyno) { |
396 | /* Check Joystick, don't map to gp2x joy */ |
397 | int q, to, joyExKey = 0; |
398 | struct usbjoy *joy = joys[joyno]; |
399 | |
400 | if (joy != NULL) { |
401 | if (joy_getaxe(JOYUP, joy)) { joyExKey |= 1 << 0; } |
402 | if (joy_getaxe(JOYDOWN, joy)) { joyExKey |= 1 << 1; } |
403 | if (joy_getaxe(JOYLEFT, joy)) { joyExKey |= 1 << 2; } |
404 | if (joy_getaxe(JOYRIGHT, joy)) { joyExKey |= 1 << 3; } |
405 | |
406 | /* loop through joy buttons to check if they are pushed */ |
407 | to = joy->numbuttons; |
408 | if (to > 32-4) to = 32-4; |
409 | for (q=0; q < to; q++) |
410 | if (joy->statebuttons[q]) joyExKey |= 1 << (q+4); |
411 | } |
412 | return joyExKey; |
413 | } |
414 | |
415 | |
416 | |
417 | void gp2x_usbjoy_deinit (void) { |
418 | int i; |
419 | for (i=0; i<num_of_joys; i++) { |
420 | joy_close (joys[i]); |
421 | } |
422 | num_of_joys = 0; |
423 | } |
424 | |