| /* |
| * Mesa 3-D graphics library |
| * Version: 6.5 |
| * Copyright (C) 1995-2006 Brian Paul |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public |
| * License along with this library; if not, write to the Free |
| * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| */ |
| |
| /* |
| * Library for glut using mesa fbdev driver |
| * |
| * Written by Sean D'Epagnier (c) 2006 |
| */ |
| |
| #include <errno.h> |
| #include <signal.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <fcntl.h> |
| #include <unistd.h> |
| #include <termios.h> |
| #include <inttypes.h> |
| |
| #include <sys/ioctl.h> |
| #include <sys/poll.h> |
| #include <sys/kd.h> |
| |
| #include <linux/keyboard.h> |
| #include <linux/fb.h> |
| #include <linux/vt.h> |
| |
| #include <GL/glut.h> |
| |
| #include "internal.h" |
| |
| #define MOUSEDEV "/dev/gpmdata" |
| |
| #ifdef HAVE_GPM |
| #include <gpm.h> |
| int GpmMouse; |
| #endif |
| |
| int CurrentVT = 0; |
| int ConsoleFD = -1; |
| |
| int KeyboardModifiers; |
| |
| int MouseX, MouseY; |
| int NumMouseButtons; |
| |
| double MouseSpeed = 0; |
| |
| int KeyRepeatMode = GLUT_KEY_REPEAT_DEFAULT; |
| |
| int MouseVisible = 0; |
| int LastMouseTime = 0; |
| |
| static int OldKDMode = -1; |
| static int OldMode = KD_TEXT; |
| static struct vt_mode OldVTMode; |
| static struct termios OldTermios; |
| |
| static int KeyboardLedState; |
| |
| static int MouseFD; |
| |
| static int kbdpipe[2]; |
| |
| static int LastStdinKeyTime, LastStdinSpecialKey = -1, LastStdinCode = -1; |
| |
| #define MODIFIER(mod) \ |
| KeyboardModifiers = release ? KeyboardModifiers & ~mod \ |
| : KeyboardModifiers | mod; |
| |
| /* signal handler attached to SIGIO on keyboard input, vt |
| switching and modifiers is handled in the signal handler |
| other keypresses read from a pipe that leaves the handler |
| if a program locks up the glut loop, you can still switch |
| vts and kill it without Alt-SysRq hack */ |
| static void KeyboardHandler(int sig) |
| { |
| unsigned char code; |
| |
| while(read(ConsoleFD, &code, 1) == 1) { |
| int release, labelval; |
| struct kbentry entry; |
| static int lalt; /* only left alt does vt switch */ |
| |
| release = code & 0x80; |
| |
| entry.kb_index = code & 0x7F; |
| entry.kb_table = 0; |
| |
| if (ioctl(ConsoleFD, KDGKBENT, &entry) < 0) { |
| sprintf(exiterror, "ioctl(KDGKBENT) failed.\n"); |
| exit(0); |
| } |
| |
| labelval = entry.kb_value; |
| |
| switch(labelval) { |
| case K_SHIFT: |
| case K_SHIFTL: |
| MODIFIER(GLUT_ACTIVE_SHIFT); |
| continue; |
| case K_CTRL: |
| MODIFIER(GLUT_ACTIVE_CTRL); |
| continue; |
| case K_ALT: |
| lalt = !release; |
| case K_ALTGR: |
| MODIFIER(GLUT_ACTIVE_ALT); |
| continue; |
| } |
| |
| if(lalt && !release) { |
| /* VT switch, we must do it */ |
| int vt = -1; |
| struct vt_stat st; |
| if(labelval >= K_F1 && labelval <= K_F12) |
| vt = labelval - K_F1 + 1; |
| |
| if(labelval == K_LEFT) |
| if(ioctl(ConsoleFD, VT_GETSTATE, &st) >= 0) |
| vt = st.v_active - 1; |
| |
| if(labelval == K_RIGHT) |
| if(ioctl(ConsoleFD, VT_GETSTATE, &st) >= 0) |
| vt = st.v_active + 1; |
| |
| if(vt != -1) { |
| if(Swapping) |
| VTSwitch = vt; |
| else |
| if(ioctl(ConsoleFD, VT_ACTIVATE, vt) < 0) |
| sprintf(exiterror, "Error switching console\n"); |
| continue; |
| } |
| } |
| write(kbdpipe[1], &code, 1); |
| } |
| } |
| |
| static void LedModifier(int led, int release) |
| { |
| static int releaseflag = K_CAPS | K_NUM | K_HOLD; |
| if(release) |
| releaseflag |= led; |
| else |
| if(releaseflag & led) { |
| KeyboardLedState ^= led; |
| releaseflag &= ~led; |
| } |
| |
| ioctl(ConsoleFD, KDSKBLED, KeyboardLedState); |
| ioctl(ConsoleFD, KDSETLED, 0x80); |
| } |
| |
| static void HandleKeyPress(unsigned char key, int up) |
| { |
| if(up) { |
| if(KeyboardUpFunc) |
| KeyboardUpFunc(key, MouseX, MouseY); |
| } else |
| if(KeyboardFunc) |
| KeyboardFunc(key, MouseX, MouseY); |
| |
| /* there was no keyboard handler to provide a way to exit the program */ |
| if(key == 27) |
| exit(0); |
| } |
| |
| static void HandleSpecialPress(int key, int up) |
| { |
| if(up) { |
| if(SpecialUpFunc) |
| SpecialUpFunc(key, MouseX, MouseY); |
| } else |
| if(SpecialFunc) |
| SpecialFunc(key, MouseX, MouseY); |
| } |
| |
| static void ReleaseStdinKey(void) |
| { |
| if(LastStdinSpecialKey != -1) { |
| HandleSpecialPress(LastStdinSpecialKey, 1); |
| LastStdinSpecialKey = -1; |
| } |
| if(LastStdinCode != -1) { |
| HandleKeyPress(LastStdinCode, 1); |
| LastStdinCode = -1; |
| } |
| } |
| |
| #define READKEY read(kbdpipe[0], &code, 1) |
| static int ReadKey(void) |
| { |
| int release, labelval, labelvalnoshift; |
| unsigned char code; |
| int specialkey = 0; |
| struct kbentry entry; |
| |
| if(READKEY != 1) { |
| /* if we are reading from stdin, we detect key releases when the key |
| does not repeat after a given timeout */ |
| if(ConsoleFD == 0 && LastStdinKeyTime + 100 < glutGet(GLUT_ELAPSED_TIME)) |
| ReleaseStdinKey(); |
| return 0; |
| } |
| |
| if(code == 0) |
| return 0; |
| |
| /* stdin input escape code based */ |
| if(ConsoleFD == 0) { |
| KeyboardModifiers = 0; |
| altset: |
| if(code == 27 && READKEY == 1) { |
| if(code != 91) { |
| KeyboardModifiers |= GLUT_ACTIVE_ALT; |
| goto altset; |
| } |
| READKEY; |
| switch(code) { |
| case 68: |
| specialkey = GLUT_KEY_LEFT; break; |
| case 65: |
| specialkey = GLUT_KEY_UP; break; |
| case 67: |
| specialkey = GLUT_KEY_RIGHT; break; |
| case 66: |
| specialkey = GLUT_KEY_DOWN; break; |
| case 52: |
| specialkey = GLUT_KEY_END; READKEY; break; |
| case 53: |
| specialkey = GLUT_KEY_PAGE_UP; READKEY; break; |
| case 54: |
| specialkey = GLUT_KEY_PAGE_DOWN; READKEY; break; |
| case 49: |
| READKEY; |
| if(code == 126) |
| specialkey = GLUT_KEY_HOME; |
| else { |
| specialkey = GLUT_KEY_F1 + code - 50; |
| READKEY; |
| } |
| break; |
| case 50: |
| READKEY; |
| if(code == 126) |
| specialkey = GLUT_KEY_INSERT; |
| else { |
| if(code > '1') |
| code--; |
| if(code > '6') |
| code--; |
| if(code > '3') { |
| KeyboardModifiers |= GLUT_ACTIVE_SHIFT; |
| code -= 12; |
| } |
| specialkey = GLUT_KEY_F1 + code - 40; |
| READKEY; |
| } |
| break; |
| case 51: |
| READKEY; |
| if(code == 126) { |
| code = '\b'; |
| goto stdkey; |
| } |
| KeyboardModifiers |= GLUT_ACTIVE_SHIFT; |
| specialkey = GLUT_KEY_F1 + code - 45; |
| READKEY; |
| break; |
| case 91: |
| READKEY; |
| specialkey = GLUT_KEY_F1 + code - 65; |
| break; |
| default: |
| return 0; |
| } |
| } |
| |
| if(specialkey) { |
| LastStdinKeyTime = glutGet(GLUT_ELAPSED_TIME); |
| |
| if(LastStdinSpecialKey != specialkey) { |
| ReleaseStdinKey(); |
| HandleSpecialPress(specialkey, 0); |
| LastStdinSpecialKey = specialkey; |
| LastStdinKeyTime += 200; /* initial repeat */ |
| } else |
| if(KeyRepeatMode != GLUT_KEY_REPEAT_OFF) |
| HandleSpecialPress(specialkey, 0); |
| } else { |
| if(code >= 1 && code <= 26 && code != '\r') { |
| KeyboardModifiers |= GLUT_ACTIVE_CTRL; |
| code += 'a' - 1; |
| } |
| if((code >= 43 && code <= 34) || (code == 60) |
| || (code >= 62 && code <= 90) || (code == 94) |
| || (code == 95) || (code >= 123 && code <= 126)) |
| KeyboardModifiers |= GLUT_ACTIVE_SHIFT; |
| |
| stdkey: |
| LastStdinKeyTime = glutGet(GLUT_ELAPSED_TIME); |
| if(LastStdinCode != code) { |
| ReleaseStdinKey(); |
| HandleKeyPress(code, 0); |
| LastStdinCode = code; |
| LastStdinKeyTime += 200; /* initial repeat */ |
| } else |
| if(KeyRepeatMode != GLUT_KEY_REPEAT_OFF) |
| HandleSpecialPress(code, 0); |
| } |
| return 1; |
| } |
| |
| /* linux kbd reading */ |
| release = code & 0x80; |
| code &= 0x7F; |
| |
| if(KeyRepeatMode == GLUT_KEY_REPEAT_OFF) { |
| static char keystates[128]; |
| if(release) |
| keystates[code] = 0; |
| else { |
| if(keystates[code]) |
| return 1; |
| keystates[code] = 1; |
| } |
| } |
| |
| entry.kb_index = code; |
| entry.kb_table = 0; |
| |
| if (ioctl(ConsoleFD, KDGKBENT, &entry) < 0) { |
| sprintf(exiterror, "ioctl(KDGKBENT) failed.\n"); |
| exit(0); |
| } |
| |
| labelvalnoshift = entry.kb_value; |
| |
| if(KeyboardModifiers & GLUT_ACTIVE_SHIFT) |
| entry.kb_table |= K_SHIFTTAB; |
| |
| if (ioctl(ConsoleFD, KDGKBENT, &entry) < 0) { |
| sprintf(exiterror, "ioctl(KDGKBENT) failed.\n"); |
| exit(0); |
| } |
| |
| labelval = entry.kb_value; |
| |
| switch(labelvalnoshift) { |
| case K_CAPS: |
| LedModifier(LED_CAP, release); |
| return 0; |
| case K_NUM: |
| LedModifier(LED_NUM, release); |
| return 0; |
| case K_HOLD: /* scroll lock suspends glut */ |
| LedModifier(LED_SCR, release); |
| while(KeyboardLedState & LED_SCR) { |
| usleep(10000); |
| ReadKey(); |
| } |
| return 0; |
| } |
| |
| /* we could queue keypresses here */ |
| if(KeyboardLedState & LED_SCR) |
| return 0; |
| |
| if(labelvalnoshift >= K_F1 && labelvalnoshift <= K_F12) |
| specialkey = GLUT_KEY_F1 + labelvalnoshift - K_F1; |
| else |
| switch(labelvalnoshift) { |
| case K_LEFT: |
| specialkey = GLUT_KEY_LEFT; break; |
| case K_UP: |
| specialkey = GLUT_KEY_UP; break; |
| case K_RIGHT: |
| specialkey = GLUT_KEY_RIGHT; break; |
| case K_DOWN: |
| specialkey = GLUT_KEY_DOWN; break; |
| case K_PGUP: |
| specialkey = GLUT_KEY_PAGE_UP; break; |
| case K_PGDN: |
| specialkey = GLUT_KEY_PAGE_DOWN; break; |
| case K_FIND: |
| specialkey = GLUT_KEY_HOME; break; |
| case K_SELECT: |
| specialkey = GLUT_KEY_END; break; |
| case K_INSERT: |
| specialkey = GLUT_KEY_INSERT; break; |
| case K_REMOVE: |
| labelval = '\b'; |
| break; |
| case K_ENTER: |
| case K_ENTER - 1: /* keypad enter */ |
| labelval = '\r'; break; |
| } |
| |
| /* dispatch callback */ |
| if(specialkey) { |
| HandleSpecialPress(specialkey, release); |
| } else { |
| char c = labelval; |
| |
| if(KeyboardLedState & LED_CAP) { |
| if(c >= 'A' && c <= 'Z') |
| c += 'a' - 'A'; |
| else |
| if(c >= 'a' && c <= 'z') |
| c += 'A' - 'a'; |
| } |
| HandleKeyPress(c, release); |
| } |
| return 1; |
| } |
| |
| void glutIgnoreKeyRepeat(int ignore) |
| { |
| KeyRepeatMode = ignore ? GLUT_KEY_REPEAT_OFF : GLUT_KEY_REPEAT_ON; |
| } |
| |
| void glutSetKeyRepeat(int repeatMode) |
| { |
| KeyRepeatMode = repeatMode; |
| } |
| |
| void glutForceJoystickFunc(void) |
| { |
| } |
| |
| static void HandleMousePress(int button, int pressed) |
| { |
| if(TryMenu(button, pressed)) |
| return; |
| |
| if(MouseFunc) |
| MouseFunc(button, pressed ? GLUT_DOWN : GLUT_UP, MouseX, MouseY); |
| } |
| |
| static int ReadMouse(void) |
| { |
| int l, r, m; |
| static int ll, lm, lr; |
| signed char dx, dy; |
| |
| #ifdef HAVE_GPM |
| if(GpmMouse) { |
| Gpm_Event event; |
| struct pollfd pfd; |
| pfd.fd = gpm_fd; |
| pfd.events = POLLIN; |
| if(poll(&pfd, 1, 1) != 1) |
| return 0; |
| |
| if(Gpm_GetEvent(&event) != 1) |
| return 0; |
| |
| l = event.buttons & GPM_B_LEFT; |
| m = event.buttons & GPM_B_MIDDLE; |
| r = event.buttons & GPM_B_RIGHT; |
| |
| /* gpm is weird in that it gives a button number when the button |
| is released, with type set to GPM_UP, this is only a problem |
| if it is the last button released */ |
| |
| if(event.type & GPM_UP) |
| if(event.buttons == GPM_B_LEFT || event.buttons == GPM_B_MIDDLE || |
| event.buttons == GPM_B_RIGHT || event.buttons == GPM_B_FOURTH) |
| l = m = r = 0; |
| |
| dx = event.dx; |
| dy = event.dy; |
| } else |
| #endif |
| { |
| char data[4]; |
| |
| if(MouseFD == -1) |
| return 0; |
| |
| if(read(MouseFD, data, 4) != 4) |
| return 0; |
| |
| l = ((data[0] & 0x20) >> 3); |
| m = ((data[3] & 0x10) >> 3); |
| r = ((data[0] & 0x10) >> 4); |
| |
| dx = (((data[0] & 0x03) << 6) | (data[1] & 0x3F)); |
| dy = (((data[0] & 0x0C) << 4) | (data[2] & 0x3F)); |
| } |
| |
| MouseX += dx * MouseSpeed; |
| if(MouseX < 0) |
| MouseX = 0; |
| else |
| if(MouseX >= VarInfo.xres) |
| MouseX = VarInfo.xres - 1; |
| |
| MouseY += dy * MouseSpeed; |
| if(MouseY < 0) |
| MouseY = 0; |
| else |
| if(MouseY >= VarInfo.yres) |
| MouseY = VarInfo.yres - 1; |
| |
| if(l != ll) |
| HandleMousePress(GLUT_LEFT_BUTTON, l); |
| if(m != lm) |
| HandleMousePress(GLUT_MIDDLE_BUTTON, m); |
| if(r != lr) |
| HandleMousePress(GLUT_RIGHT_BUTTON, r); |
| |
| ll = l, lm = m, lr = r; |
| |
| if(dx || dy || !MouseVisible) { |
| if(l || m || r) { |
| if(MotionFunc) |
| MotionFunc(MouseX, MouseY); |
| } else |
| if(PassiveMotionFunc) |
| PassiveMotionFunc(MouseX, MouseY); |
| |
| EraseCursor(); |
| |
| MouseVisible = 1; |
| |
| if(ActiveMenu) |
| Redisplay = 1; |
| else |
| SwapCursor(); |
| } |
| |
| LastMouseTime = glutGet(GLUT_ELAPSED_TIME); |
| |
| return 1; |
| } |
| |
| void ReceiveInput(void) |
| { |
| if(ConsoleFD != -1) |
| while(ReadKey()); |
| |
| while(ReadMouse()); |
| |
| /* implement a 2 second timeout on the mouse */ |
| if(MouseVisible && glutGet(GLUT_ELAPSED_TIME) - LastMouseTime > 2000) { |
| EraseCursor(); |
| MouseVisible = 0; |
| SwapCursor(); |
| } |
| } |
| |
| static void VTSwitchHandler(int sig) |
| { |
| struct vt_stat st; |
| switch(sig) { |
| case SIGUSR1: |
| ioctl(ConsoleFD, VT_RELDISP, 1); |
| Active = 0; |
| #ifdef MULTIHEAD |
| VisiblePoll = 1; |
| TestVisible(); |
| #else |
| VisibleSwitch = 1; |
| Visible = 0; |
| #endif |
| break; |
| case SIGUSR2: |
| ioctl(ConsoleFD, VT_GETSTATE, &st); |
| if(st.v_active) |
| ioctl(ConsoleFD, VT_RELDISP, VT_ACKACQ); |
| |
| RestoreColorMap(); |
| |
| Active = 1; |
| Visible = 1; |
| VisibleSwitch = 1; |
| |
| Redisplay = 1; |
| break; |
| } |
| } |
| |
| void InitializeVT(int usestdin) |
| { |
| struct termios tio; |
| struct vt_mode vt; |
| char console[128]; |
| |
| signal(SIGIO, SIG_IGN); |
| |
| /* save old terminos settings */ |
| if (tcgetattr(0, &OldTermios) < 0) { |
| sprintf(exiterror, "tcgetattr failed\n"); |
| exit(0); |
| } |
| |
| tio = OldTermios; |
| |
| /* terminos settings for straight-through mode */ |
| tio.c_lflag &= ~(ICANON | ECHO | ISIG); |
| tio.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON); |
| tio.c_iflag |= IGNBRK; |
| |
| tio.c_cc[VMIN] = 0; |
| tio.c_cc[VTIME] = 0; |
| |
| if (tcsetattr(0, TCSANOW, &tio) < 0) { |
| sprintf(exiterror, "tcsetattr failed\n"); |
| exit(0); |
| } |
| |
| Active = 1; |
| |
| if(usestdin) { |
| ConsoleFD = 0; |
| return; |
| } |
| |
| /* enable sigio for input */ |
| if(fcntl(0, F_SETFL, O_ASYNC) < 0) { |
| sprintf(exiterror, "Failed to set O_ASYNC mode on fd 0\n"); |
| exit(0); |
| } |
| |
| /* detect the current vt if it was not specified */ |
| if(CurrentVT == 0) { |
| int fd = open("/dev/tty", O_RDWR | O_NDELAY, 0); |
| struct vt_stat st; |
| if(fd == -1) { |
| sprintf(exiterror, "Failed to open /dev/tty\n"); |
| exit(0); |
| } |
| |
| if(ioctl(fd, VT_GETSTATE, &st) == -1) { |
| fprintf(stderr, "Could not detect current vt, specify with -vt\n"); |
| fprintf(stderr, "Defaulting to stdin input\n"); |
| ConsoleFD = 0; |
| close(fd); |
| return; |
| } |
| |
| CurrentVT = st.v_active; |
| close(fd); |
| } |
| |
| /* if we close with the modifier set in glutIconifyWindow, we won't |
| get the signal when they are released, so set to zero here */ |
| KeyboardModifiers = 0; |
| |
| /* open the console tty */ |
| sprintf(console, "/dev/tty%d", CurrentVT); |
| ConsoleFD = open(console, O_RDWR | O_NDELAY, 0); |
| if (ConsoleFD < 0) { |
| sprintf(exiterror, "error couldn't open %s," |
| " defaulting to stdin \n", console); |
| ConsoleFD = 0; |
| return; |
| } |
| |
| signal(SIGUSR1, VTSwitchHandler); |
| signal(SIGUSR2, VTSwitchHandler); |
| |
| if (ioctl(ConsoleFD, VT_GETMODE, &OldVTMode) < 0) { |
| sprintf(exiterror,"Failed to grab %s, defaulting to stdin\n", console); |
| close(ConsoleFD); |
| ConsoleFD = 0; |
| return; |
| } |
| |
| vt = OldVTMode; |
| |
| vt.mode = VT_PROCESS; |
| vt.waitv = 0; |
| vt.relsig = SIGUSR1; |
| vt.acqsig = SIGUSR2; |
| if (ioctl(ConsoleFD, VT_SETMODE, &vt) < 0) { |
| sprintf(exiterror, "error: ioctl(VT_SETMODE) failed: %s\n", |
| strerror(errno)); |
| close(ConsoleFD); |
| ConsoleFD = 0; |
| exit(1); |
| } |
| |
| if (ioctl(ConsoleFD, KDGKBMODE, &OldKDMode) < 0) { |
| sprintf(exiterror, "Warning: ioctl KDGKBMODE failed!\n"); |
| OldKDMode = K_XLATE; |
| } |
| |
| /* use SIGIO so VT switching can work if the program is locked */ |
| signal(SIGIO, KeyboardHandler); |
| |
| pipe(kbdpipe); |
| |
| if(fcntl(kbdpipe[0], F_SETFL, O_NONBLOCK | O_ASYNC) < 0) { |
| sprintf(exiterror, "Failed to set keyboard to non-blocking\n"); |
| exit(0); |
| } |
| |
| fcntl(0, F_SETOWN, getpid()); |
| |
| if(ioctl(ConsoleFD, KDGETMODE, &OldMode) < 0) |
| sprintf(exiterror, "Warning: Failed to get terminal mode\n"); |
| |
| #ifdef HAVE_GPM |
| if(!GpmMouse) |
| #endif |
| if(ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0) |
| sprintf(exiterror,"Warning: Failed to set terminal to graphics\n"); |
| |
| if(ioctl(ConsoleFD, KDSKBMODE, K_MEDIUMRAW) < 0) { |
| sprintf(exiterror, "ioctl KDSKBMODE failed!\n"); |
| tcsetattr(0, TCSANOW, &OldTermios); |
| exit(0); |
| } |
| |
| if(ioctl(ConsoleFD, KDGKBLED, &KeyboardLedState) < 0) { |
| sprintf(exiterror, "ioctl KDGKBLED failed!\n"); |
| exit(0); |
| } |
| } |
| |
| void RestoreVT(void) |
| { |
| if(ConsoleFD < 0) |
| return; |
| |
| if (tcsetattr(0, TCSANOW, &OldTermios) < 0) |
| fprintf(stderr, "tcsetattr failed\n"); |
| |
| /* setting the mode to text from graphics restores the colormap */ |
| if( |
| #ifdef HAVE_GPM |
| !GpmMouse || |
| #endif |
| ConsoleFD == 0) |
| if(ioctl(ConsoleFD, KDSETMODE, KD_GRAPHICS) < 0) |
| goto skipioctl; /* no need to fail twice */ |
| |
| if(ioctl(ConsoleFD, KDSETMODE, OldMode) < 0) |
| fprintf(stderr, "ioctl KDSETMODE failed!\n"); |
| |
| skipioctl: |
| |
| if(ConsoleFD == 0) |
| return; |
| |
| /* restore keyboard state */ |
| if (ioctl(ConsoleFD, VT_SETMODE, &OldVTMode) < 0) |
| fprintf(stderr, "Failed to set vtmode\n"); |
| |
| if (ioctl(ConsoleFD, KDSKBMODE, OldKDMode) < 0) |
| fprintf(stderr, "ioctl KDSKBMODE failed!\n"); |
| |
| close(ConsoleFD); |
| |
| close(kbdpipe[0]); |
| close(kbdpipe[1]); |
| } |
| |
| void InitializeMouse(void) |
| { |
| #ifdef HAVE_GPM |
| if(!GpmMouse) |
| #endif |
| { |
| const char *mousedev = getenv("MOUSE"); |
| if(!mousedev) |
| mousedev = MOUSEDEV; |
| if((MouseFD = open(mousedev, O_RDONLY | O_NONBLOCK)) >= 0) { |
| if(!MouseSpeed) |
| MouseSpeed = 1; |
| NumMouseButtons = 3; |
| return; |
| } |
| } |
| #ifdef HAVE_GPM |
| { |
| Gpm_Connect conn; |
| int c; |
| conn.eventMask = ~0; /* Want to know about all the events */ |
| conn.defaultMask = 0; /* don't handle anything by default */ |
| conn.minMod = 0; /* want everything */ |
| conn.maxMod = ~0; /* all modifiers included */ |
| if(Gpm_Open(&conn, 0) != -1) { |
| if(!MouseSpeed) |
| MouseSpeed = 8; |
| NumMouseButtons = 3; |
| return; |
| } |
| fprintf(stderr, "Cannot open gpmctl.\n"); |
| } |
| #endif |
| fprintf(stderr,"Cannot open %s.\n" |
| "Continuing without Mouse\n", MOUSEDEV); |
| } |
| |
| void CloseMouse(void) |
| { |
| #ifdef HAVE_GPM |
| if(GpmMouse) { |
| if(NumMouseButtons) |
| Gpm_Close(); |
| } else |
| #endif |
| if(MouseFD >= 0) |
| close(MouseFD); |
| } |