1137868Semax/* 2137868Semax * kbd.c 3162128Semax */ 4162128Semax 5162128Semax/*- 6162128Semax * Copyright (c) 2006 Maksim Yevmenkin <m_evmenkin@yahoo.com> 7137868Semax * All rights reserved. 8137868Semax * 9137868Semax * Redistribution and use in source and binary forms, with or without 10137868Semax * modification, are permitted provided that the following conditions 11137868Semax * are met: 12137868Semax * 1. Redistributions of source code must retain the above copyright 13137868Semax * notice, this list of conditions and the following disclaimer. 14137868Semax * 2. Redistributions in binary form must reproduce the above copyright 15137868Semax * notice, this list of conditions and the following disclaimer in the 16137868Semax * documentation and/or other materials provided with the distribution. 17137868Semax * 18137868Semax * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19137868Semax * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20137868Semax * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21137868Semax * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22137868Semax * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23137868Semax * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24137868Semax * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25137868Semax * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26137868Semax * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27137868Semax * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28137868Semax * SUCH DAMAGE. 29137868Semax * 30162128Semax * $Id: kbd.c,v 1.4 2006/09/07 21:06:53 max Exp $ 31137868Semax * $FreeBSD$ 32137868Semax */ 33137868Semax 34137868Semax#include <sys/consio.h> 35137868Semax#include <sys/ioctl.h> 36137868Semax#include <sys/kbio.h> 37137868Semax#include <sys/queue.h> 38137868Semax#include <sys/wait.h> 39137868Semax#include <assert.h> 40137868Semax#include <bluetooth.h> 41162128Semax#include <dev/usb/usb.h> 42162128Semax#include <dev/usb/usbhid.h> 43162128Semax#include <dev/vkbd/vkbd_var.h> 44137868Semax#include <errno.h> 45137868Semax#include <fcntl.h> 46137868Semax#include <limits.h> 47137868Semax#include <stdarg.h> 48137868Semax#include <stdio.h> 49137868Semax#include <stdlib.h> 50137868Semax#include <string.h> 51137868Semax#include <syslog.h> 52137868Semax#include <unistd.h> 53162128Semax#include <usbhid.h> 54162128Semax#include "bthid_config.h" 55137868Semax#include "bthidd.h" 56137868Semax#include "kbd.h" 57137868Semax 58162128Semaxstatic void kbd_write(bitstr_t *m, int32_t fb, int32_t make, int32_t fd); 59162128Semaxstatic int32_t kbd_xlate(int32_t code, int32_t make, int32_t *b, int32_t const *eob); 60137868Semax 61137868Semax/* 62137868Semax * HID code to PS/2 set 1 code translation table. 63137868Semax * 64137868Semax * http://www.microsoft.com/whdc/device/input/Scancode.mspx 65137868Semax * 66137868Semax * The table only contains "make" (key pressed) codes. 67137868Semax * The "break" (key released) code is generated as "make" | 0x80 68137868Semax */ 69137868Semax 70137868Semax#define E0PREFIX (1 << 31) 71137868Semax#define NOBREAK (1 << 30) 72137868Semax#define CODEMASK (~(E0PREFIX|NOBREAK)) 73137868Semax 74162128Semaxstatic int32_t const x[] = 75137868Semax{ 76137868Semax/*==================================================*/ 77137868Semax/* Name HID code Make Break*/ 78137868Semax/*==================================================*/ 79137868Semax/* No Event 00 */ -1, /* None */ 80137868Semax/* Overrun Error 01 */ NOBREAK|0xFF, /* None */ 81137868Semax/* POST Fail 02 */ NOBREAK|0xFC, /* None */ 82137868Semax/* ErrorUndefined 03 */ -1, /* Unassigned */ 83137868Semax/* a A 04 */ 0x1E, /* 9E */ 84137868Semax/* b B 05 */ 0x30, /* B0 */ 85137868Semax/* c C 06 */ 0x2E, /* AE */ 86137868Semax/* d D 07 */ 0x20, /* A0 */ 87137868Semax/* e E 08 */ 0x12, /* 92 */ 88137868Semax/* f F 09 */ 0x21, /* A1 */ 89137868Semax/* g G 0A */ 0x22, /* A2 */ 90137868Semax/* h H 0B */ 0x23, /* A3 */ 91137868Semax/* i I 0C */ 0x17, /* 97 */ 92137868Semax/* j J 0D */ 0x24, /* A4 */ 93137868Semax/* k K 0E */ 0x25, /* A5 */ 94137868Semax/* l L 0F */ 0x26, /* A6 */ 95137868Semax/* m M 10 */ 0x32, /* B2 */ 96137868Semax/* n N 11 */ 0x31, /* B1 */ 97137868Semax/* o O 12 */ 0x18, /* 98 */ 98137868Semax/* p P 13 */ 0x19, /* 99 */ 99137868Semax/* q Q 14 */ 0x10, /* 90 */ 100137868Semax/* r R 15 */ 0x13, /* 93 */ 101137868Semax/* s S 16 */ 0x1F, /* 9F */ 102137868Semax/* t T 17 */ 0x14, /* 94 */ 103137868Semax/* u U 18 */ 0x16, /* 96 */ 104137868Semax/* v V 19 */ 0x2F, /* AF */ 105137868Semax/* w W 1A */ 0x11, /* 91 */ 106137868Semax/* x X 1B */ 0x2D, /* AD */ 107137868Semax/* y Y 1C */ 0x15, /* 95 */ 108137868Semax/* z Z 1D */ 0x2C, /* AC */ 109137868Semax/* 1 ! 1E */ 0x02, /* 82 */ 110137868Semax/* 2 @ 1F */ 0x03, /* 83 */ 111137868Semax/* 3 # 20 */ 0x04, /* 84 */ 112137868Semax/* 4 $ 21 */ 0x05, /* 85 */ 113137868Semax/* 5 % 22 */ 0x06, /* 86 */ 114137868Semax/* 6 ^ 23 */ 0x07, /* 87 */ 115137868Semax/* 7 & 24 */ 0x08, /* 88 */ 116137868Semax/* 8 * 25 */ 0x09, /* 89 */ 117137868Semax/* 9 ( 26 */ 0x0A, /* 8A */ 118137868Semax/* 0 ) 27 */ 0x0B, /* 8B */ 119137868Semax/* Return 28 */ 0x1C, /* 9C */ 120137868Semax/* Escape 29 */ 0x01, /* 81 */ 121137868Semax/* Backspace 2A */ 0x0E, /* 8E */ 122137868Semax/* Tab 2B */ 0x0F, /* 8F */ 123137868Semax/* Space 2C */ 0x39, /* B9 */ 124137868Semax/* - _ 2D */ 0x0C, /* 8C */ 125137868Semax/* = + 2E */ 0x0D, /* 8D */ 126137868Semax/* [ { 2F */ 0x1A, /* 9A */ 127137868Semax/* ] } 30 */ 0x1B, /* 9B */ 128137868Semax/* \ | 31 */ 0x2B, /* AB */ 129137868Semax/* Europe 1 32 */ 0x2B, /* AB */ 130137868Semax/* ; : 33 */ 0x27, /* A7 */ 131137868Semax/* " ' 34 */ 0x28, /* A8 */ 132137868Semax/* ` ~ 35 */ 0x29, /* A9 */ 133137868Semax/* comma < 36 */ 0x33, /* B3 */ 134137868Semax/* . > 37 */ 0x34, /* B4 */ 135137868Semax/* / ? 38 */ 0x35, /* B5 */ 136137868Semax/* Caps Lock 39 */ 0x3A, /* BA */ 137137868Semax/* F1 3A */ 0x3B, /* BB */ 138137868Semax/* F2 3B */ 0x3C, /* BC */ 139137868Semax/* F3 3C */ 0x3D, /* BD */ 140137868Semax/* F4 3D */ 0x3E, /* BE */ 141137868Semax/* F5 3E */ 0x3F, /* BF */ 142137868Semax/* F6 3F */ 0x40, /* C0 */ 143137868Semax/* F7 40 */ 0x41, /* C1 */ 144137868Semax/* F8 41 */ 0x42, /* C2 */ 145137868Semax/* F9 42 */ 0x43, /* C3 */ 146137868Semax/* F10 43 */ 0x44, /* C4 */ 147137868Semax/* F11 44 */ 0x57, /* D7 */ 148137868Semax/* F12 45 */ 0x58, /* D8 */ 149155858Smarkus/* Print Screen 46 */ E0PREFIX|0x37, /* E0 B7 */ 150137868Semax/* Scroll Lock 47 */ 0x46, /* C6 */ 151137868Semax#if 0 152137868Semax/* Break (Ctrl-Pause) 48 */ E0 46 E0 C6, /* None */ 153137868Semax/* Pause 48 */ E1 1D 45 E1 9D C5, /* None */ 154137868Semax#else 155137868Semax/* Break (Ctrl-Pause)/Pause 48 */ NOBREAK /* Special case */, /* None */ 156137868Semax#endif 157137868Semax/* Insert 49 */ E0PREFIX|0x52, /* E0 D2 */ 158137868Semax/* Home 4A */ E0PREFIX|0x47, /* E0 C7 */ 159137868Semax/* Page Up 4B */ E0PREFIX|0x49, /* E0 C9 */ 160137868Semax/* Delete 4C */ E0PREFIX|0x53, /* E0 D3 */ 161137868Semax/* End 4D */ E0PREFIX|0x4F, /* E0 CF */ 162137868Semax/* Page Down 4E */ E0PREFIX|0x51, /* E0 D1 */ 163137868Semax/* Right Arrow 4F */ E0PREFIX|0x4D, /* E0 CD */ 164137868Semax/* Left Arrow 50 */ E0PREFIX|0x4B, /* E0 CB */ 165137868Semax/* Down Arrow 51 */ E0PREFIX|0x50, /* E0 D0 */ 166137868Semax/* Up Arrow 52 */ E0PREFIX|0x48, /* E0 C8 */ 167137868Semax/* Num Lock 53 */ 0x45, /* C5 */ 168137868Semax/* Keypad / 54 */ E0PREFIX|0x35, /* E0 B5 */ 169137868Semax/* Keypad * 55 */ 0x37, /* B7 */ 170137868Semax/* Keypad - 56 */ 0x4A, /* CA */ 171137868Semax/* Keypad + 57 */ 0x4E, /* CE */ 172137868Semax/* Keypad Enter 58 */ E0PREFIX|0x1C, /* E0 9C */ 173137868Semax/* Keypad 1 End 59 */ 0x4F, /* CF */ 174137868Semax/* Keypad 2 Down 5A */ 0x50, /* D0 */ 175137868Semax/* Keypad 3 PageDn 5B */ 0x51, /* D1 */ 176137868Semax/* Keypad 4 Left 5C */ 0x4B, /* CB */ 177137868Semax/* Keypad 5 5D */ 0x4C, /* CC */ 178137868Semax/* Keypad 6 Right 5E */ 0x4D, /* CD */ 179137868Semax/* Keypad 7 Home 5F */ 0x47, /* C7 */ 180137868Semax/* Keypad 8 Up 60 */ 0x48, /* C8 */ 181137868Semax/* Keypad 9 PageUp 61 */ 0x49, /* C9 */ 182137868Semax/* Keypad 0 Insert 62 */ 0x52, /* D2 */ 183137868Semax/* Keypad . Delete 63 */ 0x53, /* D3 */ 184137868Semax/* Europe 2 64 */ 0x56, /* D6 */ 185137868Semax/* App 65 */ E0PREFIX|0x5D, /* E0 DD */ 186137868Semax/* Keyboard Power 66 */ E0PREFIX|0x5E, /* E0 DE */ 187137868Semax/* Keypad = 67 */ 0x59, /* D9 */ 188137868Semax/* F13 68 */ 0x64, /* E4 */ 189137868Semax/* F14 69 */ 0x65, /* E5 */ 190137868Semax/* F15 6A */ 0x66, /* E6 */ 191137868Semax/* F16 6B */ 0x67, /* E7 */ 192137868Semax/* F17 6C */ 0x68, /* E8 */ 193137868Semax/* F18 6D */ 0x69, /* E9 */ 194137868Semax/* F19 6E */ 0x6A, /* EA */ 195137868Semax/* F20 6F */ 0x6B, /* EB */ 196137868Semax/* F21 70 */ 0x6C, /* EC */ 197137868Semax/* F22 71 */ 0x6D, /* ED */ 198137868Semax/* F23 72 */ 0x6E, /* EE */ 199137868Semax/* F24 73 */ 0x76, /* F6 */ 200137868Semax/* Keyboard Execute 74 */ -1, /* Unassigned */ 201137868Semax/* Keyboard Help 75 */ -1, /* Unassigned */ 202137868Semax/* Keyboard Menu 76 */ -1, /* Unassigned */ 203137868Semax/* Keyboard Select 77 */ -1, /* Unassigned */ 204137868Semax/* Keyboard Stop 78 */ -1, /* Unassigned */ 205137868Semax/* Keyboard Again 79 */ -1, /* Unassigned */ 206137868Semax/* Keyboard Undo 7A */ -1, /* Unassigned */ 207137868Semax/* Keyboard Cut 7B */ -1, /* Unassigned */ 208137868Semax/* Keyboard Copy 7C */ -1, /* Unassigned */ 209137868Semax/* Keyboard Paste 7D */ -1, /* Unassigned */ 210137868Semax/* Keyboard Find 7E */ -1, /* Unassigned */ 211137868Semax/* Keyboard Mute 7F */ -1, /* Unassigned */ 212137868Semax/* Keyboard Volume Up 80 */ -1, /* Unassigned */ 213137868Semax/* Keyboard Volume Dn 81 */ -1, /* Unassigned */ 214137868Semax/* Keyboard Locking Caps Lock 82 */ -1, /* Unassigned */ 215137868Semax/* Keyboard Locking Num Lock 83 */ -1, /* Unassigned */ 216137868Semax/* Keyboard Locking Scroll Lock 84 */ -1, /* Unassigned */ 217137868Semax/* Keypad comma 85 */ 0x7E, /* FE */ 218137868Semax/* Keyboard Equal Sign 86 */ -1, /* Unassigned */ 219137868Semax/* Keyboard Int'l 1 87 */ 0x73, /* F3 */ 220137868Semax/* Keyboard Int'l 2 88 */ 0x70, /* F0 */ 221137868Semax/* Keyboard Int'l 2 89 */ 0x7D, /* FD */ 222137868Semax/* Keyboard Int'l 4 8A */ 0x79, /* F9 */ 223137868Semax/* Keyboard Int'l 5 8B */ 0x7B, /* FB */ 224137868Semax/* Keyboard Int'l 6 8C */ 0x5C, /* DC */ 225137868Semax/* Keyboard Int'l 7 8D */ -1, /* Unassigned */ 226137868Semax/* Keyboard Int'l 8 8E */ -1, /* Unassigned */ 227137868Semax/* Keyboard Int'l 9 8F */ -1, /* Unassigned */ 228137868Semax/* Keyboard Lang 1 90 */ NOBREAK|0xF2, /* None */ 229137868Semax/* Keyboard Lang 2 91 */ NOBREAK|0xF1, /* None */ 230137868Semax/* Keyboard Lang 3 92 */ 0x78, /* F8 */ 231137868Semax/* Keyboard Lang 4 93 */ 0x77, /* F7 */ 232137868Semax/* Keyboard Lang 5 94 */ 0x76, /* F6 */ 233137868Semax/* Keyboard Lang 6 95 */ -1, /* Unassigned */ 234137868Semax/* Keyboard Lang 7 96 */ -1, /* Unassigned */ 235137868Semax/* Keyboard Lang 8 97 */ -1, /* Unassigned */ 236137868Semax/* Keyboard Lang 9 98 */ -1, /* Unassigned */ 237137868Semax/* Keyboard Alternate Erase 99 */ -1, /* Unassigned */ 238137868Semax/* Keyboard SysReq/Attention 9A */ -1, /* Unassigned */ 239137868Semax/* Keyboard Cancel 9B */ -1, /* Unassigned */ 240137868Semax/* Keyboard Clear 9C */ -1, /* Unassigned */ 241137868Semax/* Keyboard Prior 9D */ -1, /* Unassigned */ 242137868Semax/* Keyboard Return 9E */ -1, /* Unassigned */ 243137868Semax/* Keyboard Separator 9F */ -1, /* Unassigned */ 244137868Semax/* Keyboard Out A0 */ -1, /* Unassigned */ 245137868Semax/* Keyboard Oper A1 */ -1, /* Unassigned */ 246137868Semax/* Keyboard Clear/Again A2 */ -1, /* Unassigned */ 247137868Semax/* Keyboard CrSel/Props A3 */ -1, /* Unassigned */ 248137868Semax/* Keyboard ExSel A4 */ -1, /* Unassigned */ 249137868Semax/* Reserved A5 */ -1, /* Reserved */ 250137868Semax/* Reserved A6 */ -1, /* Reserved */ 251137868Semax/* Reserved A7 */ -1, /* Reserved */ 252137868Semax/* Reserved A8 */ -1, /* Reserved */ 253137868Semax/* Reserved A9 */ -1, /* Reserved */ 254137868Semax/* Reserved AA */ -1, /* Reserved */ 255137868Semax/* Reserved AB */ -1, /* Reserved */ 256137868Semax/* Reserved AC */ -1, /* Reserved */ 257137868Semax/* Reserved AD */ -1, /* Reserved */ 258137868Semax/* Reserved AE */ -1, /* Reserved */ 259137868Semax/* Reserved AF */ -1, /* Reserved */ 260137868Semax/* Reserved B0 */ -1, /* Reserved */ 261137868Semax/* Reserved B1 */ -1, /* Reserved */ 262137868Semax/* Reserved B2 */ -1, /* Reserved */ 263137868Semax/* Reserved B3 */ -1, /* Reserved */ 264137868Semax/* Reserved B4 */ -1, /* Reserved */ 265137868Semax/* Reserved B5 */ -1, /* Reserved */ 266137868Semax/* Reserved B6 */ -1, /* Reserved */ 267137868Semax/* Reserved B7 */ -1, /* Reserved */ 268137868Semax/* Reserved B8 */ -1, /* Reserved */ 269137868Semax/* Reserved B9 */ -1, /* Reserved */ 270137868Semax/* Reserved BA */ -1, /* Reserved */ 271137868Semax/* Reserved BB */ -1, /* Reserved */ 272137868Semax/* Reserved BC */ -1, /* Reserved */ 273137868Semax/* Reserved BD */ -1, /* Reserved */ 274137868Semax/* Reserved BE */ -1, /* Reserved */ 275137868Semax/* Reserved BF */ -1, /* Reserved */ 276137868Semax/* Reserved C0 */ -1, /* Reserved */ 277137868Semax/* Reserved C1 */ -1, /* Reserved */ 278137868Semax/* Reserved C2 */ -1, /* Reserved */ 279137868Semax/* Reserved C3 */ -1, /* Reserved */ 280137868Semax/* Reserved C4 */ -1, /* Reserved */ 281137868Semax/* Reserved C5 */ -1, /* Reserved */ 282137868Semax/* Reserved C6 */ -1, /* Reserved */ 283155858Smarkus/* Reserved C7 */ -1, /* Reserved */ 284137868Semax/* Reserved C8 */ -1, /* Reserved */ 285137868Semax/* Reserved C9 */ -1, /* Reserved */ 286137868Semax/* Reserved CA */ -1, /* Reserved */ 287137868Semax/* Reserved CB */ -1, /* Reserved */ 288137868Semax/* Reserved CC */ -1, /* Reserved */ 289137868Semax/* Reserved CD */ -1, /* Reserved */ 290137868Semax/* Reserved CE */ -1, /* Reserved */ 291137868Semax/* Reserved CF */ -1, /* Reserved */ 292137868Semax/* Reserved D0 */ -1, /* Reserved */ 293137868Semax/* Reserved D1 */ -1, /* Reserved */ 294137868Semax/* Reserved D2 */ -1, /* Reserved */ 295137868Semax/* Reserved D3 */ -1, /* Reserved */ 296137868Semax/* Reserved D4 */ -1, /* Reserved */ 297137868Semax/* Reserved D5 */ -1, /* Reserved */ 298137868Semax/* Reserved D6 */ -1, /* Reserved */ 299155858Smarkus/* Reserved D7 */ -1, /* Reserved */ 300137868Semax/* Reserved D8 */ -1, /* Reserved */ 301137868Semax/* Reserved D9 */ -1, /* Reserved */ 302137868Semax/* Reserved DA */ -1, /* Reserved */ 303137868Semax/* Reserved DB */ -1, /* Reserved */ 304137868Semax/* Reserved DC */ -1, /* Reserved */ 305137868Semax/* Reserved DD */ -1, /* Reserved */ 306137868Semax/* Reserved DE */ -1, /* Reserved */ 307137868Semax/* Reserved DF */ -1, /* Reserved */ 308137868Semax/* Left Control E0 */ 0x1D, /* 9D */ 309137868Semax/* Left Shift E1 */ 0x2A, /* AA */ 310137868Semax/* Left Alt E2 */ 0x38, /* B8 */ 311137868Semax/* Left GUI E3 */ E0PREFIX|0x5B, /* E0 DB */ 312137868Semax/* Right Control E4 */ E0PREFIX|0x1D, /* E0 9D */ 313137868Semax/* Right Shift E5 */ 0x36, /* B6 */ 314137868Semax/* Right Alt E6 */ E0PREFIX|0x38, /* E0 B8 */ 315137868Semax/* Right GUI E7 */ E0PREFIX|0x5C /* E0 DC */ 316137868Semax}; 317137868Semax 318162128Semax#define xsize ((int32_t)(sizeof(x)/sizeof(x[0]))) 319137868Semax 320137868Semax/* 321137868Semax * Get a max HID keycode (aligned) 322137868Semax */ 323137868Semax 324162128Semaxint32_t 325137868Semaxkbd_maxkey(void) 326137868Semax{ 327137868Semax return (xsize); 328137868Semax} 329137868Semax 330137868Semax/* 331137868Semax * Process keys 332137868Semax */ 333137868Semax 334162128Semaxint32_t 335137868Semaxkbd_process_keys(bthid_session_p s) 336137868Semax{ 337162128Semax bitstr_t diff[bitstr_size(xsize)]; 338162128Semax int32_t f1, f2, i; 339137868Semax 340137868Semax assert(s != NULL); 341137868Semax assert(s->srv != NULL); 342137868Semax 343162128Semax /* Check if the new keys have been pressed */ 344162128Semax bit_ffs(s->keys1, xsize, &f1); 345137868Semax 346162128Semax /* Check if old keys still pressed */ 347162128Semax bit_ffs(s->keys2, xsize, &f2); 348162128Semax 349162128Semax if (f1 == -1) { 350162128Semax /* no new key pressed */ 351162128Semax if (f2 != -1) { 352162128Semax /* release old keys */ 353162128Semax kbd_write(s->keys2, f2, 0, s->vkbd); 354162128Semax memset(s->keys2, 0, bitstr_size(xsize)); 355137868Semax } 356137868Semax 357137868Semax return (0); 358137868Semax } 359137868Semax 360162128Semax if (f2 == -1) { 361162128Semax /* no old keys, but new keys pressed */ 362162128Semax assert(f1 != -1); 363162128Semax 364162128Semax memcpy(s->keys2, s->keys1, bitstr_size(xsize)); 365162128Semax kbd_write(s->keys1, f1, 1, s->vkbd); 366162128Semax memset(s->keys1, 0, bitstr_size(xsize)); 367137868Semax 368137868Semax return (0); 369137868Semax } 370137868Semax 371162128Semax /* new keys got pressed, old keys got released */ 372162128Semax memset(diff, 0, bitstr_size(xsize)); 373137868Semax 374162128Semax for (i = f2; i < xsize; i ++) { 375162128Semax if (bit_test(s->keys2, i)) { 376162128Semax if (!bit_test(s->keys1, i)) { 377162128Semax bit_clear(s->keys2, i); 378162128Semax bit_set(diff, i); 379162128Semax } 380137868Semax } 381137868Semax } 382137868Semax 383162128Semax for (i = f1; i < xsize; i++) { 384162128Semax if (bit_test(s->keys1, i)) { 385162128Semax if (!bit_test(s->keys2, i)) 386162128Semax bit_set(s->keys2, i); 387137868Semax else 388162128Semax bit_clear(s->keys1, i); 389137868Semax } 390137868Semax } 391137868Semax 392162128Semax bit_ffs(diff, xsize, &f2); 393162128Semax if (f2 > 0) 394162128Semax kbd_write(diff, f2, 0, s->vkbd); 395137868Semax 396162128Semax bit_ffs(s->keys1, xsize, &f1); 397137868Semax if (f1 > 0) { 398162128Semax kbd_write(s->keys1, f1, 1, s->vkbd); 399162128Semax memset(s->keys1, 0, bitstr_size(xsize)); 400137868Semax } 401137868Semax 402137868Semax return (0); 403137868Semax} 404137868Semax 405137868Semax/* 406137868Semax * Translate given keymap and write keyscodes 407137868Semax */ 408137868Semax 409137868Semaxstatic void 410162128Semaxkbd_write(bitstr_t *m, int32_t fb, int32_t make, int32_t fd) 411137868Semax{ 412162128Semax int32_t i, *b, *eob, n, buf[64]; 413137868Semax 414137868Semax b = buf; 415137868Semax eob = b + sizeof(buf)/sizeof(buf[0]); 416137868Semax i = fb; 417137868Semax 418137868Semax while (i < xsize) { 419137868Semax if (bit_test(m, i)) { 420137868Semax n = kbd_xlate(i, make, b, eob); 421137868Semax if (n == -1) { 422137868Semax write(fd, buf, (b - buf) * sizeof(buf[0])); 423137868Semax b = buf; 424137868Semax continue; 425137868Semax } 426137868Semax 427137868Semax b += n; 428137868Semax } 429137868Semax 430137868Semax i ++; 431137868Semax } 432137868Semax 433137868Semax if (b != buf) 434137868Semax write(fd, buf, (b - buf) * sizeof(buf[0])); 435137868Semax} 436137868Semax 437137868Semax/* 438137868Semax * Translate HID code into PS/2 code and put codes into buffer b. 439137868Semax * Returns the number of codes put in b. Return -1 if buffer has not 440137868Semax * enough space. 441137868Semax */ 442137868Semax 443137868Semax#undef PUT 444137868Semax#define PUT(c, n, b, eob) \ 445137868Semaxdo { \ 446137868Semax if ((b) >= (eob)) \ 447137868Semax return (-1); \ 448137868Semax *(b) = (c); \ 449137868Semax (b) ++; \ 450137868Semax (n) ++; \ 451137868Semax} while (0) 452137868Semax 453162128Semaxstatic int32_t 454162128Semaxkbd_xlate(int32_t code, int32_t make, int32_t *b, int32_t const *eob) 455137868Semax{ 456162128Semax int32_t c, n; 457137868Semax 458137868Semax n = 0; 459137868Semax 460137868Semax if (code >= xsize) 461137868Semax return (0); /* HID code is not in the table */ 462137868Semax 463137868Semax /* Handle special case - Pause/Break */ 464137868Semax if (code == 0x48) { 465137868Semax if (!make) 466137868Semax return (0); /* No break code */ 467137868Semax 468137868Semax#if 0 469137868SemaxXXX FIXME 470137868Semax if (ctrl_is_pressed) { 471137868Semax /* Break (Ctrl-Pause) */ 472137868Semax PUT(0xe0, n, b, eob); 473137868Semax PUT(0x46, n, b, eob); 474137868Semax PUT(0xe0, n, b, eob); 475137868Semax PUT(0xc6, n, b, eob); 476137868Semax } else { 477137868Semax /* Pause */ 478137868Semax PUT(0xe1, n, b, eob); 479137868Semax PUT(0x1d, n, b, eob); 480137868Semax PUT(0x45, n, b, eob); 481137868Semax PUT(0xe1, n, b, eob); 482137868Semax PUT(0x9d, n, b, eob); 483137868Semax PUT(0xc5, n, b, eob); 484137868Semax } 485137868Semax#endif 486137868Semax 487137868Semax return (n); 488137868Semax } 489137868Semax 490137868Semax if ((c = x[code]) == -1) 491137868Semax return (0); /* HID code translation is not defined */ 492137868Semax 493137868Semax if (make) { 494137868Semax if (c & E0PREFIX) 495137868Semax PUT(0xe0, n, b, eob); 496137868Semax 497137868Semax PUT((c & CODEMASK), n, b, eob); 498137868Semax } else if (!(c & NOBREAK)) { 499137868Semax if (c & E0PREFIX) 500137868Semax PUT(0xe0, n, b, eob); 501137868Semax 502137868Semax PUT((0x80|(c & CODEMASK)), n, b, eob); 503137868Semax } 504137868Semax 505137868Semax return (n); 506137868Semax} 507137868Semax 508162128Semax/* 509162128Semax * Process status change from vkbd(4) 510162128Semax */ 511162128Semax 512162128Semaxint32_t 513162128Semaxkbd_status_changed(bthid_session_p s, uint8_t *data, int32_t len) 514162128Semax{ 515162157Semax vkbd_status_t st; 516162157Semax uint8_t leds, report_id; 517162128Semax hid_device_p hid_device; 518162128Semax hid_data_t d; 519162128Semax hid_item_t h; 520162128Semax 521162128Semax assert(s != NULL); 522162128Semax assert(len == sizeof(vkbd_status_t)); 523162128Semax 524162157Semax memcpy(&st, data, sizeof(st)); 525162157Semax leds = 0; 526162128Semax report_id = NO_REPORT_ID; 527162128Semax 528162128Semax hid_device = get_hid_device(&s->bdaddr); 529162128Semax assert(hid_device != NULL); 530162128Semax 531162128Semax for (d = hid_start_parse(hid_device->desc, 1 << hid_output, -1); 532162128Semax hid_get_item(d, &h) > 0; ) { 533162128Semax if (HID_PAGE(h.usage) == HUP_LEDS) { 534162128Semax if (report_id == NO_REPORT_ID) 535162128Semax report_id = h.report_ID; 536162128Semax else if (h.report_ID != report_id) 537162128Semax syslog(LOG_WARNING, "Output HID report IDs " \ 538162128Semax "for %s do not match: %d vs. %d. " \ 539162128Semax "Please report", 540162128Semax bt_ntoa(&s->bdaddr, NULL), 541162128Semax h.report_ID, report_id); 542162128Semax 543162128Semax switch(HID_USAGE(h.usage)) { 544162128Semax case 0x01: /* Num Lock LED */ 545162157Semax if (st.leds & LED_NUM) 546162157Semax hid_set_data(&leds, &h, 1); 547162128Semax break; 548162128Semax 549162128Semax case 0x02: /* Caps Lock LED */ 550162157Semax if (st.leds & LED_CAP) 551162157Semax hid_set_data(&leds, &h, 1); 552162128Semax break; 553162128Semax 554162128Semax case 0x03: /* Scroll Lock LED */ 555162157Semax if (st.leds & LED_SCR) 556162157Semax hid_set_data(&leds, &h, 1); 557162128Semax break; 558162128Semax 559162128Semax /* XXX add other LEDs ? */ 560162128Semax } 561162128Semax } 562162128Semax } 563162128Semax hid_end_parse(d); 564162128Semax 565162128Semax data[0] = 0xa2; /* DATA output (HID output report) */ 566162128Semax 567162128Semax if (report_id != NO_REPORT_ID) { 568162128Semax data[1] = report_id; 569162157Semax data[2] = leds; 570162128Semax len = 3; 571162128Semax } else { 572162157Semax data[1] = leds; 573162128Semax len = 2; 574162128Semax } 575162128Semax 576162128Semax write(s->intr, data, len); 577162128Semax 578162128Semax return (0); 579162128Semax} 580162128Semax 581