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