1 /*
2  *  E-UAE - The portable Amiga Emulator
3  *
4  *  BeOS joystick driver
5  *
6  *  (c) Richard Drummond 2005
7  */
8 
9 extern "C" {
10 #include "sysconfig.h"
11 #include "sysdeps.h"
12 
13 #include "options.h"
14 #include "memory_uae.h"
15 #include "custom.h"
16 #include "inputdevice.h"
17 }
18 
19 #include <device/Joystick.h>
20 #include <support/String.h>
21 
22 //#define DEBUG
23 #ifdef DEBUG
24 #define DEBUG_LOG write_log
25 #else
26 #define DEBUG_LOG(...) { }
27 #endif
28 
29 extern "C" {
30 static int           init_joysticks            (void);
31 static void          close_joysticks           (void);
32 static int           acquire_joy               (unsigned int nr, int flags);
33 static void          unacquire_joy             (unsigned int nr);
34 static void          read_joysticks            (void);
35 static unsigned int  get_joystick_count        (void);
36 static const char   *get_joystick_name         (unsigned int nr);
37 static unsigned int  get_joystick_widget_num   (unsigned int nr);
38 static int           get_joystick_widget_type  (unsigned int nr, unsigned int num, char *name);
39 static int           get_joystick_widget_first (unsigned int nr, int type);
40 };
41 
42 
43 /*
44  * The BJoystick class can't make up its mind whether it represents a joystick
45  * port or the device attached to a port.
46  *
47  * We choose to believe both and thus that there's at most one joystick attached
48  * to each port. Since USB ain't supported, I don't have any hardware which
49  * disproves that belief...
50  */
51 
52 class UAEJoystick :public BJoystick
53 {
54     public:
55 	UAEJoystick (unsigned int nr, const char *port_name);
56 
57     private:
58 	unsigned int nr;		/* Device number that UAE assigns to a joystick */
59 	BString      port_name;		/* Name used to open the joystick port */
60 	BString      name;		/* Full name used to describe this joystick to the user */
61 
62     public:
getName()63 	const char  *getName ()		{ return name.String(); }
64 
65 	int	     acquire ();
66 	void         unacquire ();
67 	void         read ();
68 };
69 
UAEJoystick(unsigned int nr,const char * port_name)70 UAEJoystick :: UAEJoystick (unsigned int nr, const char *port_name)
71 {
72     /* Create joystick name using both port and joystick name */
73     BString stick_name;
74 
75     this->Open(port_name);
76     this->GetControllerName (&stick_name);
77     this->Close ();
78 
79     this->name  = port_name;
80     this->name += ":";
81     this->name += stick_name;
82 
83     this->port_name = port_name;
84     this->nr = nr;
85 }
86 
acquire()87 int UAEJoystick :: acquire ()
88 {
89     return this->Open (this->port_name.String());
90 }
91 
unacquire()92 void UAEJoystick :: unacquire ()
93 {
94     this->Close ();
95 }
96 
read()97 void UAEJoystick :: read ()
98 {
99     DEBUG_LOG ("read: polling joy:%d\n", this->nr);
100 
101     if (this->Update () != B_ERROR) {
102 
103 	/* Read axis values */
104 	{
105 	    unsigned int nr_axes = this->CountAxes ();
106 	    int16        values[nr_axes];
107 	    unsigned int axis;
108 
109 	    this->GetAxisValues (values);
110 
111 	    for (axis = 0; axis < nr_axes; axis++)
112 		setjoystickstate (this->nr, axis, values[axis], 32767);
113 	}
114 
115 	/* Read button values */
116 	{
117 	    unsigned int nr_buttons = this->CountButtons ();
118 	    int32        values;
119 	    unsigned int button;
120 
121 	    values = this->ButtonValues ();
122 
123 	    for (button = 0; button < nr_buttons; button++) {
124 		setjoybuttonstate (this->nr, button, values & 1);
125 		values >>= 1;
126 	    }
127 	}
128    }
129 }
130 
131 
132 /*
133  * Inputdevice API
134  */
135 
136 #define MAX_JOYSTICKS	MAX_INPUT_DEVICES
137 
138 static unsigned int  nr_joysticks;
139 static UAEJoystick  *joysticks [MAX_JOYSTICKS];
140 
141 
init_joysticks(void)142 static int init_joysticks (void)
143 {
144     BJoystick joy;
145     unsigned int nr_ports;
146     unsigned int i;
147 
148     nr_joysticks = 0;
149 
150     nr_ports = joy.CountDevices ();
151     if (nr_ports > MAX_JOYSTICKS)
152 	nr_ports = MAX_JOYSTICKS;
153 
154     /*
155      * Enumerate joysticks
156      */
157 
158     for (i = 0; i < nr_ports; i++) {
159 
160 	char port_name[B_OS_NAME_LENGTH];
161 
162 	joy.GetDeviceName (i, port_name);
163 
164 	if (joy.Open (port_name)) {
165 	    BString stick_name;
166 
167 	    joy.Close ();
168 
169 	    joysticks[nr_joysticks] = new UAEJoystick (nr_joysticks, port_name);
170 
171 	    write_log ("BJoystick: device %d = %s\n", nr_joysticks,
172 						      joysticks[nr_joysticks]->getName ());
173 
174 	    nr_joysticks++;
175 	} else
176 	    DEBUG_LOG ("Failed to open port='%s'\n", port_name);
177 
178     }
179 
180     write_log ("BJoystick: Found %d joystick(s)\n", nr_joysticks);
181 
182     return 1;
183 }
184 
close_joysticks(void)185 static void close_joysticks (void)
186 {
187     unsigned int i;
188 
189     for (i = 0; i < nr_joysticks; i++)
190 	delete joysticks[i];
191 
192     nr_joysticks = 0;
193 }
194 
acquire_joy(unsigned int nr,int flags)195 static int acquire_joy (unsigned int nr, int flags)
196 {
197     int result = 0;
198 
199     DEBUG_LOG ("acquire_joy (%d)...\n", nr);
200 
201     if (nr < nr_joysticks)
202 	result = joysticks[nr]->acquire ();
203 
204     DEBUG_LOG ("%s\n", result ? "okay" : "failed");
205 
206     return result;
207 }
208 
unacquire_joy(unsigned int nr)209 static void unacquire_joy (unsigned int nr)
210 {
211     DEBUG_LOG ("unacquire_joy (%d)\n", nr);
212 
213     if (nr < nr_joysticks)
214 	joysticks[nr]->unacquire ();
215 }
216 
read_joysticks(void)217 static void read_joysticks (void)
218 {
219     unsigned int i;
220 
221     for (i = 0; i < get_joystick_count (); i++) {
222     	/* In compatibility mode, don't read joystick unless it's selected in the prefs */
223 	if (currprefs.input_selected_setting == 0) {
224 	    if (jsem_isjoy (0, &currprefs) != (int)i && jsem_isjoy (1, &currprefs) != (int)i)
225 		continue;
226 	}
227 	joysticks[i]->read ();
228     }
229 }
230 
get_joystick_num(void)231 static unsigned int get_joystick_num (void)
232 {
233     return nr_joysticks;
234 }
235 
get_joystick_friendlyname(unsigned int nr)236 static const char *get_joystick_friendlyname (unsigned int nr)
237 {
238     return joysticks[nr]->getName ();
239 }
240 
get_joystick_uniquename(unsigned int nr)241 static const char *get_joystick_uniquename (unsigned int nr)
242 {
243     return joysticks[nr]->getName ();
244 }
245 
get_joystick_widget_num(unsigned int nr)246 static unsigned int get_joystick_widget_num (unsigned int nr)
247 {
248     return joysticks[nr]->CountAxes () + joysticks[nr]->CountButtons ();
249 }
250 
get_joystick_widget_type(unsigned int nr,unsigned int widget_num,char * name,uae_u32 * what)251 static int get_joystick_widget_type (unsigned int nr, unsigned int widget_num, char *name, uae_u32 *what)
252 {
253     unsigned int nr_axes    = joysticks[nr]->CountAxes ();
254     unsigned int nr_buttons = joysticks[nr]->CountButtons ();
255 
256     if (widget_num >= nr_axes && widget_num < nr_axes + nr_buttons) {
257 	if (name)
258 	    sprintf (name, "Button %d", widget_num + 1 - nr_axes);
259 	return IDEV_WIDGET_BUTTON;
260     } else if (widget_num < nr_axes) {
261 	if (name)
262 	    sprintf (name, "Axis %d", widget_num + 1);
263 	return IDEV_WIDGET_AXIS;
264     }
265     return IDEV_WIDGET_NONE;
266 }
267 
get_joystick_widget_first(unsigned int nr,int type)268 static int get_joystick_widget_first (unsigned int nr, int type)
269 {
270     switch (type) {
271 	case IDEV_WIDGET_BUTTON:
272 	    return joysticks[nr]->CountAxes ();
273 	case IDEV_WIDGET_AXIS:
274 	    return 0;
275     }
276 
277     return -1;
278 }
279 
get_joystick_flags(int num)280 static int get_joystick_flags (int num)
281 {
282 	return 0;
283 }
284 
285 struct inputdevice_functions inputdevicefunc_joystick = {
286     init_joysticks,
287     close_joysticks,
288     acquire_joy,
289     unacquire_joy,
290     read_joysticks,
291     get_joystick_num,
292     get_joystick_friendlyname,
293     get_joystick_uniquename,
294     get_joystick_widget_num,
295     get_joystick_widget_type,
296     get_joystick_widget_first,
297 	get_joystick_flags
298 };
299 
300 /*
301  * Set default inputdevice config for joysticks
302  */
input_get_default_joystick(struct uae_input_device * uid,int num,int port,int cd32)303 int input_get_default_joystick (struct uae_input_device *uid, int num, int port, int cd32)
304 {
305     unsigned int i, port;
306 
307     for (i = 0; i < nr_joysticks; i++) {
308 	port = i & 1;
309 	uid[i].eventid[ID_AXIS_OFFSET + 0][0]   = port ? INPUTEVENT_JOY2_HORIZ : INPUTEVENT_JOY1_HORIZ;
310 	uid[i].eventid[ID_AXIS_OFFSET + 1][0]   = port ? INPUTEVENT_JOY2_VERT  : INPUTEVENT_JOY1_VERT;
311 	uid[i].eventid[ID_BUTTON_OFFSET + 0][0] = port ? INPUTEVENT_JOY2_FIRE_BUTTON : INPUTEVENT_JOY1_FIRE_BUTTON;
312 	uid[i].eventid[ID_BUTTON_OFFSET + 1][0] = port ? INPUTEVENT_JOY2_2ND_BUTTON  : INPUTEVENT_JOY1_2ND_BUTTON;
313 	uid[i].eventid[ID_BUTTON_OFFSET + 2][0] = port ? INPUTEVENT_JOY2_3RD_BUTTON  : INPUTEVENT_JOY1_3RD_BUTTON;
314     }
315     uid[0].enabled = 1;
316         if (i == 0)
317                 return 1;
318         return 0;
319 }
320