1 /****************************************************************************
3 * SciTech Multi-platform Graphics Library
5 * ========================================================================
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
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.
17 * The Original Code is Copyright (C) 1991-1998 SciTech Software, Inc.
19 * The Initial Developer of the Original Code is SciTech Software, Inc.
20 * All Rights Reserved.
22 * ========================================================================
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
32 ****************************************************************************/
34 /*---------------------------- Global Variables ---------------------------*/
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;
48 /* This defines the supported mouse drivers */
64 static mouse_drivers_t mouse_driver = EVT_noMouse;
65 static char mouse_dev[20] = "/dev/mouse";
76 #define STD_FLG (CREAD | CLOCAL | HUPCL)
78 static void _EVT_mouse_init(void);
79 static void _EVT_logitech_init(void);
80 static void _EVT_pnpmouse_init(void);
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},
92 {"IMPS2", CS7 | STD_FLG, NULL, {0xc0, 0x40, 0xc0, 0x00}, 4, 1}, /* ? */
95 #define NB_MICE (sizeof(mouse_infos)/sizeof(mouse_info))
97 /* The name of the environment variables that are used to change the defaults above */
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"
105 /* Scancode mappings on Linux for special keys */
112 /* TODO: Fix this and set it up so we can do a binary search! */
128 {81, KB_padPageDown},
141 {125,KB_leftWindows},
142 {126,KB_rightWindows},
148 /* And the keypad with num lock turned on (changes the ASCII code only) */
164 #define NB_KEYMAPS (sizeof(keymaps)/sizeof(keymaps[0]))
165 #define NB_KEYPAD (sizeof(keypad)/sizeof(keypad[0]))
172 sample_rate sampletab[]={
183 /* Number of keycodes to read at a time from the console */
185 #define KBDREADBUFFERSIZE 32
187 /*---------------------------- Implementation -----------------------------*/
189 /* These are not used under Linux */
190 #define _EVT_disableInt() 1
191 #define _EVT_restoreInt(flaps)
193 /****************************************************************************
195 scanCode - Scan code to test
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)
203 /****************************************************************************
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
209 ****************************************************************************/
210 ulong _EVT_getTicks(void)
212 static uint starttime = 0;
215 gettimeofday(&t, NULL);
217 starttime = t.tv_sec * 1000 + (t.tv_usec/1000);
218 return ((t.tv_sec * 1000 + (t.tv_usec/1000)) - starttime);
221 /****************************************************************************
223 Small Unix function that checks for availability on a file using select()
224 ****************************************************************************/
225 static ibool dataReady(
228 static struct timeval t = { 0L, 0L };
233 return select(fd+1, &fds, NULL, NULL, &t) > 0;
236 /****************************************************************************
238 Reads mouse data according to the selected mouse driver.
239 ****************************************************************************/
240 static ibool readMouseData(
245 static uchar data[32],prev = 0;
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) {
255 if ((data[0] & drv->proto[0]) != drv->proto[1])
258 /* Load a whole protocol packet */
260 while (cnt < drv->packet_len) {
261 ret = read(_EVT_mouse_fd, data+cnt, drv->read);
262 if (ret == drv->read)
269 if ((data[1] & drv->proto[2]) != drv->proto[3])
272 /* Now decode the protocol packet */
273 switch (mouse_driver) {
275 if (data[0] == 0x40 && !(prev|data[1]|data[2]))
276 *buttons = 2; /* Third button on MS compatible mouse */
278 *buttons= ((data[0] & 0x20) >> 3) | ((data[0] & 0x10) >> 4);
280 *dx = (char)(((data[0] & 0x03) << 6) | (data[1] & 0x3F));
281 *dy = (char)(((data[0] & 0x0C) << 4) | (data[2] & 0x3F));
284 *buttons = !!(data[0]&1) * 4 + !!(data[0]&2) * 1 + !!(data[0]&4) * 2;
286 *dx = (data[0] & 0x10) ? data[1]-256 : data[1];
290 *dy = -((data[0] & 0x20) ? data[2]-256 : data[2]);
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]));
300 *buttons= data[0] & 0x07;
301 *dx = (data[0] & 0x10) ? data[1] : - data[1];
302 *dy = (data[0] & 0x08) ? - data[2] : data[2];
305 *buttons= (~data[0]) & 0x07;
307 *dy = -(char)data[2];
310 *buttons = data[0] & 0x07;
311 *dx = (data[0] & 0x10) ? data[1] : - data[1];
312 *dy = (data[0] & 0x08) ? - data[2] : data[2];
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));
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];
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.
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 */
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)
355 if (drv->packet_len == 4) {
367 /* This "chord-middle" behaviour was reported by David A. van Leeuwen */
368 if (((prev ^ *buttons) & 5) == 5)
369 *buttons = *buttons ? 2 : 0;
380 /****************************************************************************
382 Map a keypress via the key mapping table
383 ****************************************************************************/
384 static int getKeyMapping(
391 for(i = 0; i < nb; i++) {
392 if (tab[i].scan == key)
398 #ifdef USE_OS_JOYSTICK
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";
405 /****************************************************************************
407 Create a joystick event from the joystick data
408 ****************************************************************************/
409 static void makeJoyEvent(
413 if (buts0 && axis0) {
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];
420 evt->where_x = evt->where_y = 0;
421 if (buts1 && axis1) {
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];
428 evt->where_x = evt->where_y = 0;
431 /****************************************************************************
433 Read the joystick axis data
434 ****************************************************************************/
435 int EVTAPI _EVT_readJoyAxis(
441 if ((js_version & ~0xffff) == 0) {
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)
447 if (jmask & EVT_JOY_AXIS_Y1)
449 mask |= EVT_JOY_AXIS_X1|EVT_JOY_AXIS_Y1;
451 if (joystick1_fd && read(joystick1_fd, &js, JS_RETURN) == JS_RETURN) {
452 if (jmask & EVT_JOY_AXIS_X2)
454 if (jmask & EVT_JOY_AXIS_Y2)
456 mask |= EVT_JOY_AXIS_X2|EVT_JOY_AXIS_Y2;
461 if (jmask & EVT_JOY_AXIS_X1)
463 if (jmask & EVT_JOY_AXIS_Y1)
465 mask |= EVT_JOY_AXIS_X1 | EVT_JOY_AXIS_Y1;
468 if (jmask & EVT_JOY_AXIS_X2)
470 if (jmask & EVT_JOY_AXIS_Y2)
472 mask |= EVT_JOY_AXIS_X2 | EVT_JOY_AXIS_Y2;
478 /****************************************************************************
480 Read the joystick button data
481 ****************************************************************************/
482 int EVTAPI _EVT_readJoyButtons(void)
486 if ((js_version & ~0xffff) == 0) {
488 struct JS_DATA_TYPE js;
489 if (joystick0_fd && read(joystick0_fd, &js, JS_RETURN) == JS_RETURN)
491 if (joystick1_fd && read(joystick1_fd, &js, JS_RETURN) == JS_RETURN)
492 buts |= js.buttons << 2;
496 buts |= EVT_JOY1_BUTTONA*buts0[0] + EVT_JOY1_BUTTONB*buts0[1];
498 buts |= EVT_JOY2_BUTTONA*buts1[0] + EVT_JOY2_BUTTONB*buts1[1];
503 /****************************************************************************
505 Returns the mask indicating what joystick axes are attached.
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.
518 EVT_joySetLowerRight, EVT_joySetCenter, EVT_joyIsPresent
519 ****************************************************************************/
520 int EVTAPI EVT_joyIsPresent(void)
524 char *tmp, name0[128], name1[128];
525 static ibool inited = false;
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));
534 if ((tmp = getenv(ENV_JOYDEV0)) != NULL)
535 strcpy(joystick0_dev,tmp);
536 if ((tmp = getenv(ENV_JOYDEV1)) != NULL)
537 strcpy(joystick1_dev,tmp);
538 if ((joystick0_fd = open(joystick0_dev, O_RDONLY)) < 0)
540 if ((joystick1_fd = open(joystick1_dev, O_RDONLY)) < 0)
542 if (!joystick0_fd && !joystick1_fd) /* No joysticks detected */
545 if (ioctl(joystick0_fd ? joystick0_fd : joystick1_fd, JSIOCGVERSION, &js_version) < 0)
548 /* Initialise joystick 0 */
550 ioctl(joystick0_fd, JSIOCGNAME(sizeof(name0)), name0);
551 if (js_version & ~0xffff) {
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)
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);
572 axis0 = PM_calloc((int)js0_axes, sizeof(short));
573 buts0 = PM_malloc((int)js0_buttons);
577 /* Initialise joystick 1 */
579 ioctl(joystick1_fd, JSIOCGNAME(sizeof(name1)), name1);
580 if (js_version & ~0xffff) {
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)
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);
601 axis1 = PM_calloc((int)js1_axes, sizeof(short));
602 buts1 = PM_malloc((int)js1_buttons);
607 fprintf(stderr,"Using joystick driver version %d.%d.%d\n",
608 js_version >> 16, (js_version >> 8) & 0xff, js_version & 0xff);
610 fprintf(stderr,"Joystick 1 (%s): %s\n", joystick0_dev, name0);
612 fprintf(stderr,"Joystick 2 (%s): %s\n", joystick1_dev, name1);
614 mask = _EVT_readJoyAxis(EVT_JOY_AXIS_ALL,EVT.joyCenter);
616 for (i = 0; i < JOY_NUM_AXES; i++)
617 EVT.joyMax[i] = EVT.joyCenter[i]*2;
622 /****************************************************************************
624 Polls the joystick for position and button information.
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.
636 Note: Most analogue joysticks will provide readings that change even
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
642 EVT_getNext, EVT_peekNext, EVT_joySetUpperLeft, EVT_joySetLowerRight,
643 EVT_joySetCenter, EVT_joyIsPresent
644 ****************************************************************************/
645 void EVTAPI EVT_pollJoystick(void)
648 int i,axis[JOY_NUM_AXES],newButState,mask,moved,ps;
650 if ((js_version & ~0xFFFF) == 0 && EVT.joyMask) {
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
656 mask = _EVT_readJoyAxis(EVT.joyMask,axis);
657 newButState = _EVT_readJoyButtons();
659 for (i = 0; i < JOY_NUM_AXES; i++) {
660 if (mask & (EVT_JOY_AXIS_X1 << i))
661 axis[i] = scaleJoyAxis(axis[i],i);
663 axis[i] = EVT.joyPrev[i];
664 if (axis[i] != EVT.joyPrev[i])
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];
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];
693 /* Read the joystick buttons, and post events to reflect the change
694 * in state for the joystick buttons.
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];
710 EVT.joyButState = newButState;
715 /****************************************************************************
717 Calibrates the joystick upper left position
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
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.
737 EVT_joySetUpperLeft, EVT_joySetLowerRight, EVT_joyIsPresent
738 ****************************************************************************/
739 void EVTAPI EVT_joySetUpperLeft(void)
741 _EVT_readJoyAxis(EVT_JOY_AXIS_ALL,EVT.joyMin);
744 /****************************************************************************
746 Calibrates the joystick lower right position
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
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.
766 EVT_joySetUpperLeft, EVT_joySetCenter, EVT_joyIsPresent
767 ****************************************************************************/
768 void EVTAPI EVT_joySetLowerRight(void)
770 _EVT_readJoyAxis(EVT_JOY_AXIS_ALL,EVT.joyMax);
773 /****************************************************************************
775 Calibrates the joystick center position
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
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.
795 EVT_joySetUpperLeft, EVT_joySetLowerRight, EVT_joySetCenter
796 ****************************************************************************/
797 void EVTAPI EVT_joySetCenter(void)
799 _EVT_readJoyAxis(EVT_JOY_AXIS_ALL,EVT.joyCenter);
803 /****************************************************************************
805 Pumps all messages in the message queue from Linux into our event queue.
806 ****************************************************************************/
807 static void _EVT_pumpMessages(void)
812 static struct kbentry ke;
813 static char buf[KBDREADBUFFERSIZE];
814 static ushort repeatKey[128] = {0};
816 /* Poll keyboard events */
817 while (dataReady(_PM_console_fd) && (numkeys = read(_PM_console_fd, buf, KBDREADBUFFERSIZE)) > 0) {
818 for (i = 0; i < numkeys; i++) {
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();
832 evt.what = EVT_KEYUP;
835 _PM_modifiers &= ~EVT_LEFTSHIFT;
838 _PM_modifiers &= ~EVT_RIGHTSHIFT;
841 _PM_modifiers &= ~(EVT_LEFTCTRL|EVT_CTRLSTATE);
843 case 97: /* Control */
844 _PM_modifiers &= ~EVT_CTRLSTATE;
847 _PM_modifiers &= ~(EVT_LEFTALT|EVT_ALTSTATE);
850 _PM_modifiers &= ~EVT_ALTSTATE;
854 evt.modifiers = _PM_modifiers;
855 evt.message = keyUpMsg[c];
856 if (EVT.count < EVENTQSIZE)
863 evt.what = EVT_KEYDOWN;
866 _PM_modifiers |= EVT_LEFTSHIFT;
869 _PM_modifiers |= EVT_RIGHTSHIFT;
872 _PM_modifiers |= EVT_LEFTCTRL|EVT_CTRLSTATE;
874 case 97: /* Control */
875 _PM_modifiers |= EVT_CTRLSTATE;
878 _PM_modifiers |= EVT_LEFTALT|EVT_ALTSTATE;
881 _PM_modifiers |= EVT_ALTSTATE;
883 case KB_capsLock: /* Caps Lock */
885 ioctl(_PM_console_fd, KDSETLED, _PM_leds);
887 case KB_numLock: /* Num Lock */
889 ioctl(_PM_console_fd, KDSETLED, _PM_leds);
891 case KB_scrollLock: /* Scroll Lock */
893 ioctl(_PM_console_fd, KDSETLED, _PM_leds);
897 evt.modifiers = _PM_modifiers;
899 evt.what = EVT_KEYREPEAT;
900 evt.message = keyUpMsg[c] | (repeatKey[c]++ << 16);
905 evt.message = getKeyMapping(keymaps, NB_KEYMAPS, c) << 8;
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);
920 asc = ASCII_backspace;
932 asc = ke.kb_value & 0xFF;
938 if ((_PM_modifiers & (EVT_CTRLSTATE|EVT_LEFTCTRL)) && isalpha(asc))
939 evt.message |= toupper(asc) - 'A' + 1;
942 keyUpMsg[c] = evt.message;
945 if (EVT.count < EVENTQSIZE)
951 /* Poll mouse events */
956 while (dataReady(_EVT_mouse_fd)) {
957 if (readMouseData(&buts, &dx, &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;
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;
977 evt.modifiers |= EVT_LEFTBUT;
979 evt.modifiers |= EVT_RIGHTBUT;
981 evt.modifiers |= EVT_MIDDLEBUT;
983 /* Left click events */
984 if ((buts&4) != (oldbuts&4)) {
986 evt.what = EVT_MOUSEDOWN;
988 evt.what = EVT_MOUSEUP;
989 evt.message = EVT_LEFTBMASK;
991 if (EVT.count < EVENTQSIZE)
995 /* Right click events */
996 if ((buts&1) != (oldbuts&1)) {
998 evt.what = EVT_MOUSEDOWN;
1000 evt.what = EVT_MOUSEUP;
1001 evt.message = EVT_RIGHTBMASK;
1003 if (EVT.count < EVENTQSIZE)
1007 /* Middle click events */
1008 if ((buts&2) != (oldbuts&2)) {
1010 evt.what = EVT_MOUSEDOWN;
1012 evt.what = EVT_MOUSEUP;
1013 evt.message = EVT_MIDDLEBMASK;
1015 if (EVT.count < EVENTQSIZE)
1019 /* Mouse movement event */
1021 evt.what = EVT_MOUSEMOVE;
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;
1029 /* Save id of this movement event */
1030 EVT.oldMove = EVT.freeHead;
1031 if (EVT.count < EVENTQSIZE)
1040 #ifdef USE_OS_JOYSTICK
1041 /* Poll joystick events using the 1.x joystick driver API in the 2.2 kernels */
1042 if (js_version & ~0xffff) {
1043 static struct js_event js;
1045 /* Read joystick axis 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;
1055 if (EVT.count < EVENTQSIZE)
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]);
1065 else if (EVT.count < EVENTQSIZE) {
1066 EVT.oldJoyMove = EVT.freeHead;
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;
1081 if (EVT.count < EVENTQSIZE)
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]);
1091 else if (EVT.count < EVENTQSIZE) {
1092 EVT.oldJoyMove = EVT.freeHead;
1102 /****************************************************************************
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
1110 ****************************************************************************/
1111 #define _EVT_maskKeyCode(evt)
1113 /****************************************************************************
1115 Set the speed of the serial port
1116 ****************************************************************************/
1117 static int setspeed(
1121 unsigned short flags)
1126 tcgetattr(fd, &tty);
1127 tty.c_iflag = IGNBRK | IGNPAR;
1131 tty.c_cc[VTIME] = 0;
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;
1138 default: tty.c_cflag = flags | B1200; break;
1140 tcsetattr(fd, TCSAFLUSH, &tty);
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;
1146 default: c = "*n"; tty.c_cflag = flags | B1200; break;
1150 tcsetattr(fd, TCSAFLUSH, &tty);
1154 /****************************************************************************
1156 Generic mouse driver init code
1157 ****************************************************************************/
1158 static void _EVT_mouse_init(void)
1162 /* Change from any available speed to the chosen one */
1163 for (i = 9600; i >= 1200; i /= 2)
1164 setspeed(_EVT_mouse_fd, i, opt_baud, mouse_infos[mouse_driver].flags);
1167 /****************************************************************************
1169 Logitech mouse driver init code
1170 ****************************************************************************/
1171 static void _EVT_logitech_init(void)
1177 /* is this a serial- or a bus- mouse? */
1178 if (fstat(_EVT_mouse_fd,&buf) == -1)
1180 i = MAJOR(buf.st_rdev);
1181 if (stat("/dev/ttyS0",&buf) == -1)
1183 busmouse=(i != MAJOR(buf.st_rdev));
1185 /* Fix the howmany field, so that serial mice have 1, while busmice have 3 */
1186 mouse_infos[mouse_driver].read = busmouse ? 3 : 1;
1188 /* Change from any available speed to the chosen one */
1189 for (i = 9600; i >= 1200; i /= 2)
1190 setspeed(_EVT_mouse_fd, i, opt_baud, mouse_infos[mouse_driver].flags);
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);
1196 /* Configure the sample rate */
1197 for (i = 0; opt_sample <= sampletab[i].sample; i++)
1199 write(_EVT_mouse_fd,sampletab[i].code,1);
1202 /****************************************************************************
1204 Microsoft Intellimouse init code
1205 ****************************************************************************/
1206 static void _EVT_pnpmouse_init(void)
1210 tcgetattr(_EVT_mouse_fd, &tty);
1211 tty.c_iflag = IGNBRK | IGNPAR;
1215 tty.c_cc[VTIME] = 0;
1217 tty.c_cflag = mouse_infos[mouse_driver].flags | B1200;
1218 tcsetattr(_EVT_mouse_fd, TCSAFLUSH, &tty); /* set parameters */
1221 /****************************************************************************
1223 mouseMove - Callback function to call wheneve the mouse needs to be moved
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.
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)
1239 /* Initialise the event queue */
1240 EVT.mouseMove = mouseMove;
1242 for (i = 0; i < 256; i++)
1245 /* Keyboard initialization */
1246 if (_PM_console_fd == -1)
1247 PM_fatalError("You must first call PM_openConsole to use the EVT functions!");
1248 _PM_keyboard_rawmode();
1249 fcntl(_PM_console_fd,F_SETFL,fcntl(_PM_console_fd,F_GETFL) | O_NONBLOCK);
1251 /* Mouse initialization */
1252 if ((tmp = getenv(ENV_MOUSEDRV)) != NULL) {
1253 for (i = 0; i < NB_MICE; i++) {
1254 if (!strcasecmp(tmp, mouse_infos[i].name)) {
1260 fprintf(stderr,"Unknown mouse driver: %s\n", tmp);
1261 mouse_driver = EVT_noMouse;
1265 if (mouse_driver != EVT_noMouse) {
1266 if (mouse_driver == EVT_gpm)
1267 strcpy(mouse_dev,"/dev/gpmdata");
1268 if ((tmp = getenv(ENV_MOUSEDEV)) != NULL)
1269 strcpy(mouse_dev,tmp);
1271 fprintf(stderr,"Using the %s MGL mouse driver on %s.\n", mouse_infos[mouse_driver].name, mouse_dev);
1273 if ((_EVT_mouse_fd = open(mouse_dev, O_RDWR)) < 0) {
1275 fprintf(stderr, "Unable to open mouse device %s, dropping mouse support.\n", mouse_dev);
1277 mouse_driver = EVT_noMouse;
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)
1292 /****************************************************************************
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(
1306 /****************************************************************************
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)
1313 /****************************************************************************
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)
1321 /* Do nothing for Linux */
1324 /****************************************************************************
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)
1331 /* Do nothing for Linux */
1334 /****************************************************************************
1336 Exits the event module for program terminatation.
1337 ****************************************************************************/
1340 /* Restore signal handlers */
1341 _PM_restore_kb_mode();
1342 if (_EVT_mouse_fd) {
1343 close(_EVT_mouse_fd);
1346 #ifdef USE_OS_JOYSTICK
1348 close(joystick0_fd);
1354 close(joystick1_fd);