Coding style cleanup
[platform/kernel/u-boot.git] / board / MAI / bios_emulator / scitech / src / pm / qnx / event.c
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:  QNX
26 *
27 * Description:  QNX fullscreen console implementation for the SciTech
28 *               cross platform event library.
29 *
30 ****************************************************************************/
31
32 #include <errno.h>
33 #include <unistd.h>
34
35 /*--------------------------- Global variables ----------------------------*/
36
37 #ifndef __QNXNTO__
38 static struct _mouse_ctrl   *_PM_mouse_ctl;
39 static int          _PM_keyboard_fd = -1;
40 /*static int            _PM_modifiers, _PM_leds; */
41 #else
42 static int          kbd_fd = -1, mouse_fd = -1;
43 #endif
44 static int          kill_pid = 0;
45 static ushort       keyUpMsg[256] = {0};/* Table of key up messages     */
46 static int          rangeX,rangeY;      /* Range of mouse coordinates   */
47
48 #define TIME_TO_MSEC(__t)   ((__t).tv_nsec / 1000000 + (__t).tv_sec * 1000)
49
50 #define LED_NUM         1
51 #define LED_CAP         2
52 #define LED_SCR         4
53
54 /* Scancode mappings on QNX for special keys */
55
56 typedef struct {
57     int scan;
58     int map;
59     } keymap;
60
61 /* TODO: Fix this and set it up so we can do a binary search! */
62
63 keymap keymaps[] = {
64     {96, KB_padEnter},
65     {74, KB_padMinus},
66     {78, KB_padPlus},
67     {55, KB_padTimes},
68     {98, KB_padDivide},
69     {71, KB_padHome},
70     {72, KB_padUp},
71     {73, KB_padPageUp},
72     {75, KB_padLeft},
73     {76, KB_padCenter},
74     {77, KB_padRight},
75     {79, KB_padEnd},
76     {80, KB_padDown},
77     {81, KB_padPageDown},
78     {82, KB_padInsert},
79     {83, KB_padDelete},
80     {105,KB_left},
81     {108,KB_down},
82     {106,KB_right},
83     {103,KB_up},
84     {110,KB_insert},
85     {102,KB_home},
86     {104,KB_pageUp},
87     {111,KB_delete},
88     {107,KB_end},
89     {109,KB_pageDown},
90     {125,KB_leftWindows},
91     {126,KB_rightWindows},
92     {127,KB_menu},
93     {100,KB_rightAlt},
94     {97,KB_rightCtrl},
95     };
96
97 /* And the keypad with num lock turned on (changes the ASCII code only) */
98
99 keymap keypad[] = {
100     {71, ASCII_7},
101     {72, ASCII_8},
102     {73, ASCII_9},
103     {75, ASCII_4},
104     {76, ASCII_5},
105     {77, ASCII_6},
106     {79, ASCII_1},
107     {80, ASCII_2},
108     {81, ASCII_3},
109     {82, ASCII_0},
110     {83, ASCII_period},
111     };
112
113 #define NB_KEYMAPS (sizeof(keymaps)/sizeof(keymaps[0]))
114 #define NB_KEYPAD (sizeof(keypad)/sizeof(keypad[0]))
115
116 /*---------------------------- Implementation -----------------------------*/
117
118 /****************************************************************************
119 REMARKS:
120 Include generic raw scancode keyboard module.
121 ****************************************************************************/
122 #include "common/keyboard.c"
123
124 /* These are not used under QNX */
125 #define _EVT_disableInt()       1
126 #define _EVT_restoreInt(flags)
127
128 /****************************************************************************
129 REMARKS:
130 This function is used to return the number of ticks since system
131 startup in milliseconds. This should be the same value that is placed into
132 the time stamp fields of events, and is used to implement auto mouse down
133 events.
134 ****************************************************************************/
135 ulong _EVT_getTicks(void)
136 {
137     struct timespec t;
138     clock_gettime(CLOCK_REALTIME,&t);
139     return (t.tv_nsec / 1000000 + t.tv_sec * 1000);
140 }
141
142 /****************************************************************************
143 REMARKS:
144 Converts a mickey movement value to a pixel adjustment value.
145 ****************************************************************************/
146 static int MickeyToPixel(
147     int mickey)
148 {
149     /* TODO: We can add some code in here to handle 'acceleration' for */
150     /*       the mouse cursor. For now just use the mickeys. */
151     return mickey;
152 }
153
154 #ifdef __QNXNTO__
155 /****************************************************************************
156 REMARKS:
157 Retrieves all events from the mouse/keyboard event queue and stuffs them
158 into the MGL event queue for further processing.
159 ****************************************************************************/
160 static void _EVT_pumpMessages(void)
161 {
162     int         rc1, rc2;
163     struct _keyboard_packet key;
164     struct _mouse_packet    ms;
165     static long     old_buttons = 0;
166     uint            message = 0, but_stat = 0, mods = 0;
167     event_t         evt;
168
169     while (EVT.count < EVENTQSIZE) {
170         rc1 = read(kbd_fd, (void *)&key, sizeof(key));
171         if (rc1 == -1) {
172             if (errno == EAGAIN)
173                 rc1 = 0;
174             else {
175                 perror("getEvents");
176                 PM_fatalError("Keyboard error");
177                 }
178             }
179         if (rc1 > 0) {
180             memset(&evt, 0, sizeof(evt));
181             if (key.data.modifiers & KEYMOD_SHIFT)
182                 mods |= EVT_LEFTSHIFT;
183             if (key.data.modifiers & KEYMOD_CTRL)
184                 mods |= EVT_CTRLSTATE;
185             if (key.data.modifiers & KEYMOD_ALT)
186                 mods |= EVT_ALTSTATE;
187
188             /* Now store the keyboard event data */
189             evt.when = TIME_TO_MSEC(key.time);
190             if (key.data.flags & KEY_SCAN_VALID)
191                 evt.message |= (key.data.key_scan & 0x7F) << 8;
192             if ((key.data.flags & KEY_SYM_VALID) &&
193                 (((key.data.key_sym & 0xff00) == 0xf000 &&
194                 (key.data.key_sym & 0xff) < 0x20) ||
195                 key.data.key_sym < 0x80))
196                 evt.message |= (key.data.key_sym & 0xFF);
197             evt.modifiers = mods;
198             if (key.data.flags & KEY_DOWN) {
199                 evt.what = EVT_KEYDOWN;
200                 keyUpMsg[evt.message >> 8] = (ushort)evt.message;
201                 }
202             else if (key.data.flags & KEY_REPEAT) {
203                 evt.message |= 0x10000;
204                 evt.what = EVT_KEYREPEAT;
205                 }
206             else {
207                 evt.what = EVT_KEYUP;
208                 evt.message = keyUpMsg[evt.message >> 8];
209                 if (evt.message == 0)
210                     continue;
211                 keyUpMsg[evt.message >> 8] = 0;
212                 }
213
214             /* Now add the new event to the event queue */
215             addEvent(&evt);
216             }
217         rc2 = read(mouse_fd, (void *)&ms, sizeof (ms));
218         if (rc2 == -1) {
219             if (errno == EAGAIN)
220                 rc2 = 0;
221             else {
222                 perror("getEvents");
223                 PM_fatalError("Mouse error");
224                 }
225             }
226         if (rc2 > 0) {
227             memset(&evt, 0, sizeof(evt));
228             ms.hdr.buttons &=
229                 (_POINTER_BUTTON_LEFT | _POINTER_BUTTON_RIGHT);
230             if (ms.hdr.buttons & _POINTER_BUTTON_LEFT)
231                 but_stat = EVT_LEFTBUT;
232             if ((ms.hdr.buttons & _POINTER_BUTTON_LEFT) !=
233                 (old_buttons & _POINTER_BUTTON_LEFT))
234                 message = EVT_LEFTBMASK;
235             if (ms.hdr.buttons & _POINTER_BUTTON_RIGHT)
236                 but_stat |= EVT_RIGHTBUT;
237             if ((ms.hdr.buttons & _POINTER_BUTTON_RIGHT) !=
238                 (old_buttons & _POINTER_BUTTON_RIGHT))
239                 message |= EVT_RIGHTBMASK;
240             if (ms.dx || ms.dy) {
241                 ms.dy = -ms.dy;
242                 EVT.mx += MickeyToPixel(ms.dx);
243                 EVT.my += MickeyToPixel(ms.dy);
244                 if (EVT.mx < 0) EVT.mx = 0;
245                 if (EVT.my < 0) EVT.my = 0;
246                 if (EVT.mx > rangeX)    EVT.mx = rangeX;
247                 if (EVT.my > rangeY)    EVT.my = rangeY;
248                 evt.what = EVT_MOUSEMOVE;
249                 evt.when = TIME_TO_MSEC(ms.hdr.time);
250                 evt.where_x = EVT.mx;
251                 evt.where_y = EVT.my;
252                 evt.relative_x = ms.dx;
253                 evt.relative_y = ms.dy;
254                 evt.modifiers = but_stat;
255                 addEvent(&evt);
256                 }
257             evt.what = ms.hdr.buttons < old_buttons ?
258                 EVT_MOUSEUP : EVT_MOUSEDOWN;
259             evt.when = TIME_TO_MSEC(ms.hdr.time);
260             evt.where_x = EVT.mx;
261             evt.where_y = EVT.my;
262             evt.relative_x = ms.dx;
263             evt.relative_y = ms.dy;
264             evt.modifiers = but_stat;
265             evt.message = message;
266             if (ms.hdr.buttons != old_buttons) {
267                 addEvent(&evt);
268                 old_buttons = ms.hdr.buttons;
269                 }
270             }
271         if (rc1 + rc2 == 0)
272             break;
273         }
274 }
275 #else
276 /****************************************************************************
277 REMARKS:
278 Retrieves all events from the mouse/keyboard event queue and stuffs them
279 into the MGL event queue for further processing.
280 ****************************************************************************/
281 static void _EVT_pumpMessages(void)
282 {
283     struct mouse_event      ev;
284     int             rc;
285     static long         old_buttons = 0;
286     uint                message = 0, but_stat = 0;
287     event_t             evt;
288     char                buf[32];
289     int             numkeys, i;
290
291     /* Poll keyboard events */
292     while ((numkeys = read(_PM_keyboard_fd, buf, sizeof buf)) > 0) {
293         for (i = 0; i < numkeys; i++) {
294             processRawScanCode(buf[i]);
295             }
296         }
297
298     if (_PM_mouse_ctl == NULL)
299         return;
300
301     /* Gobble pending mouse events */
302     while (EVT.count < EVENTQSIZE) {
303         rc = mouse_read(_PM_mouse_ctl, &ev, 1, 0, NULL);
304         if (rc == -1) {
305             perror("getEvents");
306             PM_fatalError("Mouse error (Input terminated?)");
307             }
308         if (rc == 0)
309             break;
310
311         message = 0, but_stat = 0;
312         memset(&evt, 0, sizeof(evt));
313
314         ev.buttons &= (_MOUSE_LEFT | _MOUSE_RIGHT);
315         if (ev.buttons & _MOUSE_LEFT)
316             but_stat = EVT_LEFTBUT;
317         if ((ev.buttons & _MOUSE_LEFT) != (old_buttons & _MOUSE_LEFT))
318             message = EVT_LEFTBMASK;
319         if (ev.buttons & _MOUSE_RIGHT)
320             but_stat |= EVT_RIGHTBUT;
321         if ((ev.buttons & _MOUSE_RIGHT) != (old_buttons & _MOUSE_RIGHT))
322             message |= EVT_RIGHTBMASK;
323         if (ev.dx || ev.dy) {
324             ev.dy = -ev.dy;
325             EVT.mx += MickeyToPixel(ev.dx);
326             EVT.my += MickeyToPixel(ev.dy);
327             if (EVT.mx < 0) EVT.mx = 0;
328             if (EVT.my < 0) EVT.my = 0;
329             if (EVT.mx > rangeX)    EVT.mx = rangeX;
330             if (EVT.my > rangeY)    EVT.my = rangeY;
331             evt.what = EVT_MOUSEMOVE;
332             evt.when = ev.timestamp*100;
333             evt.where_x = EVT.mx;
334             evt.where_y = EVT.my;
335             evt.relative_x = ev.dx;
336             evt.relative_y = ev.dy;
337             evt.modifiers = but_stat;
338             addEvent(&evt);
339             }
340         evt.what = ev.buttons < old_buttons ? EVT_MOUSEUP : EVT_MOUSEDOWN;
341         evt.when = ev.timestamp*100;
342         evt.where_x = EVT.mx;
343         evt.where_y = EVT.my;
344         evt.relative_x = ev.dx;
345         evt.relative_y = ev.dy;
346         evt.modifiers = but_stat;
347         evt.message = message;
348         if (ev.buttons != old_buttons) {
349             addEvent(&evt);
350             old_buttons = ev.buttons;
351             }
352         }
353 }
354 #endif  /* __QNXNTO__ */
355
356 /****************************************************************************
357 REMARKS:
358 This macro/function is used to converts the scan codes reported by the
359 keyboard to our event libraries normalised format. We only have one scan
360 code for the 'A' key, and use shift modifiers to determine if it is a
361 Ctrl-F1, Alt-F1 etc. The raw scan codes from the keyboard work this way,
362 but the OS gives us 'cooked' scan codes, we have to translate them back
363 to the raw format.
364 ****************************************************************************/
365 #define _EVT_maskKeyCode(evt)
366
367 /****************************************************************************
368 REMARKS:
369 Safely abort the event module upon catching a fatal error.
370 ****************************************************************************/
371 void _EVT_abort(
372     int signo)
373 {
374     char    buf[80];
375
376     EVT_exit();
377     sprintf(buf,"Terminating on signal %d",signo);
378     PM_fatalError(buf);
379 }
380
381 /****************************************************************************
382 PARAMETERS:
383 mouseMove   - Callback function to call wheneve the mouse needs to be moved
384
385 REMARKS:
386 Initiliase the event handling module. Here we install our mouse handling ISR
387 to be called whenever any button's are pressed or released. We also build
388 the free list of events in the event queue.
389
390 We use handler number 2 of the mouse libraries interrupt handlers for our
391 event handling routines.
392 ****************************************************************************/
393 void EVTAPI EVT_init(
394     _EVT_mouseMoveHandler mouseMove)
395 {
396     int         i;
397     struct stat st;
398     char        *iarg[16];
399 #ifdef __QNXNTO__
400     char        buf[128];
401     FILE        *p;
402     int         argno,len;
403 #endif
404
405 #ifdef __QNXNTO__
406     ThreadCtl(_NTO_TCTL_IO, 0); /* So joystick code won't blow up */
407 #endif
408
409     /* Initialise the event queue */
410     EVT.mouseMove = mouseMove;
411     initEventQueue();
412     memset(keyUpMsg,0,sizeof(keyUpMsg));
413
414 #ifdef __QNXNTO__
415     /*
416      * User may already have input running with the right parameters.
417      * Thus they could start input at boot time, using the output of
418      * inputtrap, passing the the -r flag to make it run as a resource
419      * manager.
420      */
421     if ((mouse_fd = open("/dev/mouse0", O_RDONLY | O_NONBLOCK)) < 0) {
422         /* Run inputtrap to get the args for input */
423         if ((p = popen("inputtrap", "r")) == NULL)
424             PM_fatalError("Error running 'inputtrap'");
425         fgets(buf, sizeof(buf), p);
426         pclose(p);
427
428         /* Build the argument list */
429         len = strlen(buf);
430         iarg[0] = buf;
431         for (i = 0, argno = 0; i < len && argno < 15;) {
432             if (argno == 1) {
433                 /*
434                  * Add flags to input's arg list.
435                  * '-r' means run as resource
436                  * manager, providing the /dev/mouse
437                  * and /dev/keyboard interfaces.
438                  * '-P' supresses the /dev/photon
439                  * mechanism.
440                  */
441                 iarg[argno++] = "-Pr";
442                 continue;
443                 }
444             while (buf[i] == ' ')
445                 i++;
446             if (buf[i] == '\0' || buf[i] == '\n')
447                 break;
448             iarg[argno++] = &buf[i];
449             while (buf[i] != ' '
450                 && buf[i] != '\0' && buf[i] != '\n')
451                 i++;
452             buf[i++] = '\0';
453             }
454         iarg[argno] = NULL;
455
456         if ((kill_pid = spawnvp(P_NOWAITO, iarg[0], iarg)) == -1) {
457             perror("spawning input resmgr");
458             PM_fatalError("Could not start input resmgr");
459             }
460         for (i = 0; i < 10; i++) {
461             if (stat("/dev/mouse0", &st) == 0)
462                 break;
463             sleep(1);
464             }
465         if ((mouse_fd = open("/dev/mouse0", O_RDONLY|O_NONBLOCK)) < 0) {
466             perror("/dev/mouse0");
467             PM_fatalError("Could not open /dev/mouse0");
468             }
469         }
470     if ((kbd_fd = open("/dev/keyboard0", O_RDONLY|O_NONBLOCK)) < 0) {
471         perror("/dev/keyboard0");
472         PM_fatalError("Could not open /dev/keyboard0");
473         }
474 #else
475     /* Connect to Input/Mouse for event handling */
476     if (_PM_mouse_ctl == NULL) {
477         _PM_mouse_ctl = mouse_open(0, "/dev/mouse", 0);
478
479         /* "Mouse" is not running; attempt to start it */
480         if (_PM_mouse_ctl == NULL) {
481             iarg[0] = "mousetrap";
482             iarg[1] = "start";
483             iarg[2] = NULL;
484             if ((kill_pid = spawnvp(P_NOWAITO, iarg[0], (void*)iarg)) == -1)
485                 perror("spawn (mousetrap)");
486             else {
487                 for (i = 0; i < 10; i++) {
488                     if (stat("/dev/mouse", &st) == 0)
489                         break;
490                     sleep(1);
491                     }
492                 _PM_mouse_ctl = mouse_open(0, "/dev/mouse", 0);
493                 }
494             }
495         }
496     if (_PM_keyboard_fd == -1)
497         _PM_keyboard_fd = open("/dev/kbd", O_RDONLY|O_NONBLOCK);
498 #endif
499
500     /* Catch program termination signals so we can clean up properly */
501     signal(SIGABRT, _EVT_abort);
502     signal(SIGFPE, _EVT_abort);
503     signal(SIGINT, _EVT_abort);
504 }
505
506 /****************************************************************************
507 REMARKS
508 Changes the range of coordinates returned by the mouse functions to the
509 specified range of values. This is used when changing between graphics
510 modes set the range of mouse coordinates for the new display mode.
511 ****************************************************************************/
512 void EVTAPI EVT_setMouseRange(
513     int xRes,
514     int yRes)
515 {
516     rangeX = xRes;
517     rangeY = yRes;
518 }
519
520 /****************************************************************************
521 REMARKS
522 Modifes the mouse coordinates as necessary if scaling to OS coordinates,
523 and sets the OS mouse cursor position.
524 ****************************************************************************/
525 #define _EVT_setMousePos(x,y)
526
527 /****************************************************************************
528 REMARKS:
529 Initiailises the internal event handling modules. The EVT_suspend function
530 can be called to suspend event handling (such as when shelling out to DOS),
531 and this function can be used to resume it again later.
532 ****************************************************************************/
533 void EVT_resume(void)
534 {
535     /* Do nothing for QNX */
536 }
537
538 /****************************************************************************
539 REMARKS
540 Suspends all of our event handling operations. This is also used to
541 de-install the event handling code.
542 ****************************************************************************/
543 void EVT_suspend(void)
544 {
545     /* Do nothing for QNX */
546 }
547
548 /****************************************************************************
549 REMARKS
550 Exits the event module for program terminatation.
551 ****************************************************************************/
552 void EVT_exit(void)
553 {
554 #ifdef __QNXNTO__
555     char    c;
556     int flags;
557
558     if (kbd_fd != -1) {
559         close(kbd_fd);
560         kbd_fd = -1;
561         }
562     if (mouse_fd != -1) {
563         close(mouse_fd);
564         mouse_fd = -1;
565         }
566 #endif
567
568     /* Restore signal handlers */
569     signal(SIGABRT, SIG_DFL);
570     signal(SIGFPE, SIG_DFL);
571     signal(SIGINT, SIG_DFL);
572
573 #ifndef __QNXNTO__
574     /* Kill the Input/Mouse driver if we have spawned it */
575     if (_PM_mouse_ctl != NULL) {
576         struct _fd_entry    fde;
577         uint            pid = 0;
578
579         /* Find out the pid of the mouse driver */
580         if (kill_pid > 0) {
581             if (qnx_fd_query(0,
582                 0, _PM_mouse_ctl->fd, &fde) != -1)
583                 pid = fde.pid;
584             }
585         mouse_close(_PM_mouse_ctl);
586         _PM_mouse_ctl = NULL;
587
588         if (pid > 0) {
589             /* For some reasons the PID's are different under QNX4,
590              * so we use the old mechanism to kill the mouse server.
591              */
592             kill(pid, SIGTERM);
593             kill_pid = 0;
594             }
595         }
596 #endif
597     if (kill_pid > 0) {
598         kill(kill_pid, SIGTERM);
599         kill_pid = 0;
600         }
601 }