OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [net/] [bluetooth/] [hidp/] [core.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
   HIDP implementation for Linux Bluetooth stack (BlueZ).
3
   Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
4
 
5
   This program is free software; you can redistribute it and/or modify
6
   it under the terms of the GNU General Public License version 2 as
7
   published by the Free Software Foundation;
8
 
9
   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12
   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13
   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14
   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15
   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16
   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
 
18
   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19
   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20
   SOFTWARE IS DISCLAIMED.
21
*/
22
 
23
#include <linux/module.h>
24
 
25
#include <linux/types.h>
26
#include <linux/errno.h>
27
#include <linux/kernel.h>
28
#include <linux/sched.h>
29
#include <linux/slab.h>
30
#include <linux/poll.h>
31
#include <linux/freezer.h>
32
#include <linux/fcntl.h>
33
#include <linux/skbuff.h>
34
#include <linux/socket.h>
35
#include <linux/ioctl.h>
36
#include <linux/file.h>
37
#include <linux/init.h>
38
#include <linux/wait.h>
39
#include <net/sock.h>
40
 
41
#include <linux/input.h>
42
#include <linux/hid.h>
43
 
44
#include <net/bluetooth/bluetooth.h>
45
#include <net/bluetooth/hci_core.h>
46
#include <net/bluetooth/l2cap.h>
47
 
48
#include "hidp.h"
49
 
50
#ifndef CONFIG_BT_HIDP_DEBUG
51
#undef  BT_DBG
52
#define BT_DBG(D...)
53
#endif
54
 
55
#define VERSION "1.2"
56
 
57
static DECLARE_RWSEM(hidp_session_sem);
58
static LIST_HEAD(hidp_session_list);
59
 
60
static unsigned char hidp_keycode[256] = {
61
          0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
62
         50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
63
          4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
64
         27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
65
         65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
66
        105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
67
         72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
68
        191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
69
        115,114,  0,  0,  0,121,  0, 89, 93,124, 92, 94, 95,  0,  0,  0,
70
        122,123, 90, 91, 85,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
71
          0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
72
          0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
73
          0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
74
          0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
75
         29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
76
        150,158,159,128,136,177,178,176,142,152,173,140
77
};
78
 
79
static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
80
 
81
static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
82
{
83
        struct hidp_session *session;
84
        struct list_head *p;
85
 
86
        BT_DBG("");
87
 
88
        list_for_each(p, &hidp_session_list) {
89
                session = list_entry(p, struct hidp_session, list);
90
                if (!bacmp(bdaddr, &session->bdaddr))
91
                        return session;
92
        }
93
        return NULL;
94
}
95
 
96
static void __hidp_link_session(struct hidp_session *session)
97
{
98
        __module_get(THIS_MODULE);
99
        list_add(&session->list, &hidp_session_list);
100
}
101
 
102
static void __hidp_unlink_session(struct hidp_session *session)
103
{
104
        list_del(&session->list);
105
        module_put(THIS_MODULE);
106
}
107
 
108
static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
109
{
110
        bacpy(&ci->bdaddr, &session->bdaddr);
111
 
112
        ci->flags = session->flags;
113
        ci->state = session->state;
114
 
115
        ci->vendor  = 0x0000;
116
        ci->product = 0x0000;
117
        ci->version = 0x0000;
118
        memset(ci->name, 0, 128);
119
 
120
        if (session->input) {
121
                ci->vendor  = session->input->id.vendor;
122
                ci->product = session->input->id.product;
123
                ci->version = session->input->id.version;
124
                if (session->input->name)
125
                        strncpy(ci->name, session->input->name, 128);
126
                else
127
                        strncpy(ci->name, "HID Boot Device", 128);
128
        }
129
 
130
        if (session->hid) {
131
                ci->vendor  = session->hid->vendor;
132
                ci->product = session->hid->product;
133
                ci->version = session->hid->version;
134
                strncpy(ci->name, session->hid->name, 128);
135
        }
136
}
137
 
138
static inline int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
139
                                        unsigned int type, unsigned int code, int value)
140
{
141
        unsigned char newleds;
142
        struct sk_buff *skb;
143
 
144
        BT_DBG("session %p type %d code %d value %d", session, type, code, value);
145
 
146
        if (type != EV_LED)
147
                return -1;
148
 
149
        newleds = (!!test_bit(LED_KANA,    dev->led) << 3) |
150
                  (!!test_bit(LED_COMPOSE, dev->led) << 3) |
151
                  (!!test_bit(LED_SCROLLL, dev->led) << 2) |
152
                  (!!test_bit(LED_CAPSL,   dev->led) << 1) |
153
                  (!!test_bit(LED_NUML,    dev->led));
154
 
155
        if (session->leds == newleds)
156
                return 0;
157
 
158
        session->leds = newleds;
159
 
160
        if (!(skb = alloc_skb(3, GFP_ATOMIC))) {
161
                BT_ERR("Can't allocate memory for new frame");
162
                return -ENOMEM;
163
        }
164
 
165
        *skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
166
        *skb_put(skb, 1) = 0x01;
167
        *skb_put(skb, 1) = newleds;
168
 
169
        skb_queue_tail(&session->intr_transmit, skb);
170
 
171
        hidp_schedule(session);
172
 
173
        return 0;
174
}
175
 
176
static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
177
{
178
        struct hid_device *hid = input_get_drvdata(dev);
179
        struct hidp_session *session = hid->driver_data;
180
 
181
        return hidp_queue_event(session, dev, type, code, value);
182
}
183
 
184
static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
185
{
186
        struct hidp_session *session = input_get_drvdata(dev);
187
 
188
        return hidp_queue_event(session, dev, type, code, value);
189
}
190
 
191
static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
192
{
193
        struct input_dev *dev = session->input;
194
        unsigned char *keys = session->keys;
195
        unsigned char *udata = skb->data + 1;
196
        signed char *sdata = skb->data + 1;
197
        int i, size = skb->len - 1;
198
 
199
        switch (skb->data[0]) {
200
        case 0x01:      /* Keyboard report */
201
                for (i = 0; i < 8; i++)
202
                        input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
203
 
204
                /* If all the key codes have been set to 0x01, it means
205
                 * too many keys were pressed at the same time. */
206
                if (!memcmp(udata + 2, hidp_mkeyspat, 6))
207
                        break;
208
 
209
                for (i = 2; i < 8; i++) {
210
                        if (keys[i] > 3 && memscan(udata + 2, keys[i], 6) == udata + 8) {
211
                                if (hidp_keycode[keys[i]])
212
                                        input_report_key(dev, hidp_keycode[keys[i]], 0);
213
                                else
214
                                        BT_ERR("Unknown key (scancode %#x) released.", keys[i]);
215
                        }
216
 
217
                        if (udata[i] > 3 && memscan(keys + 2, udata[i], 6) == keys + 8) {
218
                                if (hidp_keycode[udata[i]])
219
                                        input_report_key(dev, hidp_keycode[udata[i]], 1);
220
                                else
221
                                        BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]);
222
                        }
223
                }
224
 
225
                memcpy(keys, udata, 8);
226
                break;
227
 
228
        case 0x02:      /* Mouse report */
229
                input_report_key(dev, BTN_LEFT,   sdata[0] & 0x01);
230
                input_report_key(dev, BTN_RIGHT,  sdata[0] & 0x02);
231
                input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
232
                input_report_key(dev, BTN_SIDE,   sdata[0] & 0x08);
233
                input_report_key(dev, BTN_EXTRA,  sdata[0] & 0x10);
234
 
235
                input_report_rel(dev, REL_X, sdata[1]);
236
                input_report_rel(dev, REL_Y, sdata[2]);
237
 
238
                if (size > 3)
239
                        input_report_rel(dev, REL_WHEEL, sdata[3]);
240
                break;
241
        }
242
 
243
        input_sync(dev);
244
}
245
 
246
static inline int hidp_queue_report(struct hidp_session *session, unsigned char *data, int size)
247
{
248
        struct sk_buff *skb;
249
 
250
        BT_DBG("session %p hid %p data %p size %d", session, session->hid, data, size);
251
 
252
        if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
253
                BT_ERR("Can't allocate memory for new frame");
254
                return -ENOMEM;
255
        }
256
 
257
        *skb_put(skb, 1) = 0xa2;
258
        if (size > 0)
259
                memcpy(skb_put(skb, size), data, size);
260
 
261
        skb_queue_tail(&session->intr_transmit, skb);
262
 
263
        hidp_schedule(session);
264
 
265
        return 0;
266
}
267
 
268
static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
269
{
270
        unsigned char buf[32];
271
        int rsize;
272
 
273
        rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
274
        if (rsize > sizeof(buf))
275
                return -EIO;
276
 
277
        hid_output_report(report, buf);
278
 
279
        return hidp_queue_report(session, buf, rsize);
280
}
281
 
282
static void hidp_idle_timeout(unsigned long arg)
283
{
284
        struct hidp_session *session = (struct hidp_session *) arg;
285
 
286
        atomic_inc(&session->terminate);
287
        hidp_schedule(session);
288
}
289
 
290
static inline void hidp_set_timer(struct hidp_session *session)
291
{
292
        if (session->idle_to > 0)
293
                mod_timer(&session->timer, jiffies + HZ * session->idle_to);
294
}
295
 
296
static inline void hidp_del_timer(struct hidp_session *session)
297
{
298
        if (session->idle_to > 0)
299
                del_timer(&session->timer);
300
}
301
 
302
static int __hidp_send_ctrl_message(struct hidp_session *session,
303
                        unsigned char hdr, unsigned char *data, int size)
304
{
305
        struct sk_buff *skb;
306
 
307
        BT_DBG("session %p data %p size %d", session, data, size);
308
 
309
        if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
310
                BT_ERR("Can't allocate memory for new frame");
311
                return -ENOMEM;
312
        }
313
 
314
        *skb_put(skb, 1) = hdr;
315
        if (data && size > 0)
316
                memcpy(skb_put(skb, size), data, size);
317
 
318
        skb_queue_tail(&session->ctrl_transmit, skb);
319
 
320
        return 0;
321
}
322
 
323
static inline int hidp_send_ctrl_message(struct hidp_session *session,
324
                        unsigned char hdr, unsigned char *data, int size)
325
{
326
        int err;
327
 
328
        err = __hidp_send_ctrl_message(session, hdr, data, size);
329
 
330
        hidp_schedule(session);
331
 
332
        return err;
333
}
334
 
335
static inline void hidp_process_handshake(struct hidp_session *session, unsigned char param)
336
{
337
        BT_DBG("session %p param 0x%02x", session, param);
338
 
339
        switch (param) {
340
        case HIDP_HSHK_SUCCESSFUL:
341
                /* FIXME: Call into SET_ GET_ handlers here */
342
                break;
343
 
344
        case HIDP_HSHK_NOT_READY:
345
        case HIDP_HSHK_ERR_INVALID_REPORT_ID:
346
        case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
347
        case HIDP_HSHK_ERR_INVALID_PARAMETER:
348
                /* FIXME: Call into SET_ GET_ handlers here */
349
                break;
350
 
351
        case HIDP_HSHK_ERR_UNKNOWN:
352
                break;
353
 
354
        case HIDP_HSHK_ERR_FATAL:
355
                /* Device requests a reboot, as this is the only way this error
356
                 * can be recovered. */
357
                __hidp_send_ctrl_message(session,
358
                        HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
359
                break;
360
 
361
        default:
362
                __hidp_send_ctrl_message(session,
363
                        HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
364
                break;
365
        }
366
}
367
 
368
static inline void hidp_process_hid_control(struct hidp_session *session, unsigned char param)
369
{
370
        BT_DBG("session %p param 0x%02x", session, param);
371
 
372
        switch (param) {
373
        case HIDP_CTRL_NOP:
374
                break;
375
 
376
        case HIDP_CTRL_VIRTUAL_CABLE_UNPLUG:
377
                /* Flush the transmit queues */
378
                skb_queue_purge(&session->ctrl_transmit);
379
                skb_queue_purge(&session->intr_transmit);
380
 
381
                /* Kill session thread */
382
                atomic_inc(&session->terminate);
383
                break;
384
 
385
        case HIDP_CTRL_HARD_RESET:
386
        case HIDP_CTRL_SOFT_RESET:
387
        case HIDP_CTRL_SUSPEND:
388
        case HIDP_CTRL_EXIT_SUSPEND:
389
                /* FIXME: We have to parse these and return no error */
390
                break;
391
 
392
        default:
393
                __hidp_send_ctrl_message(session,
394
                        HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
395
                break;
396
        }
397
}
398
 
399
static inline void hidp_process_data(struct hidp_session *session, struct sk_buff *skb, unsigned char param)
400
{
401
        BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
402
 
403
        switch (param) {
404
        case HIDP_DATA_RTYPE_INPUT:
405
                hidp_set_timer(session);
406
 
407
                if (session->input)
408
                        hidp_input_report(session, skb);
409
 
410
                if (session->hid)
411
                        hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
412
 
413
                break;
414
 
415
        case HIDP_DATA_RTYPE_OTHER:
416
        case HIDP_DATA_RTYPE_OUPUT:
417
        case HIDP_DATA_RTYPE_FEATURE:
418
                break;
419
 
420
        default:
421
                __hidp_send_ctrl_message(session,
422
                        HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
423
        }
424
}
425
 
426
static inline void hidp_recv_ctrl_frame(struct hidp_session *session, struct sk_buff *skb)
427
{
428
        unsigned char hdr, type, param;
429
 
430
        BT_DBG("session %p skb %p len %d", session, skb, skb->len);
431
 
432
        hdr = skb->data[0];
433
        skb_pull(skb, 1);
434
 
435
        type = hdr & HIDP_HEADER_TRANS_MASK;
436
        param = hdr & HIDP_HEADER_PARAM_MASK;
437
 
438
        switch (type) {
439
        case HIDP_TRANS_HANDSHAKE:
440
                hidp_process_handshake(session, param);
441
                break;
442
 
443
        case HIDP_TRANS_HID_CONTROL:
444
                hidp_process_hid_control(session, param);
445
                break;
446
 
447
        case HIDP_TRANS_DATA:
448
                hidp_process_data(session, skb, param);
449
                break;
450
 
451
        default:
452
                __hidp_send_ctrl_message(session,
453
                        HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
454
                break;
455
        }
456
 
457
        kfree_skb(skb);
458
}
459
 
460
static inline void hidp_recv_intr_frame(struct hidp_session *session, struct sk_buff *skb)
461
{
462
        unsigned char hdr;
463
 
464
        BT_DBG("session %p skb %p len %d", session, skb, skb->len);
465
 
466
        hdr = skb->data[0];
467
        skb_pull(skb, 1);
468
 
469
        if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
470
                hidp_set_timer(session);
471
 
472
                if (session->input)
473
                        hidp_input_report(session, skb);
474
 
475
                if (session->hid) {
476
                        hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
477
                        BT_DBG("report len %d", skb->len);
478
                }
479
        } else {
480
                BT_DBG("Unsupported protocol header 0x%02x", hdr);
481
        }
482
 
483
        kfree_skb(skb);
484
}
485
 
486
static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
487
{
488
        struct kvec iv = { data, len };
489
        struct msghdr msg;
490
 
491
        BT_DBG("sock %p data %p len %d", sock, data, len);
492
 
493
        if (!len)
494
                return 0;
495
 
496
        memset(&msg, 0, sizeof(msg));
497
 
498
        return kernel_sendmsg(sock, &msg, &iv, 1, len);
499
}
500
 
501
static void hidp_process_transmit(struct hidp_session *session)
502
{
503
        struct sk_buff *skb;
504
 
505
        BT_DBG("session %p", session);
506
 
507
        while ((skb = skb_dequeue(&session->ctrl_transmit))) {
508
                if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
509
                        skb_queue_head(&session->ctrl_transmit, skb);
510
                        break;
511
                }
512
 
513
                hidp_set_timer(session);
514
                kfree_skb(skb);
515
        }
516
 
517
        while ((skb = skb_dequeue(&session->intr_transmit))) {
518
                if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
519
                        skb_queue_head(&session->intr_transmit, skb);
520
                        break;
521
                }
522
 
523
                hidp_set_timer(session);
524
                kfree_skb(skb);
525
        }
526
}
527
 
528
static int hidp_session(void *arg)
529
{
530
        struct hidp_session *session = arg;
531
        struct sock *ctrl_sk = session->ctrl_sock->sk;
532
        struct sock *intr_sk = session->intr_sock->sk;
533
        struct sk_buff *skb;
534
        int vendor = 0x0000, product = 0x0000;
535
        wait_queue_t ctrl_wait, intr_wait;
536
 
537
        BT_DBG("session %p", session);
538
 
539
        if (session->input) {
540
                vendor  = session->input->id.vendor;
541
                product = session->input->id.product;
542
        }
543
 
544
        if (session->hid) {
545
                vendor  = session->hid->vendor;
546
                product = session->hid->product;
547
        }
548
 
549
        daemonize("khidpd_%04x%04x", vendor, product);
550
        set_user_nice(current, -15);
551
 
552
        init_waitqueue_entry(&ctrl_wait, current);
553
        init_waitqueue_entry(&intr_wait, current);
554
        add_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait);
555
        add_wait_queue(intr_sk->sk_sleep, &intr_wait);
556
        while (!atomic_read(&session->terminate)) {
557
                set_current_state(TASK_INTERRUPTIBLE);
558
 
559
                if (ctrl_sk->sk_state != BT_CONNECTED || intr_sk->sk_state != BT_CONNECTED)
560
                        break;
561
 
562
                while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
563
                        skb_orphan(skb);
564
                        hidp_recv_ctrl_frame(session, skb);
565
                }
566
 
567
                while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
568
                        skb_orphan(skb);
569
                        hidp_recv_intr_frame(session, skb);
570
                }
571
 
572
                hidp_process_transmit(session);
573
 
574
                schedule();
575
        }
576
        set_current_state(TASK_RUNNING);
577
        remove_wait_queue(intr_sk->sk_sleep, &intr_wait);
578
        remove_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait);
579
 
580
        down_write(&hidp_session_sem);
581
 
582
        hidp_del_timer(session);
583
 
584
        if (session->input) {
585
                input_unregister_device(session->input);
586
                session->input = NULL;
587
        }
588
 
589
        if (session->hid) {
590
                if (session->hid->claimed & HID_CLAIMED_INPUT)
591
                        hidinput_disconnect(session->hid);
592
                hid_free_device(session->hid);
593
        }
594
 
595
        fput(session->intr_sock->file);
596
 
597
        wait_event_timeout(*(ctrl_sk->sk_sleep),
598
                (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
599
 
600
        fput(session->ctrl_sock->file);
601
 
602
        __hidp_unlink_session(session);
603
 
604
        up_write(&hidp_session_sem);
605
 
606
        kfree(session);
607
        return 0;
608
}
609
 
610
static struct device *hidp_get_device(struct hidp_session *session)
611
{
612
        bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
613
        bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
614
        struct hci_dev *hdev;
615
        struct hci_conn *conn;
616
 
617
        hdev = hci_get_route(dst, src);
618
        if (!hdev)
619
                return NULL;
620
 
621
        conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
622
 
623
        hci_dev_put(hdev);
624
 
625
        return conn ? &conn->dev : NULL;
626
}
627
 
628
static inline int hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
629
{
630
        struct input_dev *input = session->input;
631
        int i;
632
 
633
        input_set_drvdata(input, session);
634
 
635
        input->name = "Bluetooth HID Boot Protocol Device";
636
 
637
        input->id.bustype = BUS_BLUETOOTH;
638
        input->id.vendor  = req->vendor;
639
        input->id.product = req->product;
640
        input->id.version = req->version;
641
 
642
        if (req->subclass & 0x40) {
643
                set_bit(EV_KEY, input->evbit);
644
                set_bit(EV_LED, input->evbit);
645
                set_bit(EV_REP, input->evbit);
646
 
647
                set_bit(LED_NUML,    input->ledbit);
648
                set_bit(LED_CAPSL,   input->ledbit);
649
                set_bit(LED_SCROLLL, input->ledbit);
650
                set_bit(LED_COMPOSE, input->ledbit);
651
                set_bit(LED_KANA,    input->ledbit);
652
 
653
                for (i = 0; i < sizeof(hidp_keycode); i++)
654
                        set_bit(hidp_keycode[i], input->keybit);
655
                clear_bit(0, input->keybit);
656
        }
657
 
658
        if (req->subclass & 0x80) {
659
                input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
660
                input->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
661
                        BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
662
                input->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
663
                input->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |
664
                        BIT_MASK(BTN_EXTRA);
665
                input->relbit[0] |= BIT_MASK(REL_WHEEL);
666
        }
667
 
668
        input->dev.parent = hidp_get_device(session);
669
 
670
        input->event = hidp_input_event;
671
 
672
        return input_register_device(input);
673
}
674
 
675
static int hidp_open(struct hid_device *hid)
676
{
677
        return 0;
678
}
679
 
680
static void hidp_close(struct hid_device *hid)
681
{
682
}
683
 
684
static const struct {
685
        __u16 idVendor;
686
        __u16 idProduct;
687
        unsigned quirks;
688
} hidp_blacklist[] = {
689
        /* Apple wireless Mighty Mouse */
690
        { 0x05ac, 0x030c, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
691
 
692
        { }     /* Terminating entry */
693
};
694
 
695
static void hidp_setup_quirks(struct hid_device *hid)
696
{
697
        unsigned int n;
698
 
699
        for (n = 0; hidp_blacklist[n].idVendor; n++)
700
                if (hidp_blacklist[n].idVendor == le16_to_cpu(hid->vendor) &&
701
                                hidp_blacklist[n].idProduct == le16_to_cpu(hid->product))
702
                        hid->quirks = hidp_blacklist[n].quirks;
703
}
704
 
705
static inline void hidp_setup_hid(struct hidp_session *session, struct hidp_connadd_req *req)
706
{
707
        struct hid_device *hid = session->hid;
708
        struct hid_report *report;
709
        bdaddr_t src, dst;
710
 
711
        baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);
712
        baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst);
713
 
714
        hid->driver_data = session;
715
 
716
        hid->country = req->country;
717
 
718
        hid->bus     = BUS_BLUETOOTH;
719
        hid->vendor  = req->vendor;
720
        hid->product = req->product;
721
        hid->version = req->version;
722
 
723
        strncpy(hid->name, req->name, 128);
724
        strncpy(hid->phys, batostr(&src), 64);
725
        strncpy(hid->uniq, batostr(&dst), 64);
726
 
727
        hid->dev = hidp_get_device(session);
728
 
729
        hid->hid_open  = hidp_open;
730
        hid->hid_close = hidp_close;
731
 
732
        hid->hidinput_input_event = hidp_hidinput_event;
733
 
734
        hidp_setup_quirks(hid);
735
 
736
        list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
737
                hidp_send_report(session, report);
738
 
739
        list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
740
                hidp_send_report(session, report);
741
 
742
        if (hidinput_connect(hid) == 0)
743
                hid->claimed |= HID_CLAIMED_INPUT;
744
}
745
 
746
int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
747
{
748
        struct hidp_session *session, *s;
749
        int err;
750
 
751
        BT_DBG("");
752
 
753
        if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
754
                        bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
755
                return -ENOTUNIQ;
756
 
757
        session = kzalloc(sizeof(struct hidp_session), GFP_KERNEL);
758
        if (!session)
759
                return -ENOMEM;
760
 
761
        BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
762
 
763
        if (req->rd_size > 0) {
764
                unsigned char *buf = kmalloc(req->rd_size, GFP_KERNEL);
765
 
766
                if (!buf) {
767
                        kfree(session);
768
                        return -ENOMEM;
769
                }
770
 
771
                if (copy_from_user(buf, req->rd_data, req->rd_size)) {
772
                        kfree(buf);
773
                        kfree(session);
774
                        return -EFAULT;
775
                }
776
 
777
                session->hid = hid_parse_report(buf, req->rd_size);
778
 
779
                kfree(buf);
780
 
781
                if (!session->hid) {
782
                        kfree(session);
783
                        return -EINVAL;
784
                }
785
        }
786
 
787
        if (!session->hid) {
788
                session->input = input_allocate_device();
789
                if (!session->input) {
790
                        kfree(session);
791
                        return -ENOMEM;
792
                }
793
        }
794
 
795
        down_write(&hidp_session_sem);
796
 
797
        s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
798
        if (s && s->state == BT_CONNECTED) {
799
                err = -EEXIST;
800
                goto failed;
801
        }
802
 
803
        bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
804
 
805
        session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->omtu, l2cap_pi(ctrl_sock->sk)->imtu);
806
        session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->omtu, l2cap_pi(intr_sock->sk)->imtu);
807
 
808
        BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
809
 
810
        session->ctrl_sock = ctrl_sock;
811
        session->intr_sock = intr_sock;
812
        session->state     = BT_CONNECTED;
813
 
814
        init_timer(&session->timer);
815
 
816
        session->timer.function = hidp_idle_timeout;
817
        session->timer.data     = (unsigned long) session;
818
 
819
        skb_queue_head_init(&session->ctrl_transmit);
820
        skb_queue_head_init(&session->intr_transmit);
821
 
822
        session->flags   = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
823
        session->idle_to = req->idle_to;
824
 
825
        if (session->input) {
826
                err = hidp_setup_input(session, req);
827
                if (err < 0)
828
                        goto failed;
829
        }
830
 
831
        if (session->hid)
832
                hidp_setup_hid(session, req);
833
 
834
        __hidp_link_session(session);
835
 
836
        hidp_set_timer(session);
837
 
838
        err = kernel_thread(hidp_session, session, CLONE_KERNEL);
839
        if (err < 0)
840
                goto unlink;
841
 
842
        if (session->input) {
843
                hidp_send_ctrl_message(session,
844
                        HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
845
                session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
846
 
847
                session->leds = 0xff;
848
                hidp_input_event(session->input, EV_LED, 0, 0);
849
        }
850
 
851
        up_write(&hidp_session_sem);
852
        return 0;
853
 
854
unlink:
855
        hidp_del_timer(session);
856
 
857
        __hidp_unlink_session(session);
858
 
859
        if (session->input) {
860
                input_unregister_device(session->input);
861
                session->input = NULL; /* don't try to free it here */
862
        }
863
 
864
failed:
865
        up_write(&hidp_session_sem);
866
 
867
        if (session->hid)
868
                hid_free_device(session->hid);
869
 
870
        input_free_device(session->input);
871
        kfree(session);
872
        return err;
873
}
874
 
875
int hidp_del_connection(struct hidp_conndel_req *req)
876
{
877
        struct hidp_session *session;
878
        int err = 0;
879
 
880
        BT_DBG("");
881
 
882
        down_read(&hidp_session_sem);
883
 
884
        session = __hidp_get_session(&req->bdaddr);
885
        if (session) {
886
                if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
887
                        hidp_send_ctrl_message(session,
888
                                HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
889
                } else {
890
                        /* Flush the transmit queues */
891
                        skb_queue_purge(&session->ctrl_transmit);
892
                        skb_queue_purge(&session->intr_transmit);
893
 
894
                        /* Kill session thread */
895
                        atomic_inc(&session->terminate);
896
                        hidp_schedule(session);
897
                }
898
        } else
899
                err = -ENOENT;
900
 
901
        up_read(&hidp_session_sem);
902
        return err;
903
}
904
 
905
int hidp_get_connlist(struct hidp_connlist_req *req)
906
{
907
        struct list_head *p;
908
        int err = 0, n = 0;
909
 
910
        BT_DBG("");
911
 
912
        down_read(&hidp_session_sem);
913
 
914
        list_for_each(p, &hidp_session_list) {
915
                struct hidp_session *session;
916
                struct hidp_conninfo ci;
917
 
918
                session = list_entry(p, struct hidp_session, list);
919
 
920
                __hidp_copy_session(session, &ci);
921
 
922
                if (copy_to_user(req->ci, &ci, sizeof(ci))) {
923
                        err = -EFAULT;
924
                        break;
925
                }
926
 
927
                if (++n >= req->cnum)
928
                        break;
929
 
930
                req->ci++;
931
        }
932
        req->cnum = n;
933
 
934
        up_read(&hidp_session_sem);
935
        return err;
936
}
937
 
938
int hidp_get_conninfo(struct hidp_conninfo *ci)
939
{
940
        struct hidp_session *session;
941
        int err = 0;
942
 
943
        down_read(&hidp_session_sem);
944
 
945
        session = __hidp_get_session(&ci->bdaddr);
946
        if (session)
947
                __hidp_copy_session(session, ci);
948
        else
949
                err = -ENOENT;
950
 
951
        up_read(&hidp_session_sem);
952
        return err;
953
}
954
 
955
static int __init hidp_init(void)
956
{
957
        l2cap_load();
958
 
959
        BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
960
 
961
        return hidp_init_sockets();
962
}
963
 
964
static void __exit hidp_exit(void)
965
{
966
        hidp_cleanup_sockets();
967
}
968
 
969
module_init(hidp_init);
970
module_exit(hidp_exit);
971
 
972
MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
973
MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
974
MODULE_VERSION(VERSION);
975
MODULE_LICENSE("GPL");
976
MODULE_ALIAS("bt-proto-6");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.