1 /** \file   joy-unix.c
2  * \brief   Linux/BSD joystick support
3  *
4  * \author  Bernhard Kuhn <kuhn@eikon.e-technik.tu-muenchen.de>
5  * \author  Ulmer Lionel <ulmer@poly.polytechnique.fr>
6  * \author  Marco van den Heuvel <blackystardust68@yahoo.com>
7  * \author  Daniel Sladic <sladic@eecg.toronto.edu>
8  * \author  Krister Walfridsson <cato@df.lth.se>
9  * \author  Luca Montecchiani  <m.luca@usa.net> (http://i.am/m.luca)
10  */
11 
12 /*
13  * This file is part of VICE, the Versatile Commodore Emulator.
14  * See README for copyright notice.
15  *
16  *  This program is free software; you can redistribute it and/or modify
17  *  it under the terms of the GNU General Public License as published by
18  *  the Free Software Foundation; either version 2 of the License, or
19  *  (at your option) any later version.
20  *
21  *  This program is distributed in the hope that it will be useful,
22  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
23  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  *  GNU General Public License for more details.
25  *
26  *  You should have received a copy of the GNU General Public License
27  *  along with this program; if not, write to the Free Software
28  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
29  *  02111-1307  USA.
30  *
31  */
32 
33 #include "vice.h"
34 #include "archdep_defs.h"
35 
36 #if defined(UNIX_COMPILE) && !defined(MACOSX_SUPPORT)
37 
38 #include <fcntl.h>
39 #include <stdio.h>
40 #include <sys/types.h>
41 #include <sys/stat.h>
42 #include <unistd.h>
43 
44 #include "cmdline.h"
45 #include "joy.h"
46 #include "joyport.h"
47 #include "joystick.h"
48 #include "keyboard.h"
49 #include "log.h"
50 #include "resources.h"
51 #include "types.h"
52 
joy_arch_set_device(int port,int new_dev)53 int joy_arch_set_device(int port, int new_dev)
54 {
55     if (new_dev < 0 || new_dev > JOYDEV_MAX) {
56         return -1;
57     }
58 
59     return 0;
60 }
61 
62 /* Resources.  */
63 
64 
joy_arch_resources_init(void)65 int joy_arch_resources_init(void)
66 {
67     return 0;
68 }
69 
70 /* Command-line options.  */
71 
72 #if 0
73 static const cmdline_option_t joydev1cmdline_options[] =
74 {
75     { "-joydev1", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
76       NULL, NULL, "JoyDevice1", NULL,
77 #ifdef HAS_USB_JOYSTICK
78     "<0-13>", "Set device for joystick port 1 (0: None, 1: Numpad, 2: Keyset 1, 3: Keyset 2, 4: Analog joystick 0, 5: Analog joystick 1, 6: Analog joystick 2, 7: Analog joystick 3, 8: Analog joystick 4, 9: Analog joystick 5, 10: Digital joystick 0, 11: Digital joystick 1, 12: USB joystick 0, 13: USB joystick 1)" },
79 #else
80 #  ifdef HAS_DIGITAL_JOYSTICK
81     "<0-11>", "Set device for joystick port 1 (0: None, 1: Numpad, 2: Keyset 1, 3: Keyset 2, 4: Analog joystick 0, 5: Analog joystick 1, 6: Analog joystick 2, 7: Analog joystick 3, 8: Analog joystick 4, 9: Analog joystick 5, 10: Digital joystick 0, 11: Digital joystick 1)" },
82 #  else
83     "<0-9>", "Set device for joystick port 1 (0: None, 1: Numpad, 2: Keyset 1, 3: Keyset 2, 4: Analog joystick 0, 5: Analog joystick 1, 6: Analog joystick 2, 7: Analog joystick 3, 8: Analog joystick 4, 9: Analog joystick 5)" },
84 #  endif
85 #endif
86     CMDLINE_LIST_END
87 };
88 
89 static const cmdline_option_t joydev2cmdline_options[] =
90 {
91     { "-joydev2", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
92       NULL, NULL, "JoyDevice2", NULL,
93 #ifdef HAS_USB_JOYSTICK
94     "<0-13>", "Set device for joystick port 2 (0: None, 1: Numpad, 2: Keyset 1, 3: Keyset 2, 4: Analog joystick 0, 5: Analog joystick 1, 6: Analog joystick 2, 7: Analog joystick 3, 8: Analog joystick 4, 9: Analog joystick 5, 10: Digital joystick 0, 11: Digital joystick 1, 12: USB joystick 0, 13: USB joystick 1)" },
95 #else
96 #  ifdef HAS_DIGITAL_JOYSTICK
97     "<0-11>", "Set device for joystick port 2 (0: None, 1: Numpad, 2: Keyset 1, 3: Keyset 2, 4: Analog joystick 0, 5: Analog joystick 1, 6: Analog joystick 2, 7: Analog joystick 3, 8: Analog joystick 4, 9: Analog joystick 5, 10: Digital joystick 0, 11: Digital joystick 1)" },
98 #  else
99     "<0-9>", "Set device for joystick port 2 (0: None, 1: Numpad, 2: Keyset 1, 3: Keyset 2, 4: Analog joystick 0, 5: Analog joystick 1, 6: Analog joystick 2, 7: Analog joystick 3, 8: Analog joystick 4, 9: Analog joystick 5)" },
100 #  endif
101 #endif
102     CMDLINE_LIST_END
103 };
104 
105 static const cmdline_option_t joydev3cmdline_options[] =
106 {
107     { "-extrajoydev1", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
108       NULL, NULL, "JoyDevice3", NULL,
109 
110 #ifdef HAS_USB_JOYSTICK
111     "<0-13>", "Set device for extra joystick port 1 (0: None, 1: Numpad, 2: Keyset 1, 3: Keyset 2, 4: Analog joystick 0, 5: Analog joystick 1, 6: Analog joystick 2, 7: Analog joystick 3, 8: Analog joystick 4, 9: Analog joystick 5, 10: Digital joystick 0, 11: Digital joystick 1, 12: USB joystick 0, 13: USB joystick 1)" },
112 #else
113 #  ifdef HAS_DIGITAL_JOYSTICK
114     "<0-11>", "Set device for extra joystick port 1 (0: None, 1: Numpad, 2: Keyset 1, 3: Keyset 2, 4: Analog joystick 0, 5: Analog joystick 1, 6: Analog joystick 2, 7: Analog joystick 3, 8: Analog joystick 4, 9: Analog joystick 5, 10: Digital joystick 0, 11: Digital joystick 1)" },
115 #  else
116     "<0-9>", "Set device for extra joystick port 1 (0: None, 1: Numpad, 2: Keyset 1, 3: Keyset 2, 4: Analog joystick 0, 5: Analog joystick 1, 6: Analog joystick 2, 7: Analog joystick 3, 8: Analog joystick 4, 9: Analog joystick 5)" },
117 #  endif
118 #endif
119     CMDLINE_LIST_END
120 };
121 
122 static const cmdline_option_t joydev4cmdline_options[] =
123 {
124     { "-extrajoydev2", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
125       NULL, NULL, "JoyDevice4", NULL,
126 #ifdef HAS_USB_JOYSTICK
127     "<0-13>", "Set device for extra joystick port 2 (0: None, 1: Numpad, 2: Keyset 1, 3: Keyset 2, 4: Analog joystick 0, 5: Analog joystick 1, 6: Analog joystick 2, 7: Analog joystick 3, 8: Analog joystick 4, 9: Analog joystick 5, 10: Digital joystick 0, 11: Digital joystick 1, 12: USB joystick 0, 13: USB joystick 1)" },
128 #else
129 #  ifdef HAS_DIGITAL_JOYSTICK
130     "<0-11>", "Set device for extra joystick port 2 (0: None, 1: Numpad, 2: Keyset 1, 3: Keyset 2, 4: Analog joystick 0, 5: Analog joystick 1, 6: Analog joystick 2, 7: Analog joystick 3, 8: Analog joystick 4, 9: Analog joystick 5, 10: Digital joystick 0, 11: Digital joystick 1)" },
131 #  else
132     "<0-9>", "Set device for extra joystick port 2 (0: None, 1: Numpad, 2: Keyset 1, 3: Keyset 2, 4: Analog joystick 0, 5: Analog joystick 1, 6: Analog joystick 2, 7: Analog joystick 3, 8: Analog joystick 4, 9: Analog joystick 5)" },
133 #  endif
134 #endif
135     CMDLINE_LIST_END
136 };
137 
138 static const cmdline_option_t joydev5cmdline_options[] =
139 {
140     { "-extrajoydev3", SET_RESOURCE, CMDLINE_ATTRIB_NEED_ARGS,
141       NULL, NULL, "JoyDevice5", NULL,
142 #ifdef HAS_USB_JOYSTICK
143     "<0-13>", "Set device for extra joystick port 3 (0: None, 1: Numpad, 2: Keyset 1, 3: Keyset 2, 4: Analog joystick 0, 5: Analog joystick 1, 6: Analog joystick 2, 7: Analog joystick 3, 8: Analog joystick 4, 9: Analog joystick 5, 10: Digital joystick 0, 11: Digital joystick 1, 12: USB joystick 0, 13: USB joystick 1)" },
144 #else
145 #  ifdef HAS_DIGITAL_JOYSTICK
146     "<0-11>", "Set device for extra joystick port 3 (0: None, 1: Numpad, 2: Keyset 1, 3: Keyset 2, 4: Analog joystick 0, 5: Analog joystick 1, 6: Analog joystick 2, 7: Analog joystick 3, 8: Analog joystick 4, 9: Analog joystick 5, 10: Digital joystick 0, 11: Digital joystick 1)" },
147 #  else
148     "<0-9>", "Set device for extra joystick port 3 (0: None, 1: Numpad, 2: Keyset 1, 3: Keyset 2, 4: Analog joystick 0, 5: Analog joystick 1, 6: Analog joystick 2, 7: Analog joystick 3, 8: Analog joystick 4, 9: Analog joystick 5)" },
149 #  endif
150 #endif
151     CMDLINE_LIST_END
152 };
153 #endif
154 
155 
joy_arch_cmdline_options_init(void)156 int joy_arch_cmdline_options_init(void)
157 {
158     /* NOP */
159     return 0;
160 }
161 #if 0
162     if (joyport_get_port_name(JOYPORT_1)) {
163         if (cmdline_register_options(joydev1cmdline_options) < 0) {
164             return -1;
165         }
166     }
167     if (joyport_get_port_name(JOYPORT_2)) {
168         if (cmdline_register_options(joydev2cmdline_options) < 0) {
169             return -1;
170         }
171     }
172     if (joyport_get_port_name(JOYPORT_3)) {
173         if (cmdline_register_options(joydev3cmdline_options) < 0) {
174             return -1;
175         }
176     }
177     if (joyport_get_port_name(JOYPORT_4)) {
178         if (cmdline_register_options(joydev4cmdline_options) < 0) {
179             return -1;
180         }
181     }
182     if (joyport_get_port_name(JOYPORT_5)) {
183         if (cmdline_register_options(joydev5cmdline_options) < 0) {
184             return -1;
185         }
186     }
187 
188     return 0;
189 }
190 #endif
191 
192 /* ------------------------------------------------------------------------- */
193 
194 #    ifdef LINUX_JOYSTICK
195 #      include <linux/joystick.h>
196 
197 /* Compile time New 1.1.xx API presence check */
198 #      ifdef JS_VERSION
199 #        include <sys/ioctl.h>
200 #        include <errno.h>
201 #        define NEW_JOYSTICK 1
202 #        undef HAS_DIGITAL_JOYSTICK
203 static int use_old_api=0;       /**< FIXME: make this a #define? */
204 #      else
205 static int use_old_api=1;
206 #      endif
207 
208 #    elif defined(BSD_JOYSTICK)
209 #      ifdef HAVE_MACHINE_JOYSTICK_H
210 #        include <machine/joystick.h>
211 #      endif
212 #      ifdef HAVE_SYS_JOYSTICK_H
213 #        include <sys/joystick.h>
214 #      endif
215 #      define JS_DATA_TYPE joystick
216 #      define JS_RETURN sizeof(struct joystick)
217 int use_old_api=1;
218 #    else
219 #      error Unknown Joystick
220 #    endif
221 
222 #    define ANALOG_JOY_NUM (JOYDEV_ANALOG_7 - JOYDEV_ANALOG_0 + 1)
223 
224 /* file handles for the joystick device files */
225 
226 static int ajoyfd[ANALOG_JOY_NUM] = { -1, -1, -1, -1, -1, -1, -1, -1 };
227 static int djoyfd[2] = { -1, -1 };
228 
229 #    define JOYCALLOOPS 100
230 #    define JOYSENSITIVITY 5
231 static int joyxcal[2];
232 static int joyycal[2];
233 static int joyxmin[2];
234 static int joyxmax[2];
235 static int joyymin[2];
236 static int joyymax[2];
237 
238 log_t joystick_log = LOG_ERR;
239 
240 /* ------------------------------------------------------------------------- */
241 
242 /**********************************************************
243  * Generic high level joy routine                         *
244  **********************************************************/
joy_arch_init(void)245 int joy_arch_init(void)
246 {
247     if (use_old_api) {
248         old_joystick_init();
249     } else {
250         new_joystick_init();
251     }
252 #    ifdef HAS_USB_JOYSTICK
253     usb_joystick_init();
254 #    endif
255     return 0;
256 }
257 
joystick_close(void)258 void joystick_close(void)
259 {
260     if (use_old_api) {
261         old_joystick_close();
262     } else {
263         new_joystick_close();
264     }
265 #    ifdef HAS_USB_JOYSTICK
266     usb_joystick_close();
267 #    endif
268 }
269 
joystick(void)270 void joystick(void)
271 {
272     if (use_old_api) {
273         old_joystick();
274     } else {
275         new_joystick();
276     }
277 #    ifdef HAS_USB_JOYSTICK
278     usb_joystick();
279 #    endif
280 }
281 
282 /** \brief  Struct containing device name and id
283  */
284 typedef struct device_info_s {
285     const char *name;   /**< device name */
286     int         id;     /**< device ID (\see joy.h) */
287 } device_info_t;
288 
289 static device_info_t predefined_device_list[] = {
290     { "Analog joystick 0",  JOYDEV_ANALOG_0 },
291     { "Analog joystick 1",  JOYDEV_ANALOG_1 },
292     { "Analog joystick 2",  JOYDEV_ANALOG_2 },
293     { "Analog joystick 3",  JOYDEV_ANALOG_3 },
294     { "Analog joystick 4",  JOYDEV_ANALOG_4 },
295     { "Analog joystick 5",  JOYDEV_ANALOG_5 },
296     { "Analog joystick 6",  JOYDEV_ANALOG_6 },
297     { "Analog joystick 7",  JOYDEV_ANALOG_7 },
298 #ifdef HAS_DIGITAL_JOYSTICK
299     { "Digital joystick 0", JOYDEV_DIGITAL_0 },
300     { "Digital joystick 1", JOYDEV_DIGITAL_1 },
301 #endif
302 #ifdef HAS_USB_JOYSTICK
303     { "USB joystick 0",     JOYDEV_USB_0 },
304     { "USB joystick 1",     JOYDEV_USB_1 },
305 #endif
306     { NULL, -1 }
307 };
308 
309 static int joystickdeviceidx = 0;
310 
joystick_ui_reset_device_list(void)311 void joystick_ui_reset_device_list(void)
312 {
313     joystickdeviceidx = 0;
314 }
315 
316 /* FIXME: proper device names will be returned only when using the "new" API
317           and only for "analog" joysticks. */
joystick_ui_get_next_device_name(int * id)318 const char *joystick_ui_get_next_device_name(int *id)
319 {
320     const char *name;
321 #ifndef ARCHDEP_OS_BSD
322     static char jname[0x80];
323     int idx;
324 #endif
325 
326     /* printf("joystick_ui_get_next_device_name  id: %d\n", joystickdeviceidx); */
327 
328     if ((name = predefined_device_list[joystickdeviceidx].name)) {
329         *id = predefined_device_list[joystickdeviceidx].id;
330         joystickdeviceidx++;
331 
332         if (!use_old_api) {
333 #ifndef ARCHDEP_OS_BSD
334             if ((*id >= JOYDEV_ANALOG_0) && (*id <= JOYDEV_ANALOG_5)) {
335                 idx = *id - JOYDEV_ANALOG_0;
336                 if (ajoyfd[idx] >= 0) {
337                     sprintf(jname, "%d: ", idx);
338                     ioctl(ajoyfd[idx], JSIOCGNAME (sizeof (jname) - 4), &jname[3]);
339                     *id = idx + JOYDEV_ANALOG_0;
340                     /* printf("joystick_ui_get_next_device_name  got name: %d: %s: %s\n", *id, name, jname); */
341                     return jname;
342                 } else {
343                     /* no joystick at this port */
344                     return NULL;
345                 }
346             }
347 #endif /* BSD */
348         }
349         /* return name from the predefined list instead */
350         return name;
351     }
352     return NULL;
353 }
354 
355 /**********************************************************
356  * Older Joystick routine 0.8x Linux/BSD driver           *
357  **********************************************************/
old_joystick_init(void)358 void old_joystick_init(void)
359 {
360     int i;
361 
362     joystick_log = log_open("Joystick");
363 
364     /* close all device files */
365     for (i = 0; i < 2; i++) {
366         if (ajoyfd[i] != -1) {
367             close(ajoyfd[i]);
368         }
369         if (djoyfd[i] != -1) {
370             close(djoyfd[i]);
371         }
372     }
373 
374     /* open analog device files */
375     for (i = 0; i < 2; i++) {
376 
377         const char *dev;
378 #    ifdef LINUX_JOYSTICK
379         dev = (i == 0) ? "/dev/js0" : "/dev/js1";
380 #    elif defined(BSD_JOYSTICK)
381         dev = (i == 0) ? "/dev/joy0" : "/dev/joy1";
382 #    endif
383 
384         ajoyfd[i] = open(dev, O_RDONLY);
385         if (ajoyfd[i] < 0) {
386             log_warning(joystick_log, "Cannot open joystick device `%s'.", dev);
387         } else {
388             int j;
389 
390             /* calibration loop */
391             for (j = 0; j < JOYCALLOOPS; j++) {
392                 struct JS_DATA_TYPE js;
393                 ssize_t status = read(ajoyfd[i], &js, JS_RETURN);
394 
395                 if (status != JS_RETURN) {
396                     log_warning(joystick_log, "Error reading joystick device `%s'.", dev);
397                 } else {
398                     /* determine average */
399                     joyxcal[i] += js.x;
400                     joyycal[i] += js.y;
401                 }
402             }
403 
404             /* correct average */
405             joyxcal[i] /= JOYCALLOOPS;
406             joyycal[i] /= JOYCALLOOPS;
407 
408             /* determine tresholds */
409             joyxmin[i] = joyxcal[i] - joyxcal[i] / JOYSENSITIVITY;
410             joyxmax[i] = joyxcal[i] + joyxcal[i] / JOYSENSITIVITY;
411             joyymin[i] = joyycal[i] - joyycal[i] / JOYSENSITIVITY;
412             joyymax[i] = joyycal[i] + joyycal[i] / JOYSENSITIVITY;
413 
414             log_message(joystick_log, "Hardware joystick calibration for device `%s':", dev);
415             log_message(joystick_log, "  X: min: %i , mid: %i , max: %i.", joyxmin[i], joyxcal[i], joyxmax[i]);
416             log_message(joystick_log, "  Y: min: %i , mid: %i , max: %i.", joyymin[i], joyycal[i], joyymax[i]);
417         }
418     }
419 
420 #    ifdef HAS_DIGITAL_JOYSTICK
421     /* open device files for digital joystick */
422     for (i = 0; i < 2; i++) {
423         const char *dev;
424         dev = (i == 0) ? "/dev/djs0" : "/dev/djs1";
425 
426         djoyfd[i] = open(dev, O_RDONLY);
427         if (djoyfd[i] < 0) {
428             log_message(joystick_log, "Cannot open joystick device `%s'.", dev);
429         }
430     }
431 #    endif
432 }
433 
old_joystick_close(void)434 void old_joystick_close(void)
435 {
436     if (ajoyfd[0] > 0) {
437         close(ajoyfd[0]);
438     }
439     if (ajoyfd[1] > 0) {
440         close(ajoyfd[1]);
441     }
442     if (djoyfd[0] > 0) {
443         close(djoyfd[0]);
444     }
445     if (djoyfd[1] > 0) {
446         close(djoyfd[1]);
447     }
448 }
449 
old_joystick(void)450 void old_joystick(void)
451 {
452     int i;
453 
454     for (i = 1; i <= 5; i++) {
455         int joyport = joystick_port_map[i - 1];
456 
457 #    ifdef HAS_DIGITAL_JOYSTICK
458         if (joyport == JOYDEV_DIGITAL_0 || joyport == JOYDEV_DIGITAL_1) {
459             int status;
460             struct DJS_DATA_TYPE djs;
461             int djoyport = joyport - JOYDEV_DIGITAL_0;
462 
463             if (djoyfd[djoyport] > 0) {
464                 status = read(djoyfd[djoyport], &djs, DJS_RETURN);
465                 if (status != DJS_RETURN) {
466                     log_error(joystick_log, "Error reading digital joystick device.");
467                 } else {
468                     BYTE newval;
469 
470                     newval = ((joystick_get_value_absolute & 0xe0) | ((~(djs.switches >> 3)) & 0x1f));
471                     joystick_set_value_absolute(i, newval);
472                 }
473             }
474         } else
475 #    endif
476         if (joyport == JOYDEV_ANALOG_0 || joyport == JOYDEV_ANALOG_1) {
477             ssize_t status;
478             struct JS_DATA_TYPE js;
479             int ajoyport = joyport - JOYDEV_ANALOG_0;
480 
481             if (ajoyfd[ajoyport] > 0) {
482                 status = read(ajoyfd[ajoyport], &js, JS_RETURN);
483                 if (status != JS_RETURN) {
484                     log_error(joystick_log, "Error reading joystick device.");
485                 } else {
486                     joystick_set_value_absolute(i, 0);
487 
488                     if (js.y < joyymin[ajoyport]) {
489                         joystick_set_value_or(i, 1);
490                     }
491                     if (js.y > joyymax[ajoyport]) {
492                         joystick_set_value_or(i, 2);
493                     }
494                     if (js.x < joyxmin[ajoyport]) {
495                         joystick_set_value_or(i, 4);
496                     }
497                     if (js.x > joyxmax[ajoyport]) {
498                         joystick_set_value_or(i, 8);
499                     }
500 #    ifdef LINUX_JOYSTICK
501                     if (js.buttons) {
502                         joystick_set_value_or(i, 16);
503                     }
504 #    elif defined(BSD_JOYSTICK)
505                     if (js.b1 || js.b2) {
506                         joystick_set_value_or(i, 16);
507                     }
508 #    endif
509                 }
510             }
511         }
512     }
513 }
514 
515 #    ifndef NEW_JOYSTICK
new_joystick_init(void)516 void new_joystick_init(void)
517 {
518 }
519 
new_joystick_close(void)520 void new_joystick_close(void)
521 {
522 }
523 
new_joystick(void)524 void new_joystick(void)
525 {
526 }
527 #    else /* NEW_JOYSTICK */
new_joystick_init(void)528 void new_joystick_init(void)
529 {
530     int i;
531     int ver = 0;
532     int axes, buttons;
533     char name[60];
534     struct JS_DATA_TYPE js;
535 
536     const char *joydevs[ANALOG_JOY_NUM][2] = {
537         { "/dev/js0", "/dev/input/js0" },
538         { "/dev/js1", "/dev/input/js1" },
539         { "/dev/js2", "/dev/input/js2" },
540         { "/dev/js3", "/dev/input/js3" },
541         { "/dev/js4", "/dev/input/js4" },
542         { "/dev/js5", "/dev/input/js5" },
543         { "/dev/js6", "/dev/input/js6" },
544         { "/dev/js7", "/dev/input/js7" }
545     };
546 
547     if (joystick_log == LOG_ERR) {
548         joystick_log = log_open("Joystick");
549     }
550 
551     log_message(joystick_log, "Linux joystick interface initialization...");
552     /* close all device files */
553     for (i = 0; i < ANALOG_JOY_NUM; i++) {
554         if (ajoyfd[i] != -1) {
555             close (ajoyfd[i]);
556         }
557     }
558 
559     /* open analog device files */
560 
561     for (i = 0; i < ANALOG_JOY_NUM; i++) {
562         const char *dev;
563         int j;
564         for (j = 0; j < 2; j++) {
565             dev = joydevs[i][j];
566             ajoyfd[i] = open(dev, O_RDONLY);
567             if (ajoyfd[i] >= 0) {
568                 break;
569             }
570         }
571 
572         if (ajoyfd[i] >= 0) {
573             if (read (ajoyfd[i], &js, sizeof(struct JS_DATA_TYPE)) < 0) {
574                 close (ajoyfd[i]);
575                 ajoyfd[i] = -1;
576                 continue;
577             }
578             if (ioctl(ajoyfd[i], JSIOCGVERSION, &ver)) {
579                 log_message(joystick_log, "%s unknown type", dev);
580                 log_message(joystick_log, "Built in driver version: %d.%d.%d", JS_VERSION >> 16, (JS_VERSION >> 8) & 0xff, JS_VERSION & 0xff);
581                 log_message(joystick_log, "Kernel driver version  : 0.8 ??");
582                 log_message(joystick_log, "Please update your Joystick driver!");
583                 log_message(joystick_log, "Fall back to old api routine");
584                 use_old_api = 1;
585                 old_joystick_init();
586                 return;
587             }
588             ioctl(ajoyfd[i], JSIOCGVERSION, &ver);
589             ioctl(ajoyfd[i], JSIOCGAXES, &axes);
590             ioctl(ajoyfd[i], JSIOCGBUTTONS, &buttons);
591             ioctl(ajoyfd[i], JSIOCGNAME (sizeof (name)), name);
592             log_message(joystick_log, "%s is %s", dev, name);
593             log_message(joystick_log, "Built in driver version: %d.%d.%d", JS_VERSION >> 16, (JS_VERSION >> 8) & 0xff, JS_VERSION & 0xff);
594             log_message(joystick_log, "Kernel driver version  : %d.%d.%d", ver >> 16, (ver >> 8) & 0xff, ver & 0xff);
595             fcntl(ajoyfd[i], F_SETFL, O_NONBLOCK);
596         } else {
597             log_warning(joystick_log, "Cannot open joystick device `%s'.", dev);
598         }
599     }
600 }
601 
new_joystick_close(void)602 void new_joystick_close(void)
603 {
604     int i;
605 
606     for (i = 0; i < ANALOG_JOY_NUM; ++i) {
607         if (ajoyfd[i] > 0) {
608             close (ajoyfd[i]);
609         }
610     }
611 }
612 
new_joystick(void)613 void new_joystick(void)
614 {
615     int i;
616     struct js_event e;
617     int ajoyport;
618 
619     for (i = 1; i <= ANALOG_JOY_NUM; i++) {
620         int joyport = joystick_port_map[i - 1];
621 
622         if ((joyport < JOYDEV_ANALOG_0) || (joyport > JOYDEV_ANALOG_7)) {
623             continue;
624         }
625 
626         ajoyport = joyport - JOYDEV_ANALOG_0;
627 
628         if (ajoyfd[ajoyport] < 0) {
629             continue;
630         }
631 
632         /* Read all queued events. */
633         while (read(ajoyfd[ajoyport], &e, sizeof(struct js_event)) == sizeof(struct js_event)) {
634             switch (e.type & ~JS_EVENT_INIT) {
635             case JS_EVENT_BUTTON:
636                 /* Generally, only the first few buttons are "fire" on a modern
637                    joystick, the others being reserved for more esoteric things
638                    like "SELECT", "START", "PAUSE", and directional movement.
639                    The following treats only the first four buttons on a joystick
640                    as fire buttons and ignores the rest.
641                 */
642                 /* printf("e.number: %d e.value: %d\n", e.number, e.value); */
643                 /* FIXME: we need a gui to let the user map this, see SDL port */
644                 if (! (e.number & ~3)) { /* only first four buttons are fire */
645                     if (e.number == 0) {
646                         /* regular fire button */
647                         joystick_set_value_and(i, ~16); /* reset fire bit */
648                         if (e.value) {
649                             joystick_set_value_or(i, 16);
650                         }
651                     }
652                     if (e.number == 1) {
653                         /* 2nd fire button (POTX) */
654                         joystick_set_value_and(i, ~32); /* reset fire bit */
655                         if (e.value) {
656                             joystick_set_value_or(i, 32);
657                         }
658                     }
659                     if (e.number == 2) {
660                         /* 3rd fire button (POTY) */
661                         joystick_set_value_and(i, ~64); /* reset fire bit */
662                         if (e.value) {
663                             joystick_set_value_or(i, 64);
664                         }
665                     }
666                 }
667                 break;
668             case JS_EVENT_AXIS:
669                 /* printf("JS_EVENT_AXIS e.number: %d e.value: %d\n", e.number, e.value); */
670                 if (e.number == 0) {
671                     joystick_set_value_and(i, 19); /* reset 2 bit */
672                     if (e.value > 16384) {
673                         joystick_set_value_or(i, 8);
674                     } else if (e.value < -16384) {
675                         joystick_set_value_or(i, 4);
676                     }
677                 }
678                 if (e.number == 1) {
679                     joystick_set_value_and(i, 28); /* reset 2 bit */
680                     if (e.value > 16384) {
681                         joystick_set_value_or(i, 2);
682                     } else if (e.value < -16384) {
683                         joystick_set_value_or(i, 1);
684                     }
685                 }
686                 break;
687             }
688         }
689     }
690 }
691 #    endif  /* NEW_JOYSTICK */
692 
693 #endif
694