kbd.c revision 155858
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: head/usr.sbin/bluetooth/bthidd/kbd.c 155858 2006-02-20 10:07:40Z markus $ 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 51static void kbd_write(bitstr_t *m, int fb, int make, int fd); 52static 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 67static 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|0x37, /* 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 C7 */ -1, /* Reserved */ 277/* Reserved C8 */ -1, /* Reserved */ 278/* Reserved C9 */ -1, /* Reserved */ 279/* Reserved CA */ -1, /* Reserved */ 280/* Reserved CB */ -1, /* Reserved */ 281/* Reserved CC */ -1, /* Reserved */ 282/* Reserved CD */ -1, /* Reserved */ 283/* Reserved CE */ -1, /* Reserved */ 284/* Reserved CF */ -1, /* Reserved */ 285/* Reserved D0 */ -1, /* Reserved */ 286/* Reserved D1 */ -1, /* Reserved */ 287/* Reserved D2 */ -1, /* Reserved */ 288/* Reserved D3 */ -1, /* Reserved */ 289/* Reserved D4 */ -1, /* Reserved */ 290/* Reserved D5 */ -1, /* Reserved */ 291/* Reserved D6 */ -1, /* Reserved */ 292/* Reserved D7 */ -1, /* Reserved */ 293/* Reserved D8 */ -1, /* Reserved */ 294/* Reserved D9 */ -1, /* Reserved */ 295/* Reserved DA */ -1, /* Reserved */ 296/* Reserved DB */ -1, /* Reserved */ 297/* Reserved DC */ -1, /* Reserved */ 298/* Reserved DD */ -1, /* Reserved */ 299/* Reserved DE */ -1, /* Reserved */ 300/* Reserved DF */ -1, /* Reserved */ 301/* Left Control E0 */ 0x1D, /* 9D */ 302/* Left Shift E1 */ 0x2A, /* AA */ 303/* Left Alt E2 */ 0x38, /* B8 */ 304/* Left GUI E3 */ E0PREFIX|0x5B, /* E0 DB */ 305/* Right Control E4 */ E0PREFIX|0x1D, /* E0 9D */ 306/* Right Shift E5 */ 0x36, /* B6 */ 307/* Right Alt E6 */ E0PREFIX|0x38, /* E0 B8 */ 308/* Right GUI E7 */ E0PREFIX|0x5C /* E0 DC */ 309}; 310 311#define xsize (sizeof(x)/sizeof(x[0])) 312 313/* 314 * Get a max HID keycode (aligned) 315 */ 316 317int 318kbd_maxkey(void) 319{ 320 return (xsize); 321} 322 323/* 324 * Process keys 325 */ 326 327int 328kbd_process_keys(bthid_session_p s) 329{ 330 bitstr_t r[bitstr_size(xsize)]; 331 int f0, f1, i; 332 333 assert(s != NULL); 334 assert(s->srv != NULL); 335 336 bit_ffs(s->srv->keys, xsize, &f0); 337 bit_ffs(s->keys, xsize, &f1); 338 339 if (f0 == -1) { 340 /* all keys are released, no keys pressed */ 341 if (f1 != -1) { 342 kbd_write(s->keys, f1, 0, s->srv->vkbd); 343 memset(s->keys, 0, bitstr_size(xsize)); 344 } 345 346 return (0); 347 } 348 349 if (f1 == -1) { 350 /* some keys got pressed, no keys released */ 351 if (f0 != -1) { 352 memcpy(s->keys, s->srv->keys, bitstr_size(xsize)); 353 kbd_write(s->keys, f0, 1, s->srv->vkbd); 354 memset(s->srv->keys, 0, bitstr_size(xsize)); 355 } 356 357 return (0); 358 } 359 360 /* some keys got pressed, some keys got released */ 361 memset(r, 0, bitstr_size(xsize)); 362 363 for (i = f1; i < xsize; i++) { 364 if (bit_test(s->keys, i)) { 365 if (!bit_test(s->srv->keys, i)) { 366 bit_clear(s->keys, i); 367 bit_set(r, i); 368 } else 369 bit_clear(s->srv->keys, i); 370 } 371 } 372 373 for (i = f0; i < xsize; i++) { 374 if (bit_test(s->srv->keys, i)) { 375 if (!bit_test(s->keys, i)) 376 bit_set(s->keys, i); 377 else 378 bit_clear(s->srv->keys, i); 379 } 380 } 381 382 bit_ffs(r, xsize, &f0); 383 bit_ffs(s->srv->keys, xsize, &f1); 384 385 if (f0 > 0) 386 kbd_write(r, f0, 0, s->srv->vkbd); 387 388 if (f1 > 0) { 389 kbd_write(s->srv->keys, f1, 1, s->srv->vkbd); 390 memset(s->srv->keys, 0, bitstr_size(xsize)); 391 } 392 393 return (0); 394} 395 396/* 397 * Get current keyboard index (fd version) 398 */ 399 400int 401kbd_get_index_fd(int fd) 402{ 403 keyboard_info_t info; 404 405 return ((ioctl(fd, KDGKBINFO, &info) < 0)? -1 : info.kb_index); 406} 407 408/* 409 * Get current keyboard index (device node version) 410 */ 411 412int 413kbd_get_index(char const *device) 414{ 415 int fd, index; 416 417 fd = open(device, O_RDONLY); 418 if (fd < 0) 419 return (-1); 420 421 index = kbd_get_index_fd(fd); 422 423 close(fd); 424 425 return (index); 426} 427 428/* 429 * Switch keyboards. Execute external script to switch keyboards. The keyboard 430 * index will be passed to the script in the first argument (argv[1]). We use 431 * external script here to allow user to customize his/her wireless keyboard, 432 * i.e. set mapping etc. In theory, all parameters could be picked up from the 433 * rc.conf. 434 */ 435 436int 437kbd_switch(char const *script, int index) 438{ 439 pid_t pid; 440 int status; 441 442 if (script == NULL) { 443 syslog(LOG_NOTICE, "Could not switch keyboards. " \ 444 "Switch script is not defined"); 445 return (-1); 446 } 447 448 if (access(script, X_OK) < 0) { 449 syslog(LOG_ERR, "The %s is not executable. %s (%d)", 450 script, strerror(errno), errno); 451 return (-1); 452 } 453 454 pid = fork(); 455 456 if (pid == (pid_t) -1) { 457 syslog(LOG_ERR, "Could not create process for %s. %s (%d)", 458 script, strerror(errno), errno); 459 return (-1); 460 } 461 462 if (pid == 0) { 463 char arg[16]; 464 char *argv[3] = { (char *) script, arg, NULL }; 465 466 snprintf(arg, sizeof(arg), "%d", index); 467 execv(script, argv); 468 469 syslog(LOG_ERR, "Could not execute '%s %d'. %s (%d)", 470 script, index, strerror(errno), errno); 471 472 exit(1); 473 } 474 475 if (waitpid(pid, &status, 0) < 0) { 476 syslog(LOG_ERR, "Could not waitpid for %s. %s (%d)", 477 script, strerror(errno), errno); 478 return (-1); 479 } 480 481 if (WIFEXITED(status) && WEXITSTATUS(status)) { 482 syslog(LOG_ERR, "External command '%s %d' failed, exit code %d", 483 script, index, WEXITSTATUS(status)); 484 return (-1); 485 } 486 487 return (0); 488} 489 490/* 491 * Translate given keymap and write keyscodes 492 */ 493 494static void 495kbd_write(bitstr_t *m, int fb, int make, int fd) 496{ 497 int i, *b, *eob, n, buf[64]; 498 499 b = buf; 500 eob = b + sizeof(buf)/sizeof(buf[0]); 501 i = fb; 502 503 while (i < xsize) { 504 if (bit_test(m, i)) { 505 n = kbd_xlate(i, make, b, eob); 506 if (n == -1) { 507 write(fd, buf, (b - buf) * sizeof(buf[0])); 508 b = buf; 509 continue; 510 } 511 512 b += n; 513 } 514 515 i ++; 516 } 517 518 if (b != buf) 519 write(fd, buf, (b - buf) * sizeof(buf[0])); 520} 521 522 523/* 524 * Translate HID code into PS/2 code and put codes into buffer b. 525 * Returns the number of codes put in b. Return -1 if buffer has not 526 * enough space. 527 */ 528 529#undef PUT 530#define PUT(c, n, b, eob) \ 531do { \ 532 if ((b) >= (eob)) \ 533 return (-1); \ 534 *(b) = (c); \ 535 (b) ++; \ 536 (n) ++; \ 537} while (0) 538 539static int 540kbd_xlate(int code, int make, int *b, int const *eob) 541{ 542 int c, n; 543 544 n = 0; 545 546 if (code >= xsize) 547 return (0); /* HID code is not in the table */ 548 549 /* Handle special case - Pause/Break */ 550 if (code == 0x48) { 551 if (!make) 552 return (0); /* No break code */ 553 554#if 0 555XXX FIXME 556 if (ctrl_is_pressed) { 557 /* Break (Ctrl-Pause) */ 558 PUT(0xe0, n, b, eob); 559 PUT(0x46, n, b, eob); 560 PUT(0xe0, n, b, eob); 561 PUT(0xc6, n, b, eob); 562 } else { 563 /* Pause */ 564 PUT(0xe1, n, b, eob); 565 PUT(0x1d, n, b, eob); 566 PUT(0x45, n, b, eob); 567 PUT(0xe1, n, b, eob); 568 PUT(0x9d, n, b, eob); 569 PUT(0xc5, n, b, eob); 570 } 571#endif 572 573 return (n); 574 } 575 576 if ((c = x[code]) == -1) 577 return (0); /* HID code translation is not defined */ 578 579 if (make) { 580 if (c & E0PREFIX) 581 PUT(0xe0, n, b, eob); 582 583 PUT((c & CODEMASK), n, b, eob); 584 } else if (!(c & NOBREAK)) { 585 if (c & E0PREFIX) 586 PUT(0xe0, n, b, eob); 587 588 PUT((0x80|(c & CODEMASK)), n, b, eob); 589 } 590 591 return (n); 592} 593 594