SDL_fbevents.c
上传用户:sun1608
上传日期:2007-02-02
资源大小:6116k
文件大小:29k
源码类别:

流媒体/Mpeg4/MP4

开发平台:

Visual C++

  1. /*
  2. SDL - Simple DirectMedia Layer
  3. Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  Sam Lantinga
  4. This library is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU Library General Public
  6. License as published by the Free Software Foundation; either
  7. version 2 of the License, or (at your option) any later version.
  8. This library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11. Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with this library; if not, write to the Free
  14. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15. Sam Lantinga
  16. slouken@libsdl.org
  17. */
  18. #ifdef SAVE_RCSID
  19. static char rcsid =
  20.  "@(#) $Id: SDL_fbevents.c,v 1.4 2002/04/22 21:38:04 wmay Exp $";
  21. #endif
  22. /* Handle the event stream, converting console events into SDL events */
  23. #include <sys/types.h>
  24. #include <sys/time.h>
  25. #include <sys/ioctl.h>
  26. #include <stdlib.h>
  27. #include <stdio.h>
  28. #include <unistd.h>
  29. #include <fcntl.h>
  30. #include <string.h>
  31. #include <errno.h>
  32. #include <limits.h>
  33. /* For parsing /proc */
  34. #include <dirent.h>
  35. #include <ctype.h>
  36. #include <linux/vt.h>
  37. #include <linux/kd.h>
  38. #include <linux/keyboard.h>
  39. #include "SDL.h"
  40. #include "SDL_mutex.h"
  41. #include "SDL_sysevents.h"
  42. #include "SDL_sysvideo.h"
  43. #include "SDL_events_c.h"
  44. #include "SDL_fbvideo.h"
  45. #include "SDL_fbevents_c.h"
  46. #include "SDL_fbkeys.h"
  47. #include "SDL_fbelo.h"
  48. #ifndef GPM_NODE_FIFO
  49. #define GPM_NODE_FIFO "/dev/gpmdata"
  50. #endif
  51. /* The translation tables from a console scancode to a SDL keysym */
  52. #define NUM_VGAKEYMAPS (1<<KG_CAPSSHIFT)
  53. static Uint16 vga_keymap[NUM_VGAKEYMAPS][NR_KEYS];
  54. static SDLKey keymap[128];
  55. static Uint16 keymap_temp[128]; /* only used at startup */
  56. static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym);
  57. /* Ugh, we have to duplicate the kernel's keysym mapping code...
  58.    Oh, it's not so bad. :-)
  59.    FIXME: Add keyboard LED handling code
  60.  */
  61. static void FB_vgainitkeymaps(int fd)
  62. {
  63. struct kbentry entry;
  64. int map, i;
  65. /* Don't do anything if we are passed a closed keyboard */
  66. if ( fd < 0 ) {
  67. return;
  68. }
  69. /* Load all the keysym mappings */
  70. for ( map=0; map<NUM_VGAKEYMAPS; ++map ) {
  71. memset(vga_keymap[map], 0, NR_KEYS*sizeof(Uint16));
  72. for ( i=0; i<NR_KEYS; ++i ) {
  73. entry.kb_table = map;
  74. entry.kb_index = i;
  75. if ( ioctl(fd, KDGKBENT, &entry) == 0 ) {
  76. /* fill keytemp. This replaces SDL_fbkeys.h */
  77. if ( (map == 0) && (i<128) ) {
  78. keymap_temp[i] = entry.kb_value;
  79. }
  80. /* The "Enter" key is a special case */
  81. if ( entry.kb_value == K_ENTER ) {
  82. entry.kb_value = K(KT_ASCII,13);
  83. }
  84. /* Handle numpad specially as well */
  85. if ( KTYP(entry.kb_value) == KT_PAD ) {
  86. switch ( entry.kb_value ) {
  87. case K_P0:
  88. case K_P1:
  89. case K_P2:
  90. case K_P3:
  91. case K_P4:
  92. case K_P5:
  93. case K_P6:
  94. case K_P7:
  95. case K_P8:
  96. case K_P9:
  97. vga_keymap[map][i]=entry.kb_value;
  98. vga_keymap[map][i]+= '0';
  99. break;
  100. case K_PPLUS:
  101. vga_keymap[map][i]=K(KT_ASCII,'+');
  102. break;
  103. case K_PMINUS:
  104. vga_keymap[map][i]=K(KT_ASCII,'-');
  105. break;
  106. case K_PSTAR:
  107. vga_keymap[map][i]=K(KT_ASCII,'*');
  108. break;
  109. case K_PSLASH:
  110. vga_keymap[map][i]=K(KT_ASCII,'/');
  111. break;
  112. case K_PENTER:
  113. vga_keymap[map][i]=K(KT_ASCII,'r');
  114. break;
  115. case K_PCOMMA:
  116. vga_keymap[map][i]=K(KT_ASCII,',');
  117. break;
  118. case K_PDOT:
  119. vga_keymap[map][i]=K(KT_ASCII,'.');
  120. break;
  121. default:
  122. break;
  123. }
  124. }
  125. /* Do the normal key translation */
  126. if ( (KTYP(entry.kb_value) == KT_LATIN) ||
  127.  (KTYP(entry.kb_value) == KT_ASCII) ||
  128.  (KTYP(entry.kb_value) == KT_LETTER) ) {
  129. vga_keymap[map][i] = entry.kb_value;
  130. }
  131. }
  132. }
  133. }
  134. }
  135. int FB_InGraphicsMode(_THIS)
  136. {
  137. return((keyboard_fd >= 0) && (saved_kbd_mode >= 0));
  138. }
  139. int FB_EnterGraphicsMode(_THIS)
  140. {
  141. struct termios keyboard_termios;
  142. /* Set medium-raw keyboard mode */
  143. if ( (keyboard_fd >= 0) && !FB_InGraphicsMode(this) ) {
  144. /* Switch to the correct virtual terminal */
  145. if ( current_vt > 0 ) {
  146. struct vt_stat vtstate;
  147. if ( ioctl(keyboard_fd, VT_GETSTATE, &vtstate) == 0 ) {
  148. saved_vt = vtstate.v_active;
  149. }
  150. if ( ioctl(keyboard_fd, VT_ACTIVATE, current_vt) == 0 ) {
  151. ioctl(keyboard_fd, VT_WAITACTIVE, current_vt);
  152. }
  153. }
  154. /* Set the terminal input mode */
  155. if ( tcgetattr(keyboard_fd, &saved_kbd_termios) < 0 ) {
  156. SDL_SetError("Unable to get terminal attributes");
  157. if ( keyboard_fd > 0 ) {
  158. close(keyboard_fd);
  159. }
  160. keyboard_fd = -1;
  161. return(-1);
  162. }
  163. if ( ioctl(keyboard_fd, KDGKBMODE, &saved_kbd_mode) < 0 ) {
  164. SDL_SetError("Unable to get current keyboard mode");
  165. if ( keyboard_fd > 0 ) {
  166. close(keyboard_fd);
  167. }
  168. keyboard_fd = -1;
  169. return(-1);
  170. }
  171. keyboard_termios = saved_kbd_termios;
  172. keyboard_termios.c_lflag &= ~(ICANON | ECHO | ISIG);
  173. keyboard_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
  174. keyboard_termios.c_cc[VMIN] = 0;
  175. keyboard_termios.c_cc[VTIME] = 0;
  176. if (tcsetattr(keyboard_fd, TCSAFLUSH, &keyboard_termios) < 0) {
  177. FB_CloseKeyboard(this);
  178. SDL_SetError("Unable to set terminal attributes");
  179. return(-1);
  180. }
  181. /* This will fail if we aren't root or this isn't our tty */
  182. if ( ioctl(keyboard_fd, KDSKBMODE, K_MEDIUMRAW) < 0 ) {
  183. FB_CloseKeyboard(this);
  184. SDL_SetError("Unable to set keyboard in raw mode");
  185. return(-1);
  186. }
  187. if ( ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS) < 0 ) {
  188. FB_CloseKeyboard(this);
  189. SDL_SetError("Unable to set keyboard in graphics mode");
  190. return(-1);
  191. }
  192. }
  193. return(keyboard_fd);
  194. }
  195. void FB_LeaveGraphicsMode(_THIS)
  196. {
  197. if ( FB_InGraphicsMode(this) ) {
  198. ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
  199. ioctl(keyboard_fd, KDSKBMODE, saved_kbd_mode);
  200. tcsetattr(keyboard_fd, TCSAFLUSH, &saved_kbd_termios);
  201. saved_kbd_mode = -1;
  202. /* Head back over to the original virtual terminal */
  203. if ( saved_vt > 0 ) {
  204. ioctl(keyboard_fd, VT_ACTIVATE, saved_vt);
  205. }
  206. }
  207. }
  208. void FB_CloseKeyboard(_THIS)
  209. {
  210. if ( keyboard_fd >= 0 ) {
  211. FB_LeaveGraphicsMode(this);
  212. if ( keyboard_fd > 0 ) {
  213. close(keyboard_fd);
  214. }
  215. }
  216. keyboard_fd = -1;
  217. }
  218. int FB_OpenKeyboard(_THIS)
  219. {
  220. /* Open only if not already opened */
  221.   if ( keyboard_fd < 0 ) {
  222. static const char * const tty0[] = { "/dev/tty0", "/dev/vc/0", NULL };
  223. static const char * const vcs[] = { "/dev/vc/%d", "/dev/tty%d", NULL };
  224. int i, tty0_fd;
  225. /* Try to query for a free virtual terminal */
  226. tty0_fd = -1;
  227. for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) {
  228. tty0_fd = open(tty0[i], O_WRONLY, 0);
  229. }
  230. if ( tty0_fd < 0 ) {
  231. tty0_fd = dup(0); /* Maybe stdin is a VT? */
  232. }
  233. ioctl(tty0_fd, VT_OPENQRY, &current_vt);
  234. close(tty0_fd);
  235. if ( (geteuid() == 0) && (current_vt > 0) ) {
  236. for ( i=0; vcs[i] && (keyboard_fd < 0); ++i ) {
  237. char vtpath[12];
  238. sprintf(vtpath, vcs[i], current_vt);
  239. keyboard_fd = open(vtpath, O_RDWR, 0);
  240. #ifdef DEBUG_KEYBOARD
  241. fprintf(stderr, "vtpath = %s, fd = %dn",
  242. vtpath, keyboard_fd);
  243. #endif /* DEBUG_KEYBOARD */
  244. /* This needs to be our controlling tty
  245.    so that the kernel ioctl() calls work
  246. */
  247. if ( keyboard_fd >= 0 ) {
  248. tty0_fd = open("/dev/tty", O_RDWR, 0);
  249. if ( tty0_fd >= 0 ) {
  250. ioctl(tty0_fd, TIOCNOTTY, 0);
  251. close(tty0_fd);
  252. }
  253. }
  254. }
  255. }
  256.   if ( keyboard_fd < 0 ) {
  257. /* Last resort, maybe our tty is a usable VT */
  258. current_vt = 0;
  259. keyboard_fd = open("/dev/tty", O_RDWR);
  260.   }
  261. #ifdef DEBUG_KEYBOARD
  262. fprintf(stderr, "Current VT: %dn", current_vt);
  263. #endif
  264.   saved_kbd_mode = -1;
  265. /* Make sure that our input is a console terminal */
  266. { int dummy;
  267.   if ( ioctl(keyboard_fd, KDGKBMODE, &dummy) < 0 ) {
  268. close(keyboard_fd);
  269. keyboard_fd = -1;
  270. SDL_SetError("Unable to open a console terminal");
  271.   }
  272. }
  273. /* Set up keymap */
  274. FB_vgainitkeymaps(keyboard_fd);
  275.   }
  276.   return(keyboard_fd);
  277. }
  278. static enum {
  279. MOUSE_NONE = -1,
  280. MOUSE_MSC, /* Note: GPM uses the MSC protocol */
  281. MOUSE_PS2,
  282. MOUSE_IMPS2,
  283. MOUSE_MS,
  284. MOUSE_BM,
  285. MOUSE_ELO,
  286. NUM_MOUSE_DRVS
  287. } mouse_drv = MOUSE_NONE;
  288. void FB_CloseMouse(_THIS)
  289. {
  290. if ( mouse_fd > 0 ) {
  291. close(mouse_fd);
  292. }
  293. mouse_fd = -1;
  294. }
  295. /* Returns processes listed in /proc with the desired name */
  296. static int find_pid(DIR *proc, const char *wanted_name)
  297. {
  298. struct dirent *entry;
  299. int pid;
  300. /* First scan proc for the gpm process */
  301. pid = 0;
  302. while ( (pid == 0) && ((entry=readdir(proc)) != NULL) ) {
  303. if ( isdigit(entry->d_name[0]) ) {
  304. FILE *status;
  305. char path[PATH_MAX];
  306. char name[PATH_MAX];
  307. sprintf(path, "/proc/%s/status", entry->d_name);
  308. status=fopen(path, "r");
  309. if ( status ) {
  310. name[0] = '';
  311. fscanf(status, "Name: %s", name);
  312. if ( strcmp(name, wanted_name) == 0 ) {
  313. pid = atoi(entry->d_name);
  314. }
  315. fclose(status);
  316. }
  317. }
  318. }
  319. return pid;
  320. }
  321. /* Returns true if /dev/gpmdata is being written to by gpm */
  322. static int gpm_available(void)
  323. {
  324. int available;
  325. DIR *proc;
  326. int pid;
  327. int cmdline, len, arglen;
  328. char path[PATH_MAX];
  329. char args[PATH_MAX], *arg;
  330. /* Don't bother looking if the fifo isn't there */
  331. if ( access(GPM_NODE_FIFO, F_OK) < 0 ) {
  332. return(0);
  333. }
  334. available = 0;
  335. proc = opendir("/proc");
  336. if ( proc ) {
  337. while ( (pid=find_pid(proc, "gpm")) > 0 ) {
  338. sprintf(path, "/proc/%d/cmdline", pid);
  339. cmdline = open(path, O_RDONLY, 0);
  340. if ( cmdline >= 0 ) {
  341. len = read(cmdline, args, sizeof(args));
  342. arg = args;
  343. while ( len > 0 ) {
  344. if ( strcmp(arg, "-R") == 0 ) {
  345. available = 1;
  346. }
  347. arglen = strlen(arg)+1;
  348. len -= arglen;
  349. arg += arglen;
  350. }
  351. close(cmdline);
  352. }
  353. }
  354. closedir(proc);
  355. }
  356. return available;
  357. }
  358. /* rcg06112001 Set up IMPS/2 mode, if possible. This gives
  359.  *  us access to the mousewheel, etc. Returns zero if
  360.  *  writes to device failed, but you still need to query the
  361.  *  device to see which mode it's actually in.
  362.  */
  363. static int set_imps2_mode(int fd)
  364. {
  365. /* If you wanted to control the mouse mode (and we do :)  ) ...
  366. Set IMPS/2 protocol:
  367. {0xf3,200,0xf3,100,0xf3,80}
  368. Reset mouse device:
  369. {0xFF}
  370. */
  371. Uint8 set_imps2[] = {0xf3, 200, 0xf3, 100, 0xf3, 80};
  372. Uint8 reset = 0xff;
  373. fd_set fdset;
  374. struct timeval tv;
  375. int retval = 0;
  376. if ( write(fd, &set_imps2, sizeof(set_imps2)) == sizeof(set_imps2) ) {
  377. if (write(fd, &reset, sizeof (reset)) == sizeof (reset) ) {
  378. retval = 1;
  379. }
  380. }
  381. /* Get rid of any chatter from the above */
  382. FD_ZERO(&fdset);
  383. FD_SET(fd, &fdset);
  384. tv.tv_sec = 0;
  385. tv.tv_usec = 0;
  386. while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {
  387. char temp[32];
  388. read(fd, temp, sizeof(temp));
  389. }
  390. return retval;
  391. }
  392. /* Returns true if the mouse uses the IMPS/2 protocol */
  393. static int detect_imps2(int fd)
  394. {
  395. int imps2;
  396. imps2 = 0;
  397. if ( getenv("SDL_MOUSEDEV_IMPS2") ) {
  398. imps2 = 1;
  399. }
  400. if ( ! imps2 ) {
  401. Uint8 query_ps2 = 0xF2;
  402. fd_set fdset;
  403. struct timeval tv;
  404. /* Get rid of any mouse motion noise */
  405. FD_ZERO(&fdset);
  406. FD_SET(fd, &fdset);
  407. tv.tv_sec = 0;
  408. tv.tv_usec = 0;
  409. while ( select(fd+1, &fdset, 0, 0, &tv) > 0 ) {
  410. char temp[32];
  411. read(fd, temp, sizeof(temp));
  412. }
  413.     /* Query for the type of mouse protocol */
  414.     if ( write(fd, &query_ps2, sizeof (query_ps2)) == sizeof (query_ps2)) {
  415.     Uint8 ch = 0;
  416. /* Get the mouse protocol response */
  417. do {
  418. FD_ZERO(&fdset);
  419. FD_SET(fd, &fdset);
  420. tv.tv_sec = 1;
  421. tv.tv_usec = 0;
  422. if ( select(fd+1, &fdset, 0, 0, &tv) < 1 ) {
  423. break;
  424. }
  425. } while ( (read(fd, &ch, sizeof (ch)) == sizeof (ch)) &&
  426.           ((ch == 0xFA) || (ch == 0xAA)) );
  427. /* Experimental values (Logitech wheelmouse) */
  428. #ifdef DEBUG_MOUSE
  429. fprintf(stderr, "Last mouse mode: 0x%xn", ch);
  430. #endif
  431. if ( (ch == 3) || (ch == 4) ) {
  432. imps2 = 1;
  433. }
  434. }
  435. }
  436. return imps2;
  437. }
  438. int FB_OpenMouse(_THIS)
  439. {
  440. int i;
  441. const char *mousedev;
  442. const char *mousedrv;
  443. mousedrv = getenv("SDL_MOUSEDRV");
  444. mousedev = getenv("SDL_MOUSEDEV");
  445. mouse_fd = -1;
  446. /* ELO TOUCHSCREEN SUPPORT */
  447. if( (mousedrv != NULL) && (strcmp(mousedrv, "ELO") == 0) ) {
  448. mouse_fd = open(mousedev, O_RDWR);
  449. if ( mouse_fd >= 0 ) {
  450. if(eloInitController(mouse_fd)) {
  451. #ifdef DEBUG_MOUSE
  452. fprintf(stderr, "Using ELO touchscreenn");
  453. #endif
  454.     mouse_drv = MOUSE_ELO;
  455. }
  456. }
  457. else if ( mouse_fd < 0 ) {
  458. mouse_drv = MOUSE_NONE;
  459. }
  460. return(mouse_fd);
  461. }
  462. /* STD MICE */
  463. if ( mousedev == NULL ) {
  464. /* FIXME someday... allow multiple mice in this driver */
  465. static const char * const ps2mice[] = {
  466.     "/dev/input/mice", "/dev/usbmouse", "/dev/psaux", NULL
  467. };
  468. /* First try to use GPM in repeater mode */
  469. if ( mouse_fd < 0 ) {
  470. if ( gpm_available() ) {
  471. mouse_fd = open(GPM_NODE_FIFO, O_RDONLY, 0);
  472. if ( mouse_fd >= 0 ) {
  473. #ifdef DEBUG_MOUSE
  474. fprintf(stderr, "Using GPM mousen");
  475. #endif
  476. mouse_drv = MOUSE_MSC;
  477. }
  478. }
  479. }
  480. /* Now try to use a modern PS/2 mouse */
  481. for ( i=0; (mouse_fd < 0) && ps2mice[i]; ++i ) {
  482. mouse_fd = open(ps2mice[i], O_RDWR, 0);
  483. if (mouse_fd < 0) {
  484. mouse_fd = open(ps2mice[i], O_RDONLY, 0);
  485. }
  486. if (mouse_fd >= 0) {
  487. /* rcg06112001 Attempt to set IMPS/2 mode */
  488. if ( i == 0 ) {
  489. set_imps2_mode(mouse_fd);
  490. }
  491. if (detect_imps2(mouse_fd)) {
  492. #ifdef DEBUG_MOUSE
  493. fprintf(stderr, "Using IMPS2 mousen");
  494. #endif
  495. mouse_drv = MOUSE_IMPS2;
  496. } else {
  497. #ifdef DEBUG_MOUSE
  498. fprintf(stderr, "Using PS2 mousen");
  499. #endif
  500. mouse_drv = MOUSE_PS2;
  501. }
  502. }
  503. }
  504. /* Next try to use a PPC ADB port mouse */
  505. if ( mouse_fd < 0 ) {
  506. mouse_fd = open("/dev/adbmouse", O_RDONLY, 0);
  507. if ( mouse_fd >= 0 ) {
  508. #ifdef DEBUG_MOUSE
  509. fprintf(stderr, "Using ADB mousen");
  510. #endif
  511. mouse_drv = MOUSE_BM;
  512. }
  513. }
  514. }
  515. /* Default to a serial Microsoft mouse */
  516. if ( mouse_fd < 0 ) {
  517. if ( mousedev == NULL ) {
  518. mousedev = "/dev/mouse";
  519. }
  520. mouse_fd = open(mousedev, O_RDONLY, 0);
  521. if ( mouse_fd >= 0 ) {
  522. struct termios mouse_termios;
  523. /* Set the sampling speed to 1200 baud */
  524. tcgetattr(mouse_fd, &mouse_termios);
  525. mouse_termios.c_iflag = IGNBRK | IGNPAR;
  526. mouse_termios.c_oflag = 0;
  527. mouse_termios.c_lflag = 0;
  528. mouse_termios.c_line = 0;
  529. mouse_termios.c_cc[VTIME] = 0;
  530. mouse_termios.c_cc[VMIN] = 1;
  531. mouse_termios.c_cflag = CREAD | CLOCAL | HUPCL;
  532. mouse_termios.c_cflag |= CS8;
  533. mouse_termios.c_cflag |= B1200;
  534. tcsetattr(mouse_fd, TCSAFLUSH, &mouse_termios);
  535. #ifdef DEBUG_MOUSE
  536. fprintf(stderr, "Using Microsoft mouse on %sn", mousedev);
  537. #endif
  538. mouse_drv = MOUSE_MS;
  539. }
  540. }
  541. if ( mouse_fd < 0 ) {
  542. mouse_drv = MOUSE_NONE;
  543. }
  544. return(mouse_fd);
  545. }
  546. static int posted = 0;
  547. void FB_vgamousecallback(int button, int relative, int dx, int dy)
  548. {
  549. int button_1, button_3;
  550. int button_state;
  551. int state_changed;
  552. int i;
  553. Uint8 state;
  554. if ( dx || dy ) {
  555. posted += SDL_PrivateMouseMotion(0, relative, dx, dy);
  556. }
  557. /* Swap button 1 and 3 */
  558. button_1 = (button & 0x04) >> 2;
  559. button_3 = (button & 0x01) << 2;
  560. button &= ~0x05;
  561. button |= (button_1|button_3);
  562. /* See what changed */
  563. button_state = SDL_GetMouseState(NULL, NULL);
  564. state_changed = button_state ^ button;
  565. for ( i=0; i<8; ++i ) {
  566. if ( state_changed & (1<<i) ) {
  567. if ( button & (1<<i) ) {
  568. state = SDL_PRESSED;
  569. } else {
  570. state = SDL_RELEASED;
  571. }
  572. posted += SDL_PrivateMouseButton(state, i+1, 0, 0);
  573. }
  574. }
  575. }
  576. /* For now, use MSC, PS/2, and MS protocols
  577.    Driver adapted from the SVGAlib mouse driver code (taken from gpm, etc.)
  578.  */
  579. static void handle_mouse(_THIS)
  580. {
  581. static int start = 0;
  582. static unsigned char mousebuf[BUFSIZ];
  583. static int relative = 1;
  584. int i, nread;
  585. int button = 0;
  586. int dx = 0, dy = 0;
  587. int packetsize = 0;
  588. int realx, realy;
  589. /* Figure out the mouse packet size */
  590. switch (mouse_drv) {
  591. case MOUSE_NONE:
  592. /* Ack! */
  593. read(mouse_fd, mousebuf, BUFSIZ);
  594. return;
  595. case MOUSE_MSC:
  596. packetsize = 5;
  597. break;
  598. case MOUSE_IMPS2:
  599. packetsize = 4;
  600. break;
  601. case MOUSE_PS2:
  602. case MOUSE_MS:
  603. case MOUSE_BM:
  604. packetsize = 3;
  605. break;
  606. case MOUSE_ELO:
  607. packetsize = ELO_PACKET_SIZE;
  608. relative = 0;
  609. break;
  610. case NUM_MOUSE_DRVS:
  611. /* Uh oh.. */
  612. packetsize = 0;
  613. break;
  614. }
  615. /* Special handling for the quite sensitive ELO controller */
  616. if (mouse_drv == MOUSE_ELO) {
  617.     /* try to read the next packet */
  618.     if(eloReadPosition(this, mouse_fd, &dx, &dy, &button, &realx, &realy)) {
  619. button = (button & 0x01) << 2;
  620.      FB_vgamousecallback(button, relative, dx, dy);
  621.     }
  622.     
  623.     return;
  624. }
  625. /* Read as many packets as possible */
  626. nread = read(mouse_fd, &mousebuf[start], BUFSIZ-start);
  627. if ( nread < 0 ) {
  628. return;
  629. }
  630. nread += start;
  631. #ifdef DEBUG_MOUSE
  632. fprintf(stderr, "Read %d bytes from mouse, start = %dn", nread, start);
  633. #endif
  634. for ( i=0; i<(nread-(packetsize-1)); i += packetsize ) {
  635. switch (mouse_drv) {
  636. case MOUSE_NONE:
  637. break;
  638. case MOUSE_MSC:
  639. /* MSC protocol has 0x80 in high byte */
  640. if ( (mousebuf[i] & 0xF8) != 0x80 ) {
  641. /* Go to next byte */
  642. i -= (packetsize-1);
  643. continue;
  644. }
  645. /* Get current mouse state */
  646. button = (~mousebuf[i]) & 0x07;
  647. dx =   (signed char)(mousebuf[i+1]) +
  648.        (signed char)(mousebuf[i+3]);
  649. dy = -((signed char)(mousebuf[i+2]) +
  650.        (signed char)(mousebuf[i+4]));
  651. break;
  652. case MOUSE_PS2:
  653. /* PS/2 protocol has nothing in high byte */
  654. if ( (mousebuf[i] & 0xC0) != 0 ) {
  655. /* Go to next byte */
  656. i -= (packetsize-1);
  657. continue;
  658. }
  659. /* Get current mouse state */
  660. button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/
  661.     (mousebuf[i] & 0x02) >> 1 | /*Right*/
  662.     (mousebuf[i] & 0x01) << 2;  /*Left*/
  663.    dx = (mousebuf[i] & 0x10) ?
  664.          mousebuf[i+1] - 256 : mousebuf[i+1];
  665.    dy = (mousebuf[i] & 0x20) ?
  666.          -(mousebuf[i+2] - 256) : -mousebuf[i+2];
  667. break;
  668. case MOUSE_IMPS2:
  669. /* Get current mouse state */
  670. button = (mousebuf[i] & 0x04) >> 1 | /*Middle*/
  671.     (mousebuf[i] & 0x02) >> 1 | /*Right*/
  672.     (mousebuf[i] & 0x01) << 2 | /*Left*/
  673.     (mousebuf[i] & 0x40) >> 3 | /* 4 */
  674.     (mousebuf[i] & 0x80) >> 3;  /* 5 */
  675.    dx = (mousebuf[i] & 0x10) ?
  676.          mousebuf[i+1] - 256 : mousebuf[i+1];
  677.    dy = (mousebuf[i] & 0x20) ?
  678.          -(mousebuf[i+2] - 256) : -mousebuf[i+2];
  679. switch (mousebuf[i+3]&0x0F) {
  680.     case 0x0E: /* DX = +1 */
  681.     case 0x02: /* DX = -1 */
  682. break;
  683.     case 0x0F: /* DY = +1 (map button 4) */
  684.                                        FB_vgamousecallback(button | (1<<3),
  685.                                                            1, 0, 0);
  686. break;
  687.     case 0x01: /* DY = -1 (map button 5) */
  688.                                        FB_vgamousecallback(button | (1<<4),
  689.                                                            1, 0, 0);
  690. break;
  691. }
  692. break;
  693. case MOUSE_MS:
  694. /* Microsoft protocol has 0x40 in high byte */
  695. if ( (mousebuf[i] & 0x40) != 0x40 ) {
  696. /* Go to next byte */
  697. i -= (packetsize-1);
  698. continue;
  699. }
  700. /* Get current mouse state */
  701. button = ((mousebuf[i] & 0x20) >> 3) |
  702.          ((mousebuf[i] & 0x10) >> 4);
  703. dx = (signed char)(((mousebuf[i] & 0x03) << 6) |
  704.                    (mousebuf[i + 1] & 0x3F));
  705. dy = (signed char)(((mousebuf[i] & 0x0C) << 4) |
  706.                     (mousebuf[i + 2] & 0x3F));
  707. break;
  708. case MOUSE_BM:
  709. /* BusMouse protocol has 0xF8 in high byte */
  710. if ( (mousebuf[i] & 0xF8) != 0x80 ) {
  711. /* Go to next byte */
  712. i -= (packetsize-1);
  713. continue;
  714. }
  715. /* Get current mouse state */
  716. button = (~mousebuf[i]) & 0x07;
  717. dx =  (signed char)mousebuf[i+1];
  718. dy = -(signed char)mousebuf[i+2];
  719. break;
  720. /*
  721. case MOUSE_ELO:
  722. if ( mousebuf[i] != ELO_START_BYTE ) {
  723. i -= (packetsize-1);
  724. continue;
  725. }
  726. if(!eloParsePacket(&(mousebuf[i]), &dx, &dy, &button)) {
  727. i -= (packetsize-1);
  728. continue;
  729. }
  730. button = (button & 0x01) << 2;
  731. eloConvertXY(this, &dx, &dy);
  732. break;
  733. */
  734. case MOUSE_ELO:
  735. case NUM_MOUSE_DRVS:
  736. /* Uh oh.. */
  737. dx = 0;
  738. dy = 0;
  739. break;
  740. }
  741. FB_vgamousecallback(button, relative, dx, dy);
  742. }
  743. if ( i < nread ) {
  744. memcpy(mousebuf, &mousebuf[i], (nread-i));
  745. start = (nread-i);
  746. } else {
  747. start = 0;
  748. }
  749. return;
  750. }
  751. /* Handle switching to another VC, returns when our VC is back.
  752.    This isn't necessarily the best solution.  For SDL 1.3 we need
  753.    a way of notifying the application when we lose access to the
  754.    video hardware and when we regain it.
  755.  */
  756. static void switch_vt(_THIS, unsigned short which)
  757. {
  758. struct vt_stat vtstate;
  759. unsigned short current;
  760. SDL_Surface *screen;
  761. __u16 saved_pal[3*256];
  762. Uint32 screen_arealen;
  763. Uint8 *screen_contents;
  764. /* Figure out whether or not we're switching to a new console */
  765. if ( (ioctl(keyboard_fd, VT_GETSTATE, &vtstate) < 0) ||
  766.      (which == vtstate.v_active) ) {
  767. return;
  768. }
  769. current = vtstate.v_active;
  770. /* Save the contents of the screen, and go to text mode */
  771. SDL_mutexP(hw_lock);
  772. wait_idle(this);
  773. screen = SDL_VideoSurface;
  774. screen_arealen = (screen->h*screen->pitch);
  775. screen_contents = (Uint8 *)malloc(screen_arealen);
  776. if ( screen_contents ) {
  777. memcpy(screen_contents, screen->pixels, screen_arealen);
  778. }
  779. FB_SavePaletteTo(this, 256, saved_pal);
  780. ioctl(keyboard_fd, KDSETMODE, KD_TEXT);
  781. /* New console, switch to it */
  782. if ( ioctl(keyboard_fd, VT_ACTIVATE, which) == 0 ) {
  783. /* Wait for our console to be activated again */
  784. ioctl(keyboard_fd, VT_WAITACTIVE, which);
  785. while ( ioctl(keyboard_fd, VT_WAITACTIVE, current) < 0 ) {
  786. if ( (errno != EINTR) && (errno != EAGAIN) ) {
  787. /* Unknown VT error - cancel this */
  788. break;
  789. }
  790. SDL_Delay(500);
  791. }
  792. }
  793. /* Restore graphics mode and the contents of the screen */
  794. ioctl(keyboard_fd, KDSETMODE, KD_GRAPHICS);
  795. FB_RestorePaletteFrom(this, 256, saved_pal);
  796. if ( screen_contents ) {
  797. memcpy(screen->pixels, screen_contents, screen_arealen);
  798. free(screen_contents);
  799. }
  800. SDL_mutexV(hw_lock);
  801. }
  802. static void handle_keyboard(_THIS)
  803. {
  804. unsigned char keybuf[BUFSIZ];
  805. int i, nread;
  806. int pressed;
  807. int scancode;
  808. SDL_keysym keysym;
  809. nread = read(keyboard_fd, keybuf, BUFSIZ);
  810. for ( i=0; i<nread; ++i ) {
  811. scancode = keybuf[i] & 0x7F;
  812. if ( keybuf[i] & 0x80 ) {
  813. pressed = SDL_RELEASED;
  814. } else {
  815. pressed = SDL_PRESSED;
  816. }
  817. TranslateKey(scancode, &keysym);
  818. /* Handle Alt-FN for vt switch */
  819. switch (keysym.sym) {
  820.     case SDLK_F1:
  821.     case SDLK_F2:
  822.     case SDLK_F3:
  823.     case SDLK_F4:
  824.     case SDLK_F5:
  825.     case SDLK_F6:
  826.     case SDLK_F7:
  827.     case SDLK_F8:
  828.     case SDLK_F9:
  829.     case SDLK_F10:
  830.     case SDLK_F11:
  831.     case SDLK_F12:
  832. if ( SDL_GetModState() & KMOD_ALT ) {
  833. if ( pressed ) {
  834. switch_vt(this, (keysym.sym-SDLK_F1)+1);
  835. }
  836. break;
  837. }
  838. /* Fall through to normal processing */
  839.     default:
  840. posted += SDL_PrivateKeyboard(pressed, &keysym);
  841. break;
  842. }
  843. }
  844. }
  845. void FB_PumpEvents(_THIS)
  846. {
  847. fd_set fdset;
  848. int max_fd;
  849. static struct timeval zero;
  850. do {
  851. posted = 0;
  852. FD_ZERO(&fdset);
  853. max_fd = 0;
  854. if ( keyboard_fd >= 0 ) {
  855. FD_SET(keyboard_fd, &fdset);
  856. if ( max_fd < keyboard_fd ) {
  857. max_fd = keyboard_fd;
  858. }
  859. }
  860. if ( mouse_fd >= 0 ) {
  861. FD_SET(mouse_fd, &fdset);
  862. if ( max_fd < mouse_fd ) {
  863. max_fd = mouse_fd;
  864. }
  865. }
  866. if ( select(max_fd+1, &fdset, NULL, NULL, &zero) > 0 ) {
  867. if ( keyboard_fd >= 0 ) {
  868. if ( FD_ISSET(keyboard_fd, &fdset) ) {
  869. handle_keyboard(this);
  870. }
  871. }
  872. if ( mouse_fd >= 0 ) {
  873. if ( FD_ISSET(mouse_fd, &fdset) ) {
  874. handle_mouse(this);
  875. }
  876. }
  877. }
  878. } while ( posted );
  879. }
  880. void FB_InitOSKeymap(_THIS)
  881. {
  882. int i;
  883. /* Initialize the Linux key translation table */
  884. /* First get the ascii keys and others not well handled */
  885. for (i=0; i<SDL_TABLESIZE(keymap); ++i) {
  886.   switch(i) {
  887.   /* These aren't handled by the x86 kernel keymapping (?) */
  888.   case SCANCODE_PRINTSCREEN:
  889.     keymap[i] = SDLK_PRINT;
  890.     break;
  891.   case SCANCODE_BREAK:
  892.     keymap[i] = SDLK_BREAK;
  893.     break;
  894.   case SCANCODE_BREAK_ALTERNATIVE:
  895.     keymap[i] = SDLK_PAUSE;
  896.     break;
  897.   case SCANCODE_LEFTSHIFT:
  898.     keymap[i] = SDLK_LSHIFT;
  899.     break;
  900.   case SCANCODE_RIGHTSHIFT:
  901.     keymap[i] = SDLK_RSHIFT;
  902.     break;
  903.   case SCANCODE_LEFTCONTROL:
  904.     keymap[i] = SDLK_LCTRL;
  905.     break;
  906.   case SCANCODE_RIGHTCONTROL:
  907.     keymap[i] = SDLK_RCTRL;
  908.     break;
  909.   case SCANCODE_RIGHTWIN:
  910.     keymap[i] = SDLK_RSUPER;
  911.     break;
  912.   case SCANCODE_LEFTWIN:
  913.     keymap[i] = SDLK_LSUPER;
  914.     break;
  915.   case 127:
  916.     keymap[i] = SDLK_MENU;
  917.     break;
  918.   /* this should take care of all standard ascii keys */
  919.   default:
  920.     keymap[i] = KVAL(vga_keymap[0][i]);
  921.     break;
  922.           }
  923. }
  924. for (i=0; i<SDL_TABLESIZE(keymap); ++i) {
  925.   switch(keymap_temp[i]) {
  926.     case K_F1:  keymap[i] = SDLK_F1;  break;
  927.     case K_F2:  keymap[i] = SDLK_F2;  break;
  928.     case K_F3:  keymap[i] = SDLK_F3;  break;
  929.     case K_F4:  keymap[i] = SDLK_F4;  break;
  930.     case K_F5:  keymap[i] = SDLK_F5;  break;
  931.     case K_F6:  keymap[i] = SDLK_F6;  break;
  932.     case K_F7:  keymap[i] = SDLK_F7;  break;
  933.     case K_F8:  keymap[i] = SDLK_F8;  break;
  934.     case K_F9:  keymap[i] = SDLK_F9;  break;
  935.     case K_F10: keymap[i] = SDLK_F10; break;
  936.     case K_F11: keymap[i] = SDLK_F11; break;
  937.     case K_F12: keymap[i] = SDLK_F12; break;
  938.     case K_DOWN:  keymap[i] = SDLK_DOWN;  break;
  939.     case K_LEFT:  keymap[i] = SDLK_LEFT;  break;
  940.     case K_RIGHT: keymap[i] = SDLK_RIGHT; break;
  941.     case K_UP:    keymap[i] = SDLK_UP;    break;
  942.     case K_P0:     keymap[i] = SDLK_KP0; break;
  943.     case K_P1:     keymap[i] = SDLK_KP1; break;
  944.     case K_P2:     keymap[i] = SDLK_KP2; break;
  945.     case K_P3:     keymap[i] = SDLK_KP3; break;
  946.     case K_P4:     keymap[i] = SDLK_KP4; break;
  947.     case K_P5:     keymap[i] = SDLK_KP5; break;
  948.     case K_P6:     keymap[i] = SDLK_KP6; break;
  949.     case K_P7:     keymap[i] = SDLK_KP7; break;
  950.     case K_P8:     keymap[i] = SDLK_KP8; break;
  951.     case K_P9:     keymap[i] = SDLK_KP9; break;
  952.     case K_PPLUS:  keymap[i] = SDLK_KP_PLUS; break;
  953.     case K_PMINUS: keymap[i] = SDLK_KP_MINUS; break;
  954.     case K_PSTAR:  keymap[i] = SDLK_KP_MULTIPLY; break;
  955.     case K_PSLASH: keymap[i] = SDLK_KP_DIVIDE; break;
  956.     case K_PENTER: keymap[i] = SDLK_KP_ENTER; break;
  957.     case K_PDOT:   keymap[i] = SDLK_KP_PERIOD; break;
  958.     case K_SHIFT:  if ( keymap[i] != SDLK_RSHIFT )
  959.                      keymap[i] = SDLK_LSHIFT;
  960.                    break;
  961.     case K_SHIFTL: keymap[i] = SDLK_LSHIFT; break;
  962.     case K_SHIFTR: keymap[i] = SDLK_RSHIFT; break;
  963.     case K_CTRL:  if ( keymap[i] != SDLK_RCTRL )
  964.                      keymap[i] = SDLK_LCTRL;
  965.                    break;
  966.     case K_CTRLL:  keymap[i] = SDLK_LCTRL;  break;
  967.     case K_CTRLR:  keymap[i] = SDLK_RCTRL;  break;
  968.     case K_ALT:    keymap[i] = SDLK_LALT;   break;
  969.     case K_ALTGR:  keymap[i] = SDLK_RALT;   break;
  970.     case K_INSERT: keymap[i] = SDLK_INSERT;   break;
  971.     case K_REMOVE: keymap[i] = SDLK_DELETE;   break;
  972.     case K_PGUP:   keymap[i] = SDLK_PAGEUP;   break;
  973.     case K_PGDN:   keymap[i] = SDLK_PAGEDOWN; break;
  974.     case K_FIND:   keymap[i] = SDLK_HOME;     break;
  975.     case K_SELECT: keymap[i] = SDLK_END;      break;
  976.     case K_NUM:  keymap[i] = SDLK_NUMLOCK;   break;
  977.     case K_CAPS: keymap[i] = SDLK_CAPSLOCK;  break;
  978.     case K_F13:   keymap[i] = SDLK_PRINT;     break;
  979.     case K_HOLD:  keymap[i] = SDLK_SCROLLOCK; break;
  980.     case K_PAUSE: keymap[i] = SDLK_PAUSE;     break;
  981.     case 127: keymap[i] = SDLK_BACKSPACE; break;
  982.      
  983.     default: break;
  984.   }
  985. }
  986. }
  987. static SDL_keysym *TranslateKey(int scancode, SDL_keysym *keysym)
  988. {
  989. /* Set the keysym information */
  990. keysym->scancode = scancode;
  991. keysym->sym = keymap[scancode];
  992. keysym->mod = KMOD_NONE;
  993. /* If UNICODE is on, get the UNICODE value for the key */
  994. keysym->unicode = 0;
  995. if ( SDL_TranslateUNICODE ) {
  996. int map;
  997. SDLMod modstate;
  998. modstate = SDL_GetModState();
  999. map = 0;
  1000. if ( modstate & KMOD_SHIFT ) {
  1001. map |= (1<<KG_SHIFT);
  1002. }
  1003. if ( modstate & KMOD_CTRL ) {
  1004. map |= (1<<KG_CTRL);
  1005. }
  1006. if ( modstate & KMOD_ALT ) {
  1007. map |= (1<<KG_ALT);
  1008. }
  1009. if ( modstate & KMOD_MODE ) {
  1010. map |= (1<<KG_ALTGR);
  1011. }
  1012. if ( KTYP(vga_keymap[map][scancode]) == KT_LETTER ) {
  1013. if ( modstate & KMOD_CAPS ) {
  1014. map ^= (1<<KG_SHIFT);
  1015. }
  1016. }
  1017. if ( KTYP(vga_keymap[map][scancode]) == KT_PAD ) {
  1018. if ( modstate & KMOD_NUM ) {
  1019. keysym->unicode=KVAL(vga_keymap[map][scancode]);
  1020. }
  1021. } else {
  1022. keysym->unicode = KVAL(vga_keymap[map][scancode]);
  1023. }
  1024. }
  1025. return(keysym);
  1026. }