Deleted Added
full compact
hid.c (156965) hid.c (162128)
1/*
2 * hid.c
1/*
2 * hid.c
3 *
4 * Copyright (c) 2004 Maksim Yevmenkin <m_evmenkin@yahoo.com>
3 */
4
5/*-
6 * Copyright (c) 2006 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

--- 7 unchanged lines hidden (view full) ---

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 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright

--- 7 unchanged lines hidden (view full) ---

22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
29 *
28 * $Id: hid.c,v 1.4 2004/11/17 21:59:42 max Exp $
29 * $FreeBSD: head/usr.sbin/bluetooth/bthidd/hid.c 156965 2006-03-21 18:42:52Z emax $
30 * $Id: hid.c,v 1.5 2006/09/07 21:06:53 max Exp $
31 * $FreeBSD: head/usr.sbin/bluetooth/bthidd/hid.c 162128 2006-09-07 21:47:49Z emax $
30 */
31
32#include <sys/consio.h>
33#include <sys/mouse.h>
34#include <sys/queue.h>
35#include <assert.h>
36#include <bluetooth.h>
32 */
33
34#include <sys/consio.h>
35#include <sys/mouse.h>
36#include <sys/queue.h>
37#include <assert.h>
38#include <bluetooth.h>
37#include <errno.h>
38#include <dev/usb/usb.h>
39#include <dev/usb/usbhid.h>
39#include <dev/usb/usb.h>
40#include <dev/usb/usbhid.h>
41#include <errno.h>
40#include <stdio.h>
41#include <string.h>
42#include <syslog.h>
43#include <unistd.h>
44#include <usbhid.h>
42#include <stdio.h>
43#include <string.h>
44#include <syslog.h>
45#include <unistd.h>
46#include <usbhid.h>
45#include "bthidd.h"
46#include "bthid_config.h"
47#include "bthid_config.h"
48#include "bthidd.h"
47#include "kbd.h"
48
49#undef min
50#define min(x, y) (((x) < (y))? (x) : (y))
51
52#undef ASIZE
53#define ASIZE(a) (sizeof(a)/sizeof(a[0]))
54
49#include "kbd.h"
50
51#undef min
52#define min(x, y) (((x) < (y))? (x) : (y))
53
54#undef ASIZE
55#define ASIZE(a) (sizeof(a)/sizeof(a[0]))
56
55#undef HID_BUT
56#define HID_BUT(i) ((i) < 3 ? (((i) ^ 3) % 3) : (i))
57
58/*
59 * Process data from control channel
60 */
61
57/*
58 * Process data from control channel
59 */
60
62int
63hid_control(bthid_session_p s, char *data, int len)
61int32_t
62hid_control(bthid_session_p s, uint8_t *data, int32_t len)
64{
65 assert(s != NULL);
66 assert(data != NULL);
67 assert(len > 0);
68
69 switch (data[0] >> 4) {
70 case 0: /* Handshake (response to command) */
71 if (data[0] & 0xf)

--- 46 unchanged lines hidden (view full) ---

118
119 return (0);
120}
121
122/*
123 * Process data from the interrupt channel
124 */
125
63{
64 assert(s != NULL);
65 assert(data != NULL);
66 assert(len > 0);
67
68 switch (data[0] >> 4) {
69 case 0: /* Handshake (response to command) */
70 if (data[0] & 0xf)

--- 46 unchanged lines hidden (view full) ---

117
118 return (0);
119}
120
121/*
122 * Process data from the interrupt channel
123 */
124
126int
127hid_interrupt(bthid_session_p s, char *data, int len)
125int32_t
126hid_interrupt(bthid_session_p s, uint8_t *data, int32_t len)
128{
127{
129 hid_device_p hid_device = NULL;
128 hid_device_p hid_device;
130 hid_data_t d;
131 hid_item_t h;
129 hid_data_t d;
130 hid_item_t h;
132 int report_id, usage, page, val,
131 int32_t report_id, usage, page, val,
133 mouse_x, mouse_y, mouse_z, mouse_butt,
134 mevents, kevents;
135
136 assert(s != NULL);
137 assert(s->srv != NULL);
138 assert(data != NULL);
139
140 if (len < 3) {
141 syslog(LOG_ERR, "Got short message (%d bytes) on Interrupt " \
142 "channel from %s", len, bt_ntoa(&s->bdaddr, NULL));
143 return (-1);
144 }
145
132 mouse_x, mouse_y, mouse_z, mouse_butt,
133 mevents, kevents;
134
135 assert(s != NULL);
136 assert(s->srv != NULL);
137 assert(data != NULL);
138
139 if (len < 3) {
140 syslog(LOG_ERR, "Got short message (%d bytes) on Interrupt " \
141 "channel from %s", len, bt_ntoa(&s->bdaddr, NULL));
142 return (-1);
143 }
144
146 if ((unsigned char) data[0] != 0xa1) {
145 if (data[0] != 0xa1) {
147 syslog(LOG_ERR, "Got unexpected message 0x%x on " \
148 "Interrupt channel from %s",
149 data[0], bt_ntoa(&s->bdaddr, NULL));
150 return (-1);
151 }
152
153 report_id = data[1];
154 data += 2;

--- 38 unchanged lines hidden (view full) ---

193 }
194 break;
195
196 case HUP_KEYBOARD:
197 kevents ++;
198
199 if (h.flags & HIO_VARIABLE) {
200 if (val && usage < kbd_maxkey())
146 syslog(LOG_ERR, "Got unexpected message 0x%x on " \
147 "Interrupt channel from %s",
148 data[0], bt_ntoa(&s->bdaddr, NULL));
149 return (-1);
150 }
151
152 report_id = data[1];
153 data += 2;

--- 38 unchanged lines hidden (view full) ---

192 }
193 break;
194
195 case HUP_KEYBOARD:
196 kevents ++;
197
198 if (h.flags & HIO_VARIABLE) {
199 if (val && usage < kbd_maxkey())
201 bit_set(s->srv->keys, usage);
200 bit_set(s->keys1, usage);
202 } else {
203 if (val && val < kbd_maxkey())
201 } else {
202 if (val && val < kbd_maxkey())
204 bit_set(s->srv->keys, val);
203 bit_set(s->keys1, val);
205
206 data ++;
207 len --;
208
209 len = min(len, h.report_size);
210 while (len > 0) {
211 val = hid_get_data(data, &h);
212 if (val && val < kbd_maxkey())
204
205 data ++;
206 len --;
207
208 len = min(len, h.report_size);
209 while (len > 0) {
210 val = hid_get_data(data, &h);
211 if (val && val < kbd_maxkey())
213 bit_set(s->srv->keys, val);
212 bit_set(s->keys1, val);
214
215 data ++;
216 len --;
217 }
218 }
219 break;
220
221 case HUP_BUTTON:
213
214 data ++;
215 len --;
216 }
217 }
218 break;
219
220 case HUP_BUTTON:
222 mouse_butt |= (val << HID_BUT(usage - 1));
223 mevents ++;
221 if (usage != 0) {
222 if (usage == 2)
223 usage = 3;
224 else if (usage == 3)
225 usage = 2;
226
227 mouse_butt |= (val << (usage - 1));
228 mevents ++;
229 }
224 break;
225
226 case HUP_CONSUMER:
227 if (!val)
228 break;
229
230 switch (usage) {
231 case 0xb5: /* Scan Next Track */

--- 55 unchanged lines hidden (view full) ---

287 case 0x225: /* WWW Forward */
288 val = 0x69;
289 break;
290
291 case 0x226: /* WWW Stop */
292 val = 0x68;
293 break;
294
230 break;
231
232 case HUP_CONSUMER:
233 if (!val)
234 break;
235
236 switch (usage) {
237 case 0xb5: /* Scan Next Track */

--- 55 unchanged lines hidden (view full) ---

293 case 0x225: /* WWW Forward */
294 val = 0x69;
295 break;
296
297 case 0x226: /* WWW Stop */
298 val = 0x68;
299 break;
300
295 case 0x227: /* WWW Refresh */
301 case 0227: /* WWW Refresh */
296 val = 0x67;
297 break;
298
299 case 0x22a: /* WWW Favorites */
300 val = 0x66;
301 break;
302
303 default:
304 val = 0;
305 break;
306 }
307
308 /* XXX FIXME - UGLY HACK */
309 if (val != 0) {
302 val = 0x67;
303 break;
304
305 case 0x22a: /* WWW Favorites */
306 val = 0x66;
307 break;
308
309 default:
310 val = 0;
311 break;
312 }
313
314 /* XXX FIXME - UGLY HACK */
315 if (val != 0) {
310 int buf[4] = { 0xe0, val, 0xe0, val|0x80 };
316 if (hid_device->keyboard) {
317 int32_t buf[4] = { 0xe0, val,
318 0xe0, val|0x80 };
311
319
312 write(s->srv->vkbd, buf, sizeof(buf));
320 assert(s->vkbd != -1);
321 write(s->vkbd, buf, sizeof(buf));
322 } else
323 syslog(LOG_ERR, "Keyboard events " \
324 "received from non-keyboard " \
325 "device %s. Please report",
326 bt_ntoa(&s->bdaddr, NULL));
313 }
314 break;
315
316 case HUP_MICROSOFT:
317 switch (usage) {
318 case 0xfe01:
319 if (!hid_device->battery_power)
320 break;

--- 17 unchanged lines hidden (view full) ---

338 }
339 break;
340 }
341 break;
342 }
343 }
344 hid_end_parse(d);
345
327 }
328 break;
329
330 case HUP_MICROSOFT:
331 switch (usage) {
332 case 0xfe01:
333 if (!hid_device->battery_power)
334 break;

--- 17 unchanged lines hidden (view full) ---

352 }
353 break;
354 }
355 break;
356 }
357 }
358 hid_end_parse(d);
359
346 /* Feed keyboard events into kernel */
347 if (kevents > 0)
348 kbd_process_keys(s);
360 /*
361 * XXX FIXME Feed keyboard events into kernel.
362 * The code below works, bit host also needs to track
363 * and handle repeat.
364 *
365 * Key repeat currently works in X, but not in console.
366 */
349
367
368 if (kevents > 0) {
369 if (hid_device->keyboard) {
370 assert(s->vkbd != -1);
371 kbd_process_keys(s);
372 } else
373 syslog(LOG_ERR, "Keyboard events received from " \
374 "non-keyboard device %s. Please report",
375 bt_ntoa(&s->bdaddr, NULL));
376 }
377
350 /*
351 * XXX FIXME Feed mouse events into kernel.
352 * The code block below works, but it is not good enough.
353 * Need to track double-clicks etc.
378 /*
379 * XXX FIXME Feed mouse events into kernel.
380 * The code block below works, but it is not good enough.
381 * Need to track double-clicks etc.
382 *
383 * Double click currently works in X, but not in console.
354 */
355
356 if (mevents > 0) {
357 struct mouse_info mi;
358
359 mi.operation = MOUSE_ACTION;
360 mi.u.data.x = mouse_x;
361 mi.u.data.y = mouse_y;
362 mi.u.data.z = mouse_z;
363 mi.u.data.buttons = mouse_butt;
364
365 if (ioctl(s->srv->cons, CONS_MOUSECTL, &mi) < 0)
366 syslog(LOG_ERR, "Could not process mouse events from " \
367 "%s. %s (%d)", bt_ntoa(&s->bdaddr, NULL),
368 strerror(errno), errno);
369 }
370
371 return (0);
372}
384 */
385
386 if (mevents > 0) {
387 struct mouse_info mi;
388
389 mi.operation = MOUSE_ACTION;
390 mi.u.data.x = mouse_x;
391 mi.u.data.y = mouse_y;
392 mi.u.data.z = mouse_z;
393 mi.u.data.buttons = mouse_butt;
394
395 if (ioctl(s->srv->cons, CONS_MOUSECTL, &mi) < 0)
396 syslog(LOG_ERR, "Could not process mouse events from " \
397 "%s. %s (%d)", bt_ntoa(&s->bdaddr, NULL),
398 strerror(errno), errno);
399 }
400
401 return (0);
402}
373