]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/bluetooth/bthidd/kbd.c
This commit was generated by cvs2svn to compensate for changes in r153200,
[FreeBSD/FreeBSD.git] / usr.sbin / bluetooth / bthidd / kbd.c
1 /*
2  * kbd.c
3  *
4  * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $Id: kbd.c,v 1.2 2004/11/17 21:59:42 max Exp $
29  * $FreeBSD$
30  */
31
32 #include <sys/consio.h>
33 #include <sys/ioctl.h>
34 #include <sys/kbio.h>
35 #include <sys/queue.h>
36 #include <sys/wait.h>
37 #include <assert.h>
38 #include <bluetooth.h>
39 #include <errno.h>
40 #include <fcntl.h>
41 #include <limits.h>
42 #include <stdarg.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <syslog.h>
47 #include <unistd.h>
48 #include "bthidd.h"
49 #include "kbd.h"
50
51 static void     kbd_write(bitstr_t *m, int fb, int make, int fd);
52 static int      kbd_xlate(int code, int make, int *b, int const *eob);
53
54 /*
55  * HID code to PS/2 set 1 code translation table.
56  *
57  * http://www.microsoft.com/whdc/device/input/Scancode.mspx
58  *
59  * The table only contains "make" (key pressed) codes.
60  * The "break" (key released) code is generated as "make" | 0x80
61  */
62
63 #define E0PREFIX        (1 << 31)
64 #define NOBREAK         (1 << 30)
65 #define CODEMASK        (~(E0PREFIX|NOBREAK))
66
67 static int const        x[] =
68 {
69 /*==================================================*/
70 /* Name                   HID code    Make     Break*/
71 /*==================================================*/
72 /* No Event                     00 */ -1,   /* None */
73 /* Overrun Error                01 */ NOBREAK|0xFF, /* None */
74 /* POST Fail                    02 */ NOBREAK|0xFC, /* None */
75 /* ErrorUndefined               03 */ -1,   /* Unassigned */
76 /* a A                          04 */ 0x1E, /* 9E */
77 /* b B                          05 */ 0x30, /* B0 */
78 /* c C                          06 */ 0x2E, /* AE */
79 /* d D                          07 */ 0x20, /* A0 */
80 /* e E                          08 */ 0x12, /* 92 */
81 /* f F                          09 */ 0x21, /* A1 */
82 /* g G                          0A */ 0x22, /* A2 */
83 /* h H                          0B */ 0x23, /* A3 */
84 /* i I                          0C */ 0x17, /* 97 */
85 /* j J                          0D */ 0x24, /* A4 */
86 /* k K                          0E */ 0x25, /* A5 */
87 /* l L                          0F */ 0x26, /* A6 */
88 /* m M                          10 */ 0x32, /* B2 */
89 /* n N                          11 */ 0x31, /* B1 */
90 /* o O                          12 */ 0x18, /* 98 */
91 /* p P                          13 */ 0x19, /* 99 */
92 /* q Q                          14 */ 0x10, /* 90 */
93 /* r R                          15 */ 0x13, /* 93 */
94 /* s S                          16 */ 0x1F, /* 9F */
95 /* t T                          17 */ 0x14, /* 94 */
96 /* u U                          18 */ 0x16, /* 96 */
97 /* v V                          19 */ 0x2F, /* AF */
98 /* w W                          1A */ 0x11, /* 91 */
99 /* x X                          1B */ 0x2D, /* AD */
100 /* y Y                          1C */ 0x15, /* 95 */
101 /* z Z                          1D */ 0x2C, /* AC */
102 /* 1 !                          1E */ 0x02, /* 82 */
103 /* 2 @                          1F */ 0x03, /* 83 */
104 /* 3 #                          20 */ 0x04, /* 84 */
105 /* 4 $                          21 */ 0x05, /* 85 */
106 /* 5 %                          22 */ 0x06, /* 86 */
107 /* 6 ^                          23 */ 0x07, /* 87 */
108 /* 7 &                          24 */ 0x08, /* 88 */
109 /* 8 *                          25 */ 0x09, /* 89 */
110 /* 9 (                          26 */ 0x0A, /* 8A */
111 /* 0 )                          27 */ 0x0B, /* 8B */
112 /* Return                       28 */ 0x1C, /* 9C */
113 /* Escape                       29 */ 0x01, /* 81 */
114 /* Backspace                    2A */ 0x0E, /* 8E */
115 /* Tab                          2B */ 0x0F, /* 8F */
116 /* Space                        2C */ 0x39, /* B9 */
117 /* - _                          2D */ 0x0C, /* 8C */
118 /* = +                          2E */ 0x0D, /* 8D */
119 /* [ {                          2F */ 0x1A, /* 9A */
120 /* ] }                          30 */ 0x1B, /* 9B */
121 /* \ |                          31 */ 0x2B, /* AB */
122 /* Europe 1                     32 */ 0x2B, /* AB */
123 /* ; :                          33 */ 0x27, /* A7 */
124 /* " '                          34 */ 0x28, /* A8 */
125 /* ` ~                          35 */ 0x29, /* A9 */
126 /* comma <                      36 */ 0x33, /* B3 */
127 /* . >                          37 */ 0x34, /* B4 */
128 /* / ?                          38 */ 0x35, /* B5 */
129 /* Caps Lock                    39 */ 0x3A, /* BA */
130 /* F1                           3A */ 0x3B, /* BB */
131 /* F2                           3B */ 0x3C, /* BC */
132 /* F3                           3C */ 0x3D, /* BD */
133 /* F4                           3D */ 0x3E, /* BE */
134 /* F5                           3E */ 0x3F, /* BF */
135 /* F6                           3F */ 0x40, /* C0 */
136 /* F7                           40 */ 0x41, /* C1 */
137 /* F8                           41 */ 0x42, /* C2 */
138 /* F9                           42 */ 0x43, /* C3 */
139 /* F10                          43 */ 0x44, /* C4 */
140 /* F11                          44 */ 0x57, /* D7 */
141 /* F12                          45 */ 0x58, /* D8 */
142 /* Print Screen                 46 */ E0PREFIX|37, /* E0 B7 */
143 /* Scroll Lock                  47 */ 0x46, /* C6 */
144 #if 0
145 /* Break (Ctrl-Pause)           48 */ E0 46 E0 C6, /* None */
146 /* Pause                        48 */ E1 1D 45 E1 9D C5, /* None */
147 #else
148 /* Break (Ctrl-Pause)/Pause     48 */ NOBREAK /* Special case */, /* None */
149 #endif
150 /* Insert                       49 */ E0PREFIX|0x52, /* E0 D2 */
151 /* Home                         4A */ E0PREFIX|0x47, /* E0 C7 */
152 /* Page Up                      4B */ E0PREFIX|0x49, /* E0 C9 */
153 /* Delete                       4C */ E0PREFIX|0x53, /* E0 D3 */
154 /* End                          4D */ E0PREFIX|0x4F, /* E0 CF */
155 /* Page Down                    4E */ E0PREFIX|0x51, /* E0 D1 */
156 /* Right Arrow                  4F */ E0PREFIX|0x4D, /* E0 CD */
157 /* Left Arrow                   50 */ E0PREFIX|0x4B, /* E0 CB */
158 /* Down Arrow                   51 */ E0PREFIX|0x50, /* E0 D0 */
159 /* Up Arrow                     52 */ E0PREFIX|0x48, /* E0 C8 */
160 /* Num Lock                     53 */ 0x45, /* C5 */
161 /* Keypad /                     54 */ E0PREFIX|0x35, /* E0 B5 */
162 /* Keypad *                     55 */ 0x37, /* B7 */
163 /* Keypad -                     56 */ 0x4A, /* CA */
164 /* Keypad +                     57 */ 0x4E, /* CE */
165 /* Keypad Enter                 58 */ E0PREFIX|0x1C, /* E0 9C */
166 /* Keypad 1 End                 59 */ 0x4F, /* CF */
167 /* Keypad 2 Down                5A */ 0x50, /* D0 */
168 /* Keypad 3 PageDn              5B */ 0x51, /* D1 */
169 /* Keypad 4 Left                5C */ 0x4B, /* CB */
170 /* Keypad 5                     5D */ 0x4C, /* CC */
171 /* Keypad 6 Right               5E */ 0x4D, /* CD */
172 /* Keypad 7 Home                5F */ 0x47, /* C7 */
173 /* Keypad 8 Up                  60 */ 0x48, /* C8 */
174 /* Keypad 9 PageUp              61 */ 0x49, /* C9 */
175 /* Keypad 0 Insert              62 */ 0x52, /* D2 */
176 /* Keypad . Delete              63 */ 0x53, /* D3 */
177 /* Europe 2                     64 */ 0x56, /* D6 */
178 /* App                          65 */ E0PREFIX|0x5D, /* E0 DD */
179 /* Keyboard Power               66 */ E0PREFIX|0x5E, /* E0 DE */
180 /* Keypad =                     67 */ 0x59, /* D9 */
181 /* F13                          68 */ 0x64, /* E4 */
182 /* F14                          69 */ 0x65, /* E5 */
183 /* F15                          6A */ 0x66, /* E6 */
184 /* F16                          6B */ 0x67, /* E7 */
185 /* F17                          6C */ 0x68, /* E8 */
186 /* F18                          6D */ 0x69, /* E9 */
187 /* F19                          6E */ 0x6A, /* EA */
188 /* F20                          6F */ 0x6B, /* EB */
189 /* F21                          70 */ 0x6C, /* EC */
190 /* F22                          71 */ 0x6D, /* ED */
191 /* F23                          72 */ 0x6E, /* EE */
192 /* F24                          73 */ 0x76, /* F6 */
193 /* Keyboard Execute             74 */ -1,   /* Unassigned */
194 /* Keyboard Help                75 */ -1,   /* Unassigned */
195 /* Keyboard Menu                76 */ -1,   /* Unassigned */
196 /* Keyboard Select              77 */ -1,   /* Unassigned */
197 /* Keyboard Stop                78 */ -1,   /* Unassigned */
198 /* Keyboard Again               79 */ -1,   /* Unassigned */
199 /* Keyboard Undo                7A */ -1,   /* Unassigned */
200 /* Keyboard Cut                 7B */ -1,   /* Unassigned */
201 /* Keyboard Copy                7C */ -1,   /* Unassigned */
202 /* Keyboard Paste               7D */ -1,   /* Unassigned */
203 /* Keyboard Find                7E */ -1,   /* Unassigned */
204 /* Keyboard Mute                7F */ -1,   /* Unassigned */
205 /* Keyboard Volume Up           80 */ -1,   /* Unassigned */
206 /* Keyboard Volume Dn           81 */ -1,   /* Unassigned */
207 /* Keyboard Locking Caps Lock   82 */ -1,   /* Unassigned */
208 /* Keyboard Locking Num Lock    83 */ -1,   /* Unassigned */
209 /* Keyboard Locking Scroll Lock 84 */ -1,   /* Unassigned */
210 /* Keypad comma                 85 */ 0x7E, /* FE */
211 /* Keyboard Equal Sign          86 */ -1,   /* Unassigned */
212 /* Keyboard Int'l 1             87 */ 0x73, /* F3 */
213 /* Keyboard Int'l 2             88 */ 0x70, /* F0 */
214 /* Keyboard Int'l 2             89 */ 0x7D, /* FD */
215 /* Keyboard Int'l 4             8A */ 0x79, /* F9 */
216 /* Keyboard Int'l 5             8B */ 0x7B, /* FB */
217 /* Keyboard Int'l 6             8C */ 0x5C, /* DC */
218 /* Keyboard Int'l 7             8D */ -1,   /* Unassigned */
219 /* Keyboard Int'l 8             8E */ -1,   /* Unassigned */
220 /* Keyboard Int'l 9             8F */ -1,   /* Unassigned */
221 /* Keyboard Lang 1              90 */ NOBREAK|0xF2, /* None */
222 /* Keyboard Lang 2              91 */ NOBREAK|0xF1, /* None */
223 /* Keyboard Lang 3              92 */ 0x78, /* F8 */
224 /* Keyboard Lang 4              93 */ 0x77, /* F7 */
225 /* Keyboard Lang 5              94 */ 0x76, /* F6 */
226 /* Keyboard Lang 6              95 */ -1,   /* Unassigned */
227 /* Keyboard Lang 7              96 */ -1,   /* Unassigned */
228 /* Keyboard Lang 8              97 */ -1,   /* Unassigned */
229 /* Keyboard Lang 9              98 */ -1,   /* Unassigned */
230 /* Keyboard Alternate Erase     99 */ -1,   /* Unassigned */
231 /* Keyboard SysReq/Attention    9A */ -1,   /* Unassigned */
232 /* Keyboard Cancel              9B */ -1,   /* Unassigned */
233 /* Keyboard Clear               9C */ -1,   /* Unassigned */
234 /* Keyboard Prior               9D */ -1,   /* Unassigned */
235 /* Keyboard Return              9E */ -1,   /* Unassigned */
236 /* Keyboard Separator           9F */ -1,   /* Unassigned */
237 /* Keyboard Out                 A0 */ -1,   /* Unassigned */
238 /* Keyboard Oper                A1 */ -1,   /* Unassigned */
239 /* Keyboard Clear/Again         A2 */ -1,   /* Unassigned */
240 /* Keyboard CrSel/Props         A3 */ -1,   /* Unassigned */
241 /* Keyboard ExSel               A4 */ -1,   /* Unassigned */
242 /* Reserved                     A5 */ -1,   /* Reserved */
243 /* Reserved                     A6 */ -1,   /* Reserved */
244 /* Reserved                     A7 */ -1,   /* Reserved */
245 /* Reserved                     A8 */ -1,   /* Reserved */
246 /* Reserved                     A9 */ -1,   /* Reserved */
247 /* Reserved                     AA */ -1,   /* Reserved */
248 /* Reserved                     AB */ -1,   /* Reserved */
249 /* Reserved                     AC */ -1,   /* Reserved */
250 /* Reserved                     AD */ -1,   /* Reserved */
251 /* Reserved                     AE */ -1,   /* Reserved */
252 /* Reserved                     AF */ -1,   /* Reserved */
253 /* Reserved                     B0 */ -1,   /* Reserved */
254 /* Reserved                     B1 */ -1,   /* Reserved */
255 /* Reserved                     B2 */ -1,   /* Reserved */
256 /* Reserved                     B3 */ -1,   /* Reserved */
257 /* Reserved                     B4 */ -1,   /* Reserved */
258 /* Reserved                     B5 */ -1,   /* Reserved */
259 /* Reserved                     B6 */ -1,   /* Reserved */
260 /* Reserved                     B7 */ -1,   /* Reserved */
261 /* Reserved                     B8 */ -1,   /* Reserved */
262 /* Reserved                     B9 */ -1,   /* Reserved */
263 /* Reserved                     BA */ -1,   /* Reserved */
264 /* Reserved                     BB */ -1,   /* Reserved */
265 /* Reserved                     BC */ -1,   /* Reserved */
266 /* Reserved                     BD */ -1,   /* Reserved */
267 /* Reserved                     BE */ -1,   /* Reserved */
268 /* Reserved                     BF */ -1,   /* Reserved */
269 /* Reserved                     C0 */ -1,   /* Reserved */
270 /* Reserved                     C1 */ -1,   /* Reserved */
271 /* Reserved                     C2 */ -1,   /* Reserved */
272 /* Reserved                     C3 */ -1,   /* Reserved */
273 /* Reserved                     C4 */ -1,   /* Reserved */
274 /* Reserved                     C5 */ -1,   /* Reserved */
275 /* Reserved                     C6 */ -1,   /* Reserved */
276 /* Reserved                     C8 */ -1,   /* Reserved */
277 /* Reserved                     C9 */ -1,   /* Reserved */
278 /* Reserved                     CA */ -1,   /* Reserved */
279 /* Reserved                     CB */ -1,   /* Reserved */
280 /* Reserved                     CC */ -1,   /* Reserved */
281 /* Reserved                     CD */ -1,   /* Reserved */
282 /* Reserved                     CE */ -1,   /* Reserved */
283 /* Reserved                     CF */ -1,   /* Reserved */
284 /* Reserved                     D0 */ -1,   /* Reserved */
285 /* Reserved                     D1 */ -1,   /* Reserved */
286 /* Reserved                     D2 */ -1,   /* Reserved */
287 /* Reserved                     D3 */ -1,   /* Reserved */
288 /* Reserved                     D4 */ -1,   /* Reserved */
289 /* Reserved                     D5 */ -1,   /* Reserved */
290 /* Reserved                     D6 */ -1,   /* Reserved */
291 /* Reserved                     D8 */ -1,   /* Reserved */
292 /* Reserved                     D9 */ -1,   /* Reserved */
293 /* Reserved                     DA */ -1,   /* Reserved */
294 /* Reserved                     DB */ -1,   /* Reserved */
295 /* Reserved                     DC */ -1,   /* Reserved */
296 /* Reserved                     DD */ -1,   /* Reserved */
297 /* Reserved                     DE */ -1,   /* Reserved */
298 /* Reserved                     DF */ -1,   /* Reserved */
299 /* Left Control                 E0 */ 0x1D, /* 9D */
300 /* Left Control                 E0 */ 0x1D, /* 9D */
301 /* Left Shift                   E1 */ 0x2A, /* AA */
302 /* Left Alt                     E2 */ 0x38, /* B8 */
303 /* Left GUI                     E3 */ E0PREFIX|0x5B, /* E0 DB */
304 /* Right Control                E4 */ E0PREFIX|0x1D, /* E0 9D */
305 /* Right Shift                  E5 */ 0x36, /* B6 */
306 /* Right Alt                    E6 */ E0PREFIX|0x38, /* E0 B8 */
307 /* Right GUI                    E7 */ E0PREFIX|0x5C  /* E0 DC */
308 };
309
310 #define xsize   (sizeof(x)/sizeof(x[0]))
311
312 /*
313  * Get a max HID keycode (aligned)
314  */
315
316 int
317 kbd_maxkey(void)
318 {
319         return (xsize);
320 }
321
322 /*
323  * Process keys
324  */
325
326 int
327 kbd_process_keys(bthid_session_p s)
328 {
329         bitstr_t        r[bitstr_size(xsize)];
330         int             f0, f1, i;
331
332         assert(s != NULL);
333         assert(s->srv != NULL);
334
335         bit_ffs(s->srv->keys, xsize, &f0);
336         bit_ffs(s->keys, xsize, &f1);
337
338         if (f0 == -1) {
339                 /* all keys are released, no keys pressed */
340                 if (f1 != -1) {
341                         kbd_write(s->keys, f1, 0, s->srv->vkbd);
342                         memset(s->keys, 0, bitstr_size(xsize));
343                 }
344
345                 return (0);
346         }
347
348         if (f1 == -1) {
349                 /* some keys got pressed, no keys released */
350                 if (f0 != -1) {
351                         memcpy(s->keys, s->srv->keys, bitstr_size(xsize));
352                         kbd_write(s->keys, f0, 1, s->srv->vkbd);
353                         memset(s->srv->keys, 0, bitstr_size(xsize));
354                 }
355
356                 return (0);
357         }
358
359         /* some keys got pressed, some keys got released */
360         memset(r, 0, bitstr_size(xsize));
361
362         for (i = f1; i < xsize; i++) {
363                 if (bit_test(s->keys, i)) {
364                         if (!bit_test(s->srv->keys, i)) {
365                                 bit_clear(s->keys, i);
366                                 bit_set(r, i);
367                         } else
368                                 bit_clear(s->srv->keys, i);
369                 }
370         }
371
372         for (i = f0; i < xsize; i++) {
373                 if (bit_test(s->srv->keys, i)) {
374                         if (!bit_test(s->keys, i))
375                                 bit_set(s->keys, i);
376                         else
377                                 bit_clear(s->srv->keys, i);
378                 }
379         }
380
381         bit_ffs(r, xsize, &f0);
382         bit_ffs(s->srv->keys, xsize, &f1);
383
384         if (f0 > 0)
385                 kbd_write(r, f0, 0, s->srv->vkbd);
386
387         if (f1 > 0) {
388                 kbd_write(s->srv->keys, f1, 1, s->srv->vkbd);
389                 memset(s->srv->keys, 0, bitstr_size(xsize));
390         }
391
392         return (0);
393 }
394
395 /*
396  * Get current keyboard index (fd version)
397  */
398
399 int
400 kbd_get_index_fd(int fd)
401 {
402         keyboard_info_t info;
403
404         return ((ioctl(fd, KDGKBINFO, &info) < 0)? -1 : info.kb_index);
405 }
406
407 /*
408  * Get current keyboard index (device node version)
409  */
410
411 int
412 kbd_get_index(char const *device)
413 {
414         int     fd, index;
415
416         fd = open(device, O_RDONLY);
417         if (fd < 0)
418                 return (-1);
419
420         index = kbd_get_index_fd(fd);
421
422         close(fd);
423
424         return (index);
425 }
426
427 /*
428  * Switch keyboards. Execute external script to switch keyboards. The keyboard
429  * index will be passed to the script in the first argument (argv[1]). We use
430  * external script here to allow user to customize his/her wireless keyboard,
431  * i.e. set mapping etc. In theory, all parameters could be picked up from the
432  * rc.conf.
433  */
434
435 int
436 kbd_switch(char const *script, int index)
437 {
438         pid_t   pid;
439         int     status;
440
441         if (script == NULL) {
442                 syslog(LOG_NOTICE, "Could not switch keyboards. " \
443                         "Switch script is not defined");
444                 return (-1);
445         }
446
447         if (access(script, X_OK) < 0) {
448                 syslog(LOG_ERR, "The %s is not executable. %s (%d)",
449                         script, strerror(errno), errno);
450                 return (-1);
451         }
452
453         pid = fork();
454
455         if (pid == (pid_t) -1) {
456                 syslog(LOG_ERR, "Could not create process for %s. %s (%d)",
457                         script, strerror(errno), errno);
458                 return (-1);
459         }
460
461         if (pid == 0) {
462                 char     arg[16];
463                 char    *argv[3] = { (char *) script, arg, NULL };
464
465                 snprintf(arg, sizeof(arg), "%d", index);
466                 execv(script, argv);
467
468                 syslog(LOG_ERR, "Could not execute '%s %d'. %s (%d)",
469                         script, index, strerror(errno), errno);
470
471                 exit(1);
472         }
473
474         if (waitpid(pid, &status, 0) < 0) {
475                 syslog(LOG_ERR, "Could not waitpid for %s. %s (%d)",
476                         script, strerror(errno), errno);
477                 return (-1);
478         }
479
480         if (WIFEXITED(status) && WEXITSTATUS(status)) {
481                 syslog(LOG_ERR, "External command '%s %d' failed, exit code %d",
482                         script, index, WEXITSTATUS(status));
483                 return (-1);
484         }
485
486         return (0);
487 }
488
489 /*
490  * Translate given keymap and write keyscodes
491  */ 
492
493 static void
494 kbd_write(bitstr_t *m, int fb, int make, int fd)
495 {
496         int     i, *b, *eob, n, buf[64];
497
498         b = buf;
499         eob = b + sizeof(buf)/sizeof(buf[0]);
500         i = fb;
501
502         while (i < xsize) {
503                 if (bit_test(m, i)) {
504                         n = kbd_xlate(i, make, b, eob);
505                         if (n == -1) {
506                                 write(fd, buf, (b - buf) * sizeof(buf[0]));
507                                 b = buf;
508                                 continue;
509                         }
510
511                         b += n;
512                 }
513
514                 i ++;
515         }
516
517         if (b != buf)
518                 write(fd, buf, (b - buf) * sizeof(buf[0]));
519 }
520
521
522 /*
523  * Translate HID code into PS/2 code and put codes into buffer b.
524  * Returns the number of codes put in b. Return -1 if buffer has not
525  * enough space.
526  */
527
528 #undef  PUT
529 #define PUT(c, n, b, eob)       \
530 do {                            \
531         if ((b) >= (eob))       \
532                 return (-1);    \
533         *(b) = (c);             \
534         (b) ++;                 \
535         (n) ++;                 \
536 } while (0)
537
538 static int
539 kbd_xlate(int code, int make, int *b, int const *eob)
540 {
541         int     c, n;
542
543         n = 0;
544
545         if (code >= xsize)
546                 return (0); /* HID code is not in the table */
547
548         /* Handle special case - Pause/Break */
549         if (code == 0x48) {
550                 if (!make)
551                         return (0); /* No break code */
552
553 #if 0
554 XXX FIXME
555                 if (ctrl_is_pressed) {
556                         /* Break (Ctrl-Pause) */
557                         PUT(0xe0, n, b, eob);
558                         PUT(0x46, n, b, eob);
559                         PUT(0xe0, n, b, eob);
560                         PUT(0xc6, n, b, eob);
561                 } else {
562                         /* Pause */
563                         PUT(0xe1, n, b, eob);
564                         PUT(0x1d, n, b, eob);
565                         PUT(0x45, n, b, eob);
566                         PUT(0xe1, n, b, eob);
567                         PUT(0x9d, n, b, eob);
568                         PUT(0xc5, n, b, eob);
569                 }
570 #endif
571
572                 return (n);
573         }
574
575         if ((c = x[code]) == -1)
576                 return (0); /* HID code translation is not defined */
577
578         if (make) {
579                 if (c & E0PREFIX)
580                         PUT(0xe0, n, b, eob);
581
582                 PUT((c & CODEMASK), n, b, eob);
583         } else if (!(c & NOBREAK)) {
584                 if (c & E0PREFIX)
585                         PUT(0xe0, n, b, eob);
586
587                 PUT((0x80|(c & CODEMASK)), n, b, eob);
588         }
589
590         return (n);
591 }
592