]>
Commit | Line | Data |
---|---|---|
c7de829c WD |
1 | /**************************************************************************** |
2 | * | |
3 | * SciTech Multi-platform Graphics Library | |
4 | * | |
5 | * ======================================================================== | |
6 | * | |
7 | * The contents of this file are subject to the SciTech MGL Public | |
8 | * License Version 1.0 (the "License"); you may not use this file | |
9 | * except in compliance with the License. You may obtain a copy of | |
10 | * the License at http://www.scitechsoft.com/mgl-license.txt | |
11 | * | |
12 | * Software distributed under the License is distributed on an | |
13 | * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | |
14 | * implied. See the License for the specific language governing | |
15 | * rights and limitations under the License. | |
16 | * | |
17 | * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc. | |
18 | * | |
19 | * The Initial Developer of the Original Code is SciTech Software, Inc. | |
20 | * All Rights Reserved. | |
21 | * | |
22 | * ======================================================================== | |
23 | * | |
24 | * Language: ANSI C | |
25 | * Environment: Linux | |
26 | * | |
27 | * Description: Linux fullscreen console implementation for the SciTech | |
28 | * cross platform event library. | |
29 | * Portions ripped straigth from the gpm source code for mouse | |
30 | * handling. | |
31 | * | |
32 | ****************************************************************************/ | |
33 | ||
34 | /*---------------------------- Global Variables ---------------------------*/ | |
35 | ||
36 | extern int _PM_console_fd; | |
37 | static ushort keyUpMsg[256] = {0}; | |
38 | static int _EVT_mouse_fd = 0; | |
39 | static int range_x, range_y; | |
40 | static int opt_baud = 1200, opt_sample = 100; | |
41 | #ifdef USE_OS_JOYSTICK | |
42 | static short *axis0 = NULL, *axis1 = NULL; | |
43 | static uchar *buts0 = NULL, *buts1 = NULL; | |
44 | static int joystick0_fd = 0, joystick1_fd = 0; | |
45 | static int js_version = 0; | |
46 | #endif | |
47 | ||
48 | /* This defines the supported mouse drivers */ | |
49 | ||
50 | typedef enum { | |
51 | EVT_noMouse = -1, | |
52 | EVT_microsoft = 0, | |
53 | EVT_ps2, | |
54 | EVT_mousesystems, | |
55 | EVT_gpm, | |
56 | EVT_MMseries, | |
57 | EVT_logitech, | |
58 | EVT_busmouse, | |
59 | EVT_mouseman, | |
60 | EVT_intellimouse, | |
61 | EVT_intellimouse_ps2, | |
62 | } mouse_drivers_t; | |
63 | ||
64 | static mouse_drivers_t mouse_driver = EVT_noMouse; | |
65 | static char mouse_dev[20] = "/dev/mouse"; | |
66 | ||
67 | typedef struct { | |
68 | char *name; | |
69 | int flags; | |
70 | void (*init)(void); | |
71 | uchar proto[4]; | |
72 | int packet_len; | |
73 | int read; | |
74 | } mouse_info; | |
75 | ||
76 | #define STD_FLG (CREAD | CLOCAL | HUPCL) | |
77 | ||
78 | static void _EVT_mouse_init(void); | |
79 | static void _EVT_logitech_init(void); | |
80 | static void _EVT_pnpmouse_init(void); | |
81 | ||
82 | mouse_info mouse_infos[] = { | |
83 | {"Microsoft", CS7 | B1200 | STD_FLG, _EVT_mouse_init, {0x40, 0x40, 0x40, 0x00}, 3, 1}, | |
84 | {"PS2", STD_FLG, NULL, {0xc0, 0x00, 0x00, 0x00}, 3, 1}, | |
85 | {"MouseSystems", CS8 | CSTOPB | STD_FLG, _EVT_mouse_init, {0xf8, 0x80, 0x00, 0x00}, 5, 5}, | |
86 | {"GPM", CS8 | CSTOPB | STD_FLG, NULL, {0xf8, 0x80, 0x00, 0x00}, 5, 5}, | |
87 | {"MMSeries", CS8 | PARENB | PARODD | STD_FLG, _EVT_mouse_init, {0xe0, 0x80, 0x80, 0x00}, 3, 1}, | |
88 | {"Logitech", CS8 | CSTOPB | STD_FLG, _EVT_logitech_init, {0xe0, 0x80, 0x80, 0x00}, 3, 3}, | |
89 | {"BusMouse", STD_FLG, NULL, {0xf8, 0x80, 0x00, 0x00}, 3, 3}, | |
90 | {"MouseMan", CS7 | STD_FLG, _EVT_mouse_init, {0x40, 0x40, 0x40, 0x00}, 3, 1}, | |
91 | {"IntelliMouse", CS7 | STD_FLG, _EVT_pnpmouse_init, {0xc0, 0x40, 0xc0, 0x00}, 4, 1}, | |
8bde7f77 | 92 | {"IMPS2", CS7 | STD_FLG, NULL, {0xc0, 0x40, 0xc0, 0x00}, 4, 1}, /* ? */ |
c7de829c WD |
93 | }; |
94 | ||
95 | #define NB_MICE (sizeof(mouse_infos)/sizeof(mouse_info)) | |
96 | ||
97 | /* The name of the environment variables that are used to change the defaults above */ | |
98 | ||
99 | #define ENV_MOUSEDRV "MGL_MOUSEDRV" | |
100 | #define ENV_MOUSEDEV "MGL_MOUSEDEV" | |
101 | #define ENV_MOUSESPD "MGL_MOUSESPD" | |
102 | #define ENV_JOYDEV0 "MGL_JOYDEV1" | |
103 | #define ENV_JOYDEV1 "MGL_JOYDEV2" | |
104 | ||
105 | /* Scancode mappings on Linux for special keys */ | |
106 | ||
107 | typedef struct { | |
108 | int scan; | |
109 | int map; | |
110 | } keymap; | |
111 | ||
8bde7f77 | 112 | /* TODO: Fix this and set it up so we can do a binary search! */ |
c7de829c WD |
113 | |
114 | keymap keymaps[] = { | |
115 | {96, KB_padEnter}, | |
116 | {74, KB_padMinus}, | |
117 | {78, KB_padPlus}, | |
118 | {55, KB_padTimes}, | |
119 | {98, KB_padDivide}, | |
120 | {71, KB_padHome}, | |
121 | {72, KB_padUp}, | |
122 | {73, KB_padPageUp}, | |
123 | {75, KB_padLeft}, | |
124 | {76, KB_padCenter}, | |
125 | {77, KB_padRight}, | |
126 | {79, KB_padEnd}, | |
127 | {80, KB_padDown}, | |
128 | {81, KB_padPageDown}, | |
129 | {82, KB_padInsert}, | |
130 | {83, KB_padDelete}, | |
131 | {105,KB_left}, | |
132 | {108,KB_down}, | |
133 | {106,KB_right}, | |
134 | {103,KB_up}, | |
135 | {110,KB_insert}, | |
136 | {102,KB_home}, | |
137 | {104,KB_pageUp}, | |
138 | {111,KB_delete}, | |
139 | {107,KB_end}, | |
140 | {109,KB_pageDown}, | |
141 | {125,KB_leftWindows}, | |
142 | {126,KB_rightWindows}, | |
143 | {127,KB_menu}, | |
144 | {100,KB_rightAlt}, | |
145 | {97,KB_rightCtrl}, | |
146 | }; | |
147 | ||
148 | /* And the keypad with num lock turned on (changes the ASCII code only) */ | |
149 | ||
150 | keymap keypad[] = { | |
151 | {71, ASCII_7}, | |
152 | {72, ASCII_8}, | |
153 | {73, ASCII_9}, | |
154 | {75, ASCII_4}, | |
155 | {76, ASCII_5}, | |
156 | {77, ASCII_6}, | |
157 | {79, ASCII_1}, | |
158 | {80, ASCII_2}, | |
159 | {81, ASCII_3}, | |
160 | {82, ASCII_0}, | |
161 | {83, ASCII_period}, | |
162 | }; | |
163 | ||
164 | #define NB_KEYMAPS (sizeof(keymaps)/sizeof(keymaps[0])) | |
165 | #define NB_KEYPAD (sizeof(keypad)/sizeof(keypad[0])) | |
166 | ||
167 | typedef struct { | |
168 | int sample; | |
169 | char code[2]; | |
170 | } sample_rate; | |
171 | ||
172 | sample_rate sampletab[]={ | |
173 | { 0,"O"}, | |
174 | { 15,"J"}, | |
175 | { 27,"K"}, | |
176 | { 42,"L"}, | |
177 | { 60,"R"}, | |
178 | { 85,"M"}, | |
179 | {125,"Q"}, | |
180 | {1E9,"N"}, | |
181 | }; | |
182 | ||
183 | /* Number of keycodes to read at a time from the console */ | |
184 | ||
185 | #define KBDREADBUFFERSIZE 32 | |
186 | ||
187 | /*---------------------------- Implementation -----------------------------*/ | |
188 | ||
189 | /* These are not used under Linux */ | |
190 | #define _EVT_disableInt() 1 | |
191 | #define _EVT_restoreInt(flaps) | |
192 | ||
193 | /**************************************************************************** | |
194 | PARAMETERS: | |
195 | scanCode - Scan code to test | |
196 | ||
197 | REMARKS: | |
198 | This macro determines if a specified key is currently down at the | |
199 | time that the call is made. | |
200 | ****************************************************************************/ | |
201 | #define _EVT_isKeyDown(scanCode) (keyUpMsg[scanCode] != 0) | |
202 | ||
203 | /**************************************************************************** | |
204 | REMARKS: | |
205 | This function is used to return the number of ticks since system | |
206 | startup in milliseconds. This should be the same value that is placed into | |
207 | the time stamp fields of events, and is used to implement auto mouse down | |
208 | events. | |
209 | ****************************************************************************/ | |
210 | ulong _EVT_getTicks(void) | |
211 | { | |
212 | static uint starttime = 0; | |
213 | struct timeval t; | |
214 | ||
215 | gettimeofday(&t, NULL); | |
216 | if (starttime == 0) | |
217 | starttime = t.tv_sec * 1000 + (t.tv_usec/1000); | |
218 | return ((t.tv_sec * 1000 + (t.tv_usec/1000)) - starttime); | |
219 | } | |
220 | ||
221 | /**************************************************************************** | |
222 | REMARKS: | |
223 | Small Unix function that checks for availability on a file using select() | |
224 | ****************************************************************************/ | |
225 | static ibool dataReady( | |
226 | int fd) | |
227 | { | |
228 | static struct timeval t = { 0L, 0L }; | |
229 | fd_set fds; | |
230 | ||
231 | FD_ZERO(&fds); | |
232 | FD_SET(fd, &fds); | |
233 | return select(fd+1, &fds, NULL, NULL, &t) > 0; | |
234 | } | |
235 | ||
236 | /**************************************************************************** | |
237 | REMARKS: | |
238 | Reads mouse data according to the selected mouse driver. | |
239 | ****************************************************************************/ | |
240 | static ibool readMouseData( | |
241 | int *buttons, | |
242 | int *dx, | |
243 | int *dy) | |
244 | { | |
245 | static uchar data[32],prev = 0; | |
246 | int cnt = 0,ret; | |
247 | mouse_info *drv; | |
248 | ||
249 | /* Read the first byte to check for the protocol */ | |
250 | drv = &mouse_infos[mouse_driver]; | |
251 | if (read(_EVT_mouse_fd, data, drv->read) != drv->read) { | |
8bde7f77 WD |
252 | perror("read"); |
253 | return false; | |
254 | } | |
c7de829c | 255 | if ((data[0] & drv->proto[0]) != drv->proto[1]) |
8bde7f77 | 256 | return false; |
c7de829c WD |
257 | |
258 | /* Load a whole protocol packet */ | |
259 | cnt += drv->read; | |
260 | while (cnt < drv->packet_len) { | |
8bde7f77 WD |
261 | ret = read(_EVT_mouse_fd, data+cnt, drv->read); |
262 | if (ret == drv->read) | |
263 | cnt += ret; | |
264 | else { | |
265 | perror("read"); | |
266 | return false; | |
267 | } | |
268 | } | |
c7de829c | 269 | if ((data[1] & drv->proto[2]) != drv->proto[3]) |
8bde7f77 | 270 | return false; |
c7de829c WD |
271 | |
272 | /* Now decode the protocol packet */ | |
273 | switch (mouse_driver) { | |
8bde7f77 WD |
274 | case EVT_microsoft: |
275 | if (data[0] == 0x40 && !(prev|data[1]|data[2])) | |
276 | *buttons = 2; /* Third button on MS compatible mouse */ | |
277 | else | |
278 | *buttons= ((data[0] & 0x20) >> 3) | ((data[0] & 0x10) >> 4); | |
279 | prev = *buttons; | |
280 | *dx = (char)(((data[0] & 0x03) << 6) | (data[1] & 0x3F)); | |
281 | *dy = (char)(((data[0] & 0x0C) << 4) | (data[2] & 0x3F)); | |
282 | break; | |
283 | case EVT_ps2: | |
284 | *buttons = !!(data[0]&1) * 4 + !!(data[0]&2) * 1 + !!(data[0]&4) * 2; | |
285 | if (data[1] != 0) | |
286 | *dx = (data[0] & 0x10) ? data[1]-256 : data[1]; | |
287 | else | |
288 | *dx = 0; | |
289 | if (data[2] != 0) | |
290 | *dy = -((data[0] & 0x20) ? data[2]-256 : data[2]); | |
291 | else | |
292 | *dy = 0; | |
293 | break; | |
294 | case EVT_mousesystems: case EVT_gpm: | |
295 | *buttons = (~data[0]) & 0x07; | |
296 | *dx = (char)(data[1]) + (char)(data[3]); | |
297 | *dy = -((char)(data[2]) + (char)(data[4])); | |
298 | break; | |
299 | case EVT_logitech: | |
300 | *buttons= data[0] & 0x07; | |
301 | *dx = (data[0] & 0x10) ? data[1] : - data[1]; | |
302 | *dy = (data[0] & 0x08) ? - data[2] : data[2]; | |
303 | break; | |
304 | case EVT_busmouse: | |
305 | *buttons= (~data[0]) & 0x07; | |
306 | *dx = (char)data[1]; | |
307 | *dy = -(char)data[2]; | |
308 | break; | |
309 | case EVT_MMseries: | |
310 | *buttons = data[0] & 0x07; | |
311 | *dx = (data[0] & 0x10) ? data[1] : - data[1]; | |
312 | *dy = (data[0] & 0x08) ? - data[2] : data[2]; | |
313 | break; | |
314 | case EVT_intellimouse: | |
315 | *buttons = ((data[0] & 0x20) >> 3) /* left */ | |
316 | | ((data[3] & 0x10) >> 3) /* middle */ | |
317 | | ((data[0] & 0x10) >> 4); /* right */ | |
318 | *dx = (char)(((data[0] & 0x03) << 6) | (data[1] & 0x3F)); | |
319 | *dy = (char)(((data[0] & 0x0C) << 4) | (data[2] & 0x3F)); | |
320 | break; | |
321 | case EVT_intellimouse_ps2: | |
322 | *buttons = (data[0] & 0x04) >> 1 /* Middle */ | |
323 | | (data[0] & 0x02) >> 1 /* Right */ | |
324 | | (data[0] & 0x01) << 2; /* Left */ | |
325 | *dx = (data[0] & 0x10) ? data[1]-256 : data[1]; | |
326 | *dy = (data[0] & 0x20) ? -(data[2]-256) : -data[2]; | |
327 | break; | |
328 | case EVT_mouseman: { | |
329 | static int getextra; | |
330 | static uchar prev=0; | |
331 | uchar b; | |
332 | ||
333 | /* The damned MouseMan has 3/4 bytes packets. The extra byte | |
334 | * is only there if the middle button is active. | |
335 | * I get the extra byte as a packet with magic numbers in it. | |
336 | * and then switch to 4-byte mode. | |
337 | */ | |
338 | if (data[1] == 0xAA && data[2] == 0x55) { | |
339 | /* Got unexpected fourth byte */ | |
340 | if ((b = (*data>>4)) > 0x3) | |
341 | return false; /* just a sanity check */ | |
342 | *dx = *dy = 0; | |
343 | drv->packet_len=4; | |
344 | getextra=0; | |
345 | } | |
346 | else { | |
347 | /* Got 3/4, as expected */ | |
348 | /* Motion is independent of packetlen... */ | |
349 | *dx = (char)(((data[0] & 0x03) << 6) | (data[1] & 0x3F)); | |
350 | *dy = (char)(((data[0] & 0x0C) << 4) | (data[2] & 0x3F)); | |
351 | prev = ((data[0] & 0x20) >> 3) | ((data[0] & 0x10) >> 4); | |
352 | if (drv->packet_len==4) | |
353 | b = data[3]>>4; | |
354 | } | |
355 | if (drv->packet_len == 4) { | |
356 | if (b == 0) { | |
357 | drv->packet_len = 3; | |
358 | getextra = 1; | |
359 | } | |
360 | else { | |
361 | if (b & 0x2) | |
362 | prev |= 2; | |
363 | } | |
364 | } | |
365 | *buttons = prev; | |
366 | ||
367 | /* This "chord-middle" behaviour was reported by David A. van Leeuwen */ | |
368 | if (((prev ^ *buttons) & 5) == 5) | |
369 | *buttons = *buttons ? 2 : 0; | |
370 | prev = *buttons; | |
371 | break; | |
372 | } | |
373 | case EVT_noMouse: | |
374 | return false; | |
375 | break; | |
376 | } | |
c7de829c WD |
377 | return true; |
378 | } | |
379 | ||
380 | /**************************************************************************** | |
381 | REMARKS: | |
382 | Map a keypress via the key mapping table | |
383 | ****************************************************************************/ | |
384 | static int getKeyMapping( | |
385 | keymap *tab, | |
386 | int nb, | |
387 | int key) | |
388 | { | |
389 | int i; | |
390 | ||
391 | for(i = 0; i < nb; i++) { | |
8bde7f77 WD |
392 | if (tab[i].scan == key) |
393 | return tab[i].map; | |
394 | } | |
c7de829c WD |
395 | return key; |
396 | } | |
397 | ||
398 | #ifdef USE_OS_JOYSTICK | |
399 | ||
400 | static char js0_axes = 0, js0_buttons = 0; | |
401 | static char js1_axes = 0, js1_buttons = 0; | |
402 | static char joystick0_dev[20] = "/dev/js0"; | |
403 | static char joystick1_dev[20] = "/dev/js1"; | |
404 | ||
405 | /**************************************************************************** | |
406 | REMARKS: | |
407 | Create a joystick event from the joystick data | |
408 | ****************************************************************************/ | |
409 | static void makeJoyEvent( | |
410 | event_t *evt) | |
411 | { | |
412 | evt->message = 0; | |
413 | if (buts0 && axis0) { | |
8bde7f77 WD |
414 | if (buts0[0]) evt->message |= EVT_JOY1_BUTTONA; |
415 | if (buts0[1]) evt->message |= EVT_JOY1_BUTTONB; | |
416 | evt->where_x = axis0[0]; | |
417 | evt->where_y = axis0[1]; | |
418 | } | |
c7de829c | 419 | else |
8bde7f77 | 420 | evt->where_x = evt->where_y = 0; |
c7de829c | 421 | if (buts1 && axis1) { |
8bde7f77 WD |
422 | if (buts1[0]) evt->message |= EVT_JOY2_BUTTONA; |
423 | if (buts1[1]) evt->message |= EVT_JOY2_BUTTONB; | |
424 | evt->where_x = axis1[0]; | |
425 | evt->where_y = axis1[1]; | |
426 | } | |
c7de829c | 427 | else |
8bde7f77 | 428 | evt->where_x = evt->where_y = 0; |
c7de829c WD |
429 | } |
430 | ||
431 | /**************************************************************************** | |
432 | REMARKS: | |
433 | Read the joystick axis data | |
434 | ****************************************************************************/ | |
435 | int EVTAPI _EVT_readJoyAxis( | |
436 | int jmask, | |
437 | int *axis) | |
438 | { | |
439 | int mask = 0; | |
440 | ||
441 | if ((js_version & ~0xffff) == 0) { | |
8bde7f77 WD |
442 | /* Old 0.x driver */ |
443 | struct JS_DATA_TYPE js; | |
444 | if (joystick0_fd && read(joystick0_fd, &js, JS_RETURN) == JS_RETURN) { | |
445 | if (jmask & EVT_JOY_AXIS_X1) | |
446 | axis[0] = js.x; | |
447 | if (jmask & EVT_JOY_AXIS_Y1) | |
448 | axis[1] = js.y; | |
449 | mask |= EVT_JOY_AXIS_X1|EVT_JOY_AXIS_Y1; | |
450 | } | |
451 | if (joystick1_fd && read(joystick1_fd, &js, JS_RETURN) == JS_RETURN) { | |
452 | if (jmask & EVT_JOY_AXIS_X2) | |
453 | axis[2] = js.x; | |
454 | if (jmask & EVT_JOY_AXIS_Y2) | |
455 | axis[3] = js.y; | |
456 | mask |= EVT_JOY_AXIS_X2|EVT_JOY_AXIS_Y2; | |
457 | } | |
458 | } | |
c7de829c | 459 | else { |
8bde7f77 WD |
460 | if (axis0) { |
461 | if (jmask & EVT_JOY_AXIS_X1) | |
462 | axis[0] = axis0[0]; | |
463 | if (jmask & EVT_JOY_AXIS_Y1) | |
464 | axis[1] = axis0[1]; | |
465 | mask |= EVT_JOY_AXIS_X1 | EVT_JOY_AXIS_Y1; | |
466 | } | |
467 | if (axis1) { | |
468 | if (jmask & EVT_JOY_AXIS_X2) | |
469 | axis[2] = axis1[0]; | |
470 | if (jmask & EVT_JOY_AXIS_Y2) | |
471 | axis[3] = axis1[1]; | |
472 | mask |= EVT_JOY_AXIS_X2 | EVT_JOY_AXIS_Y2; | |
473 | } | |
474 | } | |
c7de829c WD |
475 | return mask; |
476 | } | |
477 | ||
478 | /**************************************************************************** | |
479 | REMARKS: | |
480 | Read the joystick button data | |
481 | ****************************************************************************/ | |
482 | int EVTAPI _EVT_readJoyButtons(void) | |
483 | { | |
484 | int buts = 0; | |
485 | ||
486 | if ((js_version & ~0xffff) == 0) { | |
8bde7f77 WD |
487 | /* Old 0.x driver */ |
488 | struct JS_DATA_TYPE js; | |
489 | if (joystick0_fd && read(joystick0_fd, &js, JS_RETURN) == JS_RETURN) | |
490 | buts = js.buttons; | |
491 | if (joystick1_fd && read(joystick1_fd, &js, JS_RETURN) == JS_RETURN) | |
492 | buts |= js.buttons << 2; | |
493 | } | |
c7de829c | 494 | else { |
8bde7f77 WD |
495 | if (buts0) |
496 | buts |= EVT_JOY1_BUTTONA*buts0[0] + EVT_JOY1_BUTTONB*buts0[1]; | |
497 | if (buts1) | |
498 | buts |= EVT_JOY2_BUTTONA*buts1[0] + EVT_JOY2_BUTTONB*buts1[1]; | |
499 | } | |
c7de829c WD |
500 | return buts; |
501 | } | |
502 | ||
503 | /**************************************************************************** | |
504 | DESCRIPTION: | |
505 | Returns the mask indicating what joystick axes are attached. | |
506 | ||
507 | HEADER: | |
508 | event.h | |
509 | ||
510 | REMARKS: | |
511 | This function is used to detect the attached joysticks, and determine | |
512 | what axes are present and functioning. This function will re-detect any | |
513 | attached joysticks when it is called, so if the user forgot to attach | |
514 | the joystick when the application started, you can call this function to | |
515 | re-detect any newly attached joysticks. | |
516 | ||
517 | SEE ALSO: | |
518 | EVT_joySetLowerRight, EVT_joySetCenter, EVT_joyIsPresent | |
519 | ****************************************************************************/ | |
520 | int EVTAPI EVT_joyIsPresent(void) | |
521 | { | |
522 | static int mask = 0; | |
523 | int i; | |
524 | char *tmp, name0[128], name1[128]; | |
525 | static ibool inited = false; | |
526 | ||
527 | if (inited) | |
8bde7f77 | 528 | return mask; |
c7de829c WD |
529 | memset(EVT.joyMin,0,sizeof(EVT.joyMin)); |
530 | memset(EVT.joyCenter,0,sizeof(EVT.joyCenter)); | |
531 | memset(EVT.joyMax,0,sizeof(EVT.joyMax)); | |
532 | memset(EVT.joyPrev,0,sizeof(EVT.joyPrev)); | |
533 | EVT.joyButState = 0; | |
534 | if ((tmp = getenv(ENV_JOYDEV0)) != NULL) | |
8bde7f77 | 535 | strcpy(joystick0_dev,tmp); |
c7de829c | 536 | if ((tmp = getenv(ENV_JOYDEV1)) != NULL) |
8bde7f77 | 537 | strcpy(joystick1_dev,tmp); |
c7de829c | 538 | if ((joystick0_fd = open(joystick0_dev, O_RDONLY)) < 0) |
8bde7f77 | 539 | joystick0_fd = 0; |
c7de829c | 540 | if ((joystick1_fd = open(joystick1_dev, O_RDONLY)) < 0) |
8bde7f77 WD |
541 | joystick1_fd = 0; |
542 | if (!joystick0_fd && !joystick1_fd) /* No joysticks detected */ | |
543 | return 0; | |
c7de829c WD |
544 | inited = true; |
545 | if (ioctl(joystick0_fd ? joystick0_fd : joystick1_fd, JSIOCGVERSION, &js_version) < 0) | |
8bde7f77 | 546 | return 0; |
c7de829c WD |
547 | |
548 | /* Initialise joystick 0 */ | |
549 | if (joystick0_fd) { | |
8bde7f77 WD |
550 | ioctl(joystick0_fd, JSIOCGNAME(sizeof(name0)), name0); |
551 | if (js_version & ~0xffff) { | |
552 | struct js_event js; | |
553 | ||
554 | ioctl(joystick0_fd, JSIOCGAXES, &js0_axes); | |
555 | ioctl(joystick0_fd, JSIOCGBUTTONS, &js0_buttons); | |
556 | axis0 = PM_calloc((int)js0_axes, sizeof(short)); | |
557 | buts0 = PM_malloc((int)js0_buttons); | |
558 | /* Read the initial events */ | |
559 | while(dataReady(joystick0_fd) | |
560 | && read(joystick0_fd, &js, sizeof(struct js_event)) == sizeof(struct js_event) | |
561 | && (js.type & JS_EVENT_INIT) | |
562 | ) { | |
563 | if (js.type & JS_EVENT_BUTTON) | |
564 | buts0[js.number] = js.value; | |
565 | else if (js.type & JS_EVENT_AXIS) | |
566 | axis0[js.number] = scaleJoyAxis(js.value,js.number); | |
567 | } | |
568 | } | |
569 | else { | |
570 | js0_axes = 2; | |
571 | js0_buttons = 2; | |
572 | axis0 = PM_calloc((int)js0_axes, sizeof(short)); | |
573 | buts0 = PM_malloc((int)js0_buttons); | |
574 | } | |
575 | } | |
c7de829c WD |
576 | |
577 | /* Initialise joystick 1 */ | |
578 | if (joystick1_fd) { | |
8bde7f77 WD |
579 | ioctl(joystick1_fd, JSIOCGNAME(sizeof(name1)), name1); |
580 | if (js_version & ~0xffff) { | |
581 | struct js_event js; | |
582 | ||
583 | ioctl(joystick1_fd, JSIOCGAXES, &js1_axes); | |
584 | ioctl(joystick1_fd, JSIOCGBUTTONS, &js1_buttons); | |
585 | axis1 = PM_calloc((int)js1_axes, sizeof(short)); | |
586 | buts1 = PM_malloc((int)js1_buttons); | |
587 | /* Read the initial events */ | |
588 | while(dataReady(joystick1_fd) | |
589 | && read(joystick1_fd, &js, sizeof(struct js_event))==sizeof(struct js_event) | |
590 | && (js.type & JS_EVENT_INIT) | |
591 | ) { | |
592 | if (js.type & JS_EVENT_BUTTON) | |
593 | buts1[js.number] = js.value; | |
594 | else if (js.type & JS_EVENT_AXIS) | |
595 | axis1[js.number] = scaleJoyAxis(js.value,js.number<<2); | |
596 | } | |
597 | } | |
598 | else { | |
599 | js1_axes = 2; | |
600 | js1_buttons = 2; | |
601 | axis1 = PM_calloc((int)js1_axes, sizeof(short)); | |
602 | buts1 = PM_malloc((int)js1_buttons); | |
603 | } | |
604 | } | |
c7de829c WD |
605 | |
606 | #ifdef CHECKED | |
8bde7f77 WD |
607 | fprintf(stderr,"Using joystick driver version %d.%d.%d\n", |
608 | js_version >> 16, (js_version >> 8) & 0xff, js_version & 0xff); | |
c7de829c | 609 | if (joystick0_fd) |
8bde7f77 | 610 | fprintf(stderr,"Joystick 1 (%s): %s\n", joystick0_dev, name0); |
c7de829c | 611 | if (joystick1_fd) |
8bde7f77 | 612 | fprintf(stderr,"Joystick 2 (%s): %s\n", joystick1_dev, name1); |
c7de829c WD |
613 | #endif |
614 | mask = _EVT_readJoyAxis(EVT_JOY_AXIS_ALL,EVT.joyCenter); | |
615 | if (mask) { | |
8bde7f77 WD |
616 | for (i = 0; i < JOY_NUM_AXES; i++) |
617 | EVT.joyMax[i] = EVT.joyCenter[i]*2; | |
618 | } | |
c7de829c WD |
619 | return mask; |
620 | } | |
621 | ||
622 | /**************************************************************************** | |
623 | DESCRIPTION: | |
624 | Polls the joystick for position and button information. | |
625 | ||
626 | HEADER: | |
627 | event.h | |
628 | ||
629 | REMARKS: | |
630 | This routine is used to poll analogue joysticks for button and position | |
631 | information. It should be called once for each main loop of the user | |
632 | application, just before processing all pending events via EVT_getNext. | |
633 | All information polled from the joystick will be posted to the event | |
634 | queue for later retrieval. | |
635 | ||
636 | Note: Most analogue joysticks will provide readings that change even | |
8bde7f77 WD |
637 | though the joystick has not moved. Hence if you call this routine |
638 | you will likely get an EVT_JOYMOVE event every time through your | |
639 | event loop. | |
c7de829c WD |
640 | |
641 | SEE ALSO: | |
642 | EVT_getNext, EVT_peekNext, EVT_joySetUpperLeft, EVT_joySetLowerRight, | |
643 | EVT_joySetCenter, EVT_joyIsPresent | |
644 | ****************************************************************************/ | |
645 | void EVTAPI EVT_pollJoystick(void) | |
646 | { | |
647 | event_t evt; | |
648 | int i,axis[JOY_NUM_AXES],newButState,mask,moved,ps; | |
649 | ||
650 | if ((js_version & ~0xFFFF) == 0 && EVT.joyMask) { | |
8bde7f77 WD |
651 | /* Read joystick axes and post movement events if they have |
652 | * changed since the last time we polled. Until the events are | |
653 | * actually flushed, we keep modifying the same joystick movement | |
654 | * event, so you won't get multiple movement event | |
655 | */ | |
656 | mask = _EVT_readJoyAxis(EVT.joyMask,axis); | |
657 | newButState = _EVT_readJoyButtons(); | |
658 | moved = false; | |
659 | for (i = 0; i < JOY_NUM_AXES; i++) { | |
660 | if (mask & (EVT_JOY_AXIS_X1 << i)) | |
661 | axis[i] = scaleJoyAxis(axis[i],i); | |
662 | else | |
663 | axis[i] = EVT.joyPrev[i]; | |
664 | if (axis[i] != EVT.joyPrev[i]) | |
665 | moved = true; | |
666 | } | |
667 | if (moved) { | |
668 | memcpy(EVT.joyPrev,axis,sizeof(EVT.joyPrev)); | |
669 | ps = _EVT_disableInt(); | |
670 | if (EVT.oldJoyMove != -1) { | |
671 | /* Modify the existing joystick movement event */ | |
672 | EVT.evtq[EVT.oldJoyMove].message = newButState; | |
673 | EVT.evtq[EVT.oldJoyMove].where_x = EVT.joyPrev[0]; | |
674 | EVT.evtq[EVT.oldJoyMove].where_y = EVT.joyPrev[1]; | |
675 | EVT.evtq[EVT.oldJoyMove].relative_x = EVT.joyPrev[2]; | |
676 | EVT.evtq[EVT.oldJoyMove].relative_y = EVT.joyPrev[3]; | |
677 | } | |
678 | else if (EVT.count < EVENTQSIZE) { | |
679 | /* Add a new joystick movement event */ | |
680 | EVT.oldJoyMove = EVT.freeHead; | |
681 | memset(&evt,0,sizeof(evt)); | |
682 | evt.what = EVT_JOYMOVE; | |
683 | evt.message = EVT.joyButState; | |
684 | evt.where_x = EVT.joyPrev[0]; | |
685 | evt.where_y = EVT.joyPrev[1]; | |
686 | evt.relative_x = EVT.joyPrev[2]; | |
687 | evt.relative_y = EVT.joyPrev[3]; | |
688 | addEvent(&evt); | |
689 | } | |
690 | _EVT_restoreInt(ps); | |
691 | } | |
692 | ||
693 | /* Read the joystick buttons, and post events to reflect the change | |
694 | * in state for the joystick buttons. | |
695 | */ | |
696 | if (newButState != EVT.joyButState) { | |
697 | if (EVT.count < EVENTQSIZE) { | |
698 | /* Add a new joystick movement event */ | |
699 | ps = _EVT_disableInt(); | |
700 | memset(&evt,0,sizeof(evt)); | |
701 | evt.what = EVT_JOYCLICK; | |
702 | evt.message = newButState; | |
703 | EVT.evtq[EVT.oldJoyMove].where_x = EVT.joyPrev[0]; | |
704 | EVT.evtq[EVT.oldJoyMove].where_y = EVT.joyPrev[1]; | |
705 | EVT.evtq[EVT.oldJoyMove].relative_x = EVT.joyPrev[2]; | |
706 | EVT.evtq[EVT.oldJoyMove].relative_y = EVT.joyPrev[3]; | |
707 | addEvent(&evt); | |
708 | _EVT_restoreInt(ps); | |
709 | } | |
710 | EVT.joyButState = newButState; | |
711 | } | |
712 | } | |
c7de829c WD |
713 | } |
714 | ||
715 | /**************************************************************************** | |
716 | DESCRIPTION: | |
717 | Calibrates the joystick upper left position | |
718 | ||
719 | HEADER: | |
720 | event.h | |
721 | ||
722 | REMARKS: | |
723 | This function can be used to zero in on better joystick calibration factors, | |
724 | which may work better than the default simplistic calibration (which assumes | |
725 | the joystick is centered when the event library is initialised). | |
726 | To use this function, ask the user to hold the stick in the upper left | |
727 | position and then have them press a key or button. and then call this | |
728 | function. This function will then read the joystick and update the | |
729 | calibration factors. | |
730 | ||
731 | Usually, assuming that the stick was centered when the event library was | |
732 | initialized, you really only need to call EVT_joySetLowerRight since the | |
733 | upper left position is usually always 0,0 on most joysticks. However, the | |
734 | safest procedure is to call all three calibration functions. | |
735 | ||
736 | SEE ALSO: | |
737 | EVT_joySetUpperLeft, EVT_joySetLowerRight, EVT_joyIsPresent | |
738 | ****************************************************************************/ | |
739 | void EVTAPI EVT_joySetUpperLeft(void) | |
740 | { | |
741 | _EVT_readJoyAxis(EVT_JOY_AXIS_ALL,EVT.joyMin); | |
742 | } | |
743 | ||
744 | /**************************************************************************** | |
745 | DESCRIPTION: | |
746 | Calibrates the joystick lower right position | |
747 | ||
748 | HEADER: | |
749 | event.h | |
750 | ||
751 | REMARKS: | |
752 | This function can be used to zero in on better joystick calibration factors, | |
753 | which may work better than the default simplistic calibration (which assumes | |
754 | the joystick is centered when the event library is initialised). | |
755 | To use this function, ask the user to hold the stick in the lower right | |
756 | position and then have them press a key or button. and then call this | |
757 | function. This function will then read the joystick and update the | |
758 | calibration factors. | |
759 | ||
760 | Usually, assuming that the stick was centered when the event library was | |
761 | initialized, you really only need to call EVT_joySetLowerRight since the | |
762 | upper left position is usually always 0,0 on most joysticks. However, the | |
763 | safest procedure is to call all three calibration functions. | |
764 | ||
765 | SEE ALSO: | |
766 | EVT_joySetUpperLeft, EVT_joySetCenter, EVT_joyIsPresent | |
767 | ****************************************************************************/ | |
768 | void EVTAPI EVT_joySetLowerRight(void) | |
769 | { | |
770 | _EVT_readJoyAxis(EVT_JOY_AXIS_ALL,EVT.joyMax); | |
771 | } | |
772 | ||
773 | /**************************************************************************** | |
774 | DESCRIPTION: | |
775 | Calibrates the joystick center position | |
776 | ||
777 | HEADER: | |
778 | event.h | |
779 | ||
780 | REMARKS: | |
781 | This function can be used to zero in on better joystick calibration factors, | |
782 | which may work better than the default simplistic calibration (which assumes | |
783 | the joystick is centered when the event library is initialised). | |
784 | To use this function, ask the user to hold the stick in the center | |
785 | position and then have them press a key or button. and then call this | |
786 | function. This function will then read the joystick and update the | |
787 | calibration factors. | |
788 | ||
789 | Usually, assuming that the stick was centered when the event library was | |
790 | initialized, you really only need to call EVT_joySetLowerRight since the | |
791 | upper left position is usually always 0,0 on most joysticks. However, the | |
792 | safest procedure is to call all three calibration functions. | |
793 | ||
794 | SEE ALSO: | |
795 | EVT_joySetUpperLeft, EVT_joySetLowerRight, EVT_joySetCenter | |
796 | ****************************************************************************/ | |
797 | void EVTAPI EVT_joySetCenter(void) | |
798 | { | |
799 | _EVT_readJoyAxis(EVT_JOY_AXIS_ALL,EVT.joyCenter); | |
800 | } | |
801 | #endif | |
802 | ||
803 | /**************************************************************************** | |
804 | REMARKS: | |
805 | Pumps all messages in the message queue from Linux into our event queue. | |
806 | ****************************************************************************/ | |
807 | static void _EVT_pumpMessages(void) | |
808 | { | |
809 | event_t evt; | |
810 | int i,numkeys, c; | |
811 | ibool release; | |
812 | static struct kbentry ke; | |
813 | static char buf[KBDREADBUFFERSIZE]; | |
814 | static ushort repeatKey[128] = {0}; | |
815 | ||
816 | /* Poll keyboard events */ | |
817 | while (dataReady(_PM_console_fd) && (numkeys = read(_PM_console_fd, buf, KBDREADBUFFERSIZE)) > 0) { | |
8bde7f77 WD |
818 | for (i = 0; i < numkeys; i++) { |
819 | c = buf[i]; | |
820 | release = c & 0x80; | |
821 | c &= 0x7F; | |
822 | ||
823 | /* TODO: This is wrong! We need this to be the time stamp at */ | |
824 | /* ** interrupt ** time!! One solution would be to */ | |
825 | /* put the keyboard and mouse polling loops into */ | |
826 | /* a separate thread that can block on I/O to the */ | |
827 | /* necessay file descriptor. */ | |
828 | evt.when = _EVT_getTicks(); | |
829 | ||
830 | if (release) { | |
831 | /* Key released */ | |
832 | evt.what = EVT_KEYUP; | |
833 | switch (c) { | |
834 | case KB_leftShift: | |
835 | _PM_modifiers &= ~EVT_LEFTSHIFT; | |
836 | break; | |
837 | case KB_rightShift: | |
838 | _PM_modifiers &= ~EVT_RIGHTSHIFT; | |
839 | break; | |
840 | case 29: | |
841 | _PM_modifiers &= ~(EVT_LEFTCTRL|EVT_CTRLSTATE); | |
842 | break; | |
843 | case 97: /* Control */ | |
844 | _PM_modifiers &= ~EVT_CTRLSTATE; | |
845 | break; | |
846 | case 56: | |
847 | _PM_modifiers &= ~(EVT_LEFTALT|EVT_ALTSTATE); | |
848 | break; | |
849 | case 100: | |
850 | _PM_modifiers &= ~EVT_ALTSTATE; | |
851 | break; | |
852 | default: | |
853 | } | |
854 | evt.modifiers = _PM_modifiers; | |
855 | evt.message = keyUpMsg[c]; | |
856 | if (EVT.count < EVENTQSIZE) | |
857 | addEvent(&evt); | |
858 | keyUpMsg[c] = 0; | |
859 | repeatKey[c] = 0; | |
860 | } | |
861 | else { | |
862 | /* Key pressed */ | |
863 | evt.what = EVT_KEYDOWN; | |
864 | switch (c) { | |
865 | case KB_leftShift: | |
866 | _PM_modifiers |= EVT_LEFTSHIFT; | |
867 | break; | |
868 | case KB_rightShift: | |
869 | _PM_modifiers |= EVT_RIGHTSHIFT; | |
870 | break; | |
871 | case 29: | |
872 | _PM_modifiers |= EVT_LEFTCTRL|EVT_CTRLSTATE; | |
873 | break; | |
874 | case 97: /* Control */ | |
875 | _PM_modifiers |= EVT_CTRLSTATE; | |
876 | break; | |
877 | case 56: | |
878 | _PM_modifiers |= EVT_LEFTALT|EVT_ALTSTATE; | |
879 | break; | |
880 | case 100: | |
881 | _PM_modifiers |= EVT_ALTSTATE; | |
882 | break; | |
883 | case KB_capsLock: /* Caps Lock */ | |
884 | _PM_leds ^= LED_CAP; | |
885 | ioctl(_PM_console_fd, KDSETLED, _PM_leds); | |
886 | break; | |
887 | case KB_numLock: /* Num Lock */ | |
888 | _PM_leds ^= LED_NUM; | |
889 | ioctl(_PM_console_fd, KDSETLED, _PM_leds); | |
890 | break; | |
891 | case KB_scrollLock: /* Scroll Lock */ | |
892 | _PM_leds ^= LED_SCR; | |
893 | ioctl(_PM_console_fd, KDSETLED, _PM_leds); | |
894 | break; | |
895 | default: | |
896 | } | |
897 | evt.modifiers = _PM_modifiers; | |
898 | if (keyUpMsg[c]) { | |
899 | evt.what = EVT_KEYREPEAT; | |
900 | evt.message = keyUpMsg[c] | (repeatKey[c]++ << 16); | |
901 | } | |
902 | else { | |
903 | int asc; | |
904 | ||
905 | evt.message = getKeyMapping(keymaps, NB_KEYMAPS, c) << 8; | |
906 | ke.kb_index = c; | |
907 | ke.kb_table = 0; | |
908 | if ((_PM_modifiers & EVT_SHIFTKEY) || (_PM_leds & LED_CAP)) | |
909 | ke.kb_table |= K_SHIFTTAB; | |
910 | if (_PM_modifiers & (EVT_LEFTALT | EVT_ALTSTATE)) | |
911 | ke.kb_table |= K_ALTTAB; | |
912 | if (ioctl(_PM_console_fd, KDGKBENT, (unsigned long)&ke)<0) | |
913 | perror("ioctl(KDGKBENT)"); | |
914 | if ((_PM_leds & LED_NUM) && (getKeyMapping(keypad, NB_KEYPAD, c)!=c)) { | |
915 | asc = getKeyMapping(keypad, NB_KEYPAD, c); | |
916 | } | |
917 | else { | |
918 | switch (c) { | |
919 | case 14: | |
920 | asc = ASCII_backspace; | |
921 | break; | |
922 | case 15: | |
923 | asc = ASCII_tab; | |
924 | break; | |
925 | case 28: | |
926 | case 96: | |
927 | asc = ASCII_enter; | |
928 | break; | |
929 | case 1: | |
930 | asc = ASCII_esc; | |
931 | default: | |
932 | asc = ke.kb_value & 0xFF; | |
933 | if (asc < 0x1B) | |
934 | asc = 0; | |
935 | break; | |
936 | } | |
937 | } | |
938 | if ((_PM_modifiers & (EVT_CTRLSTATE|EVT_LEFTCTRL)) && isalpha(asc)) | |
939 | evt.message |= toupper(asc) - 'A' + 1; | |
940 | else | |
941 | evt.message |= asc; | |
942 | keyUpMsg[c] = evt.message; | |
943 | repeatKey[c]++; | |
944 | } | |
945 | if (EVT.count < EVENTQSIZE) | |
946 | addEvent(&evt); | |
947 | } | |
948 | } | |
949 | } | |
c7de829c WD |
950 | |
951 | /* Poll mouse events */ | |
952 | if (_EVT_mouse_fd) { | |
8bde7f77 WD |
953 | int dx, dy, buts; |
954 | static int oldbuts; | |
955 | ||
956 | while (dataReady(_EVT_mouse_fd)) { | |
957 | if (readMouseData(&buts, &dx, &dy)) { | |
958 | EVT.mx += dx; | |
959 | EVT.my += dy; | |
960 | if (EVT.mx < 0) EVT.mx = 0; | |
961 | if (EVT.my < 0) EVT.my = 0; | |
962 | if (EVT.mx > range_x) EVT.mx = range_x; | |
963 | if (EVT.my > range_y) EVT.my = range_y; | |
964 | evt.where_x = EVT.mx; | |
965 | evt.where_y = EVT.my; | |
966 | evt.relative_x = dx; | |
967 | evt.relative_y = dy; | |
968 | ||
969 | /* TODO: This is wrong! We need this to be the time stamp at */ | |
970 | /* ** interrupt ** time!! One solution would be to */ | |
971 | /* put the keyboard and mouse polling loops into */ | |
972 | /* a separate thread that can block on I/O to the */ | |
973 | /* necessay file descriptor. */ | |
974 | evt.when = _EVT_getTicks(); | |
975 | evt.modifiers = _PM_modifiers; | |
976 | if (buts & 4) | |
977 | evt.modifiers |= EVT_LEFTBUT; | |
978 | if (buts & 1) | |
979 | evt.modifiers |= EVT_RIGHTBUT; | |
980 | if (buts & 2) | |
981 | evt.modifiers |= EVT_MIDDLEBUT; | |
982 | ||
983 | /* Left click events */ | |
984 | if ((buts&4) != (oldbuts&4)) { | |
985 | if (buts&4) | |
986 | evt.what = EVT_MOUSEDOWN; | |
987 | else | |
988 | evt.what = EVT_MOUSEUP; | |
989 | evt.message = EVT_LEFTBMASK; | |
990 | EVT.oldMove = -1; | |
991 | if (EVT.count < EVENTQSIZE) | |
992 | addEvent(&evt); | |
993 | } | |
994 | ||
995 | /* Right click events */ | |
996 | if ((buts&1) != (oldbuts&1)) { | |
997 | if (buts&1) | |
998 | evt.what = EVT_MOUSEDOWN; | |
999 | else | |
1000 | evt.what = EVT_MOUSEUP; | |
1001 | evt.message = EVT_RIGHTBMASK; | |
1002 | EVT.oldMove = -1; | |
1003 | if (EVT.count < EVENTQSIZE) | |
1004 | addEvent(&evt); | |
1005 | } | |
1006 | ||
1007 | /* Middle click events */ | |
1008 | if ((buts&2) != (oldbuts&2)) { | |
1009 | if (buts&2) | |
1010 | evt.what = EVT_MOUSEDOWN; | |
1011 | else | |
1012 | evt.what = EVT_MOUSEUP; | |
1013 | evt.message = EVT_MIDDLEBMASK; | |
1014 | EVT.oldMove = -1; | |
1015 | if (EVT.count < EVENTQSIZE) | |
1016 | addEvent(&evt); | |
1017 | } | |
1018 | ||
1019 | /* Mouse movement event */ | |
1020 | if (dx || dy) { | |
1021 | evt.what = EVT_MOUSEMOVE; | |
1022 | evt.message = 0; | |
1023 | if (EVT.oldMove != -1) { | |
1024 | /* Modify existing movement event */ | |
1025 | EVT.evtq[EVT.oldMove].where_x = evt.where_x; | |
1026 | EVT.evtq[EVT.oldMove].where_y = evt.where_y; | |
1027 | } | |
1028 | else { | |
1029 | /* Save id of this movement event */ | |
1030 | EVT.oldMove = EVT.freeHead; | |
1031 | if (EVT.count < EVENTQSIZE) | |
1032 | addEvent(&evt); | |
1033 | } | |
1034 | } | |
1035 | oldbuts = buts; | |
1036 | } | |
1037 | } | |
1038 | } | |
c7de829c WD |
1039 | |
1040 | #ifdef USE_OS_JOYSTICK | |
8bde7f77 | 1041 | /* Poll joystick events using the 1.x joystick driver API in the 2.2 kernels */ |
c7de829c | 1042 | if (js_version & ~0xffff) { |
8bde7f77 WD |
1043 | static struct js_event js; |
1044 | ||
1045 | /* Read joystick axis 0 */ | |
1046 | evt.when = 0; | |
1047 | evt.modifiers = _PM_modifiers; | |
1048 | if (joystick0_fd && dataReady(joystick0_fd) && | |
1049 | read(joystick0_fd, &js, sizeof(js)) == sizeof(js)) { | |
1050 | if (js.type & JS_EVENT_BUTTON) { | |
1051 | if (js.number < 2) { /* Only 2 buttons for now :( */ | |
1052 | buts0[js.number] = js.value; | |
1053 | evt.what = EVT_JOYCLICK; | |
1054 | makeJoyEvent(&evt); | |
1055 | if (EVT.count < EVENTQSIZE) | |
1056 | addEvent(&evt); | |
1057 | } | |
1058 | } | |
1059 | else if (js.type & JS_EVENT_AXIS) { | |
1060 | axis0[js.number] = scaleJoyAxis(js.value,js.number); | |
1061 | evt.what = EVT_JOYMOVE; | |
1062 | if (EVT.oldJoyMove != -1) { | |
1063 | makeJoyEvent(&EVT.evtq[EVT.oldJoyMove]); | |
1064 | } | |
1065 | else if (EVT.count < EVENTQSIZE) { | |
1066 | EVT.oldJoyMove = EVT.freeHead; | |
1067 | makeJoyEvent(&evt); | |
1068 | addEvent(&evt); | |
1069 | } | |
1070 | } | |
1071 | } | |
1072 | ||
1073 | /* Read joystick axis 1 */ | |
1074 | if (joystick1_fd && dataReady(joystick1_fd) && | |
1075 | read(joystick1_fd, &js, sizeof(js))==sizeof(js)) { | |
1076 | if (js.type & JS_EVENT_BUTTON) { | |
1077 | if (js.number < 2) { /* Only 2 buttons for now :( */ | |
1078 | buts1[js.number] = js.value; | |
1079 | evt.what = EVT_JOYCLICK; | |
1080 | makeJoyEvent(&evt); | |
1081 | if (EVT.count < EVENTQSIZE) | |
1082 | addEvent(&evt); | |
1083 | } | |
1084 | } | |
1085 | else if (js.type & JS_EVENT_AXIS) { | |
1086 | axis1[js.number] = scaleJoyAxis(js.value,js.number<<2); | |
1087 | evt.what = EVT_JOYMOVE; | |
1088 | if (EVT.oldJoyMove != -1) { | |
1089 | makeJoyEvent(&EVT.evtq[EVT.oldJoyMove]); | |
1090 | } | |
1091 | else if (EVT.count < EVENTQSIZE) { | |
1092 | EVT.oldJoyMove = EVT.freeHead; | |
1093 | makeJoyEvent(&evt); | |
1094 | addEvent(&evt); | |
1095 | } | |
1096 | } | |
1097 | } | |
1098 | } | |
c7de829c WD |
1099 | #endif |
1100 | } | |
1101 | ||
1102 | /**************************************************************************** | |
1103 | REMARKS: | |
1104 | This macro/function is used to converts the scan codes reported by the | |
1105 | keyboard to our event libraries normalised format. We only have one scan | |
1106 | code for the 'A' key, and use shift _PM_modifiers to determine if it is a | |
1107 | Ctrl-F1, Alt-F1 etc. The raw scan codes from the keyboard work this way, | |
1108 | but the OS gives us 'cooked' scan codes, we have to translate them back | |
1109 | to the raw format. | |
1110 | ****************************************************************************/ | |
1111 | #define _EVT_maskKeyCode(evt) | |
1112 | ||
1113 | /**************************************************************************** | |
1114 | REMARKS: | |
1115 | Set the speed of the serial port | |
1116 | ****************************************************************************/ | |
1117 | static int setspeed( | |
1118 | int fd, | |
1119 | int old, | |
1120 | int new, | |
1121 | unsigned short flags) | |
1122 | { | |
1123 | struct termios tty; | |
1124 | char *c; | |
8bde7f77 | 1125 | |
c7de829c WD |
1126 | tcgetattr(fd, &tty); |
1127 | tty.c_iflag = IGNBRK | IGNPAR; | |
1128 | tty.c_oflag = 0; | |
1129 | tty.c_lflag = 0; | |
1130 | tty.c_line = 0; | |
1131 | tty.c_cc[VTIME] = 0; | |
1132 | tty.c_cc[VMIN] = 1; | |
1133 | switch (old) { | |
8bde7f77 WD |
1134 | case 9600: tty.c_cflag = flags | B9600; break; |
1135 | case 4800: tty.c_cflag = flags | B4800; break; | |
1136 | case 2400: tty.c_cflag = flags | B2400; break; | |
1137 | case 1200: | |
1138 | default: tty.c_cflag = flags | B1200; break; | |
1139 | } | |
c7de829c WD |
1140 | tcsetattr(fd, TCSAFLUSH, &tty); |
1141 | switch (new) { | |
8bde7f77 WD |
1142 | case 9600: c = "*q"; tty.c_cflag = flags | B9600; break; |
1143 | case 4800: c = "*p"; tty.c_cflag = flags | B4800; break; | |
1144 | case 2400: c = "*o"; tty.c_cflag = flags | B2400; break; | |
1145 | case 1200: | |
1146 | default: c = "*n"; tty.c_cflag = flags | B1200; break; | |
1147 | } | |
c7de829c WD |
1148 | write(fd, c, 2); |
1149 | usleep(100000); | |
1150 | tcsetattr(fd, TCSAFLUSH, &tty); | |
1151 | return 0; | |
1152 | } | |
1153 | ||
1154 | /**************************************************************************** | |
1155 | REMARKS: | |
1156 | Generic mouse driver init code | |
1157 | ****************************************************************************/ | |
1158 | static void _EVT_mouse_init(void) | |
1159 | { | |
1160 | int i; | |
1161 | ||
1162 | /* Change from any available speed to the chosen one */ | |
1163 | for (i = 9600; i >= 1200; i /= 2) | |
8bde7f77 | 1164 | setspeed(_EVT_mouse_fd, i, opt_baud, mouse_infos[mouse_driver].flags); |
c7de829c WD |
1165 | } |
1166 | ||
1167 | /**************************************************************************** | |
1168 | REMARKS: | |
1169 | Logitech mouse driver init code | |
1170 | ****************************************************************************/ | |
1171 | static void _EVT_logitech_init(void) | |
1172 | { | |
1173 | int i; | |
1174 | struct stat buf; | |
1175 | int busmouse; | |
8bde7f77 | 1176 | |
c7de829c WD |
1177 | /* is this a serial- or a bus- mouse? */ |
1178 | if (fstat(_EVT_mouse_fd,&buf) == -1) | |
8bde7f77 | 1179 | perror("fstat"); |
c7de829c WD |
1180 | i = MAJOR(buf.st_rdev); |
1181 | if (stat("/dev/ttyS0",&buf) == -1) | |
8bde7f77 | 1182 | perror("stat"); |
c7de829c | 1183 | busmouse=(i != MAJOR(buf.st_rdev)); |
8bde7f77 | 1184 | |
c7de829c WD |
1185 | /* Fix the howmany field, so that serial mice have 1, while busmice have 3 */ |
1186 | mouse_infos[mouse_driver].read = busmouse ? 3 : 1; | |
8bde7f77 | 1187 | |
c7de829c WD |
1188 | /* Change from any available speed to the chosen one */ |
1189 | for (i = 9600; i >= 1200; i /= 2) | |
8bde7f77 WD |
1190 | setspeed(_EVT_mouse_fd, i, opt_baud, mouse_infos[mouse_driver].flags); |
1191 | ||
c7de829c WD |
1192 | /* This stuff is peculiar of logitech mice, also for the serial ones */ |
1193 | write(_EVT_mouse_fd, "S", 1); | |
1194 | setspeed(_EVT_mouse_fd, opt_baud, opt_baud,CS8 |PARENB |PARODD |CREAD |CLOCAL |HUPCL); | |
8bde7f77 | 1195 | |
c7de829c WD |
1196 | /* Configure the sample rate */ |
1197 | for (i = 0; opt_sample <= sampletab[i].sample; i++) | |
8bde7f77 | 1198 | ; |
c7de829c WD |
1199 | write(_EVT_mouse_fd,sampletab[i].code,1); |
1200 | } | |
1201 | ||
1202 | /**************************************************************************** | |
1203 | REMARKS: | |
1204 | Microsoft Intellimouse init code | |
1205 | ****************************************************************************/ | |
1206 | static void _EVT_pnpmouse_init(void) | |
1207 | { | |
1208 | struct termios tty; | |
8bde7f77 | 1209 | |
c7de829c WD |
1210 | tcgetattr(_EVT_mouse_fd, &tty); |
1211 | tty.c_iflag = IGNBRK | IGNPAR; | |
1212 | tty.c_oflag = 0; | |
1213 | tty.c_lflag = 0; | |
1214 | tty.c_line = 0; | |
1215 | tty.c_cc[VTIME] = 0; | |
1216 | tty.c_cc[VMIN] = 1; | |
1217 | tty.c_cflag = mouse_infos[mouse_driver].flags | B1200; | |
1218 | tcsetattr(_EVT_mouse_fd, TCSAFLUSH, &tty); /* set parameters */ | |
1219 | } | |
1220 | ||
1221 | /**************************************************************************** | |
1222 | PARAMETERS: | |
1223 | mouseMove - Callback function to call wheneve the mouse needs to be moved | |
1224 | ||
1225 | REMARKS: | |
1226 | Initiliase the event handling module. Here we install our mouse handling ISR | |
1227 | to be called whenever any button's are pressed or released. We also build | |
1228 | the free list of events in the event queue. | |
1229 | ||
1230 | We use handler number 2 of the mouse libraries interrupt handlers for our | |
1231 | event handling routines. | |
1232 | ****************************************************************************/ | |
1233 | void EVTAPI EVT_init( | |
1234 | _EVT_mouseMoveHandler mouseMove) | |
1235 | { | |
1236 | int i; | |
1237 | char *tmp; | |
1238 | ||
1239 | /* Initialise the event queue */ | |
1240 | EVT.mouseMove = mouseMove; | |
1241 | initEventQueue(); | |
1242 | for (i = 0; i < 256; i++) | |
8bde7f77 | 1243 | keyUpMsg[i] = 0; |
c7de829c WD |
1244 | |
1245 | /* Keyboard initialization */ | |
1246 | if (_PM_console_fd == -1) | |
8bde7f77 | 1247 | PM_fatalError("You must first call PM_openConsole to use the EVT functions!"); |
c7de829c WD |
1248 | _PM_keyboard_rawmode(); |
1249 | fcntl(_PM_console_fd,F_SETFL,fcntl(_PM_console_fd,F_GETFL) | O_NONBLOCK); | |
1250 | ||
1251 | /* Mouse initialization */ | |
1252 | if ((tmp = getenv(ENV_MOUSEDRV)) != NULL) { | |
8bde7f77 WD |
1253 | for (i = 0; i < NB_MICE; i++) { |
1254 | if (!strcasecmp(tmp, mouse_infos[i].name)) { | |
1255 | mouse_driver = i; | |
1256 | break; | |
1257 | } | |
1258 | } | |
1259 | if (i == NB_MICE) { | |
1260 | fprintf(stderr,"Unknown mouse driver: %s\n", tmp); | |
1261 | mouse_driver = EVT_noMouse; | |
1262 | _EVT_mouse_fd = 0; | |
1263 | } | |
1264 | } | |
c7de829c | 1265 | if (mouse_driver != EVT_noMouse) { |
8bde7f77 WD |
1266 | if (mouse_driver == EVT_gpm) |
1267 | strcpy(mouse_dev,"/dev/gpmdata"); | |
1268 | if ((tmp = getenv(ENV_MOUSEDEV)) != NULL) | |
1269 | strcpy(mouse_dev,tmp); | |
c7de829c | 1270 | #ifdef CHECKED |
8bde7f77 | 1271 | fprintf(stderr,"Using the %s MGL mouse driver on %s.\n", mouse_infos[mouse_driver].name, mouse_dev); |
c7de829c | 1272 | #endif |
8bde7f77 WD |
1273 | if ((_EVT_mouse_fd = open(mouse_dev, O_RDWR)) < 0) { |
1274 | perror("open"); | |
1275 | fprintf(stderr, "Unable to open mouse device %s, dropping mouse support.\n", mouse_dev); | |
1276 | sleep(1); | |
1277 | mouse_driver = EVT_noMouse; | |
1278 | _EVT_mouse_fd = 0; | |
1279 | } | |
1280 | else { | |
1281 | char c; | |
1282 | ||
1283 | /* Init and flush the mouse pending input queue */ | |
1284 | if (mouse_infos[mouse_driver].init) | |
1285 | mouse_infos[mouse_driver].init(); | |
1286 | while(dataReady(_EVT_mouse_fd) && read(_EVT_mouse_fd, &c, 1) == 1) | |
1287 | ; | |
1288 | } | |
1289 | } | |
c7de829c WD |
1290 | } |
1291 | ||
1292 | /**************************************************************************** | |
1293 | REMARKS | |
1294 | Changes the range of coordinates returned by the mouse functions to the | |
1295 | specified range of values. This is used when changing between graphics | |
1296 | modes set the range of mouse coordinates for the new display mode. | |
1297 | ****************************************************************************/ | |
1298 | void EVTAPI EVT_setMouseRange( | |
1299 | int xRes, | |
1300 | int yRes) | |
1301 | { | |
1302 | range_x = xRes; | |
1303 | range_y = yRes; | |
1304 | } | |
1305 | ||
1306 | /**************************************************************************** | |
1307 | REMARKS | |
1308 | Modifes the mouse coordinates as necessary if scaling to OS coordinates, | |
1309 | and sets the OS mouse cursor position. | |
1310 | ****************************************************************************/ | |
1311 | #define _EVT_setMousePos(x,y) | |
1312 | ||
1313 | /**************************************************************************** | |
1314 | REMARKS: | |
1315 | Initiailises the internal event handling modules. The EVT_suspend function | |
1316 | can be called to suspend event handling (such as when shelling out to DOS), | |
1317 | and this function can be used to resume it again later. | |
1318 | ****************************************************************************/ | |
1319 | void EVT_resume(void) | |
1320 | { | |
8bde7f77 | 1321 | /* Do nothing for Linux */ |
c7de829c WD |
1322 | } |
1323 | ||
1324 | /**************************************************************************** | |
1325 | REMARKS | |
1326 | Suspends all of our event handling operations. This is also used to | |
1327 | de-install the event handling code. | |
1328 | ****************************************************************************/ | |
1329 | void EVT_suspend(void) | |
1330 | { | |
8bde7f77 | 1331 | /* Do nothing for Linux */ |
c7de829c WD |
1332 | } |
1333 | ||
1334 | /**************************************************************************** | |
1335 | REMARKS | |
1336 | Exits the event module for program terminatation. | |
1337 | ****************************************************************************/ | |
1338 | void EVT_exit(void) | |
1339 | { | |
1340 | /* Restore signal handlers */ | |
1341 | _PM_restore_kb_mode(); | |
1342 | if (_EVT_mouse_fd) { | |
8bde7f77 WD |
1343 | close(_EVT_mouse_fd); |
1344 | _EVT_mouse_fd = 0; | |
1345 | } | |
c7de829c WD |
1346 | #ifdef USE_OS_JOYSTICK |
1347 | if (joystick0_fd) { | |
8bde7f77 WD |
1348 | close(joystick0_fd); |
1349 | free(axis0); | |
1350 | free(buts0); | |
1351 | joystick0_fd = 0; | |
1352 | } | |
c7de829c | 1353 | if (joystick1_fd) { |
8bde7f77 WD |
1354 | close(joystick1_fd); |
1355 | free(axis1); | |
1356 | free(buts1); | |
1357 | joystick1_fd = 0; | |
1358 | } | |
c7de829c WD |
1359 | #endif |
1360 | } |