Merge branch 'nouveau-import'
[mesa.git] / src / glut / fbdev / input.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 * Copyright (C) 1995-2006 Brian Paul
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public
17 * License along with this library; if not, write to the Free
18 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 /*
22 * Library for glut using mesa fbdev driver
23 *
24 * Written by Sean D'Epagnier (c) 2006
25 */
26
27 #include <errno.h>
28 #include <signal.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <unistd.h>
34 #include <termios.h>
35 #include <inttypes.h>
36
37 #include <sys/ioctl.h>
38 #include <sys/poll.h>
39 #include <sys/kd.h>
40
41 #include <linux/keyboard.h>
42 #include <linux/fb.h>
43 #include <linux/vt.h>
44
45 #include <GL/glut.h>
46
47 #include "internal.h"
48
49 #define MOUSEDEV "/dev/gpmdata"
50
51 #ifdef HAVE_GPM
52 #include <gpm.h>
53 int GpmMouse;
54 #endif
55
56 int CurrentVT = 0;
57 int ConsoleFD = -1;
58
59 int KeyboardModifiers;
60
61 int MouseX, MouseY;
62 int NumMouseButtons;
63
64 double MouseSpeed = 0;
65
66 int KeyRepeatMode = GLUT_KEY_REPEAT_DEFAULT;
67
68 int MouseVisible = 0;
69 int LastMouseTime = 0;
70
71 static int OldKDMode = -1;
72 static int OldMode = KD_TEXT;
73 static struct vt_mode OldVTMode;
74 static struct termios OldTermios;
75
76 static int KeyboardLedState;
77
78 static int MouseFD;
79
80 static int kbdpipe[2];
81
82 static int LastStdinKeyTime, LastStdinSpecialKey = -1, LastStdinCode = -1;
83
84 #define MODIFIER(mod) \
85 KeyboardModifiers = release ? KeyboardModifiers & ~mod \
86 : KeyboardModifiers | mod;
87
88 /* signal handler attached to SIGIO on keyboard input, vt
89 switching and modifiers is handled in the signal handler
90 other keypresses read from a pipe that leaves the handler
91 if a program locks up the glut loop, you can still switch
92 vts and kill it without Alt-SysRq hack */
93 static void KeyboardHandler(int sig)
94 {
95 unsigned char code;
96
97 while(read(ConsoleFD, &code, 1) == 1) {
98 int release, labelval;
99 struct kbentry entry;
100 static int lalt; /* only left alt does vt switch */
101
102 release = code & 0x80;
103
104 entry.kb_index = code & 0x7F;
105 entry.kb_table = 0;
106
107 if (ioctl(ConsoleFD, KDGKBENT, &entry) < 0) {
108 sprintf(exiterror, "ioctl(KDGKBENT) failed.\n");
109 exit(0);
110 }
111
112 labelval = entry.kb_value;
113
114 switch(labelval) {
115 case K_SHIFT:
116 case K_SHIFTL:
117 MODIFIER(GLUT_ACTIVE_SHIFT);
118 continue;
119 case K_CTRL:
120 MODIFIER(GLUT_ACTIVE_CTRL);
121 continue;
122 case K_ALT:
123 lalt = !release;
124 case K_ALTGR:
125 MODIFIER(GLUT_ACTIVE_ALT);
126 continue;
127 }
128
129 if(lalt && !release) {
130 /* VT switch, we must do it */
131 int vt = -1;
132 struct vt_stat st;
133 if(labelval >= K_F1 && labelval <= K_F12)
134 vt = labelval - K_F1 + 1;
135
136 if(labelval == K_LEFT)
137 if(ioctl(ConsoleFD, VT_GETSTATE, &st) >= 0)
138 vt = st.v_active - 1;
139
140 if(labelval == K_RIGHT)
141 if(ioctl(ConsoleFD, VT_GETSTATE, &st) >= 0)
142 vt = st.v_active + 1;
143
144 if(vt != -1) {
145 if(Swapping)
146 VTSwitch = vt;
147 else
148 if(ioctl(ConsoleFD, VT_ACTIVATE, vt) < 0)
149 sprintf(exiterror, "Error switching console\n");
150 continue;
151 }
152 }
153 write(kbdpipe[1], &code, 1);
154 }
155 }
156
157 static void LedModifier(int led, int release)
158 {
159 static int releaseflag = K_CAPS | K_NUM | K_HOLD;
160 if(release)
161 releaseflag |= led;
162 else
163 if(releaseflag & led) {
164 KeyboardLedState ^= led;
165 releaseflag &= ~led;
166 }
167
168 ioctl(ConsoleFD, KDSKBLED, KeyboardLedState);
169 ioctl(ConsoleFD, KDSETLED, 0x80);
170 }
171
172 static void HandleKeyPress(unsigned char key, int up)
173 {
174 if(up) {
175 if(KeyboardUpFunc)
176 KeyboardUpFunc(key, MouseX, MouseY);
177 } else
178 if(KeyboardFunc)
179 KeyboardFunc(key, MouseX, MouseY);
180
181 /* there was no keyboard handler to provide a way to exit the program */
182 if(key == 27)
183 exit(0);
184 }
185
186 static void HandleSpecialPress(int key, int up)
187 {
188 if(up) {
189 if(SpecialUpFunc)
190 SpecialUpFunc(key, MouseX, MouseY);
191 } else
192 if(SpecialFunc)
193 SpecialFunc(key, MouseX, MouseY);
194 }
195
196 static void ReleaseStdinKey(void)
197 {
198 if(LastStdinSpecialKey != -1) {
199 HandleSpecialPress(LastStdinSpecialKey, 1);
200 LastStdinSpecialKey = -1;
201 }
202 if(LastStdinCode != -1) {
203 HandleKeyPress(LastStdinCode, 1);
204 LastStdinCode = -1;
205 }
206 }
207
208 #define READKEY read(kbdpipe[0], &code, 1)
209 static int ReadKey(void)
210 {
211 int release, labelval, labelvalnoshift;
212 unsigned char code;
213 int specialkey = 0;
214 struct kbentry entry;
215
216 if(READKEY != 1) {
217 /* if we are reading from stdin, we detect key releases when the key
218 does not repeat after a given timeout */
219 if(ConsoleFD == 0 && LastStdinKeyTime + 100 < glutGet(GLUT_ELAPSED_TIME))
220 ReleaseStdinKey();
221 return 0;
222 }
223
224 if(code == 0)
225 return 0;
226
227 /* stdin input escape code based */
228 if(ConsoleFD == 0) {
229 KeyboardModifiers = 0;
230 altset:
231 if(code == 27 && READKEY == 1) {
232 if(code != 91) {
233 KeyboardModifiers |= GLUT_ACTIVE_ALT;
234 goto altset;
235 }
236 READKEY;
237 switch(code) {
238 case 68:
239 specialkey = GLUT_KEY_LEFT; break;
240 case 65:
241 specialkey = GLUT_KEY_UP; break;
242 case 67:
243 specialkey = GLUT_KEY_RIGHT; break;
244 case 66:
245 specialkey = GLUT_KEY_DOWN; break;
246 case 52:
247 specialkey = GLUT_KEY_END; READKEY; break;
248 case 53:
249 specialkey = GLUT_KEY_PAGE_UP; READKEY; break;
250 case 54:
251 specialkey = GLUT_KEY_PAGE_DOWN; READKEY; break;
252 case 49:
253 READKEY;
254 if(code == 126)
255 specialkey = GLUT_KEY_HOME;
256 else {
257 specialkey = GLUT_KEY_F1 + code - 50;
258 READKEY;
259 }
260 break;
261 case 50:
262 READKEY;
263 if(code == 126)
264 specialkey = GLUT_KEY_INSERT;
265 else {
266 if(code > '1')
267 code--;
268 if(code > '6')
269 code--;
270 if(code > '3') {
271 KeyboardModifiers |= GLUT_ACTIVE_SHIFT;
272 code -= 12;
273 }
274 specialkey = GLUT_KEY_F1 + code - 40;
275 READKEY;
276 }
277 break;
278 case 51:
279 READKEY;
280 if(code == 126) {
281 code = '\b';
282 goto stdkey;
283 }
284 KeyboardModifiers |= GLUT_ACTIVE_SHIFT;
285 specialkey = GLUT_KEY_F1 + code - 45;
286 READKEY;
287 break;
288 case 91:
289 READKEY;
290 specialkey = GLUT_KEY_F1 + code - 65;
291 break;
292 default:
293 return 0;
294 }
295 }
296
297 if(specialkey) {
298 LastStdinKeyTime = glutGet(GLUT_ELAPSED_TIME);
299
300 if(LastStdinSpecialKey != specialkey) {
301 ReleaseStdinKey();
302 HandleSpecialPress(specialkey, 0);
303 LastStdinSpecialKey = specialkey;
304 LastStdinKeyTime += 200; /* initial repeat */
305 } else
306 if(KeyRepeatMode != GLUT_KEY_REPEAT_OFF)
307 HandleSpecialPress(specialkey, 0);
308 } else {
309 if(code >= 1 && code <= 26 && code != '\r') {
310 KeyboardModifiers |= GLUT_ACTIVE_CTRL;
311 code += 'a' - 1;
312 }
313 if((code >= 43 && code <= 34) || (code == 60)
314 || (code >= 62 && code <= 90) || (code == 94)
315 || (code == 95) || (code >= 123 && code <= 126))
316 KeyboardModifiers |= GLUT_ACTIVE_SHIFT;
317
318 stdkey:
319 LastStdinKeyTime = glutGet(GLUT_ELAPSED_TIME);
320 if(LastStdinCode != code) {
321 ReleaseStdinKey();
322 HandleKeyPress(code, 0);
323 LastStdinCode = code;
324 LastStdinKeyTime += 200; /* initial repeat */
325 } else
326 if(KeyRepeatMode != GLUT_KEY_REPEAT_OFF)
327 HandleSpecialPress(code, 0);
328 }
329 return 1;
330 }
331
332 /* linux kbd reading */
333 release = code & 0x80;
334 code &= 0x7F;
335
336 if(KeyRepeatMode == GLUT_KEY_REPEAT_OFF) {
337 static char keystates[128];
338 if(release)
339 keystates[code] = 0;
340 else {
341 if(keystates[code])
342 return 1;
343 keystates[code] = 1;
344 }
345 }
346
347 entry.kb_index = code;
348 entry.kb_table = 0;
349
350 if (ioctl(ConsoleFD, KDGKBENT, &entry) < 0) {
351 sprintf(exiterror, "ioctl(KDGKBENT) failed.\n");
352 exit(0);
353 }
354
355 labelvalnoshift = entry.kb_value;
356
357 if(KeyboardModifiers & GLUT_ACTIVE_SHIFT)
358 entry.kb_table |= K_SHIFTTAB;
359
360 if (ioctl(ConsoleFD, KDGKBENT, &entry) < 0) {
361 sprintf(exiterror, "ioctl(KDGKBENT) failed.\n");
362 exit(0);
363 }
364
365 labelval = entry.kb_value;
366
367 switch(labelvalnoshift) {
368 case K_CAPS:
369 LedModifier(LED_CAP, release);
370 return 0;
371 case K_NUM:
372 LedModifier(LED_NUM, release);
373 return 0;
374 case K_HOLD: /* scroll lock suspends glut */
375 LedModifier(LED_SCR, release);
376 while(KeyboardLedState & LED_SCR) {
377 usleep(10000);
378 ReadKey();
379 }
380 return 0;
381 }
382
383 /* we could queue keypresses here */
384 if(KeyboardLedState & LED_SCR)
385 return 0;
386
387 if(labelvalnoshift >= K_F1 && labelvalnoshift <= K_F12)
388 specialkey = GLUT_KEY_F1 + labelvalnoshift - K_F1;
389 else
390 switch(labelvalnoshift) {
391 case K_LEFT:
392 specialkey = GLUT_KEY_LEFT; break;
393 case K_UP:
394 specialkey = GLUT_KEY_UP; break;
395 case K_RIGHT:
396 specialkey = GLUT_KEY_RIGHT; break;
397 case K_DOWN:
398 specialkey = GLUT_KEY_DOWN; break;
399 case K_PGUP:
400 specialkey = GLUT_KEY_PAGE_UP; break;
401 case K_PGDN:
402 specialkey = GLUT_KEY_PAGE_DOWN; break;
403 case K_FIND:
404 specialkey = GLUT_KEY_HOME; break;
405 case K_SELECT:
406 specialkey = GLUT_KEY_END; break;
407 case K_INSERT:
408 specialkey = GLUT_KEY_INSERT; break;
409 case K_REMOVE:
410 labelval = '\b';
411 break;
412 case K_ENTER:
413 case K_ENTER - 1: /* keypad enter */
414 labelval = '\r'; break;
415 }
416
417 /* dispatch callback */
418 if(specialkey) {
419 HandleSpecialPress(specialkey, release);
420 } else {
421 char c = labelval;
422
423 if(KeyboardLedState & LED_CAP) {
424 if(c >= 'A' && c <= 'Z')
425 c += 'a' - 'A';
426 else
427 if(c >= 'a' && c <= 'z')
428 c += 'A' - 'a';
429 }
430 HandleKeyPress(c, release);
431 }
432 return 1;
433 }
434
435 void glutIgnoreKeyRepeat(int ignore)
436 {
437 KeyRepeatMode = ignore ? GLUT_KEY_REPEAT_OFF : GLUT_KEY_REPEAT_ON;
438 }
439
440 void glutSetKeyRepeat(int repeatMode)
441 {
442 KeyRepeatMode = repeatMode;
443 }
444
445 void glutForceJoystickFunc(void)
446 {
447 }
448
449 static void HandleMousePress(int button, int pressed)
450 {
451 if(TryMenu(button, pressed))
452 return;
453
454 if(MouseFunc)
455 MouseFunc(button, pressed ? GLUT_DOWN : GLUT_UP, MouseX, MouseY);
456 }
457
458 static int ReadMouse(void)
459 {
460 int l, r, m;
461 static int ll, lm, lr;
462 signed char dx, dy;
463
464 #ifdef HAVE_GPM
465 if(GpmMouse) {
466 Gpm_Event event;
467 struct pollfd pfd;
468 pfd.fd = gpm_fd;
469 pfd.events = POLLIN;
470 if(poll(&pfd, 1, 1) != 1)
471 return 0;
472
473 if(Gpm_GetEvent(&event) != 1)
474 return 0;
475
476 l = event.buttons & GPM_B_LEFT;
477 m = event.buttons & GPM_B_MIDDLE;
478 r = event.buttons & GPM_B_RIGHT;
479
480 /* gpm is weird in that it gives a button number when the button
481 is released, with type set to GPM_UP, this is only a problem
482 if it is the last button released */
483
484 if(event.type & GPM_UP)
485 if(event.buttons == GPM_B_LEFT || event.buttons == GPM_B_MIDDLE ||
486 event.buttons == GPM_B_RIGHT || event.buttons == GPM_B_FOURTH)
487 l = m = r = 0;
488
489 dx = event.dx;
490 dy = event.dy;
491 } else
492 #endif
493 {
494 char data[4];
495
496 if(MouseFD == -1)
497 return 0;
498
499 if(read(MouseFD, data, 4) != 4)
500 return 0;
501
502 l = ((data[0] & 0x20) >> 3);
503 m = ((data[3] & 0x10) >> 3);
504 r = ((data[0] & 0x10) >> 4);
505
506 dx = (((data[0] & 0x03) << 6) | (data[1] & 0x3F));
507 dy = (((data[0] & 0x0C) << 4) | (data[2] & 0x3F));
508 }
509
510 MouseX += dx * MouseSpeed;
511 if(MouseX < 0)
512 MouseX = 0;
513 else
514 if(MouseX >= VarInfo.xres)
515 MouseX = VarInfo.xres - 1;
516
517 MouseY += dy * MouseSpeed;
518 if(MouseY < 0)
519 MouseY = 0;
520 else
521 if(MouseY >= VarInfo.yres)
522 MouseY = VarInfo.yres - 1;
523
524 if(l != ll)
525 HandleMousePress(GLUT_LEFT_BUTTON, l);
526 if(m != lm)
527 HandleMousePress(GLUT_MIDDLE_BUTTON, m);
528 if(r != lr)
529 HandleMousePress(GLUT_RIGHT_BUTTON, r);
530
531 ll = l, lm = m, lr = r;
532
533 if(dx || dy || !MouseVisible) {
534 if(l || m || r) {
535 if(MotionFunc)
536 MotionFunc(MouseX, MouseY);
537 } else
538 if(PassiveMotionFunc)
539 PassiveMotionFunc(MouseX, MouseY);
540
541 EraseCursor();
542
543 MouseVisible = 1;
544
545 if(ActiveMenu)
546 Redisplay = 1;
547 else
548 SwapCursor();
549 }
550
551 LastMouseTime = glutGet(GLUT_ELAPSED_TIME);
552
553 return 1;
554 }
555
556 void ReceiveInput(void)
557 {
558 if(ConsoleFD != -1)
559 while(ReadKey());
560
561 while(ReadMouse());
562
563 /* implement a 2 second timeout on the mouse */
564 if(MouseVisible && glutGet(GLUT_ELAPSED_TIME) - LastMouseTime > 2000) {
565 EraseCursor();
566 MouseVisible = 0;
567 SwapCursor();
568 }
569 }
570
571 static void VTSwitchHandler(int sig)
572 {
573 struct vt_stat st;
574 switch(sig) {
575 case SIGUSR1:
576 ioctl(ConsoleFD, VT_RELDISP, 1);
577 Active = 0;
578 #ifdef MULTIHEAD
579 VisiblePoll = 1;
580 TestVisible();
581 #else
582 VisibleSwitch = 1;
583 Visible = 0;
584 #endif
585 break;
586 case SIGUSR2:
587 ioctl(ConsoleFD, VT_GETSTATE, &st);
588 if(st.v_active)
589 ioctl(ConsoleFD, VT_RELDISP, VT_ACKACQ);
590
591 RestoreColorMap();
592
593 Active = 1;
594 Visible = 1;
595 VisibleSwitch = 1;
596
597 Redisplay = 1;
598 break;
599 }
600 }
601
602 void InitializeVT(int usestdin)
603 {
604 struct termios tio;
605 struct vt_mode vt;
606 char console[128];
607
608 signal(SIGIO, SIG_IGN);
609
610 /* save old terminos settings */
611 if (tcgetattr(0, &OldTermios) < 0) {
612 sprintf(exiterror, "tcgetattr failed\n");
613 exit(0);
614 }
615
616 tio = OldTermios;
617
618 /* terminos settings for straight-through mode */
619 tio.c_lflag &= ~(ICANON | ECHO | ISIG);
620 tio.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
621 tio.c_iflag |= IGNBRK;
622
623 tio.c_cc[VMIN] = 0;
624 tio.c_cc[VTIME] = 0;
625
626 if (tcsetattr(0, TCSANOW, &tio) < 0) {
627 sprintf(exiterror, "tcsetattr failed\n");
628 exit(0);
629 }
630
631 Active = 1;
632
633 if(usestdin) {
634 ConsoleFD = 0;
635 return;
636 }
637
638 /* enable sigio for input */
639 if(fcntl(0, F_SETFL, O_ASYNC) < 0) {
640 sprintf(exiterror, "Failed to set O_ASYNC mode on fd 0\n");
641 exit(0);
642 }
643
644 /* detect the current vt if it was not specified */
645 if(CurrentVT == 0) {
646 int fd = open("/dev/tty", O_RDWR | O_NDELAY, 0);
647 struct vt_stat st;
648 if(fd == -1) {
649 sprintf(exiterror, "Failed to open /dev/tty\n");
650 exit(0);
651 }
652
653 if(ioctl(fd, VT_GETSTATE, &st) == -1) {
654 fprintf(stderr, "Could not detect current vt, specify with -vt\n");
655 fprintf(stderr, "Defaulting to stdin input\n");
656 ConsoleFD = 0;
657 close(fd);
658 return;
659 }
660
661 CurrentVT = st.v_active;
662 close(fd);
663 }
664
665 /* if we close with the modifier set in glutIconifyWindow, we won't
666 get the signal when they are released, so set to zero here */
667 KeyboardModifiers = 0;
668
669 /* open the console tty */
670 sprintf(console, "/dev/tty%d", CurrentVT);
671 ConsoleFD = open(console, O_RDWR | O_NDELAY, 0);
672 if (ConsoleFD < 0) {
673 sprintf(exiterror, "error couldn't open %s,"
674 " defaulting to stdin \n", console);
675 ConsoleFD = 0;
676 return;
677 }
678
679 signal(SIGUSR1, VTSwitchHandler);
680 signal(SIGUSR2, VTSwitchHandler);
681
682 if (ioctl(ConsoleFD, VT_GETMODE, &OldVTMode) < 0) {
683 sprintf(exiterror,"Failed to grab %s, defaulting to stdin\n", console);
684 close(ConsoleFD);
685 ConsoleFD = 0;
686 return;
687 }
688
689 vt = OldVTMode;
690
691 vt.mode = VT_PROCESS;
692 vt.waitv = 0;
693 vt.relsig = SIGUSR1;
694 vt.acqsig = SIGUSR2;
695 if (ioctl(ConsoleFD, VT_SETMODE, &vt) < 0) {
696 sprintf(exiterror, "error: ioctl(VT_SETMODE) failed: %s\n",
697 strerror(errno));
698 close(ConsoleFD);
699 ConsoleFD = 0;
700 exit(1);
701 }
702
703 if (ioctl(ConsoleFD, KDGKBMODE, &OldKDMode) < 0) {
704 sprintf(exiterror, "Warning: ioctl KDGKBMODE failed!\n");
705 OldKDMode = K_XLATE;
706 }
707
708 /* use SIGIO so VT switching can work if the program is locked */
709 signal(SIGIO, KeyboardHandler);
710
711 pipe(kbdpipe);
712
713 if(fcntl(kbdpipe[0], F_SETFL, O_NONBLOCK | O_ASYNC) < 0) {
714 sprintf(exiterror, "Failed to set keyboard to non-blocking\n");
715 exit(0);
716 }
717
718 fcntl(0, F_SETOWN, getpid());
719
720 if(ioctl(ConsoleFD, KDGETMODE, &OldMode) < 0)
721 sprintf(exiterror, "Warning: Failed to get terminal mode\n");
722
723 #ifdef HAVE_GPM
724 if(!GpmMouse)
725 #endif
726 if(ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0)
727 sprintf(exiterror,"Warning: Failed to set terminal to graphics\n");
728
729 if(ioctl(ConsoleFD, KDSKBMODE, K_MEDIUMRAW) < 0) {
730 sprintf(exiterror, "ioctl KDSKBMODE failed!\n");
731 tcsetattr(0, TCSANOW, &OldTermios);
732 exit(0);
733 }
734
735 if(ioctl(ConsoleFD, KDGKBLED, &KeyboardLedState) < 0) {
736 sprintf(exiterror, "ioctl KDGKBLED failed!\n");
737 exit(0);
738 }
739 }
740
741 void RestoreVT(void)
742 {
743 if(ConsoleFD < 0)
744 return;
745
746 if (tcsetattr(0, TCSANOW, &OldTermios) < 0)
747 fprintf(stderr, "tcsetattr failed\n");
748
749 /* setting the mode to text from graphics restores the colormap */
750 if(
751 #ifdef HAVE_GPM
752 !GpmMouse ||
753 #endif
754 ConsoleFD == 0)
755 if(ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0)
756 goto skipioctl; /* no need to fail twice */
757
758 if(ioctl(ConsoleFD, KDSETMODE, OldMode) < 0)
759 fprintf(stderr, "ioctl KDSETMODE failed!\n");
760
761 skipioctl:
762
763 if(ConsoleFD == 0)
764 return;
765
766 /* restore keyboard state */
767 if (ioctl(ConsoleFD, VT_SETMODE, &OldVTMode) < 0)
768 fprintf(stderr, "Failed to set vtmode\n");
769
770 if (ioctl(ConsoleFD, KDSKBMODE, OldKDMode) < 0)
771 fprintf(stderr, "ioctl KDSKBMODE failed!\n");
772
773 close(ConsoleFD);
774
775 close(kbdpipe[0]);
776 close(kbdpipe[1]);
777 }
778
779 void InitializeMouse(void)
780 {
781 #ifdef HAVE_GPM
782 if(!GpmMouse)
783 #endif
784 {
785 const char *mousedev = getenv("MOUSE");
786 if(!mousedev)
787 mousedev = MOUSEDEV;
788 if((MouseFD = open(mousedev, O_RDONLY | O_NONBLOCK)) >= 0) {
789 if(!MouseSpeed)
790 MouseSpeed = 1;
791 NumMouseButtons = 3;
792 return;
793 }
794 }
795 #ifdef HAVE_GPM
796 {
797 Gpm_Connect conn;
798 int c;
799 conn.eventMask = ~0; /* Want to know about all the events */
800 conn.defaultMask = 0; /* don't handle anything by default */
801 conn.minMod = 0; /* want everything */
802 conn.maxMod = ~0; /* all modifiers included */
803 if(Gpm_Open(&conn, 0) != -1) {
804 if(!MouseSpeed)
805 MouseSpeed = 8;
806 NumMouseButtons = 3;
807 return;
808 }
809 fprintf(stderr, "Cannot open gpmctl.\n");
810 }
811 #endif
812 fprintf(stderr,"Cannot open %s.\n"
813 "Continuing without Mouse\n", MOUSEDEV);
814 }
815
816 void CloseMouse(void)
817 {
818 #ifdef HAVE_GPM
819 if(GpmMouse) {
820 if(NumMouseButtons)
821 Gpm_Close();
822 } else
823 #endif
824 if(MouseFD >= 0)
825 close(MouseFD);
826 }