13adfd74aSMaksim Yevmenkin /* 23adfd74aSMaksim Yevmenkin * kbd.c 37aebfa93SMaksim Yevmenkin */ 47aebfa93SMaksim Yevmenkin 57aebfa93SMaksim Yevmenkin /*- 64d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause 71de7b4b8SPedro F. Giffuni * 87aebfa93SMaksim Yevmenkin * Copyright (c) 2006 Maksim Yevmenkin <m_evmenkin@yahoo.com> 93adfd74aSMaksim Yevmenkin * All rights reserved. 103adfd74aSMaksim Yevmenkin * 113adfd74aSMaksim Yevmenkin * Redistribution and use in source and binary forms, with or without 123adfd74aSMaksim Yevmenkin * modification, are permitted provided that the following conditions 133adfd74aSMaksim Yevmenkin * are met: 143adfd74aSMaksim Yevmenkin * 1. Redistributions of source code must retain the above copyright 153adfd74aSMaksim Yevmenkin * notice, this list of conditions and the following disclaimer. 163adfd74aSMaksim Yevmenkin * 2. Redistributions in binary form must reproduce the above copyright 173adfd74aSMaksim Yevmenkin * notice, this list of conditions and the following disclaimer in the 183adfd74aSMaksim Yevmenkin * documentation and/or other materials provided with the distribution. 193adfd74aSMaksim Yevmenkin * 203adfd74aSMaksim Yevmenkin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 213adfd74aSMaksim Yevmenkin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 223adfd74aSMaksim Yevmenkin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 233adfd74aSMaksim Yevmenkin * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 243adfd74aSMaksim Yevmenkin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 253adfd74aSMaksim Yevmenkin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 263adfd74aSMaksim Yevmenkin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 273adfd74aSMaksim Yevmenkin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 283adfd74aSMaksim Yevmenkin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 293adfd74aSMaksim Yevmenkin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 303adfd74aSMaksim Yevmenkin * SUCH DAMAGE. 313adfd74aSMaksim Yevmenkin * 327aebfa93SMaksim Yevmenkin * $Id: kbd.c,v 1.4 2006/09/07 21:06:53 max Exp $ 333adfd74aSMaksim Yevmenkin */ 343adfd74aSMaksim Yevmenkin 353adfd74aSMaksim Yevmenkin #include <sys/consio.h> 363adfd74aSMaksim Yevmenkin #include <sys/ioctl.h> 373adfd74aSMaksim Yevmenkin #include <sys/kbio.h> 38fdbf7cabSElyes Haouas #include <sys/param.h> 393adfd74aSMaksim Yevmenkin #include <sys/queue.h> 403adfd74aSMaksim Yevmenkin #include <sys/wait.h> 413adfd74aSMaksim Yevmenkin #include <assert.h> 428d6f425dSTakanori Watanabe #define L2CAP_SOCKET_CHECKED 433adfd74aSMaksim Yevmenkin #include <bluetooth.h> 447aebfa93SMaksim Yevmenkin #include <dev/usb/usb.h> 457aebfa93SMaksim Yevmenkin #include <dev/usb/usbhid.h> 467aebfa93SMaksim Yevmenkin #include <dev/vkbd/vkbd_var.h> 473adfd74aSMaksim Yevmenkin #include <errno.h> 483adfd74aSMaksim Yevmenkin #include <fcntl.h> 493adfd74aSMaksim Yevmenkin #include <limits.h> 503adfd74aSMaksim Yevmenkin #include <stdarg.h> 513adfd74aSMaksim Yevmenkin #include <stdio.h> 523adfd74aSMaksim Yevmenkin #include <stdlib.h> 533adfd74aSMaksim Yevmenkin #include <string.h> 543adfd74aSMaksim Yevmenkin #include <syslog.h> 553adfd74aSMaksim Yevmenkin #include <unistd.h> 567aebfa93SMaksim Yevmenkin #include <usbhid.h> 577aebfa93SMaksim Yevmenkin #include "bthid_config.h" 583adfd74aSMaksim Yevmenkin #include "bthidd.h" 5944af5666SVladimir Kondratyev #include "btuinput.h" 603adfd74aSMaksim Yevmenkin #include "kbd.h" 613adfd74aSMaksim Yevmenkin 627aebfa93SMaksim Yevmenkin static void kbd_write(bitstr_t *m, int32_t fb, int32_t make, int32_t fd); 637aebfa93SMaksim Yevmenkin static int32_t kbd_xlate(int32_t code, int32_t make, int32_t *b, int32_t const *eob); 6444af5666SVladimir Kondratyev static void uinput_kbd_write(bitstr_t *m, int32_t fb, int32_t make, int32_t fd); 653adfd74aSMaksim Yevmenkin 663adfd74aSMaksim Yevmenkin /* 673adfd74aSMaksim Yevmenkin * HID code to PS/2 set 1 code translation table. 683adfd74aSMaksim Yevmenkin * 693adfd74aSMaksim Yevmenkin * http://www.microsoft.com/whdc/device/input/Scancode.mspx 703adfd74aSMaksim Yevmenkin * 713adfd74aSMaksim Yevmenkin * The table only contains "make" (key pressed) codes. 723adfd74aSMaksim Yevmenkin * The "break" (key released) code is generated as "make" | 0x80 733adfd74aSMaksim Yevmenkin */ 743adfd74aSMaksim Yevmenkin 757a22215cSEitan Adler #define E0PREFIX (1U << 31) 763adfd74aSMaksim Yevmenkin #define NOBREAK (1 << 30) 773adfd74aSMaksim Yevmenkin #define CODEMASK (~(E0PREFIX|NOBREAK)) 783adfd74aSMaksim Yevmenkin 797aebfa93SMaksim Yevmenkin static int32_t const x[] = 803adfd74aSMaksim Yevmenkin { 813adfd74aSMaksim Yevmenkin /*==================================================*/ 823adfd74aSMaksim Yevmenkin /* Name HID code Make Break*/ 833adfd74aSMaksim Yevmenkin /*==================================================*/ 843adfd74aSMaksim Yevmenkin /* No Event 00 */ -1, /* None */ 853adfd74aSMaksim Yevmenkin /* Overrun Error 01 */ NOBREAK|0xFF, /* None */ 863adfd74aSMaksim Yevmenkin /* POST Fail 02 */ NOBREAK|0xFC, /* None */ 873adfd74aSMaksim Yevmenkin /* ErrorUndefined 03 */ -1, /* Unassigned */ 883adfd74aSMaksim Yevmenkin /* a A 04 */ 0x1E, /* 9E */ 893adfd74aSMaksim Yevmenkin /* b B 05 */ 0x30, /* B0 */ 903adfd74aSMaksim Yevmenkin /* c C 06 */ 0x2E, /* AE */ 913adfd74aSMaksim Yevmenkin /* d D 07 */ 0x20, /* A0 */ 923adfd74aSMaksim Yevmenkin /* e E 08 */ 0x12, /* 92 */ 933adfd74aSMaksim Yevmenkin /* f F 09 */ 0x21, /* A1 */ 943adfd74aSMaksim Yevmenkin /* g G 0A */ 0x22, /* A2 */ 953adfd74aSMaksim Yevmenkin /* h H 0B */ 0x23, /* A3 */ 963adfd74aSMaksim Yevmenkin /* i I 0C */ 0x17, /* 97 */ 973adfd74aSMaksim Yevmenkin /* j J 0D */ 0x24, /* A4 */ 983adfd74aSMaksim Yevmenkin /* k K 0E */ 0x25, /* A5 */ 993adfd74aSMaksim Yevmenkin /* l L 0F */ 0x26, /* A6 */ 1003adfd74aSMaksim Yevmenkin /* m M 10 */ 0x32, /* B2 */ 1013adfd74aSMaksim Yevmenkin /* n N 11 */ 0x31, /* B1 */ 1023adfd74aSMaksim Yevmenkin /* o O 12 */ 0x18, /* 98 */ 1033adfd74aSMaksim Yevmenkin /* p P 13 */ 0x19, /* 99 */ 1043adfd74aSMaksim Yevmenkin /* q Q 14 */ 0x10, /* 90 */ 1053adfd74aSMaksim Yevmenkin /* r R 15 */ 0x13, /* 93 */ 1063adfd74aSMaksim Yevmenkin /* s S 16 */ 0x1F, /* 9F */ 1073adfd74aSMaksim Yevmenkin /* t T 17 */ 0x14, /* 94 */ 1083adfd74aSMaksim Yevmenkin /* u U 18 */ 0x16, /* 96 */ 1093adfd74aSMaksim Yevmenkin /* v V 19 */ 0x2F, /* AF */ 1103adfd74aSMaksim Yevmenkin /* w W 1A */ 0x11, /* 91 */ 1113adfd74aSMaksim Yevmenkin /* x X 1B */ 0x2D, /* AD */ 1123adfd74aSMaksim Yevmenkin /* y Y 1C */ 0x15, /* 95 */ 1133adfd74aSMaksim Yevmenkin /* z Z 1D */ 0x2C, /* AC */ 1143adfd74aSMaksim Yevmenkin /* 1 ! 1E */ 0x02, /* 82 */ 1153adfd74aSMaksim Yevmenkin /* 2 @ 1F */ 0x03, /* 83 */ 1163adfd74aSMaksim Yevmenkin /* 3 # 20 */ 0x04, /* 84 */ 1173adfd74aSMaksim Yevmenkin /* 4 $ 21 */ 0x05, /* 85 */ 1183adfd74aSMaksim Yevmenkin /* 5 % 22 */ 0x06, /* 86 */ 1193adfd74aSMaksim Yevmenkin /* 6 ^ 23 */ 0x07, /* 87 */ 1203adfd74aSMaksim Yevmenkin /* 7 & 24 */ 0x08, /* 88 */ 1213adfd74aSMaksim Yevmenkin /* 8 * 25 */ 0x09, /* 89 */ 1223adfd74aSMaksim Yevmenkin /* 9 ( 26 */ 0x0A, /* 8A */ 1233adfd74aSMaksim Yevmenkin /* 0 ) 27 */ 0x0B, /* 8B */ 1243adfd74aSMaksim Yevmenkin /* Return 28 */ 0x1C, /* 9C */ 1253adfd74aSMaksim Yevmenkin /* Escape 29 */ 0x01, /* 81 */ 1263adfd74aSMaksim Yevmenkin /* Backspace 2A */ 0x0E, /* 8E */ 1273adfd74aSMaksim Yevmenkin /* Tab 2B */ 0x0F, /* 8F */ 1283adfd74aSMaksim Yevmenkin /* Space 2C */ 0x39, /* B9 */ 1293adfd74aSMaksim Yevmenkin /* - _ 2D */ 0x0C, /* 8C */ 1303adfd74aSMaksim Yevmenkin /* = + 2E */ 0x0D, /* 8D */ 1313adfd74aSMaksim Yevmenkin /* [ { 2F */ 0x1A, /* 9A */ 1323adfd74aSMaksim Yevmenkin /* ] } 30 */ 0x1B, /* 9B */ 1333adfd74aSMaksim Yevmenkin /* \ | 31 */ 0x2B, /* AB */ 1343adfd74aSMaksim Yevmenkin /* Europe 1 32 */ 0x2B, /* AB */ 1353adfd74aSMaksim Yevmenkin /* ; : 33 */ 0x27, /* A7 */ 1363adfd74aSMaksim Yevmenkin /* " ' 34 */ 0x28, /* A8 */ 1373adfd74aSMaksim Yevmenkin /* ` ~ 35 */ 0x29, /* A9 */ 1383adfd74aSMaksim Yevmenkin /* comma < 36 */ 0x33, /* B3 */ 1393adfd74aSMaksim Yevmenkin /* . > 37 */ 0x34, /* B4 */ 1403adfd74aSMaksim Yevmenkin /* / ? 38 */ 0x35, /* B5 */ 1413adfd74aSMaksim Yevmenkin /* Caps Lock 39 */ 0x3A, /* BA */ 1423adfd74aSMaksim Yevmenkin /* F1 3A */ 0x3B, /* BB */ 1433adfd74aSMaksim Yevmenkin /* F2 3B */ 0x3C, /* BC */ 1443adfd74aSMaksim Yevmenkin /* F3 3C */ 0x3D, /* BD */ 1453adfd74aSMaksim Yevmenkin /* F4 3D */ 0x3E, /* BE */ 1463adfd74aSMaksim Yevmenkin /* F5 3E */ 0x3F, /* BF */ 1473adfd74aSMaksim Yevmenkin /* F6 3F */ 0x40, /* C0 */ 1483adfd74aSMaksim Yevmenkin /* F7 40 */ 0x41, /* C1 */ 1493adfd74aSMaksim Yevmenkin /* F8 41 */ 0x42, /* C2 */ 1503adfd74aSMaksim Yevmenkin /* F9 42 */ 0x43, /* C3 */ 1513adfd74aSMaksim Yevmenkin /* F10 43 */ 0x44, /* C4 */ 1523adfd74aSMaksim Yevmenkin /* F11 44 */ 0x57, /* D7 */ 1533adfd74aSMaksim Yevmenkin /* F12 45 */ 0x58, /* D8 */ 154610e662eSMarkus Brueffer /* Print Screen 46 */ E0PREFIX|0x37, /* E0 B7 */ 1553adfd74aSMaksim Yevmenkin /* Scroll Lock 47 */ 0x46, /* C6 */ 1563adfd74aSMaksim Yevmenkin #if 0 1573adfd74aSMaksim Yevmenkin /* Break (Ctrl-Pause) 48 */ E0 46 E0 C6, /* None */ 1583adfd74aSMaksim Yevmenkin /* Pause 48 */ E1 1D 45 E1 9D C5, /* None */ 1593adfd74aSMaksim Yevmenkin #else 1603adfd74aSMaksim Yevmenkin /* Break (Ctrl-Pause)/Pause 48 */ NOBREAK /* Special case */, /* None */ 1613adfd74aSMaksim Yevmenkin #endif 1623adfd74aSMaksim Yevmenkin /* Insert 49 */ E0PREFIX|0x52, /* E0 D2 */ 1633adfd74aSMaksim Yevmenkin /* Home 4A */ E0PREFIX|0x47, /* E0 C7 */ 1643adfd74aSMaksim Yevmenkin /* Page Up 4B */ E0PREFIX|0x49, /* E0 C9 */ 1653adfd74aSMaksim Yevmenkin /* Delete 4C */ E0PREFIX|0x53, /* E0 D3 */ 1663adfd74aSMaksim Yevmenkin /* End 4D */ E0PREFIX|0x4F, /* E0 CF */ 1673adfd74aSMaksim Yevmenkin /* Page Down 4E */ E0PREFIX|0x51, /* E0 D1 */ 1683adfd74aSMaksim Yevmenkin /* Right Arrow 4F */ E0PREFIX|0x4D, /* E0 CD */ 1693adfd74aSMaksim Yevmenkin /* Left Arrow 50 */ E0PREFIX|0x4B, /* E0 CB */ 1703adfd74aSMaksim Yevmenkin /* Down Arrow 51 */ E0PREFIX|0x50, /* E0 D0 */ 1713adfd74aSMaksim Yevmenkin /* Up Arrow 52 */ E0PREFIX|0x48, /* E0 C8 */ 1723adfd74aSMaksim Yevmenkin /* Num Lock 53 */ 0x45, /* C5 */ 1733adfd74aSMaksim Yevmenkin /* Keypad / 54 */ E0PREFIX|0x35, /* E0 B5 */ 1743adfd74aSMaksim Yevmenkin /* Keypad * 55 */ 0x37, /* B7 */ 1753adfd74aSMaksim Yevmenkin /* Keypad - 56 */ 0x4A, /* CA */ 1763adfd74aSMaksim Yevmenkin /* Keypad + 57 */ 0x4E, /* CE */ 1773adfd74aSMaksim Yevmenkin /* Keypad Enter 58 */ E0PREFIX|0x1C, /* E0 9C */ 1783adfd74aSMaksim Yevmenkin /* Keypad 1 End 59 */ 0x4F, /* CF */ 1793adfd74aSMaksim Yevmenkin /* Keypad 2 Down 5A */ 0x50, /* D0 */ 1803adfd74aSMaksim Yevmenkin /* Keypad 3 PageDn 5B */ 0x51, /* D1 */ 1813adfd74aSMaksim Yevmenkin /* Keypad 4 Left 5C */ 0x4B, /* CB */ 1823adfd74aSMaksim Yevmenkin /* Keypad 5 5D */ 0x4C, /* CC */ 1833adfd74aSMaksim Yevmenkin /* Keypad 6 Right 5E */ 0x4D, /* CD */ 1843adfd74aSMaksim Yevmenkin /* Keypad 7 Home 5F */ 0x47, /* C7 */ 1853adfd74aSMaksim Yevmenkin /* Keypad 8 Up 60 */ 0x48, /* C8 */ 1863adfd74aSMaksim Yevmenkin /* Keypad 9 PageUp 61 */ 0x49, /* C9 */ 1873adfd74aSMaksim Yevmenkin /* Keypad 0 Insert 62 */ 0x52, /* D2 */ 1883adfd74aSMaksim Yevmenkin /* Keypad . Delete 63 */ 0x53, /* D3 */ 1893adfd74aSMaksim Yevmenkin /* Europe 2 64 */ 0x56, /* D6 */ 1903adfd74aSMaksim Yevmenkin /* App 65 */ E0PREFIX|0x5D, /* E0 DD */ 1913adfd74aSMaksim Yevmenkin /* Keyboard Power 66 */ E0PREFIX|0x5E, /* E0 DE */ 1923adfd74aSMaksim Yevmenkin /* Keypad = 67 */ 0x59, /* D9 */ 1933adfd74aSMaksim Yevmenkin /* F13 68 */ 0x64, /* E4 */ 1943adfd74aSMaksim Yevmenkin /* F14 69 */ 0x65, /* E5 */ 1953adfd74aSMaksim Yevmenkin /* F15 6A */ 0x66, /* E6 */ 1963adfd74aSMaksim Yevmenkin /* F16 6B */ 0x67, /* E7 */ 1973adfd74aSMaksim Yevmenkin /* F17 6C */ 0x68, /* E8 */ 1983adfd74aSMaksim Yevmenkin /* F18 6D */ 0x69, /* E9 */ 1993adfd74aSMaksim Yevmenkin /* F19 6E */ 0x6A, /* EA */ 2003adfd74aSMaksim Yevmenkin /* F20 6F */ 0x6B, /* EB */ 2013adfd74aSMaksim Yevmenkin /* F21 70 */ 0x6C, /* EC */ 2023adfd74aSMaksim Yevmenkin /* F22 71 */ 0x6D, /* ED */ 2033adfd74aSMaksim Yevmenkin /* F23 72 */ 0x6E, /* EE */ 2043adfd74aSMaksim Yevmenkin /* F24 73 */ 0x76, /* F6 */ 2053adfd74aSMaksim Yevmenkin /* Keyboard Execute 74 */ -1, /* Unassigned */ 2063adfd74aSMaksim Yevmenkin /* Keyboard Help 75 */ -1, /* Unassigned */ 2073adfd74aSMaksim Yevmenkin /* Keyboard Menu 76 */ -1, /* Unassigned */ 2083adfd74aSMaksim Yevmenkin /* Keyboard Select 77 */ -1, /* Unassigned */ 2093adfd74aSMaksim Yevmenkin /* Keyboard Stop 78 */ -1, /* Unassigned */ 2103adfd74aSMaksim Yevmenkin /* Keyboard Again 79 */ -1, /* Unassigned */ 2113adfd74aSMaksim Yevmenkin /* Keyboard Undo 7A */ -1, /* Unassigned */ 2123adfd74aSMaksim Yevmenkin /* Keyboard Cut 7B */ -1, /* Unassigned */ 2133adfd74aSMaksim Yevmenkin /* Keyboard Copy 7C */ -1, /* Unassigned */ 2143adfd74aSMaksim Yevmenkin /* Keyboard Paste 7D */ -1, /* Unassigned */ 2153adfd74aSMaksim Yevmenkin /* Keyboard Find 7E */ -1, /* Unassigned */ 2163adfd74aSMaksim Yevmenkin /* Keyboard Mute 7F */ -1, /* Unassigned */ 2173adfd74aSMaksim Yevmenkin /* Keyboard Volume Up 80 */ -1, /* Unassigned */ 2183adfd74aSMaksim Yevmenkin /* Keyboard Volume Dn 81 */ -1, /* Unassigned */ 2193adfd74aSMaksim Yevmenkin /* Keyboard Locking Caps Lock 82 */ -1, /* Unassigned */ 2203adfd74aSMaksim Yevmenkin /* Keyboard Locking Num Lock 83 */ -1, /* Unassigned */ 2213adfd74aSMaksim Yevmenkin /* Keyboard Locking Scroll Lock 84 */ -1, /* Unassigned */ 2223adfd74aSMaksim Yevmenkin /* Keypad comma 85 */ 0x7E, /* FE */ 2233adfd74aSMaksim Yevmenkin /* Keyboard Equal Sign 86 */ -1, /* Unassigned */ 2243adfd74aSMaksim Yevmenkin /* Keyboard Int'l 1 87 */ 0x73, /* F3 */ 2253adfd74aSMaksim Yevmenkin /* Keyboard Int'l 2 88 */ 0x70, /* F0 */ 2263adfd74aSMaksim Yevmenkin /* Keyboard Int'l 2 89 */ 0x7D, /* FD */ 2273adfd74aSMaksim Yevmenkin /* Keyboard Int'l 4 8A */ 0x79, /* F9 */ 2283adfd74aSMaksim Yevmenkin /* Keyboard Int'l 5 8B */ 0x7B, /* FB */ 2293adfd74aSMaksim Yevmenkin /* Keyboard Int'l 6 8C */ 0x5C, /* DC */ 2303adfd74aSMaksim Yevmenkin /* Keyboard Int'l 7 8D */ -1, /* Unassigned */ 2313adfd74aSMaksim Yevmenkin /* Keyboard Int'l 8 8E */ -1, /* Unassigned */ 2323adfd74aSMaksim Yevmenkin /* Keyboard Int'l 9 8F */ -1, /* Unassigned */ 233d6c53633SHans Petter Selasky /* Keyboard Lang 1 90 */ 0x71, /* Kana */ 234d6c53633SHans Petter Selasky /* Keyboard Lang 2 91 */ 0x72, /* Eisu */ 2353adfd74aSMaksim Yevmenkin /* Keyboard Lang 3 92 */ 0x78, /* F8 */ 2363adfd74aSMaksim Yevmenkin /* Keyboard Lang 4 93 */ 0x77, /* F7 */ 2373adfd74aSMaksim Yevmenkin /* Keyboard Lang 5 94 */ 0x76, /* F6 */ 2383adfd74aSMaksim Yevmenkin /* Keyboard Lang 6 95 */ -1, /* Unassigned */ 2393adfd74aSMaksim Yevmenkin /* Keyboard Lang 7 96 */ -1, /* Unassigned */ 2403adfd74aSMaksim Yevmenkin /* Keyboard Lang 8 97 */ -1, /* Unassigned */ 2413adfd74aSMaksim Yevmenkin /* Keyboard Lang 9 98 */ -1, /* Unassigned */ 2423adfd74aSMaksim Yevmenkin /* Keyboard Alternate Erase 99 */ -1, /* Unassigned */ 2433adfd74aSMaksim Yevmenkin /* Keyboard SysReq/Attention 9A */ -1, /* Unassigned */ 2443adfd74aSMaksim Yevmenkin /* Keyboard Cancel 9B */ -1, /* Unassigned */ 2453adfd74aSMaksim Yevmenkin /* Keyboard Clear 9C */ -1, /* Unassigned */ 2463adfd74aSMaksim Yevmenkin /* Keyboard Prior 9D */ -1, /* Unassigned */ 2473adfd74aSMaksim Yevmenkin /* Keyboard Return 9E */ -1, /* Unassigned */ 2483adfd74aSMaksim Yevmenkin /* Keyboard Separator 9F */ -1, /* Unassigned */ 2493adfd74aSMaksim Yevmenkin /* Keyboard Out A0 */ -1, /* Unassigned */ 2503adfd74aSMaksim Yevmenkin /* Keyboard Oper A1 */ -1, /* Unassigned */ 2513adfd74aSMaksim Yevmenkin /* Keyboard Clear/Again A2 */ -1, /* Unassigned */ 2523adfd74aSMaksim Yevmenkin /* Keyboard CrSel/Props A3 */ -1, /* Unassigned */ 2533adfd74aSMaksim Yevmenkin /* Keyboard ExSel A4 */ -1, /* Unassigned */ 2543adfd74aSMaksim Yevmenkin /* Reserved A5 */ -1, /* Reserved */ 2553adfd74aSMaksim Yevmenkin /* Reserved A6 */ -1, /* Reserved */ 2563adfd74aSMaksim Yevmenkin /* Reserved A7 */ -1, /* Reserved */ 2573adfd74aSMaksim Yevmenkin /* Reserved A8 */ -1, /* Reserved */ 2583adfd74aSMaksim Yevmenkin /* Reserved A9 */ -1, /* Reserved */ 2593adfd74aSMaksim Yevmenkin /* Reserved AA */ -1, /* Reserved */ 2603adfd74aSMaksim Yevmenkin /* Reserved AB */ -1, /* Reserved */ 2613adfd74aSMaksim Yevmenkin /* Reserved AC */ -1, /* Reserved */ 2623adfd74aSMaksim Yevmenkin /* Reserved AD */ -1, /* Reserved */ 2633adfd74aSMaksim Yevmenkin /* Reserved AE */ -1, /* Reserved */ 2643adfd74aSMaksim Yevmenkin /* Reserved AF */ -1, /* Reserved */ 2653adfd74aSMaksim Yevmenkin /* Reserved B0 */ -1, /* Reserved */ 2663adfd74aSMaksim Yevmenkin /* Reserved B1 */ -1, /* Reserved */ 2673adfd74aSMaksim Yevmenkin /* Reserved B2 */ -1, /* Reserved */ 2683adfd74aSMaksim Yevmenkin /* Reserved B3 */ -1, /* Reserved */ 2693adfd74aSMaksim Yevmenkin /* Reserved B4 */ -1, /* Reserved */ 2703adfd74aSMaksim Yevmenkin /* Reserved B5 */ -1, /* Reserved */ 2713adfd74aSMaksim Yevmenkin /* Reserved B6 */ -1, /* Reserved */ 2723adfd74aSMaksim Yevmenkin /* Reserved B7 */ -1, /* Reserved */ 2733adfd74aSMaksim Yevmenkin /* Reserved B8 */ -1, /* Reserved */ 2743adfd74aSMaksim Yevmenkin /* Reserved B9 */ -1, /* Reserved */ 2753adfd74aSMaksim Yevmenkin /* Reserved BA */ -1, /* Reserved */ 2763adfd74aSMaksim Yevmenkin /* Reserved BB */ -1, /* Reserved */ 2773adfd74aSMaksim Yevmenkin /* Reserved BC */ -1, /* Reserved */ 2783adfd74aSMaksim Yevmenkin /* Reserved BD */ -1, /* Reserved */ 2793adfd74aSMaksim Yevmenkin /* Reserved BE */ -1, /* Reserved */ 2803adfd74aSMaksim Yevmenkin /* Reserved BF */ -1, /* Reserved */ 2813adfd74aSMaksim Yevmenkin /* Reserved C0 */ -1, /* Reserved */ 2823adfd74aSMaksim Yevmenkin /* Reserved C1 */ -1, /* Reserved */ 2833adfd74aSMaksim Yevmenkin /* Reserved C2 */ -1, /* Reserved */ 2843adfd74aSMaksim Yevmenkin /* Reserved C3 */ -1, /* Reserved */ 2853adfd74aSMaksim Yevmenkin /* Reserved C4 */ -1, /* Reserved */ 2863adfd74aSMaksim Yevmenkin /* Reserved C5 */ -1, /* Reserved */ 2873adfd74aSMaksim Yevmenkin /* Reserved C6 */ -1, /* Reserved */ 288610e662eSMarkus Brueffer /* Reserved C7 */ -1, /* Reserved */ 2893adfd74aSMaksim Yevmenkin /* Reserved C8 */ -1, /* Reserved */ 2903adfd74aSMaksim Yevmenkin /* Reserved C9 */ -1, /* Reserved */ 2913adfd74aSMaksim Yevmenkin /* Reserved CA */ -1, /* Reserved */ 2923adfd74aSMaksim Yevmenkin /* Reserved CB */ -1, /* Reserved */ 2933adfd74aSMaksim Yevmenkin /* Reserved CC */ -1, /* Reserved */ 2943adfd74aSMaksim Yevmenkin /* Reserved CD */ -1, /* Reserved */ 2953adfd74aSMaksim Yevmenkin /* Reserved CE */ -1, /* Reserved */ 2963adfd74aSMaksim Yevmenkin /* Reserved CF */ -1, /* Reserved */ 2973adfd74aSMaksim Yevmenkin /* Reserved D0 */ -1, /* Reserved */ 2983adfd74aSMaksim Yevmenkin /* Reserved D1 */ -1, /* Reserved */ 2993adfd74aSMaksim Yevmenkin /* Reserved D2 */ -1, /* Reserved */ 3003adfd74aSMaksim Yevmenkin /* Reserved D3 */ -1, /* Reserved */ 3013adfd74aSMaksim Yevmenkin /* Reserved D4 */ -1, /* Reserved */ 3023adfd74aSMaksim Yevmenkin /* Reserved D5 */ -1, /* Reserved */ 3033adfd74aSMaksim Yevmenkin /* Reserved D6 */ -1, /* Reserved */ 304610e662eSMarkus Brueffer /* Reserved D7 */ -1, /* Reserved */ 3053adfd74aSMaksim Yevmenkin /* Reserved D8 */ -1, /* Reserved */ 3063adfd74aSMaksim Yevmenkin /* Reserved D9 */ -1, /* Reserved */ 3073adfd74aSMaksim Yevmenkin /* Reserved DA */ -1, /* Reserved */ 3083adfd74aSMaksim Yevmenkin /* Reserved DB */ -1, /* Reserved */ 3093adfd74aSMaksim Yevmenkin /* Reserved DC */ -1, /* Reserved */ 3103adfd74aSMaksim Yevmenkin /* Reserved DD */ -1, /* Reserved */ 3113adfd74aSMaksim Yevmenkin /* Reserved DE */ -1, /* Reserved */ 3123adfd74aSMaksim Yevmenkin /* Reserved DF */ -1, /* Reserved */ 3133adfd74aSMaksim Yevmenkin /* Left Control E0 */ 0x1D, /* 9D */ 3143adfd74aSMaksim Yevmenkin /* Left Shift E1 */ 0x2A, /* AA */ 3153adfd74aSMaksim Yevmenkin /* Left Alt E2 */ 0x38, /* B8 */ 3163adfd74aSMaksim Yevmenkin /* Left GUI E3 */ E0PREFIX|0x5B, /* E0 DB */ 3173adfd74aSMaksim Yevmenkin /* Right Control E4 */ E0PREFIX|0x1D, /* E0 9D */ 3183adfd74aSMaksim Yevmenkin /* Right Shift E5 */ 0x36, /* B6 */ 3193adfd74aSMaksim Yevmenkin /* Right Alt E6 */ E0PREFIX|0x38, /* E0 B8 */ 3203adfd74aSMaksim Yevmenkin /* Right GUI E7 */ E0PREFIX|0x5C /* E0 DC */ 3213adfd74aSMaksim Yevmenkin }; 3223adfd74aSMaksim Yevmenkin 323fdbf7cabSElyes Haouas #define xsize (int32_t)nitems(x) 3243adfd74aSMaksim Yevmenkin 3253adfd74aSMaksim Yevmenkin /* 3263adfd74aSMaksim Yevmenkin * Get a max HID keycode (aligned) 3273adfd74aSMaksim Yevmenkin */ 3283adfd74aSMaksim Yevmenkin 3297aebfa93SMaksim Yevmenkin int32_t 3303adfd74aSMaksim Yevmenkin kbd_maxkey(void) 3313adfd74aSMaksim Yevmenkin { 3323adfd74aSMaksim Yevmenkin return (xsize); 3333adfd74aSMaksim Yevmenkin } 3343adfd74aSMaksim Yevmenkin 3353adfd74aSMaksim Yevmenkin /* 3363adfd74aSMaksim Yevmenkin * Process keys 3373adfd74aSMaksim Yevmenkin */ 3383adfd74aSMaksim Yevmenkin 3397aebfa93SMaksim Yevmenkin int32_t 3403adfd74aSMaksim Yevmenkin kbd_process_keys(bthid_session_p s) 3413adfd74aSMaksim Yevmenkin { 342*6bd85498SRyan Libby bitstr_t bit_decl(diff, xsize); 3437aebfa93SMaksim Yevmenkin int32_t f1, f2, i; 3443adfd74aSMaksim Yevmenkin 3453adfd74aSMaksim Yevmenkin assert(s != NULL); 3463adfd74aSMaksim Yevmenkin assert(s->srv != NULL); 3473adfd74aSMaksim Yevmenkin 3487aebfa93SMaksim Yevmenkin /* Check if the new keys have been pressed */ 3497aebfa93SMaksim Yevmenkin bit_ffs(s->keys1, xsize, &f1); 3503adfd74aSMaksim Yevmenkin 3517aebfa93SMaksim Yevmenkin /* Check if old keys still pressed */ 3527aebfa93SMaksim Yevmenkin bit_ffs(s->keys2, xsize, &f2); 3533adfd74aSMaksim Yevmenkin 3543adfd74aSMaksim Yevmenkin if (f1 == -1) { 3557aebfa93SMaksim Yevmenkin /* no new key pressed */ 3567aebfa93SMaksim Yevmenkin if (f2 != -1) { 3577aebfa93SMaksim Yevmenkin /* release old keys */ 3587aebfa93SMaksim Yevmenkin kbd_write(s->keys2, f2, 0, s->vkbd); 35944af5666SVladimir Kondratyev uinput_kbd_write(s->keys2, f2, 0, s->ukbd); 3607aebfa93SMaksim Yevmenkin memset(s->keys2, 0, bitstr_size(xsize)); 3613adfd74aSMaksim Yevmenkin } 3623adfd74aSMaksim Yevmenkin 3633adfd74aSMaksim Yevmenkin return (0); 3643adfd74aSMaksim Yevmenkin } 3653adfd74aSMaksim Yevmenkin 3667aebfa93SMaksim Yevmenkin if (f2 == -1) { 3677aebfa93SMaksim Yevmenkin /* no old keys, but new keys pressed */ 3687aebfa93SMaksim Yevmenkin assert(f1 != -1); 3697aebfa93SMaksim Yevmenkin 3707aebfa93SMaksim Yevmenkin memcpy(s->keys2, s->keys1, bitstr_size(xsize)); 3717aebfa93SMaksim Yevmenkin kbd_write(s->keys1, f1, 1, s->vkbd); 37244af5666SVladimir Kondratyev uinput_kbd_write(s->keys1, f1, 1, s->ukbd); 3737aebfa93SMaksim Yevmenkin memset(s->keys1, 0, bitstr_size(xsize)); 3747aebfa93SMaksim Yevmenkin 3757aebfa93SMaksim Yevmenkin return (0); 3767aebfa93SMaksim Yevmenkin } 3777aebfa93SMaksim Yevmenkin 3787aebfa93SMaksim Yevmenkin /* new keys got pressed, old keys got released */ 3797aebfa93SMaksim Yevmenkin memset(diff, 0, bitstr_size(xsize)); 3807aebfa93SMaksim Yevmenkin 3817aebfa93SMaksim Yevmenkin for (i = f2; i < xsize; i ++) { 3827aebfa93SMaksim Yevmenkin if (bit_test(s->keys2, i)) { 3837aebfa93SMaksim Yevmenkin if (!bit_test(s->keys1, i)) { 3847aebfa93SMaksim Yevmenkin bit_clear(s->keys2, i); 3857aebfa93SMaksim Yevmenkin bit_set(diff, i); 3867aebfa93SMaksim Yevmenkin } 3877aebfa93SMaksim Yevmenkin } 3887aebfa93SMaksim Yevmenkin } 3893adfd74aSMaksim Yevmenkin 3903adfd74aSMaksim Yevmenkin for (i = f1; i < xsize; i++) { 3917aebfa93SMaksim Yevmenkin if (bit_test(s->keys1, i)) { 3927aebfa93SMaksim Yevmenkin if (!bit_test(s->keys2, i)) 3937aebfa93SMaksim Yevmenkin bit_set(s->keys2, i); 3943adfd74aSMaksim Yevmenkin else 3957aebfa93SMaksim Yevmenkin bit_clear(s->keys1, i); 3963adfd74aSMaksim Yevmenkin } 3973adfd74aSMaksim Yevmenkin } 3983adfd74aSMaksim Yevmenkin 3997aebfa93SMaksim Yevmenkin bit_ffs(diff, xsize, &f2); 40044af5666SVladimir Kondratyev if (f2 > 0) { 4017aebfa93SMaksim Yevmenkin kbd_write(diff, f2, 0, s->vkbd); 40244af5666SVladimir Kondratyev uinput_kbd_write(diff, f2, 0, s->ukbd); 40344af5666SVladimir Kondratyev } 4043adfd74aSMaksim Yevmenkin 4057aebfa93SMaksim Yevmenkin bit_ffs(s->keys1, xsize, &f1); 4063adfd74aSMaksim Yevmenkin if (f1 > 0) { 4077aebfa93SMaksim Yevmenkin kbd_write(s->keys1, f1, 1, s->vkbd); 40844af5666SVladimir Kondratyev uinput_kbd_write(s->keys1, f1, 1, s->ukbd); 4097aebfa93SMaksim Yevmenkin memset(s->keys1, 0, bitstr_size(xsize)); 4103adfd74aSMaksim Yevmenkin } 4113adfd74aSMaksim Yevmenkin 4123adfd74aSMaksim Yevmenkin return (0); 4133adfd74aSMaksim Yevmenkin } 4143adfd74aSMaksim Yevmenkin 4153adfd74aSMaksim Yevmenkin /* 4163adfd74aSMaksim Yevmenkin * Translate given keymap and write keyscodes 4173adfd74aSMaksim Yevmenkin */ 41844af5666SVladimir Kondratyev void 41944af5666SVladimir Kondratyev uinput_kbd_write(bitstr_t *m, int32_t fb, int32_t make, int32_t fd) 42044af5666SVladimir Kondratyev { 42144af5666SVladimir Kondratyev int32_t i; 42244af5666SVladimir Kondratyev 42344af5666SVladimir Kondratyev if (fd >= 0) { 42444af5666SVladimir Kondratyev for (i = fb; i < xsize; i++) { 42544af5666SVladimir Kondratyev if (bit_test(m, i)) 42644af5666SVladimir Kondratyev uinput_rep_key(fd, i, make); 42744af5666SVladimir Kondratyev } 42844af5666SVladimir Kondratyev } 42944af5666SVladimir Kondratyev } 43044af5666SVladimir Kondratyev 43144af5666SVladimir Kondratyev /* 43244af5666SVladimir Kondratyev * Translate given keymap and write keyscodes 43344af5666SVladimir Kondratyev */ 4343adfd74aSMaksim Yevmenkin 4353adfd74aSMaksim Yevmenkin static void 4367aebfa93SMaksim Yevmenkin kbd_write(bitstr_t *m, int32_t fb, int32_t make, int32_t fd) 4373adfd74aSMaksim Yevmenkin { 4387aebfa93SMaksim Yevmenkin int32_t i, *b, *eob, n, buf[64]; 4393adfd74aSMaksim Yevmenkin 4403adfd74aSMaksim Yevmenkin b = buf; 441fdbf7cabSElyes Haouas eob = b + nitems(buf); 4423adfd74aSMaksim Yevmenkin i = fb; 4433adfd74aSMaksim Yevmenkin 4443adfd74aSMaksim Yevmenkin while (i < xsize) { 4453adfd74aSMaksim Yevmenkin if (bit_test(m, i)) { 4463adfd74aSMaksim Yevmenkin n = kbd_xlate(i, make, b, eob); 4473adfd74aSMaksim Yevmenkin if (n == -1) { 4483adfd74aSMaksim Yevmenkin write(fd, buf, (b - buf) * sizeof(buf[0])); 4493adfd74aSMaksim Yevmenkin b = buf; 4503adfd74aSMaksim Yevmenkin continue; 4513adfd74aSMaksim Yevmenkin } 4523adfd74aSMaksim Yevmenkin 4533adfd74aSMaksim Yevmenkin b += n; 4543adfd74aSMaksim Yevmenkin } 4553adfd74aSMaksim Yevmenkin 4563adfd74aSMaksim Yevmenkin i ++; 4573adfd74aSMaksim Yevmenkin } 4583adfd74aSMaksim Yevmenkin 4593adfd74aSMaksim Yevmenkin if (b != buf) 4603adfd74aSMaksim Yevmenkin write(fd, buf, (b - buf) * sizeof(buf[0])); 4613adfd74aSMaksim Yevmenkin } 4623adfd74aSMaksim Yevmenkin 4633adfd74aSMaksim Yevmenkin /* 4643adfd74aSMaksim Yevmenkin * Translate HID code into PS/2 code and put codes into buffer b. 4653adfd74aSMaksim Yevmenkin * Returns the number of codes put in b. Return -1 if buffer has not 4663adfd74aSMaksim Yevmenkin * enough space. 4673adfd74aSMaksim Yevmenkin */ 4683adfd74aSMaksim Yevmenkin 4693adfd74aSMaksim Yevmenkin #undef PUT 4703adfd74aSMaksim Yevmenkin #define PUT(c, n, b, eob) \ 4713adfd74aSMaksim Yevmenkin do { \ 4723adfd74aSMaksim Yevmenkin if ((b) >= (eob)) \ 4733adfd74aSMaksim Yevmenkin return (-1); \ 4743adfd74aSMaksim Yevmenkin *(b) = (c); \ 4753adfd74aSMaksim Yevmenkin (b) ++; \ 4763adfd74aSMaksim Yevmenkin (n) ++; \ 4773adfd74aSMaksim Yevmenkin } while (0) 4783adfd74aSMaksim Yevmenkin 4797aebfa93SMaksim Yevmenkin static int32_t 4807aebfa93SMaksim Yevmenkin kbd_xlate(int32_t code, int32_t make, int32_t *b, int32_t const *eob) 4813adfd74aSMaksim Yevmenkin { 4827aebfa93SMaksim Yevmenkin int32_t c, n; 4833adfd74aSMaksim Yevmenkin 4843adfd74aSMaksim Yevmenkin n = 0; 4853adfd74aSMaksim Yevmenkin 4863adfd74aSMaksim Yevmenkin if (code >= xsize) 4873adfd74aSMaksim Yevmenkin return (0); /* HID code is not in the table */ 4883adfd74aSMaksim Yevmenkin 4893adfd74aSMaksim Yevmenkin /* Handle special case - Pause/Break */ 4903adfd74aSMaksim Yevmenkin if (code == 0x48) { 4913adfd74aSMaksim Yevmenkin if (!make) 4923adfd74aSMaksim Yevmenkin return (0); /* No break code */ 4933adfd74aSMaksim Yevmenkin 4943adfd74aSMaksim Yevmenkin #if 0 4953adfd74aSMaksim Yevmenkin XXX FIXME 4963adfd74aSMaksim Yevmenkin if (ctrl_is_pressed) { 4973adfd74aSMaksim Yevmenkin /* Break (Ctrl-Pause) */ 4983adfd74aSMaksim Yevmenkin PUT(0xe0, n, b, eob); 4993adfd74aSMaksim Yevmenkin PUT(0x46, n, b, eob); 5003adfd74aSMaksim Yevmenkin PUT(0xe0, n, b, eob); 5013adfd74aSMaksim Yevmenkin PUT(0xc6, n, b, eob); 5023adfd74aSMaksim Yevmenkin } else { 5033adfd74aSMaksim Yevmenkin /* Pause */ 5043adfd74aSMaksim Yevmenkin PUT(0xe1, n, b, eob); 5053adfd74aSMaksim Yevmenkin PUT(0x1d, n, b, eob); 5063adfd74aSMaksim Yevmenkin PUT(0x45, n, b, eob); 5073adfd74aSMaksim Yevmenkin PUT(0xe1, n, b, eob); 5083adfd74aSMaksim Yevmenkin PUT(0x9d, n, b, eob); 5093adfd74aSMaksim Yevmenkin PUT(0xc5, n, b, eob); 5103adfd74aSMaksim Yevmenkin } 5113adfd74aSMaksim Yevmenkin #endif 5123adfd74aSMaksim Yevmenkin 5133adfd74aSMaksim Yevmenkin return (n); 5143adfd74aSMaksim Yevmenkin } 5153adfd74aSMaksim Yevmenkin 5163adfd74aSMaksim Yevmenkin if ((c = x[code]) == -1) 5173adfd74aSMaksim Yevmenkin return (0); /* HID code translation is not defined */ 5183adfd74aSMaksim Yevmenkin 5193adfd74aSMaksim Yevmenkin if (make) { 5203adfd74aSMaksim Yevmenkin if (c & E0PREFIX) 5213adfd74aSMaksim Yevmenkin PUT(0xe0, n, b, eob); 5223adfd74aSMaksim Yevmenkin 5233adfd74aSMaksim Yevmenkin PUT((c & CODEMASK), n, b, eob); 5243adfd74aSMaksim Yevmenkin } else if (!(c & NOBREAK)) { 5253adfd74aSMaksim Yevmenkin if (c & E0PREFIX) 5263adfd74aSMaksim Yevmenkin PUT(0xe0, n, b, eob); 5273adfd74aSMaksim Yevmenkin 5283adfd74aSMaksim Yevmenkin PUT((0x80|(c & CODEMASK)), n, b, eob); 5293adfd74aSMaksim Yevmenkin } 5303adfd74aSMaksim Yevmenkin 5313adfd74aSMaksim Yevmenkin return (n); 5323adfd74aSMaksim Yevmenkin } 5333adfd74aSMaksim Yevmenkin 5347aebfa93SMaksim Yevmenkin /* 5357aebfa93SMaksim Yevmenkin * Process status change from vkbd(4) 5367aebfa93SMaksim Yevmenkin */ 5377aebfa93SMaksim Yevmenkin 5387aebfa93SMaksim Yevmenkin int32_t 5397aebfa93SMaksim Yevmenkin kbd_status_changed(bthid_session_p s, uint8_t *data, int32_t len) 5407aebfa93SMaksim Yevmenkin { 5412d7f9912SMaksim Yevmenkin vkbd_status_t st; 54252a4455bSMaksim Yevmenkin uint8_t found, report_id; 5437aebfa93SMaksim Yevmenkin hid_device_p hid_device; 5447aebfa93SMaksim Yevmenkin hid_data_t d; 5457aebfa93SMaksim Yevmenkin hid_item_t h; 54644af5666SVladimir Kondratyev uint8_t leds_mask = 0; 5477aebfa93SMaksim Yevmenkin 5487aebfa93SMaksim Yevmenkin assert(s != NULL); 5497aebfa93SMaksim Yevmenkin assert(len == sizeof(vkbd_status_t)); 5507aebfa93SMaksim Yevmenkin 5512d7f9912SMaksim Yevmenkin memcpy(&st, data, sizeof(st)); 55252a4455bSMaksim Yevmenkin found = 0; 5537aebfa93SMaksim Yevmenkin report_id = NO_REPORT_ID; 5547aebfa93SMaksim Yevmenkin 5557aebfa93SMaksim Yevmenkin hid_device = get_hid_device(&s->bdaddr); 5567aebfa93SMaksim Yevmenkin assert(hid_device != NULL); 5577aebfa93SMaksim Yevmenkin 55852a4455bSMaksim Yevmenkin data[0] = 0xa2; /* DATA output (HID output report) */ 55952a4455bSMaksim Yevmenkin data[1] = 0x00; 56052a4455bSMaksim Yevmenkin data[2] = 0x00; 56152a4455bSMaksim Yevmenkin 5627aebfa93SMaksim Yevmenkin for (d = hid_start_parse(hid_device->desc, 1 << hid_output, -1); 5637aebfa93SMaksim Yevmenkin hid_get_item(d, &h) > 0; ) { 5647aebfa93SMaksim Yevmenkin if (HID_PAGE(h.usage) == HUP_LEDS) { 56552a4455bSMaksim Yevmenkin found++; 56652a4455bSMaksim Yevmenkin 5677aebfa93SMaksim Yevmenkin if (report_id == NO_REPORT_ID) 5687aebfa93SMaksim Yevmenkin report_id = h.report_ID; 5697aebfa93SMaksim Yevmenkin else if (h.report_ID != report_id) 5707aebfa93SMaksim Yevmenkin syslog(LOG_WARNING, "Output HID report IDs " \ 5717aebfa93SMaksim Yevmenkin "for %s do not match: %d vs. %d. " \ 5727aebfa93SMaksim Yevmenkin "Please report", 5737aebfa93SMaksim Yevmenkin bt_ntoa(&s->bdaddr, NULL), 5747aebfa93SMaksim Yevmenkin h.report_ID, report_id); 5757aebfa93SMaksim Yevmenkin 5767aebfa93SMaksim Yevmenkin switch(HID_USAGE(h.usage)) { 5777aebfa93SMaksim Yevmenkin case 0x01: /* Num Lock LED */ 5782d7f9912SMaksim Yevmenkin if (st.leds & LED_NUM) 57952a4455bSMaksim Yevmenkin hid_set_data(&data[1], &h, 1); 58044af5666SVladimir Kondratyev leds_mask |= LED_NUM; 5817aebfa93SMaksim Yevmenkin break; 5827aebfa93SMaksim Yevmenkin 5837aebfa93SMaksim Yevmenkin case 0x02: /* Caps Lock LED */ 5842d7f9912SMaksim Yevmenkin if (st.leds & LED_CAP) 58552a4455bSMaksim Yevmenkin hid_set_data(&data[1], &h, 1); 58644af5666SVladimir Kondratyev leds_mask |= LED_CAP; 5877aebfa93SMaksim Yevmenkin break; 5887aebfa93SMaksim Yevmenkin 5897aebfa93SMaksim Yevmenkin case 0x03: /* Scroll Lock LED */ 5902d7f9912SMaksim Yevmenkin if (st.leds & LED_SCR) 59152a4455bSMaksim Yevmenkin hid_set_data(&data[1], &h, 1); 59244af5666SVladimir Kondratyev leds_mask |= LED_SCR; 5937aebfa93SMaksim Yevmenkin break; 5947aebfa93SMaksim Yevmenkin 5957aebfa93SMaksim Yevmenkin /* XXX add other LEDs ? */ 5967aebfa93SMaksim Yevmenkin } 5977aebfa93SMaksim Yevmenkin } 5987aebfa93SMaksim Yevmenkin } 5997aebfa93SMaksim Yevmenkin hid_end_parse(d); 6007aebfa93SMaksim Yevmenkin 60112df5213SVladimir Kondratyev if (report_id != NO_REPORT_ID) { 60212df5213SVladimir Kondratyev data[2] = data[1]; 60312df5213SVladimir Kondratyev data[1] = report_id; 60412df5213SVladimir Kondratyev } 60512df5213SVladimir Kondratyev 60652a4455bSMaksim Yevmenkin if (found) 60752a4455bSMaksim Yevmenkin write(s->intr, data, (report_id != NO_REPORT_ID) ? 3 : 2); 6087aebfa93SMaksim Yevmenkin 60944af5666SVladimir Kondratyev if (found && s->srv->uinput && hid_device->keyboard) 61044af5666SVladimir Kondratyev uinput_rep_leds(s->ukbd, st.leds, leds_mask); 61144af5666SVladimir Kondratyev 6127aebfa93SMaksim Yevmenkin return (0); 6137aebfa93SMaksim Yevmenkin } 6147aebfa93SMaksim Yevmenkin 615