1 /* $Id: joystick.c,v 1.6 2004-11-22 23:32:54 btb Exp $ */
4 * Linux joystick support
14 #include <linux/joystick.h>
15 #include <sys/ioctl.h>
26 char joy_installed = 0;
29 joystick_device j_joystick[MAX_JOY_DEVS];
30 joystick_axis j_axis[JOY_MAX_AXES];
31 joystick_button j_button[MAX_BUTTONS];
33 int joy_num_axes = 0, j_num_buttons = 0;
36 int j_axes_in_sticks[MAX_JOY_DEVS]; /* number of axes in the first [x] sticks */
37 int j_buttons_in_sticks[MAX_JOY_DEVS]; /* number of buttons in the first [x] sticks */
41 int j_Get_joydev_axis_number (int all_axis_number) {
42 int i, joy_axis_number = all_axis_number;
44 for (i = 0; i < j_axis[all_axis_number].joydev; i++) {
45 joy_axis_number -= j_joystick[i].num_axes;
48 return joy_axis_number;
52 int j_Get_joydev_button_number (int all_button_number) {
53 int i, joy_button_number = all_button_number;
55 for (i = 0; i < j_button[all_button_number].joydev; i++) {
56 joy_button_number -= j_joystick[i].num_buttons;
59 return joy_button_number;
63 int j_Update_state () {
64 int num_processed = 0, i;
65 struct js_event current_event;
66 struct JS_DATA_TYPE joy_data;
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();
77 j_button[i].last_state = j_button[i].state;
80 for (i = 0; i < MAX_JOY_DEVS; i++)
82 if (j_joystick[i].buffer >= 0) {
83 if (j_joystick[i].version) {
84 while (read (j_joystick[i].buffer, ¤t_event, sizeof (struct js_event)) > 0) {
86 switch (current_event.type & ~JS_EVENT_INIT) {
88 j_axis[j_axes_in_sticks[i] + current_event.number].value = current_event.value;
91 j_button[j_buttons_in_sticks[i] + current_event.number].state = current_event.value;
96 read (j_joystick[i].buffer, &joy_data, JS_RETURN);
97 j_axis[j_axes_in_sticks[i] + 0].value = joy_data.x;
98 j_axis[j_axes_in_sticks[i] + 1].value = joy_data.y;
99 j_button[j_buttons_in_sticks[i] + 0].state = (joy_data.buttons & 0x01);
100 j_button[j_buttons_in_sticks[i] + 1].state = (joy_data.buttons & 0x02) >> 1;
105 return num_processed;
109 void joy_set_cal_vals(int *axis_min, int *axis_center, int *axis_max)
111 /* stpohle - this is already done in the "joy_init" function, so we don't need it in here.
114 for (i = 0; i < JOY_NUM_AXES; i++)
116 j_axis[i].center_val = axis_center[i];
117 j_axis[i].min_val = axis_min[i];
118 j_axis[i].max_val = axis_max[i];
125 void joy_get_cal_vals(int *axis_min, int *axis_center, int *axis_max) {
128 //edited 05/18/99 Matt Mueller - we should return all axes instead of joy_num_axes, since they are all given to us in joy_set_cal_vals ( and because checker complains :)
129 for (i = 0; i < JOY_NUM_AXES; i++)
132 axis_center[i] = j_axis[i].center_val;
133 axis_min[i] = j_axis[i].min_val;
134 axis_max[i] = j_axis[i].max_val;
139 void joy_set_min (int axis_number, int value) {
140 j_axis[axis_number].min_val = value;
144 void joy_set_center (int axis_number, int value) {
145 j_axis[axis_number].center_val = value;
149 void joy_set_max (int axis_number, int value) {
150 j_axis[axis_number].max_val = value;
154 ubyte joy_get_present_mask () {
159 void joy_set_timer_rate (int max_value) {
160 timer_rate = max_value;
164 int joy_get_timer_rate () {
172 if (!joy_installed) return;
174 for (i = 0; i < j_num_buttons; i++) {
175 j_button[i].timedown = 0;
176 j_button[i].downcount = 0;
182 ubyte joystick_read_raw_axis (ubyte mask, int *axes) {
189 for (i = 0; i < joy_num_axes; i++)
191 axes[i] = j_axis[i].value;
198 /* 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. */
205 if (joy_installed) return 0;
208 if (!joy_installed) {
210 printf ("Initializing joystick... ");
212 j_joystick[0].buffer = open ("/dev/js0", O_NONBLOCK);
213 j_joystick[1].buffer = open ("/dev/js1", O_NONBLOCK);
214 j_joystick[2].buffer = open ("/dev/js2", O_NONBLOCK);
215 j_joystick[3].buffer = open ("/dev/js3", O_NONBLOCK);
216 j_joystick[0].buffer = open("/dev/input/js0", O_NONBLOCK);
217 j_joystick[1].buffer = open("/dev/input/js1", O_NONBLOCK);
218 j_joystick[2].buffer = open("/dev/input/js2", O_NONBLOCK);
219 j_joystick[3].buffer = open("/dev/input/js3", O_NONBLOCK);
221 // Determine whether any sticks were found
223 for (i = 0; i < MAX_JOY_DEVS; i++)
225 if (j_joystick[i].buffer >= 0)
235 for (i = 0; i < MAX_JOY_DEVS; i++)
237 if (j_joystick[i].buffer >= 0) {
238 ioctl (j_joystick[i].buffer, JSIOCGAXES, &j_joystick[i].num_axes);
239 ioctl (j_joystick[i].buffer, JSIOCGBUTTONS, &j_joystick[i].num_buttons);
240 ioctl (j_joystick[i].buffer, JSIOCGVERSION, &j_joystick[i].version);
241 if (!j_joystick[i].version) {
242 j_joystick[i].num_axes = 2;
243 j_joystick[i].num_buttons = 2;
244 printf ("js%d (v0.x) " , i);
246 printf ("js%d (v%d.%d.%d) ",
248 (j_joystick[i].version & 0xff0000) >> 16,
249 (j_joystick[i].version & 0xff00) >> 8,
250 j_joystick[i].version & 0xff);
253 for (j = joy_num_axes; j < (joy_num_axes + j_joystick[i].num_axes); j++)
255 j_axis[j].joydev = i;
256 if (j_joystick[i].version) {
257 j_axis[j].center_val = 0;
258 j_axis[j].max_val = 32767;
259 j_axis[j].min_val = -32767;
262 for (j = j_num_buttons; j < (j_num_buttons + j_joystick[i].num_buttons); j++) {
263 j_button[j].joydev = i;
266 joy_num_axes += j_joystick[i].num_axes;
267 j_num_buttons += j_joystick[i].num_buttons;
270 j_joystick[i].num_buttons = 0;
271 j_joystick[i].num_axes = 0;
274 for (j = 0; j < i; j++) {
275 j_axes_in_sticks[i] += j_joystick[j].num_axes;
276 j_buttons_in_sticks[i] += j_joystick[j].num_buttons;
280 printf ("no joysticks found\n");
286 if (joy_num_axes > JOY_MAX_AXES)
287 joy_num_axes = JOY_MAX_AXES;
288 if (j_num_buttons > MAX_BUTTONS)
289 j_num_buttons = MAX_BUTTONS;
303 if (!joy_installed) return;
305 for (i = 0; i < MAX_JOY_DEVS; i++)
307 if (j_joystick[i].buffer>=0) {
308 printf ("closing js%d\n", i);
309 close (j_joystick[i].buffer);
311 j_joystick[i].buffer=-1;
323 int joy_get_scaled_reading(int raw, int axis_num)
327 raw -= j_axis[axis_num].center_val;
330 d = j_axis[axis_num].center_val - j_axis[axis_num].min_val;
332 d = j_axis[axis_num].max_val - j_axis[axis_num].center_val;
337 x = ((raw << 7) / d);
346 //added on 4/13/99 by Victor Rachels to add deadzone control
347 d = (joy_deadzone) * 6;
348 if ((x > (-1*d)) && (x < d))
350 //end this section addition -VR
356 void joy_get_pos(int *x, int *y)
358 int axis[JOY_MAX_AXES];
360 if ((!joy_installed)||(!joy_present)) { *x=*y=0; return; }
362 joystick_read_raw_axis (JOY_ALL_AXIS, axis);
364 *x = joy_get_scaled_reading( axis[0], 0 );
365 *y = joy_get_scaled_reading( axis[1], 1 );
369 int joy_get_btns () {
374 int joy_get_button_state (int btn) {
377 if(btn >= j_num_buttons)
381 return j_button[btn].state;
385 int joy_get_button_down_cnt (int btn) {
392 downcount = j_button[btn].downcount;
393 j_button[btn].downcount = 0;
399 //changed 6/24/99 to finally squish the timedown bug - Owen Evans
400 fix joy_get_button_down_time(int btn) {
407 if (j_button[btn].state) {
408 downtime = timer_get_fixed_seconds() - j_button[btn].timedown;
409 j_button[btn].timedown = timer_get_fixed_seconds();
423 void joy_set_slow_reading(int flag) {