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