blob: 6df8ea1c6341dcc64a52260a6a82d43958700bbf [file] [log] [blame]
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +09001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 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
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090013 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
Linus Torvalds1da177e2005-04-16 15:20:36 -070016 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +090018 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070020 SOFTWARE IS DISCLAIMED.
21*/
22
Linus Torvalds1da177e2005-04-16 15:20:36 -070023#include <linux/module.h>
24
25#include <linux/types.h>
26#include <linux/errno.h>
27#include <linux/kernel.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <linux/sched.h>
29#include <linux/slab.h>
30#include <linux/poll.h>
Rafael J. Wysocki83144182007-07-17 04:03:35 -070031#include <linux/freezer.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070032#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>
Alan Ott0ff17312011-01-18 03:04:40 -050039#include <linux/mutex.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070040#include <net/sock.h>
41
42#include <linux/input.h>
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +010043#include <linux/hid.h>
Marcel Holtmann364f6352009-08-22 14:15:53 -070044#include <linux/hidraw.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070045
46#include <net/bluetooth/bluetooth.h>
Marcel Holtmann0a85b962006-07-06 13:09:02 +020047#include <net/bluetooth/hci_core.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070048#include <net/bluetooth/l2cap.h>
49
50#include "hidp.h"
51
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +010052#define VERSION "1.2"
Linus Torvalds1da177e2005-04-16 15:20:36 -070053
54static DECLARE_RWSEM(hidp_session_sem);
55static LIST_HEAD(hidp_session_list);
56
57static unsigned char hidp_keycode[256] = {
58 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
59 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3,
60 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26,
61 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
62 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
63 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
64 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
65 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
66 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0,
67 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
68 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
69 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
70 0, 0, 0, 0, 0, 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 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
73 150,158,159,128,136,177,178,176,142,152,173,140
74};
75
76static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
77
78static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
79{
80 struct hidp_session *session;
81 struct list_head *p;
82
83 BT_DBG("");
84
85 list_for_each(p, &hidp_session_list) {
86 session = list_entry(p, struct hidp_session, list);
87 if (!bacmp(bdaddr, &session->bdaddr))
88 return session;
89 }
90 return NULL;
91}
92
93static void __hidp_link_session(struct hidp_session *session)
94{
95 __module_get(THIS_MODULE);
96 list_add(&session->list, &hidp_session_list);
Marcel Holtmannedad6382009-08-22 14:22:15 -070097
98 hci_conn_hold_device(session->conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -070099}
100
101static void __hidp_unlink_session(struct hidp_session *session)
102{
Marcel Holtmannedad6382009-08-22 14:22:15 -0700103 hci_conn_put_device(session->conn);
104
Linus Torvalds1da177e2005-04-16 15:20:36 -0700105 list_del(&session->list);
106 module_put(THIS_MODULE);
107}
108
109static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
110{
Vasiliy Kulikovd31dbf62010-10-30 18:26:31 +0400111 memset(ci, 0, sizeof(*ci));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700112 bacpy(&ci->bdaddr, &session->bdaddr);
113
114 ci->flags = session->flags;
115 ci->state = session->state;
116
117 ci->vendor = 0x0000;
118 ci->product = 0x0000;
119 ci->version = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
121 if (session->input) {
122 ci->vendor = session->input->id.vendor;
123 ci->product = session->input->id.product;
124 ci->version = session->input->id.version;
125 if (session->input->name)
126 strncpy(ci->name, session->input->name, 128);
127 else
128 strncpy(ci->name, "HID Boot Device", 128);
129 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100130
131 if (session->hid) {
132 ci->vendor = session->hid->vendor;
133 ci->product = session->hid->product;
134 ci->version = session->hid->version;
135 strncpy(ci->name, session->hid->name, 128);
136 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137}
138
Andrew Morton91f5cca2008-02-05 03:07:58 -0800139static int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
140 unsigned int type, unsigned int code, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 unsigned char newleds;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100143 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100145 BT_DBG("session %p type %d code %d value %d", session, type, code, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
147 if (type != EV_LED)
148 return -1;
149
150 newleds = (!!test_bit(LED_KANA, dev->led) << 3) |
151 (!!test_bit(LED_COMPOSE, dev->led) << 3) |
152 (!!test_bit(LED_SCROLLL, dev->led) << 2) |
153 (!!test_bit(LED_CAPSL, dev->led) << 1) |
154 (!!test_bit(LED_NUML, dev->led));
155
156 if (session->leds == newleds)
157 return 0;
158
159 session->leds = newleds;
160
161 if (!(skb = alloc_skb(3, GFP_ATOMIC))) {
162 BT_ERR("Can't allocate memory for new frame");
163 return -ENOMEM;
164 }
165
166 *skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
167 *skb_put(skb, 1) = 0x01;
168 *skb_put(skb, 1) = newleds;
169
170 skb_queue_tail(&session->intr_transmit, skb);
171
172 hidp_schedule(session);
173
174 return 0;
175}
176
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100177static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
178{
Marcel Holtmann5be39462007-05-09 09:15:30 +0200179 struct hid_device *hid = input_get_drvdata(dev);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100180 struct hidp_session *session = hid->driver_data;
181
182 return hidp_queue_event(session, dev, type, code, value);
183}
184
185static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
186{
Marcel Holtmann5be39462007-05-09 09:15:30 +0200187 struct hidp_session *session = input_get_drvdata(dev);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100188
189 return hidp_queue_event(session, dev, type, code, value);
190}
191
Linus Torvalds1da177e2005-04-16 15:20:36 -0700192static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
193{
194 struct input_dev *dev = session->input;
195 unsigned char *keys = session->keys;
196 unsigned char *udata = skb->data + 1;
197 signed char *sdata = skb->data + 1;
198 int i, size = skb->len - 1;
199
200 switch (skb->data[0]) {
201 case 0x01: /* Keyboard report */
202 for (i = 0; i < 8; i++)
203 input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
204
205 /* If all the key codes have been set to 0x01, it means
206 * too many keys were pressed at the same time. */
207 if (!memcmp(udata + 2, hidp_mkeyspat, 6))
208 break;
209
210 for (i = 2; i < 8; i++) {
211 if (keys[i] > 3 && memscan(udata + 2, keys[i], 6) == udata + 8) {
212 if (hidp_keycode[keys[i]])
213 input_report_key(dev, hidp_keycode[keys[i]], 0);
214 else
215 BT_ERR("Unknown key (scancode %#x) released.", keys[i]);
216 }
217
218 if (udata[i] > 3 && memscan(keys + 2, udata[i], 6) == keys + 8) {
219 if (hidp_keycode[udata[i]])
220 input_report_key(dev, hidp_keycode[udata[i]], 1);
221 else
222 BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]);
223 }
224 }
225
226 memcpy(keys, udata, 8);
227 break;
228
229 case 0x02: /* Mouse report */
230 input_report_key(dev, BTN_LEFT, sdata[0] & 0x01);
231 input_report_key(dev, BTN_RIGHT, sdata[0] & 0x02);
232 input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
233 input_report_key(dev, BTN_SIDE, sdata[0] & 0x08);
234 input_report_key(dev, BTN_EXTRA, sdata[0] & 0x10);
235
236 input_report_rel(dev, REL_X, sdata[1]);
237 input_report_rel(dev, REL_Y, sdata[2]);
238
239 if (size > 3)
240 input_report_rel(dev, REL_WHEEL, sdata[3]);
241 break;
242 }
243
244 input_sync(dev);
245}
246
Bastien Nocera6bf82682010-01-20 12:00:42 +0000247static int __hidp_send_ctrl_message(struct hidp_session *session,
248 unsigned char hdr, unsigned char *data, int size)
249{
250 struct sk_buff *skb;
251
252 BT_DBG("session %p data %p size %d", session, data, size);
253
254 if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
255 BT_ERR("Can't allocate memory for new frame");
256 return -ENOMEM;
257 }
258
259 *skb_put(skb, 1) = hdr;
260 if (data && size > 0)
261 memcpy(skb_put(skb, size), data, size);
262
263 skb_queue_tail(&session->ctrl_transmit, skb);
264
265 return 0;
266}
267
268static inline int hidp_send_ctrl_message(struct hidp_session *session,
269 unsigned char hdr, unsigned char *data, int size)
270{
271 int err;
272
273 err = __hidp_send_ctrl_message(session, hdr, data, size);
274
275 hidp_schedule(session);
276
277 return err;
278}
279
Andrew Morton91f5cca2008-02-05 03:07:58 -0800280static int hidp_queue_report(struct hidp_session *session,
281 unsigned char *data, int size)
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100282{
283 struct sk_buff *skb;
284
Dave Young6792b5e2007-10-20 14:15:39 +0200285 BT_DBG("session %p hid %p data %p size %d", session, session->hid, data, size);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100286
287 if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
288 BT_ERR("Can't allocate memory for new frame");
289 return -ENOMEM;
290 }
291
292 *skb_put(skb, 1) = 0xa2;
293 if (size > 0)
294 memcpy(skb_put(skb, size), data, size);
295
296 skb_queue_tail(&session->intr_transmit, skb);
297
298 hidp_schedule(session);
299
300 return 0;
301}
302
303static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
304{
305 unsigned char buf[32];
306 int rsize;
307
308 rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
309 if (rsize > sizeof(buf))
310 return -EIO;
311
312 hid_output_report(report, buf);
313
314 return hidp_queue_report(session, buf, rsize);
315}
316
Alan Ott0ff17312011-01-18 03:04:40 -0500317static int hidp_get_raw_report(struct hid_device *hid,
318 unsigned char report_number,
319 unsigned char *data, size_t count,
320 unsigned char report_type)
321{
322 struct hidp_session *session = hid->driver_data;
323 struct sk_buff *skb;
324 size_t len;
325 int numbered_reports = hid->report_enum[report_type].numbered;
326
327 switch (report_type) {
328 case HID_FEATURE_REPORT:
329 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
330 break;
331 case HID_INPUT_REPORT:
332 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_INPUT;
333 break;
334 case HID_OUTPUT_REPORT:
335 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_OUPUT;
336 break;
337 default:
338 return -EINVAL;
339 }
340
341 if (mutex_lock_interruptible(&session->report_mutex))
342 return -ERESTARTSYS;
343
344 /* Set up our wait, and send the report request to the device. */
345 session->waiting_report_type = report_type & HIDP_DATA_RTYPE_MASK;
346 session->waiting_report_number = numbered_reports ? report_number : -1;
347 set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
348 data[0] = report_number;
349 if (hidp_send_ctrl_message(hid->driver_data, report_type, data, 1))
350 goto err_eio;
351
352 /* Wait for the return of the report. The returned report
353 gets put in session->report_return. */
354 while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
355 int res;
356
357 res = wait_event_interruptible_timeout(session->report_queue,
358 !test_bit(HIDP_WAITING_FOR_RETURN, &session->flags),
359 5*HZ);
360 if (res == 0) {
361 /* timeout */
362 goto err_eio;
363 }
364 if (res < 0) {
365 /* signal */
366 goto err_restartsys;
367 }
368 }
369
370 skb = session->report_return;
371 if (skb) {
372 len = skb->len < count ? skb->len : count;
373 memcpy(data, skb->data, len);
374
375 kfree_skb(skb);
376 session->report_return = NULL;
377 } else {
378 /* Device returned a HANDSHAKE, indicating protocol error. */
379 len = -EIO;
380 }
381
382 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
383 mutex_unlock(&session->report_mutex);
384
385 return len;
386
387err_restartsys:
388 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
389 mutex_unlock(&session->report_mutex);
390 return -ERESTARTSYS;
391err_eio:
392 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
393 mutex_unlock(&session->report_mutex);
394 return -EIO;
395}
396
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100397static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
398 unsigned char report_type)
Jiri Kosina2da31932009-11-26 16:20:56 +0100399{
Alan Ott08254112011-01-18 03:04:38 -0500400 struct hidp_session *session = hid->driver_data;
401 int ret;
402
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100403 switch (report_type) {
404 case HID_FEATURE_REPORT:
405 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
406 break;
407 case HID_OUTPUT_REPORT:
408 report_type = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
409 break;
410 default:
411 return -EINVAL;
412 }
413
Alan Ott08254112011-01-18 03:04:38 -0500414 if (mutex_lock_interruptible(&session->report_mutex))
415 return -ERESTARTSYS;
416
417 /* Set up our wait, and send the report request to the device. */
418 set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100419 if (hidp_send_ctrl_message(hid->driver_data, report_type,
Alan Ott08254112011-01-18 03:04:38 -0500420 data, count)) {
421 ret = -ENOMEM;
422 goto err;
423 }
424
425 /* Wait for the ACK from the device. */
426 while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
427 int res;
428
429 res = wait_event_interruptible_timeout(session->report_queue,
430 !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags),
431 10*HZ);
432 if (res == 0) {
433 /* timeout */
434 ret = -EIO;
435 goto err;
436 }
437 if (res < 0) {
438 /* signal */
439 ret = -ERESTARTSYS;
440 goto err;
441 }
442 }
443
444 if (!session->output_report_success) {
445 ret = -EIO;
446 goto err;
447 }
448
449 ret = count;
450
451err:
452 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
453 mutex_unlock(&session->report_mutex);
454 return ret;
Jiri Kosina2da31932009-11-26 16:20:56 +0100455}
456
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457static void hidp_idle_timeout(unsigned long arg)
458{
459 struct hidp_session *session = (struct hidp_session *) arg;
460
461 atomic_inc(&session->terminate);
462 hidp_schedule(session);
463}
464
Andrew Morton91f5cca2008-02-05 03:07:58 -0800465static void hidp_set_timer(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466{
467 if (session->idle_to > 0)
468 mod_timer(&session->timer, jiffies + HZ * session->idle_to);
469}
470
471static inline void hidp_del_timer(struct hidp_session *session)
472{
473 if (session->idle_to > 0)
474 del_timer(&session->timer);
475}
476
Andrew Morton91f5cca2008-02-05 03:07:58 -0800477static void hidp_process_handshake(struct hidp_session *session,
478 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479{
480 BT_DBG("session %p param 0x%02x", session, param);
Alan Ott08254112011-01-18 03:04:38 -0500481 session->output_report_success = 0; /* default condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482
483 switch (param) {
484 case HIDP_HSHK_SUCCESSFUL:
485 /* FIXME: Call into SET_ GET_ handlers here */
Alan Ott08254112011-01-18 03:04:38 -0500486 session->output_report_success = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 break;
488
489 case HIDP_HSHK_NOT_READY:
490 case HIDP_HSHK_ERR_INVALID_REPORT_ID:
491 case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
492 case HIDP_HSHK_ERR_INVALID_PARAMETER:
Alan Ott0ff17312011-01-18 03:04:40 -0500493 if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
494 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
495 wake_up_interruptible(&session->report_queue);
496 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 /* FIXME: Call into SET_ GET_ handlers here */
498 break;
499
500 case HIDP_HSHK_ERR_UNKNOWN:
501 break;
502
503 case HIDP_HSHK_ERR_FATAL:
504 /* Device requests a reboot, as this is the only way this error
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900505 * can be recovered. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506 __hidp_send_ctrl_message(session,
507 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
508 break;
509
510 default:
511 __hidp_send_ctrl_message(session,
512 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
513 break;
514 }
Alan Ott08254112011-01-18 03:04:38 -0500515
516 /* Wake up the waiting thread. */
517 if (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
518 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
519 wake_up_interruptible(&session->report_queue);
520 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521}
522
Andrew Morton91f5cca2008-02-05 03:07:58 -0800523static void hidp_process_hid_control(struct hidp_session *session,
524 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525{
526 BT_DBG("session %p param 0x%02x", session, param);
527
Dave Youngeff001e2008-02-05 03:07:14 -0800528 if (param == HIDP_CTRL_VIRTUAL_CABLE_UNPLUG) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 /* Flush the transmit queues */
530 skb_queue_purge(&session->ctrl_transmit);
531 skb_queue_purge(&session->intr_transmit);
532
533 /* Kill session thread */
534 atomic_inc(&session->terminate);
Vikram Kandukuri981b1412009-07-01 11:39:58 +0530535 hidp_schedule(session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 }
537}
538
Alan Ott0ff17312011-01-18 03:04:40 -0500539/* Returns true if the passed-in skb should be freed by the caller. */
540static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800541 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542{
Alan Ott0ff17312011-01-18 03:04:40 -0500543 int done_with_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544 BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
545
546 switch (param) {
547 case HIDP_DATA_RTYPE_INPUT:
548 hidp_set_timer(session);
549
550 if (session->input)
551 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100552
553 if (session->hid)
554 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555 break;
556
557 case HIDP_DATA_RTYPE_OTHER:
558 case HIDP_DATA_RTYPE_OUPUT:
559 case HIDP_DATA_RTYPE_FEATURE:
560 break;
561
562 default:
563 __hidp_send_ctrl_message(session,
564 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
565 }
Alan Ott0ff17312011-01-18 03:04:40 -0500566
567 if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
568 param == session->waiting_report_type) {
569 if (session->waiting_report_number < 0 ||
570 session->waiting_report_number == skb->data[0]) {
571 /* hidp_get_raw_report() is waiting on this report. */
572 session->report_return = skb;
573 done_with_skb = 0;
574 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
575 wake_up_interruptible(&session->report_queue);
576 }
577 }
578
579 return done_with_skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580}
581
Andrew Morton91f5cca2008-02-05 03:07:58 -0800582static void hidp_recv_ctrl_frame(struct hidp_session *session,
583 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700584{
585 unsigned char hdr, type, param;
Alan Ott0ff17312011-01-18 03:04:40 -0500586 int free_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587
588 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
589
590 hdr = skb->data[0];
591 skb_pull(skb, 1);
592
593 type = hdr & HIDP_HEADER_TRANS_MASK;
594 param = hdr & HIDP_HEADER_PARAM_MASK;
595
596 switch (type) {
597 case HIDP_TRANS_HANDSHAKE:
598 hidp_process_handshake(session, param);
599 break;
600
601 case HIDP_TRANS_HID_CONTROL:
602 hidp_process_hid_control(session, param);
603 break;
604
605 case HIDP_TRANS_DATA:
Alan Ott0ff17312011-01-18 03:04:40 -0500606 free_skb = hidp_process_data(session, skb, param);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 break;
608
609 default:
610 __hidp_send_ctrl_message(session,
611 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
612 break;
613 }
614
Alan Ott0ff17312011-01-18 03:04:40 -0500615 if (free_skb)
616 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617}
618
Andrew Morton91f5cca2008-02-05 03:07:58 -0800619static void hidp_recv_intr_frame(struct hidp_session *session,
620 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621{
622 unsigned char hdr;
623
624 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
625
626 hdr = skb->data[0];
627 skb_pull(skb, 1);
628
629 if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
630 hidp_set_timer(session);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100631
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 if (session->input)
633 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100634
635 if (session->hid) {
636 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
637 BT_DBG("report len %d", skb->len);
638 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 } else {
640 BT_DBG("Unsupported protocol header 0x%02x", hdr);
641 }
642
643 kfree_skb(skb);
644}
645
646static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
647{
648 struct kvec iv = { data, len };
649 struct msghdr msg;
650
651 BT_DBG("sock %p data %p len %d", sock, data, len);
652
653 if (!len)
654 return 0;
655
656 memset(&msg, 0, sizeof(msg));
657
658 return kernel_sendmsg(sock, &msg, &iv, 1, len);
659}
660
David S. Millerb03efcf2005-07-08 14:57:23 -0700661static void hidp_process_transmit(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700662{
663 struct sk_buff *skb;
664
665 BT_DBG("session %p", session);
666
667 while ((skb = skb_dequeue(&session->ctrl_transmit))) {
668 if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
669 skb_queue_head(&session->ctrl_transmit, skb);
670 break;
671 }
672
673 hidp_set_timer(session);
674 kfree_skb(skb);
675 }
676
677 while ((skb = skb_dequeue(&session->intr_transmit))) {
678 if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
679 skb_queue_head(&session->intr_transmit, skb);
680 break;
681 }
682
683 hidp_set_timer(session);
684 kfree_skb(skb);
685 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686}
687
688static int hidp_session(void *arg)
689{
690 struct hidp_session *session = arg;
691 struct sock *ctrl_sk = session->ctrl_sock->sk;
692 struct sock *intr_sk = session->intr_sock->sk;
693 struct sk_buff *skb;
694 int vendor = 0x0000, product = 0x0000;
695 wait_queue_t ctrl_wait, intr_wait;
696
697 BT_DBG("session %p", session);
698
699 if (session->input) {
700 vendor = session->input->id.vendor;
701 product = session->input->id.product;
702 }
703
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100704 if (session->hid) {
705 vendor = session->hid->vendor;
706 product = session->hid->product;
707 }
708
Linus Torvalds1da177e2005-04-16 15:20:36 -0700709 daemonize("khidpd_%04x%04x", vendor, product);
710 set_user_nice(current, -15);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
712 init_waitqueue_entry(&ctrl_wait, current);
713 init_waitqueue_entry(&intr_wait, current);
Eric Dumazetaa395142010-04-20 13:03:51 +0000714 add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
715 add_wait_queue(sk_sleep(intr_sk), &intr_wait);
Alan Ott0f69dca2011-01-18 03:04:37 -0500716 session->waiting_for_startup = 0;
717 wake_up_interruptible(&session->startup_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700718 while (!atomic_read(&session->terminate)) {
719 set_current_state(TASK_INTERRUPTIBLE);
720
721 if (ctrl_sk->sk_state != BT_CONNECTED || intr_sk->sk_state != BT_CONNECTED)
722 break;
723
724 while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
725 skb_orphan(skb);
726 hidp_recv_ctrl_frame(session, skb);
727 }
728
729 while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
730 skb_orphan(skb);
731 hidp_recv_intr_frame(session, skb);
732 }
733
734 hidp_process_transmit(session);
735
736 schedule();
737 }
738 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +0000739 remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
740 remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741
742 down_write(&hidp_session_sem);
743
744 hidp_del_timer(session);
745
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 if (session->input) {
747 input_unregister_device(session->input);
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500748 session->input = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 }
750
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100751 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200752 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -0700753 session->hid = NULL;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100754 }
755
Marcel Holtmannec8dab32008-07-14 20:13:53 +0200756 /* Wakeup user-space polling for socket errors */
757 session->intr_sock->sk->sk_err = EUNATCH;
758 session->ctrl_sock->sk->sk_err = EUNATCH;
759
760 hidp_schedule(session);
761
David Woodhouse1c398582007-07-07 14:58:39 -0400762 fput(session->intr_sock->file);
763
Eric Dumazetaa395142010-04-20 13:03:51 +0000764 wait_event_timeout(*(sk_sleep(ctrl_sk)),
David Woodhouse1c398582007-07-07 14:58:39 -0400765 (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
766
767 fput(session->ctrl_sock->file);
768
769 __hidp_unlink_session(session);
770
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 up_write(&hidp_session_sem);
772
773 kfree(session);
774 return 0;
775}
776
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200777static struct device *hidp_get_device(struct hidp_session *session)
778{
779 bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
780 bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700781 struct device *device = NULL;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200782 struct hci_dev *hdev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200783
784 hdev = hci_get_route(dst, src);
785 if (!hdev)
786 return NULL;
787
Marcel Holtmannedad6382009-08-22 14:22:15 -0700788 session->conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
789 if (session->conn)
790 device = &session->conn->dev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200791
792 hci_dev_put(hdev);
793
Marcel Holtmannedad6382009-08-22 14:22:15 -0700794 return device;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200795}
796
Andrew Morton91f5cca2008-02-05 03:07:58 -0800797static int hidp_setup_input(struct hidp_session *session,
798 struct hidp_connadd_req *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799{
Jiri Slabyc500c972008-05-16 11:49:16 +0200800 struct input_dev *input;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700801 int err, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802
Jiri Slabyc500c972008-05-16 11:49:16 +0200803 input = input_allocate_device();
804 if (!input)
805 return -ENOMEM;
806
807 session->input = input;
808
Marcel Holtmann5be39462007-05-09 09:15:30 +0200809 input_set_drvdata(input, session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500811 input->name = "Bluetooth HID Boot Protocol Device";
812
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813 input->id.bustype = BUS_BLUETOOTH;
814 input->id.vendor = req->vendor;
815 input->id.product = req->product;
816 input->id.version = req->version;
817
818 if (req->subclass & 0x40) {
819 set_bit(EV_KEY, input->evbit);
820 set_bit(EV_LED, input->evbit);
821 set_bit(EV_REP, input->evbit);
822
823 set_bit(LED_NUML, input->ledbit);
824 set_bit(LED_CAPSL, input->ledbit);
825 set_bit(LED_SCROLLL, input->ledbit);
826 set_bit(LED_COMPOSE, input->ledbit);
827 set_bit(LED_KANA, input->ledbit);
828
829 for (i = 0; i < sizeof(hidp_keycode); i++)
830 set_bit(hidp_keycode[i], input->keybit);
831 clear_bit(0, input->keybit);
832 }
833
834 if (req->subclass & 0x80) {
Jiri Slaby7b19ada2007-10-18 23:40:32 -0700835 input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
836 input->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
837 BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
838 input->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
839 input->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |
840 BIT_MASK(BTN_EXTRA);
841 input->relbit[0] |= BIT_MASK(REL_WHEEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 }
843
Marcel Holtmann5be39462007-05-09 09:15:30 +0200844 input->dev.parent = hidp_get_device(session);
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200845
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846 input->event = hidp_input_event;
847
Marcel Holtmannedad6382009-08-22 14:22:15 -0700848 err = input_register_device(input);
849 if (err < 0) {
850 hci_conn_put_device(session->conn);
851 return err;
852 }
853
854 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700855}
856
Marcel Holtmannf5ffd462007-02-17 23:58:53 +0100857static int hidp_open(struct hid_device *hid)
858{
859 return 0;
860}
861
862static void hidp_close(struct hid_device *hid)
863{
864}
865
Jiri Slabyc500c972008-05-16 11:49:16 +0200866static int hidp_parse(struct hid_device *hid)
867{
868 struct hidp_session *session = hid->driver_data;
Jiri Slabyc500c972008-05-16 11:49:16 +0200869
Michael Poole15c697c2010-02-05 12:23:43 -0500870 return hid_parse_report(session->hid, session->rd_data,
871 session->rd_size);
Jiri Slabyc500c972008-05-16 11:49:16 +0200872}
873
874static int hidp_start(struct hid_device *hid)
875{
876 struct hidp_session *session = hid->driver_data;
877 struct hid_report *report;
878
879 list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].
880 report_list, list)
881 hidp_send_report(session, report);
882
883 list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].
884 report_list, list)
885 hidp_send_report(session, report);
886
Jiri Slabyc500c972008-05-16 11:49:16 +0200887 return 0;
888}
889
890static void hidp_stop(struct hid_device *hid)
891{
892 struct hidp_session *session = hid->driver_data;
893
894 skb_queue_purge(&session->ctrl_transmit);
895 skb_queue_purge(&session->intr_transmit);
896
Jiri Slabyc500c972008-05-16 11:49:16 +0200897 hid->claimed = 0;
898}
899
900static struct hid_ll_driver hidp_hid_driver = {
901 .parse = hidp_parse,
902 .start = hidp_start,
903 .stop = hidp_stop,
904 .open = hidp_open,
905 .close = hidp_close,
906 .hidinput_input_event = hidp_hidinput_event,
907};
908
Alan Ott0f69dca2011-01-18 03:04:37 -0500909/* This function sets up the hid device. It does not add it
910 to the HID system. That is done in hidp_add_connection(). */
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200911static int hidp_setup_hid(struct hidp_session *session,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800912 struct hidp_connadd_req *req)
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100913{
Jiri Slabyc500c972008-05-16 11:49:16 +0200914 struct hid_device *hid;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700915 int err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100916
Michael Poole15c697c2010-02-05 12:23:43 -0500917 session->rd_data = kzalloc(req->rd_size, GFP_KERNEL);
918 if (!session->rd_data)
919 return -ENOMEM;
920
921 if (copy_from_user(session->rd_data, req->rd_data, req->rd_size)) {
922 err = -EFAULT;
923 goto fault;
924 }
925 session->rd_size = req->rd_size;
926
Jiri Slabyc500c972008-05-16 11:49:16 +0200927 hid = hid_allocate_device();
Michael Poole15c697c2010-02-05 12:23:43 -0500928 if (IS_ERR(hid)) {
929 err = PTR_ERR(hid);
930 goto fault;
931 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100932
Jiri Slabyc500c972008-05-16 11:49:16 +0200933 session->hid = hid;
Michael Poole15c697c2010-02-05 12:23:43 -0500934
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100935 hid->driver_data = session;
936
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100937 hid->bus = BUS_BLUETOOTH;
938 hid->vendor = req->vendor;
939 hid->product = req->product;
940 hid->version = req->version;
Jiri Slabyc500c972008-05-16 11:49:16 +0200941 hid->country = req->country;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100942
943 strncpy(hid->name, req->name, 128);
Gustavo F. Padovand6b2eb22010-09-03 18:29:46 -0300944 strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64);
945 strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100946
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200947 hid->dev.parent = hidp_get_device(session);
Jiri Slabyc500c972008-05-16 11:49:16 +0200948 hid->ll_driver = &hidp_hid_driver;
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200949
Alan Ott0ff17312011-01-18 03:04:40 -0500950 hid->hid_get_raw_report = hidp_get_raw_report;
Jiri Kosina2da31932009-11-26 16:20:56 +0100951 hid->hid_output_raw_report = hidp_output_raw_report;
952
Jiri Slabyc500c972008-05-16 11:49:16 +0200953 return 0;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700954
Michael Poole15c697c2010-02-05 12:23:43 -0500955fault:
956 kfree(session->rd_data);
957 session->rd_data = NULL;
958
Marcel Holtmannedad6382009-08-22 14:22:15 -0700959 return err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100960}
961
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
963{
964 struct hidp_session *session, *s;
965 int err;
966
967 BT_DBG("");
968
969 if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
970 bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
971 return -ENOTUNIQ;
972
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200973 session = kzalloc(sizeof(struct hidp_session), GFP_KERNEL);
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500974 if (!session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700976
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100977 BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
978
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 down_write(&hidp_session_sem);
980
981 s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
982 if (s && s->state == BT_CONNECTED) {
983 err = -EEXIST;
984 goto failed;
985 }
986
987 bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
988
989 session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->omtu, l2cap_pi(ctrl_sock->sk)->imtu);
990 session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->omtu, l2cap_pi(intr_sock->sk)->imtu);
991
992 BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
993
994 session->ctrl_sock = ctrl_sock;
995 session->intr_sock = intr_sock;
996 session->state = BT_CONNECTED;
997
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -0800998 setup_timer(&session->timer, hidp_idle_timeout, (unsigned long)session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999
1000 skb_queue_head_init(&session->ctrl_transmit);
1001 skb_queue_head_init(&session->intr_transmit);
1002
Alan Ott0ff17312011-01-18 03:04:40 -05001003 mutex_init(&session->report_mutex);
1004 init_waitqueue_head(&session->report_queue);
Alan Ott0f69dca2011-01-18 03:04:37 -05001005 init_waitqueue_head(&session->startup_queue);
1006 session->waiting_for_startup = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
1008 session->idle_to = req->idle_to;
1009
Jiri Slabyc500c972008-05-16 11:49:16 +02001010 if (req->rd_size > 0) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001011 err = hidp_setup_hid(session, req);
Jiri Slabyd458a9d2008-05-16 11:49:20 +02001012 if (err && err != -ENODEV)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001013 goto purge;
Jiri Slabyc500c972008-05-16 11:49:16 +02001014 }
1015
1016 if (!session->hid) {
1017 err = hidp_setup_input(session, req);
1018 if (err < 0)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001019 goto purge;
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001020 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001021
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 __hidp_link_session(session);
1023
1024 hidp_set_timer(session);
1025
1026 err = kernel_thread(hidp_session, session, CLONE_KERNEL);
1027 if (err < 0)
1028 goto unlink;
Alan Ott0f69dca2011-01-18 03:04:37 -05001029 while (session->waiting_for_startup) {
1030 wait_event_interruptible(session->startup_queue,
1031 !session->waiting_for_startup);
1032 }
1033
1034 err = hid_add_device(session->hid);
1035 if (err < 0)
1036 goto err_add_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037
1038 if (session->input) {
1039 hidp_send_ctrl_message(session,
1040 HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
1041 session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
1042
1043 session->leds = 0xff;
1044 hidp_input_event(session->input, EV_LED, 0, 0);
1045 }
1046
1047 up_write(&hidp_session_sem);
1048 return 0;
1049
Alan Ott0f69dca2011-01-18 03:04:37 -05001050err_add_device:
1051 hid_destroy_device(session->hid);
1052 session->hid = NULL;
1053 atomic_inc(&session->terminate);
1054 hidp_schedule(session);
1055
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056unlink:
1057 hidp_del_timer(session);
1058
1059 __hidp_unlink_session(session);
1060
Marcel Holtmannedad6382009-08-22 14:22:15 -07001061 if (session->input) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 input_unregister_device(session->input);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001063 session->input = NULL;
1064 }
1065
1066 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001067 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001068 session->hid = NULL;
1069 }
1070
Michael Poole15c697c2010-02-05 12:23:43 -05001071 kfree(session->rd_data);
1072 session->rd_data = NULL;
1073
Marcel Holtmannedad6382009-08-22 14:22:15 -07001074purge:
Jiri Slabyc500c972008-05-16 11:49:16 +02001075 skb_queue_purge(&session->ctrl_transmit);
1076 skb_queue_purge(&session->intr_transmit);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001077
Jiri Slabyc500c972008-05-16 11:49:16 +02001078failed:
1079 up_write(&hidp_session_sem);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001080
Marcel Holtmann5be39462007-05-09 09:15:30 +02001081 input_free_device(session->input);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 kfree(session);
1083 return err;
1084}
1085
1086int hidp_del_connection(struct hidp_conndel_req *req)
1087{
1088 struct hidp_session *session;
1089 int err = 0;
1090
1091 BT_DBG("");
1092
1093 down_read(&hidp_session_sem);
1094
1095 session = __hidp_get_session(&req->bdaddr);
1096 if (session) {
1097 if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
1098 hidp_send_ctrl_message(session,
1099 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
1100 } else {
1101 /* Flush the transmit queues */
1102 skb_queue_purge(&session->ctrl_transmit);
1103 skb_queue_purge(&session->intr_transmit);
1104
Marcel Holtmannec8dab32008-07-14 20:13:53 +02001105 /* Wakeup user-space polling for socket errors */
1106 session->intr_sock->sk->sk_err = EUNATCH;
1107 session->ctrl_sock->sk->sk_err = EUNATCH;
1108
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 /* Kill session thread */
1110 atomic_inc(&session->terminate);
1111 hidp_schedule(session);
1112 }
1113 } else
1114 err = -ENOENT;
1115
1116 up_read(&hidp_session_sem);
1117 return err;
1118}
1119
1120int hidp_get_connlist(struct hidp_connlist_req *req)
1121{
1122 struct list_head *p;
1123 int err = 0, n = 0;
1124
1125 BT_DBG("");
1126
1127 down_read(&hidp_session_sem);
1128
1129 list_for_each(p, &hidp_session_list) {
1130 struct hidp_session *session;
1131 struct hidp_conninfo ci;
1132
1133 session = list_entry(p, struct hidp_session, list);
1134
1135 __hidp_copy_session(session, &ci);
1136
1137 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
1138 err = -EFAULT;
1139 break;
1140 }
1141
1142 if (++n >= req->cnum)
1143 break;
1144
1145 req->ci++;
1146 }
1147 req->cnum = n;
1148
1149 up_read(&hidp_session_sem);
1150 return err;
1151}
1152
1153int hidp_get_conninfo(struct hidp_conninfo *ci)
1154{
1155 struct hidp_session *session;
1156 int err = 0;
1157
1158 down_read(&hidp_session_sem);
1159
1160 session = __hidp_get_session(&ci->bdaddr);
1161 if (session)
1162 __hidp_copy_session(session, ci);
1163 else
1164 err = -ENOENT;
1165
1166 up_read(&hidp_session_sem);
1167 return err;
1168}
1169
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001170static const struct hid_device_id hidp_table[] = {
1171 { HID_BLUETOOTH_DEVICE(HID_ANY_ID, HID_ANY_ID) },
1172 { }
1173};
1174
1175static struct hid_driver hidp_driver = {
1176 .name = "generic-bluetooth",
1177 .id_table = hidp_table,
1178};
1179
Linus Torvalds1da177e2005-04-16 15:20:36 -07001180static int __init hidp_init(void)
1181{
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001182 int ret;
1183
Linus Torvalds1da177e2005-04-16 15:20:36 -07001184 l2cap_load();
1185
1186 BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
1187
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001188 ret = hid_register_driver(&hidp_driver);
1189 if (ret)
1190 goto err;
1191
1192 ret = hidp_init_sockets();
1193 if (ret)
1194 goto err_drv;
1195
1196 return 0;
1197err_drv:
1198 hid_unregister_driver(&hidp_driver);
1199err:
1200 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201}
1202
1203static void __exit hidp_exit(void)
1204{
1205 hidp_cleanup_sockets();
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001206 hid_unregister_driver(&hidp_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001207}
1208
1209module_init(hidp_init);
1210module_exit(hidp_exit);
1211
1212MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
1213MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
1214MODULE_VERSION(VERSION);
1215MODULE_LICENSE("GPL");
1216MODULE_ALIAS("bt-proto-6");