1  /*
2   * UAE - The Un*x Amiga Emulator
3   *
4   * Joystick emulation for Linux and BSD. They share too much code to
5   * split this file.
6   *
7   * This uses the deprecated 0.x Linux joystick API.
8   *
9   * Copyright 1997 Bernd Schmidt
10   * Copyright 1998 Krister Walfridsson
11   * Copyright 2003-2006 Richard Drummond
12   * Copyright 2004 Nick Seow (Alternative Linux joystick device path)
13   */
14 
15 #include "sysconfig.h"
16 #include "sysdeps.h"
17 
18 #include "options.h"
19 #include "memory_uae.h"
20 #include "custom.h"
21 #include "inputdevice.h"
22 
23 #define JS_MAXPATHLEN  20      // Longest device name would be "/dev/input/js"
24 char js_prefix[JS_MAXPATHLEN]; // Joystick device, which varies, except number
25 
26 #ifdef HAVE_MACHINE_JOYSTICK_H
27 
28 /* The BSD way.  */
29 
30 # include <machine/joystick.h>
31 typedef struct joystick uae_joystick_t;
32 
33 #define JS_DEVNAME_PREFIX "joy"
34 
35 #else
36 
37 /* The Linux way.  */
38 
39 /* There are too many different versions of <linux/joystick.h>.  Rather
40  * than trying to work correctly with all of them, we duplicate the
41  * necessary definitions here.  */
42 typedef struct
43 {
44     int buttons;
45     int x;
46     int y;
47 } uae_joystick_t;
48 
49 #define JS_DEVNAME_PREFIX "js" // Try this first
50 
51 #endif
52 
53 /* Hard code these for the old joystick API */
54 #define MAX_BUTTONS  2
55 #define MAX_AXLES    2
56 #define FIRST_AXLE   0
57 #define FIRST_BUTTON 2
58 
59 static unsigned int nr_joysticks;
60 
61 static int js0, js1;
62 
63 struct joy_range
64 {
65     int minx, maxx, miny, maxy;
66     int centrex, centrey;
67 } range0, range1;
68 
69 
read_joy(unsigned int nr)70 static void read_joy (unsigned int nr)
71 {
72     uae_joystick_t buffer;
73     int len;
74     int fd = nr == 0 ? js0 : js1;
75     struct joy_range *r = nr == 0 ? &range0 : &range1;
76 
77     if (currprefs.input_selected_setting == 0) {
78 	if (jsem_isjoy (0, &currprefs) != (int)nr && jsem_isjoy (1, &currprefs) != (int)nr)
79 	    return;
80     }
81 
82     len = read(fd, &buffer, sizeof(buffer));
83     if (len != sizeof(buffer))
84 		return;
85 
86     /* According to old 0.x JS API, we don't know the range
87      * or the centre for either axis, so we try to work these
88      * out as we go along.
89      *
90      * Must be a better way to do this . . .
91      */
92     if (buffer.x < r->minx) r->minx = buffer.x;
93     if (buffer.y < r->miny) r->miny = buffer.y;
94     if (buffer.x > r->maxx) r->maxx = buffer.x;
95     if (buffer.y > r->maxy) r->maxy = buffer.y;
96 
97     r->centrex = (r->maxx-r->minx)/2 + r->minx;
98     r->centrey = (r->maxy-r->miny)/2 + r->miny;
99 
100     /* Translate these values to be centred on 0 and
101      * feed 'em to the inputdevice system */
102     setjoystickstate (nr, 0, buffer.x - r->centrex, r->centrex );
103     setjoystickstate (nr, 1, buffer.y - r->centrey, r->centrey );
104 
105 #ifdef HAVE_MACHINE_JOYSTICK_H
106     setjoybuttonstate (nr, 0, buffer.b1);
107     setjoybuttonstate (nr, 1, buffer.b2);
108 #else
109     setjoybuttonstate (nr, 0, buffer.buttons & 1);
110     setjoybuttonstate (nr, 1, buffer.buttons & 2);
111 #endif
112 }
113 
init_joysticks(void)114 static int init_joysticks(void)
115 {
116     char js_path[JS_MAXPATHLEN]; // temporary buffer for device name
117     nr_joysticks = 0;
118     js0 = -1; js1 = -1;
119 
120     snprintf (js_prefix, JS_MAXPATHLEN, "/dev/%s", JS_DEVNAME_PREFIX);
121 
122     snprintf (js_path, JS_MAXPATHLEN, "%s0", js_prefix);
123     if ((js0 = open (js_path, O_RDONLY)) >= 0)
124 		nr_joysticks++;
125 
126     snprintf (js_path, JS_MAXPATHLEN, "%s1", js_prefix);
127     if ((js1 = open (js_path, O_RDONLY)) >= 0)
128 		nr_joysticks++;
129 
130 #ifdef __linux__
131    if (nr_joysticks == 0) {
132 	/*
133 	 * If we haven't found any joysticks yet,
134 	 * look for /dev/input/js* nodes
135 	 */
136 	sprintf (js_prefix, "/dev/input/%s", JS_DEVNAME_PREFIX);
137 
138 	snprintf (js_path, JS_MAXPATHLEN, "%s0", js_prefix);
139 	if ((js0 = open (js_path, O_RDONLY)) >= 0)
140 	    nr_joysticks++;
141 
142 	snprintf (js_path, JS_MAXPATHLEN, "%s1", js_prefix);
143 	if ((js1 = open (js_path, O_RDONLY)) >= 0)
144 	    nr_joysticks++;
145     }
146 #endif
147 
148     write_log ("Found %d joystick(s)\n", nr_joysticks);
149 
150     range0.minx = INT_MAX;
151     range0.maxx = INT_MIN;
152     range0.miny = INT_MAX;
153     range0.maxy = INT_MIN;
154     range1.minx = INT_MAX;
155     range1.maxx = INT_MIN;
156     range1.miny = INT_MAX;
157     range1.maxy = INT_MIN;
158     range0.centrex = 0;
159     range1.centrey = 0;
160     return 1;
161 }
162 
close_joysticks(void)163 static void close_joysticks(void)
164 {
165     if (js0 >= 0)
166 		close (js0);
167     if (js1 >= 0)
168 		close (js1);
169 }
170 
get_joystick_num(void)171 static int get_joystick_num (void)
172 {
173     return nr_joysticks;
174 }
175 
acquire_joy(int num,int flags)176 static int acquire_joy (int num, int flags)
177 {
178     return 1;
179 }
180 
unacquire_joy(int num)181 static void unacquire_joy (int num)
182 {
183 }
184 
read_joysticks(void)185 static void read_joysticks (void)
186 {
187     int i = 0;
188     for ( ; i < get_joystick_num(); i++)
189 		read_joy (i);
190 }
191 
get_joystick_friendlyname(int joy)192 static TCHAR *get_joystick_friendlyname (int joy)
193 {
194     static char name[100];
195     sprintf (name, "%d: %s%d", joy + 1, js_prefix, joy);
196     return name;
197 }
198 
get_joystick_uniquename(int joy)199 static TCHAR *get_joystick_uniquename (int joy)
200 {
201     static char name[100];
202     sprintf (name, "%d%s%d", joy + 1, js_prefix, joy);
203     return name;
204 }
205 
get_joystick_widget_num(int joy)206 static int get_joystick_widget_num (int joy)
207 {
208     return MAX_AXLES + MAX_BUTTONS;
209 }
210 
get_joystick_widget_type(int joy,int num,TCHAR * name,uae_u32 * dummy)211 static int get_joystick_widget_type (int joy, int num, TCHAR *name, uae_u32 *dummy)
212 {
213     if (num >= MAX_AXLES && num < MAX_AXLES+MAX_BUTTONS) {
214 	if (name)
215 	    sprintf (name, "Button %d", num + 1 - MAX_AXLES);
216 	return IDEV_WIDGET_BUTTON;
217     } else if (num < MAX_AXLES) {
218 	if (name)
219 	    sprintf (name, "Axis %d", num + 1);
220 	return IDEV_WIDGET_AXIS;
221     }
222     return IDEV_WIDGET_NONE;
223 }
224 
get_joystick_widget_first(int joy,int type)225 static int get_joystick_widget_first (int joy, int type)
226 {
227     switch (type) {
228 	case IDEV_WIDGET_BUTTON:
229 	    return FIRST_BUTTON;
230 	case IDEV_WIDGET_AXIS:
231 	    return FIRST_AXLE;
232     }
233 
234     return -1;
235 }
236 
get_joystick_flags(int num)237 static int get_joystick_flags (int num)
238 {
239 	return 0;
240 }
241 
242 struct inputdevice_functions inputdevicefunc_joystick = {
243     init_joysticks,
244     close_joysticks,
245     acquire_joy,
246     unacquire_joy,
247     read_joysticks,
248     get_joystick_num,
249     get_joystick_friendlyname,
250     get_joystick_uniquename,
251     get_joystick_widget_num,
252     get_joystick_widget_type,
253     get_joystick_widget_first,
254 	get_joystick_flags
255 };
256 
257 /*
258  * Set default inputdevice config for joysticks
259  */
input_get_default_joystick(struct uae_input_device * uid,int num,int port,int af,int mode,bool gp)260 int input_get_default_joystick (struct uae_input_device *uid, int num, int port, int af, int mode, bool gp)
261 {
262 	unsigned int i;
263 
264     for (i = 0; i < nr_joysticks; i++) {
265 		port = i & 1;
266 		uid[i].eventid[ID_AXIS_OFFSET + 0][0]   = port ? INPUTEVENT_JOY2_HORIZ : INPUTEVENT_JOY1_HORIZ;
267 		uid[i].eventid[ID_AXIS_OFFSET + 1][0]   = port ? INPUTEVENT_JOY2_VERT  : INPUTEVENT_JOY1_VERT;
268 		uid[i].eventid[ID_BUTTON_OFFSET + 0][0] = port ? INPUTEVENT_JOY2_FIRE_BUTTON : INPUTEVENT_JOY1_FIRE_BUTTON;
269 		uid[i].eventid[ID_BUTTON_OFFSET + 1][0] = port ? INPUTEVENT_JOY2_2ND_BUTTON  : INPUTEVENT_JOY1_2ND_BUTTON;
270 		uid[i].eventid[ID_BUTTON_OFFSET + 2][0] = port ? INPUTEVENT_JOY2_3RD_BUTTON  : INPUTEVENT_JOY1_3RD_BUTTON;
271     }
272     uid[0].enabled = 1;
273 
274 	if (i == 0)
275 		return 1;
276 	return 0;
277 }
278