blob: a1472b75d628dc77f2cf3fafd84047f45e0c31da [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] = {
Szymon Janc17f09a72011-03-21 14:20:01 +010058 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36,
59 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45,
60 21, 44, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 1,
61 14, 15, 57, 12, 13, 26, 27, 43, 43, 39, 40, 41, 51, 52,
62 53, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 87, 88,
63 99, 70, 119, 110, 102, 104, 111, 107, 109, 106, 105, 108, 103, 69,
64 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 72, 73,
65 82, 83, 86, 127, 116, 117, 183, 184, 185, 186, 187, 188, 189, 190,
66 191, 192, 193, 194, 134, 138, 130, 132, 128, 129, 131, 137, 133, 135,
67 136, 113, 115, 114, 0, 0, 0, 121, 0, 89, 93, 124, 92, 94,
68 95, 0, 0, 0, 122, 123, 90, 91, 85, 0, 0, 0, 0, 0,
69 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,
71 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,
73 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
74 29, 42, 56, 125, 97, 54, 100, 126, 164, 166, 165, 163, 161, 115,
75 114, 113, 150, 158, 159, 128, 136, 177, 178, 176, 142, 152, 173, 140
Linus Torvalds1da177e2005-04-16 15:20:36 -070076};
77
78static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
79
80static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
81{
82 struct hidp_session *session;
83 struct list_head *p;
84
85 BT_DBG("");
86
87 list_for_each(p, &hidp_session_list) {
88 session = list_entry(p, struct hidp_session, list);
89 if (!bacmp(bdaddr, &session->bdaddr))
90 return session;
91 }
92 return NULL;
93}
94
95static void __hidp_link_session(struct hidp_session *session)
96{
97 __module_get(THIS_MODULE);
98 list_add(&session->list, &hidp_session_list);
Marcel Holtmannedad6382009-08-22 14:22:15 -070099
100 hci_conn_hold_device(session->conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101}
102
103static void __hidp_unlink_session(struct hidp_session *session)
104{
Marcel Holtmannedad6382009-08-22 14:22:15 -0700105 hci_conn_put_device(session->conn);
106
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107 list_del(&session->list);
108 module_put(THIS_MODULE);
109}
110
111static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
112{
Vasiliy Kulikovd31dbf62010-10-30 18:26:31 +0400113 memset(ci, 0, sizeof(*ci));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114 bacpy(&ci->bdaddr, &session->bdaddr);
115
116 ci->flags = session->flags;
117 ci->state = session->state;
118
119 ci->vendor = 0x0000;
120 ci->product = 0x0000;
121 ci->version = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122
123 if (session->input) {
124 ci->vendor = session->input->id.vendor;
125 ci->product = session->input->id.product;
126 ci->version = session->input->id.version;
127 if (session->input->name)
128 strncpy(ci->name, session->input->name, 128);
129 else
130 strncpy(ci->name, "HID Boot Device", 128);
131 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100132
133 if (session->hid) {
134 ci->vendor = session->hid->vendor;
135 ci->product = session->hid->product;
136 ci->version = session->hid->version;
137 strncpy(ci->name, session->hid->name, 128);
138 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139}
140
Andrew Morton91f5cca2008-02-05 03:07:58 -0800141static int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
142 unsigned int type, unsigned int code, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 unsigned char newleds;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100145 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100147 BT_DBG("session %p type %d code %d value %d", session, type, code, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148
149 if (type != EV_LED)
150 return -1;
151
152 newleds = (!!test_bit(LED_KANA, dev->led) << 3) |
153 (!!test_bit(LED_COMPOSE, dev->led) << 3) |
154 (!!test_bit(LED_SCROLLL, dev->led) << 2) |
155 (!!test_bit(LED_CAPSL, dev->led) << 1) |
156 (!!test_bit(LED_NUML, dev->led));
157
158 if (session->leds == newleds)
159 return 0;
160
161 session->leds = newleds;
162
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200163 skb = alloc_skb(3, GFP_ATOMIC);
164 if (!skb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700165 BT_ERR("Can't allocate memory for new frame");
166 return -ENOMEM;
167 }
168
169 *skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
170 *skb_put(skb, 1) = 0x01;
171 *skb_put(skb, 1) = newleds;
172
173 skb_queue_tail(&session->intr_transmit, skb);
174
175 hidp_schedule(session);
176
177 return 0;
178}
179
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100180static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
181{
Marcel Holtmann5be39462007-05-09 09:15:30 +0200182 struct hid_device *hid = input_get_drvdata(dev);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100183 struct hidp_session *session = hid->driver_data;
184
185 return hidp_queue_event(session, dev, type, code, value);
186}
187
188static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
189{
Marcel Holtmann5be39462007-05-09 09:15:30 +0200190 struct hidp_session *session = input_get_drvdata(dev);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100191
192 return hidp_queue_event(session, dev, type, code, value);
193}
194
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
196{
197 struct input_dev *dev = session->input;
198 unsigned char *keys = session->keys;
199 unsigned char *udata = skb->data + 1;
200 signed char *sdata = skb->data + 1;
201 int i, size = skb->len - 1;
202
203 switch (skb->data[0]) {
204 case 0x01: /* Keyboard report */
205 for (i = 0; i < 8; i++)
206 input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
207
208 /* If all the key codes have been set to 0x01, it means
209 * too many keys were pressed at the same time. */
210 if (!memcmp(udata + 2, hidp_mkeyspat, 6))
211 break;
212
213 for (i = 2; i < 8; i++) {
214 if (keys[i] > 3 && memscan(udata + 2, keys[i], 6) == udata + 8) {
215 if (hidp_keycode[keys[i]])
216 input_report_key(dev, hidp_keycode[keys[i]], 0);
217 else
218 BT_ERR("Unknown key (scancode %#x) released.", keys[i]);
219 }
220
221 if (udata[i] > 3 && memscan(keys + 2, udata[i], 6) == keys + 8) {
222 if (hidp_keycode[udata[i]])
223 input_report_key(dev, hidp_keycode[udata[i]], 1);
224 else
225 BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]);
226 }
227 }
228
229 memcpy(keys, udata, 8);
230 break;
231
232 case 0x02: /* Mouse report */
233 input_report_key(dev, BTN_LEFT, sdata[0] & 0x01);
234 input_report_key(dev, BTN_RIGHT, sdata[0] & 0x02);
235 input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
236 input_report_key(dev, BTN_SIDE, sdata[0] & 0x08);
237 input_report_key(dev, BTN_EXTRA, sdata[0] & 0x10);
238
239 input_report_rel(dev, REL_X, sdata[1]);
240 input_report_rel(dev, REL_Y, sdata[2]);
241
242 if (size > 3)
243 input_report_rel(dev, REL_WHEEL, sdata[3]);
244 break;
245 }
246
247 input_sync(dev);
248}
249
Bastien Nocera6bf82682010-01-20 12:00:42 +0000250static int __hidp_send_ctrl_message(struct hidp_session *session,
251 unsigned char hdr, unsigned char *data, int size)
252{
253 struct sk_buff *skb;
254
255 BT_DBG("session %p data %p size %d", session, data, size);
256
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200257 skb = alloc_skb(size + 1, GFP_ATOMIC);
258 if (!skb) {
Bastien Nocera6bf82682010-01-20 12:00:42 +0000259 BT_ERR("Can't allocate memory for new frame");
260 return -ENOMEM;
261 }
262
263 *skb_put(skb, 1) = hdr;
264 if (data && size > 0)
265 memcpy(skb_put(skb, size), data, size);
266
267 skb_queue_tail(&session->ctrl_transmit, skb);
268
269 return 0;
270}
271
272static inline int hidp_send_ctrl_message(struct hidp_session *session,
273 unsigned char hdr, unsigned char *data, int size)
274{
275 int err;
276
277 err = __hidp_send_ctrl_message(session, hdr, data, size);
278
279 hidp_schedule(session);
280
281 return err;
282}
283
Andrew Morton91f5cca2008-02-05 03:07:58 -0800284static int hidp_queue_report(struct hidp_session *session,
285 unsigned char *data, int size)
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100286{
287 struct sk_buff *skb;
288
Dave Young6792b5e2007-10-20 14:15:39 +0200289 BT_DBG("session %p hid %p data %p size %d", session, session->hid, data, size);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100290
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200291 skb = alloc_skb(size + 1, GFP_ATOMIC);
292 if (!skb) {
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100293 BT_ERR("Can't allocate memory for new frame");
294 return -ENOMEM;
295 }
296
297 *skb_put(skb, 1) = 0xa2;
298 if (size > 0)
299 memcpy(skb_put(skb, size), data, size);
300
301 skb_queue_tail(&session->intr_transmit, skb);
302
303 hidp_schedule(session);
304
305 return 0;
306}
307
308static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
309{
310 unsigned char buf[32];
311 int rsize;
312
313 rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
314 if (rsize > sizeof(buf))
315 return -EIO;
316
317 hid_output_report(report, buf);
318
319 return hidp_queue_report(session, buf, rsize);
320}
321
Alan Ott0ff17312011-01-18 03:04:40 -0500322static int hidp_get_raw_report(struct hid_device *hid,
323 unsigned char report_number,
324 unsigned char *data, size_t count,
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100325 unsigned char report_type)
Jiri Kosina2da31932009-11-26 16:20:56 +0100326{
Alan Ott0ff17312011-01-18 03:04:40 -0500327 struct hidp_session *session = hid->driver_data;
328 struct sk_buff *skb;
329 size_t len;
330 int numbered_reports = hid->report_enum[report_type].numbered;
331
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100332 switch (report_type) {
333 case HID_FEATURE_REPORT:
Alan Ott0ff17312011-01-18 03:04:40 -0500334 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
335 break;
336 case HID_INPUT_REPORT:
337 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_INPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100338 break;
339 case HID_OUTPUT_REPORT:
Alan Ott0ff17312011-01-18 03:04:40 -0500340 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_OUPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100341 break;
342 default:
343 return -EINVAL;
344 }
345
Alan Ott0ff17312011-01-18 03:04:40 -0500346 if (mutex_lock_interruptible(&session->report_mutex))
347 return -ERESTARTSYS;
348
349 /* Set up our wait, and send the report request to the device. */
350 session->waiting_report_type = report_type & HIDP_DATA_RTYPE_MASK;
351 session->waiting_report_number = numbered_reports ? report_number : -1;
352 set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
353 data[0] = report_number;
354 if (hidp_send_ctrl_message(hid->driver_data, report_type, data, 1))
355 goto err_eio;
356
357 /* Wait for the return of the report. The returned report
358 gets put in session->report_return. */
359 while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
360 int res;
361
362 res = wait_event_interruptible_timeout(session->report_queue,
363 !test_bit(HIDP_WAITING_FOR_RETURN, &session->flags),
364 5*HZ);
365 if (res == 0) {
366 /* timeout */
367 goto err_eio;
368 }
369 if (res < 0) {
370 /* signal */
371 goto err_restartsys;
372 }
373 }
374
375 skb = session->report_return;
376 if (skb) {
377 len = skb->len < count ? skb->len : count;
378 memcpy(data, skb->data, len);
379
380 kfree_skb(skb);
381 session->report_return = NULL;
382 } else {
383 /* Device returned a HANDSHAKE, indicating protocol error. */
384 len = -EIO;
385 }
386
387 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
388 mutex_unlock(&session->report_mutex);
389
390 return len;
391
392err_restartsys:
393 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
394 mutex_unlock(&session->report_mutex);
395 return -ERESTARTSYS;
396err_eio:
397 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
398 mutex_unlock(&session->report_mutex);
399 return -EIO;
400}
401
Linus Torvalds1da177e2005-04-16 15:20:36 -0700402static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
Jiri Kosina2da31932009-11-26 16:20:56 +0100403 unsigned char report_type)
404{
Alan Ott08254112011-01-18 03:04:38 -0500405 struct hidp_session *session = hid->driver_data;
406 int ret;
407
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100408 switch (report_type) {
409 case HID_FEATURE_REPORT:
410 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
411 break;
412 case HID_OUTPUT_REPORT:
Antonio Ospite97e1efb2011-02-20 18:26:46 +0100413 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100414 break;
415 default:
416 return -EINVAL;
417 }
418
Alan Ott08254112011-01-18 03:04:38 -0500419 if (mutex_lock_interruptible(&session->report_mutex))
420 return -ERESTARTSYS;
421
422 /* Set up our wait, and send the report request to the device. */
423 set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100424 if (hidp_send_ctrl_message(hid->driver_data, report_type,
Alan Ott08254112011-01-18 03:04:38 -0500425 data, count)) {
426 ret = -ENOMEM;
427 goto err;
428 }
429
430 /* Wait for the ACK from the device. */
431 while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
432 int res;
433
434 res = wait_event_interruptible_timeout(session->report_queue,
435 !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags),
436 10*HZ);
437 if (res == 0) {
438 /* timeout */
439 ret = -EIO;
440 goto err;
441 }
442 if (res < 0) {
443 /* signal */
444 ret = -ERESTARTSYS;
445 goto err;
446 }
447 }
448
449 if (!session->output_report_success) {
450 ret = -EIO;
451 goto err;
452 }
453
454 ret = count;
455
456err:
457 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
458 mutex_unlock(&session->report_mutex);
459 return ret;
Jiri Kosina2da31932009-11-26 16:20:56 +0100460}
461
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462static void hidp_idle_timeout(unsigned long arg)
463{
464 struct hidp_session *session = (struct hidp_session *) arg;
465
466 atomic_inc(&session->terminate);
467 hidp_schedule(session);
468}
469
Andrew Morton91f5cca2008-02-05 03:07:58 -0800470static void hidp_set_timer(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471{
472 if (session->idle_to > 0)
473 mod_timer(&session->timer, jiffies + HZ * session->idle_to);
474}
475
476static inline void hidp_del_timer(struct hidp_session *session)
477{
478 if (session->idle_to > 0)
479 del_timer(&session->timer);
480}
481
Andrew Morton91f5cca2008-02-05 03:07:58 -0800482static void hidp_process_handshake(struct hidp_session *session,
483 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484{
485 BT_DBG("session %p param 0x%02x", session, param);
Alan Ott08254112011-01-18 03:04:38 -0500486 session->output_report_success = 0; /* default condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487
488 switch (param) {
489 case HIDP_HSHK_SUCCESSFUL:
490 /* FIXME: Call into SET_ GET_ handlers here */
Alan Ott08254112011-01-18 03:04:38 -0500491 session->output_report_success = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 break;
493
494 case HIDP_HSHK_NOT_READY:
495 case HIDP_HSHK_ERR_INVALID_REPORT_ID:
496 case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
497 case HIDP_HSHK_ERR_INVALID_PARAMETER:
Alan Ott0ff17312011-01-18 03:04:40 -0500498 if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
499 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
500 wake_up_interruptible(&session->report_queue);
501 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 /* FIXME: Call into SET_ GET_ handlers here */
503 break;
504
505 case HIDP_HSHK_ERR_UNKNOWN:
506 break;
507
508 case HIDP_HSHK_ERR_FATAL:
509 /* Device requests a reboot, as this is the only way this error
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900510 * can be recovered. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 __hidp_send_ctrl_message(session,
512 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
513 break;
514
515 default:
516 __hidp_send_ctrl_message(session,
517 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
518 break;
519 }
Alan Ott08254112011-01-18 03:04:38 -0500520
521 /* Wake up the waiting thread. */
522 if (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
523 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
524 wake_up_interruptible(&session->report_queue);
525 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526}
527
Andrew Morton91f5cca2008-02-05 03:07:58 -0800528static void hidp_process_hid_control(struct hidp_session *session,
529 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530{
531 BT_DBG("session %p param 0x%02x", session, param);
532
Dave Youngeff001e2008-02-05 03:07:14 -0800533 if (param == HIDP_CTRL_VIRTUAL_CABLE_UNPLUG) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 /* Flush the transmit queues */
535 skb_queue_purge(&session->ctrl_transmit);
536 skb_queue_purge(&session->intr_transmit);
537
538 /* Kill session thread */
539 atomic_inc(&session->terminate);
Vikram Kandukuri981b1412009-07-01 11:39:58 +0530540 hidp_schedule(session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 }
542}
543
Alan Ott0ff17312011-01-18 03:04:40 -0500544/* Returns true if the passed-in skb should be freed by the caller. */
545static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800546 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547{
Alan Ott0ff17312011-01-18 03:04:40 -0500548 int done_with_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
550
551 switch (param) {
552 case HIDP_DATA_RTYPE_INPUT:
553 hidp_set_timer(session);
554
555 if (session->input)
556 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100557
558 if (session->hid)
559 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 break;
561
562 case HIDP_DATA_RTYPE_OTHER:
563 case HIDP_DATA_RTYPE_OUPUT:
564 case HIDP_DATA_RTYPE_FEATURE:
565 break;
566
567 default:
568 __hidp_send_ctrl_message(session,
569 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
570 }
Alan Ott0ff17312011-01-18 03:04:40 -0500571
572 if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
573 param == session->waiting_report_type) {
574 if (session->waiting_report_number < 0 ||
575 session->waiting_report_number == skb->data[0]) {
576 /* hidp_get_raw_report() is waiting on this report. */
577 session->report_return = skb;
578 done_with_skb = 0;
579 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
580 wake_up_interruptible(&session->report_queue);
581 }
582 }
583
584 return done_with_skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585}
586
Andrew Morton91f5cca2008-02-05 03:07:58 -0800587static void hidp_recv_ctrl_frame(struct hidp_session *session,
588 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589{
590 unsigned char hdr, type, param;
Alan Ott0ff17312011-01-18 03:04:40 -0500591 int free_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
593 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
594
595 hdr = skb->data[0];
596 skb_pull(skb, 1);
597
598 type = hdr & HIDP_HEADER_TRANS_MASK;
599 param = hdr & HIDP_HEADER_PARAM_MASK;
600
601 switch (type) {
602 case HIDP_TRANS_HANDSHAKE:
603 hidp_process_handshake(session, param);
604 break;
605
606 case HIDP_TRANS_HID_CONTROL:
607 hidp_process_hid_control(session, param);
608 break;
609
610 case HIDP_TRANS_DATA:
Alan Ott0ff17312011-01-18 03:04:40 -0500611 free_skb = hidp_process_data(session, skb, param);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 break;
613
614 default:
615 __hidp_send_ctrl_message(session,
616 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
617 break;
618 }
619
Alan Ott0ff17312011-01-18 03:04:40 -0500620 if (free_skb)
621 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622}
623
Andrew Morton91f5cca2008-02-05 03:07:58 -0800624static void hidp_recv_intr_frame(struct hidp_session *session,
625 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626{
627 unsigned char hdr;
628
629 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
630
631 hdr = skb->data[0];
632 skb_pull(skb, 1);
633
634 if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
635 hidp_set_timer(session);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100636
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 if (session->input)
638 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100639
640 if (session->hid) {
641 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
642 BT_DBG("report len %d", skb->len);
643 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 } else {
645 BT_DBG("Unsupported protocol header 0x%02x", hdr);
646 }
647
648 kfree_skb(skb);
649}
650
651static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
652{
653 struct kvec iv = { data, len };
654 struct msghdr msg;
655
656 BT_DBG("sock %p data %p len %d", sock, data, len);
657
658 if (!len)
659 return 0;
660
661 memset(&msg, 0, sizeof(msg));
662
663 return kernel_sendmsg(sock, &msg, &iv, 1, len);
664}
665
David S. Millerb03efcf2005-07-08 14:57:23 -0700666static void hidp_process_transmit(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700667{
668 struct sk_buff *skb;
669
670 BT_DBG("session %p", session);
671
672 while ((skb = skb_dequeue(&session->ctrl_transmit))) {
673 if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
674 skb_queue_head(&session->ctrl_transmit, skb);
675 break;
676 }
677
678 hidp_set_timer(session);
679 kfree_skb(skb);
680 }
681
682 while ((skb = skb_dequeue(&session->intr_transmit))) {
683 if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
684 skb_queue_head(&session->intr_transmit, skb);
685 break;
686 }
687
688 hidp_set_timer(session);
689 kfree_skb(skb);
690 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691}
692
693static int hidp_session(void *arg)
694{
695 struct hidp_session *session = arg;
696 struct sock *ctrl_sk = session->ctrl_sock->sk;
697 struct sock *intr_sk = session->intr_sock->sk;
698 struct sk_buff *skb;
699 int vendor = 0x0000, product = 0x0000;
700 wait_queue_t ctrl_wait, intr_wait;
701
702 BT_DBG("session %p", session);
703
704 if (session->input) {
705 vendor = session->input->id.vendor;
706 product = session->input->id.product;
707 }
708
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100709 if (session->hid) {
710 vendor = session->hid->vendor;
711 product = session->hid->product;
712 }
713
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 daemonize("khidpd_%04x%04x", vendor, product);
715 set_user_nice(current, -15);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700716
717 init_waitqueue_entry(&ctrl_wait, current);
718 init_waitqueue_entry(&intr_wait, current);
Eric Dumazetaa395142010-04-20 13:03:51 +0000719 add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
720 add_wait_queue(sk_sleep(intr_sk), &intr_wait);
Alan Ott0f69dca2011-01-18 03:04:37 -0500721 session->waiting_for_startup = 0;
722 wake_up_interruptible(&session->startup_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 while (!atomic_read(&session->terminate)) {
724 set_current_state(TASK_INTERRUPTIBLE);
725
Szymon Janc17f09a72011-03-21 14:20:01 +0100726 if (ctrl_sk->sk_state != BT_CONNECTED ||
727 intr_sk->sk_state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 break;
729
730 while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
731 skb_orphan(skb);
732 hidp_recv_ctrl_frame(session, skb);
733 }
734
735 while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
736 skb_orphan(skb);
737 hidp_recv_intr_frame(session, skb);
738 }
739
740 hidp_process_transmit(session);
741
742 schedule();
743 }
744 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +0000745 remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
746 remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747
748 down_write(&hidp_session_sem);
749
750 hidp_del_timer(session);
751
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 if (session->input) {
753 input_unregister_device(session->input);
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500754 session->input = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 }
756
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100757 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200758 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -0700759 session->hid = NULL;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100760 }
761
Marcel Holtmannec8dab32008-07-14 20:13:53 +0200762 /* Wakeup user-space polling for socket errors */
763 session->intr_sock->sk->sk_err = EUNATCH;
764 session->ctrl_sock->sk->sk_err = EUNATCH;
765
766 hidp_schedule(session);
767
David Woodhouse1c398582007-07-07 14:58:39 -0400768 fput(session->intr_sock->file);
769
Eric Dumazetaa395142010-04-20 13:03:51 +0000770 wait_event_timeout(*(sk_sleep(ctrl_sk)),
David Woodhouse1c398582007-07-07 14:58:39 -0400771 (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
772
773 fput(session->ctrl_sock->file);
774
775 __hidp_unlink_session(session);
776
Linus Torvalds1da177e2005-04-16 15:20:36 -0700777 up_write(&hidp_session_sem);
778
779 kfree(session);
780 return 0;
781}
782
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200783static struct device *hidp_get_device(struct hidp_session *session)
784{
785 bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
786 bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700787 struct device *device = NULL;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200788 struct hci_dev *hdev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200789
790 hdev = hci_get_route(dst, src);
791 if (!hdev)
792 return NULL;
793
Marcel Holtmannedad6382009-08-22 14:22:15 -0700794 session->conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
795 if (session->conn)
796 device = &session->conn->dev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200797
798 hci_dev_put(hdev);
799
Marcel Holtmannedad6382009-08-22 14:22:15 -0700800 return device;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200801}
802
Andrew Morton91f5cca2008-02-05 03:07:58 -0800803static int hidp_setup_input(struct hidp_session *session,
804 struct hidp_connadd_req *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700805{
Jiri Slabyc500c972008-05-16 11:49:16 +0200806 struct input_dev *input;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700807 int err, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808
Jiri Slabyc500c972008-05-16 11:49:16 +0200809 input = input_allocate_device();
810 if (!input)
811 return -ENOMEM;
812
813 session->input = input;
814
Marcel Holtmann5be39462007-05-09 09:15:30 +0200815 input_set_drvdata(input, session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500817 input->name = "Bluetooth HID Boot Protocol Device";
818
Linus Torvalds1da177e2005-04-16 15:20:36 -0700819 input->id.bustype = BUS_BLUETOOTH;
820 input->id.vendor = req->vendor;
821 input->id.product = req->product;
822 input->id.version = req->version;
823
824 if (req->subclass & 0x40) {
825 set_bit(EV_KEY, input->evbit);
826 set_bit(EV_LED, input->evbit);
827 set_bit(EV_REP, input->evbit);
828
829 set_bit(LED_NUML, input->ledbit);
830 set_bit(LED_CAPSL, input->ledbit);
831 set_bit(LED_SCROLLL, input->ledbit);
832 set_bit(LED_COMPOSE, input->ledbit);
833 set_bit(LED_KANA, input->ledbit);
834
835 for (i = 0; i < sizeof(hidp_keycode); i++)
836 set_bit(hidp_keycode[i], input->keybit);
837 clear_bit(0, input->keybit);
838 }
839
840 if (req->subclass & 0x80) {
Jiri Slaby7b19ada2007-10-18 23:40:32 -0700841 input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
842 input->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
843 BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
844 input->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
845 input->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |
846 BIT_MASK(BTN_EXTRA);
847 input->relbit[0] |= BIT_MASK(REL_WHEEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700848 }
849
Marcel Holtmann5be39462007-05-09 09:15:30 +0200850 input->dev.parent = hidp_get_device(session);
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200851
Linus Torvalds1da177e2005-04-16 15:20:36 -0700852 input->event = hidp_input_event;
853
Marcel Holtmannedad6382009-08-22 14:22:15 -0700854 err = input_register_device(input);
855 if (err < 0) {
856 hci_conn_put_device(session->conn);
857 return err;
858 }
859
860 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700861}
862
Marcel Holtmannf5ffd462007-02-17 23:58:53 +0100863static int hidp_open(struct hid_device *hid)
864{
865 return 0;
866}
867
868static void hidp_close(struct hid_device *hid)
869{
870}
871
Jiri Slabyc500c972008-05-16 11:49:16 +0200872static int hidp_parse(struct hid_device *hid)
873{
874 struct hidp_session *session = hid->driver_data;
Jiri Slabyc500c972008-05-16 11:49:16 +0200875
Michael Poole15c697c2010-02-05 12:23:43 -0500876 return hid_parse_report(session->hid, session->rd_data,
877 session->rd_size);
Jiri Slabyc500c972008-05-16 11:49:16 +0200878}
879
880static int hidp_start(struct hid_device *hid)
881{
882 struct hidp_session *session = hid->driver_data;
883 struct hid_report *report;
884
885 list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].
886 report_list, list)
887 hidp_send_report(session, report);
888
889 list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].
890 report_list, list)
891 hidp_send_report(session, report);
892
Jiri Slabyc500c972008-05-16 11:49:16 +0200893 return 0;
894}
895
896static void hidp_stop(struct hid_device *hid)
897{
898 struct hidp_session *session = hid->driver_data;
899
900 skb_queue_purge(&session->ctrl_transmit);
901 skb_queue_purge(&session->intr_transmit);
902
Jiri Slabyc500c972008-05-16 11:49:16 +0200903 hid->claimed = 0;
904}
905
906static struct hid_ll_driver hidp_hid_driver = {
907 .parse = hidp_parse,
908 .start = hidp_start,
909 .stop = hidp_stop,
910 .open = hidp_open,
911 .close = hidp_close,
912 .hidinput_input_event = hidp_hidinput_event,
913};
914
Alan Ott0f69dca2011-01-18 03:04:37 -0500915/* This function sets up the hid device. It does not add it
916 to the HID system. That is done in hidp_add_connection(). */
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200917static int hidp_setup_hid(struct hidp_session *session,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800918 struct hidp_connadd_req *req)
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100919{
Jiri Slabyc500c972008-05-16 11:49:16 +0200920 struct hid_device *hid;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700921 int err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100922
Michael Poole15c697c2010-02-05 12:23:43 -0500923 session->rd_data = kzalloc(req->rd_size, GFP_KERNEL);
924 if (!session->rd_data)
925 return -ENOMEM;
926
927 if (copy_from_user(session->rd_data, req->rd_data, req->rd_size)) {
928 err = -EFAULT;
929 goto fault;
930 }
931 session->rd_size = req->rd_size;
932
Jiri Slabyc500c972008-05-16 11:49:16 +0200933 hid = hid_allocate_device();
Michael Poole15c697c2010-02-05 12:23:43 -0500934 if (IS_ERR(hid)) {
935 err = PTR_ERR(hid);
936 goto fault;
937 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100938
Jiri Slabyc500c972008-05-16 11:49:16 +0200939 session->hid = hid;
Michael Poole15c697c2010-02-05 12:23:43 -0500940
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100941 hid->driver_data = session;
942
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100943 hid->bus = BUS_BLUETOOTH;
944 hid->vendor = req->vendor;
945 hid->product = req->product;
946 hid->version = req->version;
Jiri Slabyc500c972008-05-16 11:49:16 +0200947 hid->country = req->country;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100948
949 strncpy(hid->name, req->name, 128);
Gustavo F. Padovand6b2eb22010-09-03 18:29:46 -0300950 strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64);
951 strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100952
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200953 hid->dev.parent = hidp_get_device(session);
Jiri Slabyc500c972008-05-16 11:49:16 +0200954 hid->ll_driver = &hidp_hid_driver;
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200955
Alan Ott0ff17312011-01-18 03:04:40 -0500956 hid->hid_get_raw_report = hidp_get_raw_report;
Jiri Kosina2da31932009-11-26 16:20:56 +0100957 hid->hid_output_raw_report = hidp_output_raw_report;
958
Jiri Slabyc500c972008-05-16 11:49:16 +0200959 return 0;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700960
Michael Poole15c697c2010-02-05 12:23:43 -0500961fault:
962 kfree(session->rd_data);
963 session->rd_data = NULL;
964
Marcel Holtmannedad6382009-08-22 14:22:15 -0700965 return err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100966}
967
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
969{
970 struct hidp_session *session, *s;
971 int err;
972
973 BT_DBG("");
974
975 if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
976 bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
977 return -ENOTUNIQ;
978
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200979 session = kzalloc(sizeof(struct hidp_session), GFP_KERNEL);
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500980 if (!session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700981 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100983 BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
984
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985 down_write(&hidp_session_sem);
986
987 s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
988 if (s && s->state == BT_CONNECTED) {
989 err = -EEXIST;
990 goto failed;
991 }
992
993 bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
994
995 session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->omtu, l2cap_pi(ctrl_sock->sk)->imtu);
996 session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->omtu, l2cap_pi(intr_sock->sk)->imtu);
997
998 BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
999
1000 session->ctrl_sock = ctrl_sock;
1001 session->intr_sock = intr_sock;
1002 session->state = BT_CONNECTED;
1003
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001004 setup_timer(&session->timer, hidp_idle_timeout, (unsigned long)session);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005
1006 skb_queue_head_init(&session->ctrl_transmit);
1007 skb_queue_head_init(&session->intr_transmit);
1008
Alan Ott0ff17312011-01-18 03:04:40 -05001009 mutex_init(&session->report_mutex);
1010 init_waitqueue_head(&session->report_queue);
Alan Ott0f69dca2011-01-18 03:04:37 -05001011 init_waitqueue_head(&session->startup_queue);
1012 session->waiting_for_startup = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
1014 session->idle_to = req->idle_to;
1015
Jiri Slabyc500c972008-05-16 11:49:16 +02001016 if (req->rd_size > 0) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001017 err = hidp_setup_hid(session, req);
Jiri Slabyd458a9d2008-05-16 11:49:20 +02001018 if (err && err != -ENODEV)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001019 goto purge;
Jiri Slabyc500c972008-05-16 11:49:16 +02001020 }
1021
1022 if (!session->hid) {
1023 err = hidp_setup_input(session, req);
1024 if (err < 0)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001025 goto purge;
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001026 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001027
Linus Torvalds1da177e2005-04-16 15:20:36 -07001028 __hidp_link_session(session);
1029
1030 hidp_set_timer(session);
1031
1032 err = kernel_thread(hidp_session, session, CLONE_KERNEL);
1033 if (err < 0)
1034 goto unlink;
Alan Ott0f69dca2011-01-18 03:04:37 -05001035 while (session->waiting_for_startup) {
1036 wait_event_interruptible(session->startup_queue,
1037 !session->waiting_for_startup);
1038 }
1039
1040 err = hid_add_device(session->hid);
1041 if (err < 0)
1042 goto err_add_device;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043
1044 if (session->input) {
1045 hidp_send_ctrl_message(session,
1046 HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
1047 session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
1048
1049 session->leds = 0xff;
1050 hidp_input_event(session->input, EV_LED, 0, 0);
1051 }
1052
1053 up_write(&hidp_session_sem);
1054 return 0;
1055
Alan Ott0f69dca2011-01-18 03:04:37 -05001056err_add_device:
1057 hid_destroy_device(session->hid);
1058 session->hid = NULL;
1059 atomic_inc(&session->terminate);
1060 hidp_schedule(session);
1061
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062unlink:
1063 hidp_del_timer(session);
1064
1065 __hidp_unlink_session(session);
1066
Marcel Holtmannedad6382009-08-22 14:22:15 -07001067 if (session->input) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001068 input_unregister_device(session->input);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001069 session->input = NULL;
1070 }
1071
1072 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001073 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001074 session->hid = NULL;
1075 }
1076
Michael Poole15c697c2010-02-05 12:23:43 -05001077 kfree(session->rd_data);
1078 session->rd_data = NULL;
1079
Marcel Holtmannedad6382009-08-22 14:22:15 -07001080purge:
Jiri Slabyc500c972008-05-16 11:49:16 +02001081 skb_queue_purge(&session->ctrl_transmit);
1082 skb_queue_purge(&session->intr_transmit);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001083
Jiri Slabyc500c972008-05-16 11:49:16 +02001084failed:
1085 up_write(&hidp_session_sem);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001086
Marcel Holtmann5be39462007-05-09 09:15:30 +02001087 input_free_device(session->input);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001088 kfree(session);
1089 return err;
1090}
1091
1092int hidp_del_connection(struct hidp_conndel_req *req)
1093{
1094 struct hidp_session *session;
1095 int err = 0;
1096
1097 BT_DBG("");
1098
1099 down_read(&hidp_session_sem);
1100
1101 session = __hidp_get_session(&req->bdaddr);
1102 if (session) {
1103 if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
1104 hidp_send_ctrl_message(session,
1105 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
1106 } else {
1107 /* Flush the transmit queues */
1108 skb_queue_purge(&session->ctrl_transmit);
1109 skb_queue_purge(&session->intr_transmit);
1110
Marcel Holtmannec8dab32008-07-14 20:13:53 +02001111 /* Wakeup user-space polling for socket errors */
1112 session->intr_sock->sk->sk_err = EUNATCH;
1113 session->ctrl_sock->sk->sk_err = EUNATCH;
1114
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 /* Kill session thread */
1116 atomic_inc(&session->terminate);
1117 hidp_schedule(session);
1118 }
1119 } else
1120 err = -ENOENT;
1121
1122 up_read(&hidp_session_sem);
1123 return err;
1124}
1125
1126int hidp_get_connlist(struct hidp_connlist_req *req)
1127{
1128 struct list_head *p;
1129 int err = 0, n = 0;
1130
1131 BT_DBG("");
1132
1133 down_read(&hidp_session_sem);
1134
1135 list_for_each(p, &hidp_session_list) {
1136 struct hidp_session *session;
1137 struct hidp_conninfo ci;
1138
1139 session = list_entry(p, struct hidp_session, list);
1140
1141 __hidp_copy_session(session, &ci);
1142
1143 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
1144 err = -EFAULT;
1145 break;
1146 }
1147
1148 if (++n >= req->cnum)
1149 break;
1150
1151 req->ci++;
1152 }
1153 req->cnum = n;
1154
1155 up_read(&hidp_session_sem);
1156 return err;
1157}
1158
1159int hidp_get_conninfo(struct hidp_conninfo *ci)
1160{
1161 struct hidp_session *session;
1162 int err = 0;
1163
1164 down_read(&hidp_session_sem);
1165
1166 session = __hidp_get_session(&ci->bdaddr);
1167 if (session)
1168 __hidp_copy_session(session, ci);
1169 else
1170 err = -ENOENT;
1171
1172 up_read(&hidp_session_sem);
1173 return err;
1174}
1175
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001176static const struct hid_device_id hidp_table[] = {
1177 { HID_BLUETOOTH_DEVICE(HID_ANY_ID, HID_ANY_ID) },
1178 { }
1179};
1180
1181static struct hid_driver hidp_driver = {
1182 .name = "generic-bluetooth",
1183 .id_table = hidp_table,
1184};
1185
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186static int __init hidp_init(void)
1187{
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001188 int ret;
1189
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190 BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
1191
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001192 ret = hid_register_driver(&hidp_driver);
1193 if (ret)
1194 goto err;
1195
1196 ret = hidp_init_sockets();
1197 if (ret)
1198 goto err_drv;
1199
1200 return 0;
1201err_drv:
1202 hid_unregister_driver(&hidp_driver);
1203err:
1204 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205}
1206
1207static void __exit hidp_exit(void)
1208{
1209 hidp_cleanup_sockets();
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001210 hid_unregister_driver(&hidp_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211}
1212
1213module_init(hidp_init);
1214module_exit(hidp_exit);
1215
1216MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
1217MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
1218MODULE_VERSION(VERSION);
1219MODULE_LICENSE("GPL");
1220MODULE_ALIAS("bt-proto-6");