1 /* $Id: joystick.c,v 1.2 2003/01/01 00:55:03 btb Exp $ */
2 /*
3  *
4  * Linux joystick support
5  *
6  */
7 
8 #ifdef HAVE_CONFIG_H
9 #include <conf.h>
10 #endif
11 
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <linux/joystick.h>
15 #include <sys/ioctl.h>
16 #include <fcntl.h>
17 #include <unistd.h>
18 
19 #include "timer.h"
20 #include "pstypes.h"
21 #include "mono.h"
22 #include "joy.h"
23 
24 #include "joystick.h"
25 
26 char joy_installed = 0;
27 char joy_present = 0;
28 
29 joystick_device j_joystick[4];
30 joystick_axis j_axis[MAX_AXES];
31 joystick_button j_button[MAX_BUTTONS];
32 
33 int j_num_axes = 0, j_num_buttons = 0;
34 int timer_rate;
35 
36 int j_axes_in_sticks[4]; 	/* number of axes in the first [x] sticks */
37 int j_buttons_in_sticks[4];     /* number of buttons in the first [x] sticks */
38 
39 int joy_deadzone = 0;
40 
j_Get_joydev_axis_number(int all_axis_number)41 int j_Get_joydev_axis_number (int all_axis_number) {
42 	int i, joy_axis_number = all_axis_number;
43 
44 	for (i = 0; i < j_axis[all_axis_number].joydev; i++) {
45 		joy_axis_number -= j_joystick[i].num_axes;
46 	}
47 
48 	return joy_axis_number;
49 }
50 
51 
j_Get_joydev_button_number(int all_button_number)52 int j_Get_joydev_button_number (int all_button_number) {
53 	int i, joy_button_number = all_button_number;
54 
55 	for (i = 0; i < j_button[all_button_number].joydev; i++) {
56 		joy_button_number -= j_joystick[i].num_buttons;
57 	}
58 
59 	return joy_button_number;
60 }
61 
62 
j_Update_state()63 int j_Update_state () {
64 	int num_processed = 0, i;
65 	struct js_event current_event;
66 	struct JS_DATA_TYPE joy_data;
67 
68 	for (i = 0; i < j_num_buttons; i++) {
69 		//changed 6/24/1999 to finally squish the timedown bug - Owen Evans
70 		if (j_button[i].state != j_button[i].last_state) {
71 			if (j_button[i].state) {
72 				j_button[i].downcount++;
73 				j_button[i].timedown = timer_get_fixed_seconds();
74 			}
75 		}
76 		//end changed - OE
77 		j_button[i].last_state = j_button[i].state;
78 	}
79 
80 	for (i = 0; i < 4; i++) {
81 		if (j_joystick[i].buffer >= 0) {
82 			if (j_joystick[i].version) {
83 				while (read (j_joystick[i].buffer, &current_event, sizeof (struct js_event)) > 0) {
84 					num_processed++;
85 					switch (current_event.type & ~JS_EVENT_INIT) {
86 						case JS_EVENT_AXIS:
87 							j_axis[j_axes_in_sticks[i] + current_event.number].value = current_event.value;
88 							break;
89 						case JS_EVENT_BUTTON:
90 							j_button[j_buttons_in_sticks[i] + current_event.number].state = current_event.value;
91 							break;
92 					}
93 				}
94 			} else {
95 				read (j_joystick[i].buffer, &joy_data, JS_RETURN);
96 				j_axis[j_axes_in_sticks[i] + 0].value = joy_data.x;
97 				j_axis[j_axes_in_sticks[i] + 1].value = joy_data.y;
98 				j_button[j_buttons_in_sticks[i] + 0].state = (joy_data.buttons & 0x01);
99 				j_button[j_buttons_in_sticks[i] + 1].state = (joy_data.buttons & 0x02) >> 1;
100 			}
101 		}
102 	}
103 
104 	return num_processed;
105 }
106 
107 
joy_set_cal_vals(int * axis_min,int * axis_center,int * axis_max)108 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
109 {
110 /* stpohle - this is already done in the "joy_init" function, so we don't need it in here.
111 	int i;
112 
113 	for (i = 0; i < 4; i++) {
114 		j_axis[i].center_val = axis_center[i];
115 		j_axis[i].min_val = axis_min[i];
116 		j_axis[i].max_val = axis_max[i];
117 	}
118 
119 */
120 }
121 
122 
joy_get_cal_vals(int * axis_min,int * axis_center,int * axis_max)123 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max) {
124 	int i;
125 
126 	//edited 05/18/99 Matt Mueller - we should return all axes instead of j_num_axes, since they are all given to us in joy_set_cal_vals ( and because checker complains :)
127 	for (i = 0; i < 4; i++) {
128 	//end edit -MM
129 		axis_center[i] = j_axis[i].center_val;
130 		axis_min[i] = j_axis[i].min_val;
131 		axis_max[i] = j_axis[i].max_val;
132 	}
133 }
134 
135 
joy_set_min(int axis_number,int value)136 void joy_set_min (int axis_number, int value) {
137 	j_axis[axis_number].min_val = value;
138 }
139 
140 
joy_set_center(int axis_number,int value)141 void joy_set_center (int axis_number, int value) {
142 	j_axis[axis_number].center_val = value;
143 }
144 
145 
joy_set_max(int axis_number,int value)146 void joy_set_max (int axis_number, int value) {
147 	j_axis[axis_number].max_val = value;
148 }
149 
150 
joy_get_present_mask()151 ubyte joy_get_present_mask () {
152 	return 1;
153 }
154 
155 
joy_set_timer_rate(int max_value)156 void joy_set_timer_rate (int max_value) {
157 	timer_rate = max_value;
158 }
159 
160 
joy_get_timer_rate()161 int joy_get_timer_rate () {
162 	return timer_rate;
163 }
164 
165 
joy_flush()166 void joy_flush () {
167 	int i;
168 
169 	if (!joy_installed) return;
170 
171 	for (i = 0; i < j_num_buttons; i++) {
172 		j_button[i].timedown = 0;
173 		j_button[i].downcount = 0;
174 	}
175 
176 }
177 
178 
joystick_read_raw_axis(ubyte mask,int * axes)179 ubyte joystick_read_raw_axis (ubyte mask, int *axes) {
180 	int i;
181 
182 	j_Update_state();
183 
184 	for (i = 0; i < j_num_axes; i++) {
185 		axes[i] = j_axis[i].value;
186 	}
187 
188 	return 0;
189 }
190 
191 
192 /* joy_init () is pretty huge, a bit klunky, and by no means pretty.  But who cares?  It does the job and it's only run once. */
193 
194 
joy_init()195 int joy_init () {
196 	int i, j;
197 
198 	if (joy_installed) return 0;
199 	joy_flush ();
200 
201 	if (!joy_installed)	{
202 
203 		printf ("Initializing joystick... ");
204 
205 		j_joystick[0].buffer = open ("/dev/js0", O_NONBLOCK);
206 		j_joystick[1].buffer = open ("/dev/js1", O_NONBLOCK);
207 		j_joystick[2].buffer = open ("/dev/js2", O_NONBLOCK);
208 		j_joystick[3].buffer = open ("/dev/js3", O_NONBLOCK);
209 
210 		if (j_joystick[0].buffer >= 0 || j_joystick[1].buffer >= 0 || j_joystick[2].buffer >= 0 || j_joystick[3].buffer >= 0) {
211 			printf ("found: ");
212 
213 			for (i = 0; i < 4; i++) {
214 				if (j_joystick[i].buffer >= 0) {
215 					ioctl (j_joystick[i].buffer, JSIOCGAXES, &j_joystick[i].num_axes);
216 					ioctl (j_joystick[i].buffer, JSIOCGBUTTONS, &j_joystick[i].num_buttons);
217 					ioctl (j_joystick[i].buffer, JSIOCGVERSION, &j_joystick[i].version);
218 					if (!j_joystick[i].version) {
219 						j_joystick[i].num_axes = 2;
220 						j_joystick[i].num_buttons = 2;
221 						printf ("js%d (v0.x)  " , i);
222 					} else {
223 						printf ("js%d (v%d.%d.%d)  ",
224 							i,
225 							(j_joystick[i].version & 0xff0000) >> 16,
226 							(j_joystick[i].version & 0xff00) >> 8,
227 							j_joystick[i].version & 0xff);
228 					}
229 
230 					for (j = j_num_axes; j < (j_num_axes + j_joystick[i].num_axes); j++) {
231 						j_axis[j].joydev = i;
232 						if (j_joystick[i].version) {
233 							j_axis[j].center_val = 0;
234 							j_axis[j].max_val = 32767;
235 							j_axis[j].min_val = -32767;
236 						}
237 					}
238 					for (j = j_num_buttons; j < (j_num_buttons + j_joystick[i].num_buttons); j++) {
239 						j_button[j].joydev = i;
240 					}
241 
242 					j_num_axes += j_joystick[i].num_axes;
243 					j_num_buttons += j_joystick[i].num_buttons;
244 
245 				} else {
246 					j_joystick[i].num_buttons = 0;
247 					j_joystick[i].num_axes = 0;
248 				}
249 
250 				for (j = 0; j < i; j++) {
251 					j_axes_in_sticks[i] += j_joystick[j].num_axes;
252 					j_buttons_in_sticks[i] += j_joystick[j].num_buttons;
253 				}
254 			}
255 		} else {
256 			printf ("no joysticks found\n");
257 			return 0;
258 		}
259 
260 		printf ("\n");
261 
262 		if (j_num_axes > MAX_AXES)
263 			j_num_axes = MAX_AXES;
264 		if (j_num_buttons > MAX_BUTTONS)
265 			j_num_buttons = MAX_BUTTONS;
266 
267 		joy_present = 1;
268 		joy_installed = 1;
269 		return 1;
270 	}
271 
272 	return 1;
273 }
274 
275 
joy_close()276 void joy_close() {
277 	int i;
278 
279 	if (!joy_installed) return;
280 
281 	for (i = 0; i < 4; i++) {
282 		if (j_joystick[i].buffer>=0) {
283 			printf ("closing js%d\n", i);
284 			close (j_joystick[i].buffer);
285 		}
286 		j_joystick[i].buffer=-1;
287 	}
288 
289 	joy_present=0;
290 	joy_installed=0;
291 }
292 
293 
joy_set_cen()294 void joy_set_cen() {
295 }
296 
297 
joy_get_scaled_reading(int raw,int axis_num)298 int joy_get_scaled_reading(int raw, int axis_num)
299 {
300  int d, x;
301 
302   raw -= j_axis[axis_num].center_val;
303 
304    if (raw < 0)
305     d = j_axis[axis_num].center_val - j_axis[axis_num].min_val;
306    else if (raw > 0)
307     d = j_axis[axis_num].max_val - j_axis[axis_num].center_val;
308    else
309     d = 0;
310 
311    if (d)
312     x = ((raw << 7) / d);
313    else
314     x = 0;
315 
316    if ( x < -128 )
317     x = -128;
318    if ( x > 127 )
319     x = 127;
320 
321 //added on 4/13/99 by Victor Rachels to add deadzone control
322   d =  (joy_deadzone) * 6;
323    if ((x > (-1*d)) && (x < d))
324     x = 0;
325 //end this section addition -VR
326 
327   return x;
328 }
329 
330 
joy_get_pos(int * x,int * y)331 void joy_get_pos(int *x, int *y) {
332 	int axis[MAX_AXES];
333 
334 	if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; }
335 
336 	joystick_read_raw_axis (JOY_ALL_AXIS, axis);
337 
338 	*x = joy_get_scaled_reading( axis[0], 0 );
339 	*y = joy_get_scaled_reading( axis[1], 1 );
340 }
341 
342 
joy_get_btns()343 int joy_get_btns () {
344 	return 0;
345 }
346 
347 
joy_get_button_state(int btn)348 int joy_get_button_state (int btn) {
349   if(btn >= j_num_buttons)
350    return 0;
351         j_Update_state ();
352 
353         return j_button[btn].state;
354 }
355 
356 
joy_get_button_down_cnt(int btn)357 int joy_get_button_down_cnt (int btn) {
358 	int downcount;
359 
360 	j_Update_state ();
361 
362 	downcount = j_button[btn].downcount;
363 	j_button[btn].downcount = 0;
364 
365 	return downcount;
366 }
367 
368 
369 //changed 6/24/99 to finally squish the timedown bug - Owen Evans
joy_get_button_down_time(int btn)370 fix joy_get_button_down_time(int btn)  {
371 	fix downtime;
372 	j_Update_state ();
373 
374 	if (j_button[btn].state) {
375 		downtime = timer_get_fixed_seconds() - j_button[btn].timedown;
376 		j_button[btn].timedown = timer_get_fixed_seconds();
377 	} else {
378 		downtime = 0;
379 	}
380 
381 	return downtime;
382 }
383 //end changed - OE
384 
joy_poll()385 void joy_poll() {
386 
387 }
388 
389 
joy_set_slow_reading(int flag)390 void joy_set_slow_reading(int flag) {
391 
392 }
393