blob: d7bae2be83b2a192969aaab8d14143c0d7123e22 [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>
Szymon Jancaabf6f82011-04-05 15:37:45 +020040#include <linux/kthread.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <net/sock.h>
42
43#include <linux/input.h>
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +010044#include <linux/hid.h>
Marcel Holtmann364f6352009-08-22 14:15:53 -070045#include <linux/hidraw.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070046
47#include <net/bluetooth/bluetooth.h>
Marcel Holtmann0a85b962006-07-06 13:09:02 +020048#include <net/bluetooth/hci_core.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <net/bluetooth/l2cap.h>
50
51#include "hidp.h"
52
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +010053#define VERSION "1.2"
Linus Torvalds1da177e2005-04-16 15:20:36 -070054
55static DECLARE_RWSEM(hidp_session_sem);
56static LIST_HEAD(hidp_session_list);
57
58static unsigned char hidp_keycode[256] = {
Szymon Janc17f09a72011-03-21 14:20:01 +010059 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36,
60 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45,
61 21, 44, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 1,
62 14, 15, 57, 12, 13, 26, 27, 43, 43, 39, 40, 41, 51, 52,
63 53, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 87, 88,
64 99, 70, 119, 110, 102, 104, 111, 107, 109, 106, 105, 108, 103, 69,
65 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 72, 73,
66 82, 83, 86, 127, 116, 117, 183, 184, 185, 186, 187, 188, 189, 190,
67 191, 192, 193, 194, 134, 138, 130, 132, 128, 129, 131, 137, 133, 135,
68 136, 113, 115, 114, 0, 0, 0, 121, 0, 89, 93, 124, 92, 94,
69 95, 0, 0, 0, 122, 123, 90, 91, 85, 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 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,
76 114, 113, 150, 158, 159, 128, 136, 177, 178, 176, 142, 152, 173, 140
Linus Torvalds1da177e2005-04-16 15:20:36 -070077};
78
79static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
80
81static 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
96static void __hidp_link_session(struct hidp_session *session)
97{
98 __module_get(THIS_MODULE);
99 list_add(&session->list, &hidp_session_list);
Marcel Holtmannedad6382009-08-22 14:22:15 -0700100
101 hci_conn_hold_device(session->conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102}
103
104static void __hidp_unlink_session(struct hidp_session *session)
105{
Marcel Holtmannedad6382009-08-22 14:22:15 -0700106 hci_conn_put_device(session->conn);
107
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108 list_del(&session->list);
109 module_put(THIS_MODULE);
110}
111
112static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
113{
Vasiliy Kulikovd31dbf62010-10-30 18:26:31 +0400114 memset(ci, 0, sizeof(*ci));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 bacpy(&ci->bdaddr, &session->bdaddr);
116
117 ci->flags = session->flags;
118 ci->state = session->state;
119
120 ci->vendor = 0x0000;
121 ci->product = 0x0000;
122 ci->version = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
124 if (session->input) {
125 ci->vendor = session->input->id.vendor;
126 ci->product = session->input->id.product;
127 ci->version = session->input->id.version;
128 if (session->input->name)
129 strncpy(ci->name, session->input->name, 128);
130 else
131 strncpy(ci->name, "HID Boot Device", 128);
132 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100133
134 if (session->hid) {
135 ci->vendor = session->hid->vendor;
136 ci->product = session->hid->product;
137 ci->version = session->hid->version;
138 strncpy(ci->name, session->hid->name, 128);
139 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700140}
141
Andrew Morton91f5cca2008-02-05 03:07:58 -0800142static int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
143 unsigned int type, unsigned int code, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145 unsigned char newleds;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100146 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100148 BT_DBG("session %p type %d code %d value %d", session, type, code, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149
150 if (type != EV_LED)
151 return -1;
152
153 newleds = (!!test_bit(LED_KANA, dev->led) << 3) |
154 (!!test_bit(LED_COMPOSE, dev->led) << 3) |
155 (!!test_bit(LED_SCROLLL, dev->led) << 2) |
156 (!!test_bit(LED_CAPSL, dev->led) << 1) |
157 (!!test_bit(LED_NUML, dev->led));
158
159 if (session->leds == newleds)
160 return 0;
161
162 session->leds = newleds;
163
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200164 skb = alloc_skb(3, GFP_ATOMIC);
165 if (!skb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700166 BT_ERR("Can't allocate memory for new frame");
167 return -ENOMEM;
168 }
169
170 *skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
171 *skb_put(skb, 1) = 0x01;
172 *skb_put(skb, 1) = newleds;
173
174 skb_queue_tail(&session->intr_transmit, skb);
175
176 hidp_schedule(session);
177
178 return 0;
179}
180
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100181static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
182{
Marcel Holtmann5be39462007-05-09 09:15:30 +0200183 struct hid_device *hid = input_get_drvdata(dev);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100184 struct hidp_session *session = hid->driver_data;
185
186 return hidp_queue_event(session, dev, type, code, value);
187}
188
189static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
190{
Marcel Holtmann5be39462007-05-09 09:15:30 +0200191 struct hidp_session *session = input_get_drvdata(dev);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100192
193 return hidp_queue_event(session, dev, type, code, value);
194}
195
Linus Torvalds1da177e2005-04-16 15:20:36 -0700196static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
197{
198 struct input_dev *dev = session->input;
199 unsigned char *keys = session->keys;
200 unsigned char *udata = skb->data + 1;
201 signed char *sdata = skb->data + 1;
202 int i, size = skb->len - 1;
203
204 switch (skb->data[0]) {
205 case 0x01: /* Keyboard report */
206 for (i = 0; i < 8; i++)
207 input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
208
209 /* If all the key codes have been set to 0x01, it means
210 * too many keys were pressed at the same time. */
211 if (!memcmp(udata + 2, hidp_mkeyspat, 6))
212 break;
213
214 for (i = 2; i < 8; i++) {
215 if (keys[i] > 3 && memscan(udata + 2, keys[i], 6) == udata + 8) {
216 if (hidp_keycode[keys[i]])
217 input_report_key(dev, hidp_keycode[keys[i]], 0);
218 else
219 BT_ERR("Unknown key (scancode %#x) released.", keys[i]);
220 }
221
222 if (udata[i] > 3 && memscan(keys + 2, udata[i], 6) == keys + 8) {
223 if (hidp_keycode[udata[i]])
224 input_report_key(dev, hidp_keycode[udata[i]], 1);
225 else
226 BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]);
227 }
228 }
229
230 memcpy(keys, udata, 8);
231 break;
232
233 case 0x02: /* Mouse report */
234 input_report_key(dev, BTN_LEFT, sdata[0] & 0x01);
235 input_report_key(dev, BTN_RIGHT, sdata[0] & 0x02);
236 input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
237 input_report_key(dev, BTN_SIDE, sdata[0] & 0x08);
238 input_report_key(dev, BTN_EXTRA, sdata[0] & 0x10);
239
240 input_report_rel(dev, REL_X, sdata[1]);
241 input_report_rel(dev, REL_Y, sdata[2]);
242
243 if (size > 3)
244 input_report_rel(dev, REL_WHEEL, sdata[3]);
245 break;
246 }
247
248 input_sync(dev);
249}
250
Bastien Nocera6bf82682010-01-20 12:00:42 +0000251static int __hidp_send_ctrl_message(struct hidp_session *session,
252 unsigned char hdr, unsigned char *data, int size)
253{
254 struct sk_buff *skb;
255
256 BT_DBG("session %p data %p size %d", session, data, size);
257
David Herrmann794d1752011-08-26 14:06:02 +0200258 if (atomic_read(&session->terminate))
259 return -EIO;
260
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200261 skb = alloc_skb(size + 1, GFP_ATOMIC);
262 if (!skb) {
Bastien Nocera6bf82682010-01-20 12:00:42 +0000263 BT_ERR("Can't allocate memory for new frame");
264 return -ENOMEM;
265 }
266
267 *skb_put(skb, 1) = hdr;
268 if (data && size > 0)
269 memcpy(skb_put(skb, size), data, size);
270
271 skb_queue_tail(&session->ctrl_transmit, skb);
272
273 return 0;
274}
275
276static inline int hidp_send_ctrl_message(struct hidp_session *session,
277 unsigned char hdr, unsigned char *data, int size)
278{
279 int err;
280
281 err = __hidp_send_ctrl_message(session, hdr, data, size);
282
283 hidp_schedule(session);
284
285 return err;
286}
287
Andrew Morton91f5cca2008-02-05 03:07:58 -0800288static int hidp_queue_report(struct hidp_session *session,
289 unsigned char *data, int size)
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100290{
291 struct sk_buff *skb;
292
Dave Young6792b5e2007-10-20 14:15:39 +0200293 BT_DBG("session %p hid %p data %p size %d", session, session->hid, data, size);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100294
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200295 skb = alloc_skb(size + 1, GFP_ATOMIC);
296 if (!skb) {
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100297 BT_ERR("Can't allocate memory for new frame");
298 return -ENOMEM;
299 }
300
301 *skb_put(skb, 1) = 0xa2;
302 if (size > 0)
303 memcpy(skb_put(skb, size), data, size);
304
305 skb_queue_tail(&session->intr_transmit, skb);
306
307 hidp_schedule(session);
308
309 return 0;
310}
311
312static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
313{
314 unsigned char buf[32];
315 int rsize;
316
317 rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
318 if (rsize > sizeof(buf))
319 return -EIO;
320
321 hid_output_report(report, buf);
322
323 return hidp_queue_report(session, buf, rsize);
324}
325
Alan Ott0ff17312011-01-18 03:04:40 -0500326static int hidp_get_raw_report(struct hid_device *hid,
327 unsigned char report_number,
328 unsigned char *data, size_t count,
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100329 unsigned char report_type)
Jiri Kosina2da31932009-11-26 16:20:56 +0100330{
Alan Ott0ff17312011-01-18 03:04:40 -0500331 struct hidp_session *session = hid->driver_data;
332 struct sk_buff *skb;
333 size_t len;
334 int numbered_reports = hid->report_enum[report_type].numbered;
David Herrmann794d1752011-08-26 14:06:02 +0200335 int ret;
Alan Ott0ff17312011-01-18 03:04:40 -0500336
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100337 switch (report_type) {
338 case HID_FEATURE_REPORT:
Alan Ott0ff17312011-01-18 03:04:40 -0500339 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
340 break;
341 case HID_INPUT_REPORT:
342 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_INPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100343 break;
344 case HID_OUTPUT_REPORT:
Alan Ott0ff17312011-01-18 03:04:40 -0500345 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_OUPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100346 break;
347 default:
348 return -EINVAL;
349 }
350
Alan Ott0ff17312011-01-18 03:04:40 -0500351 if (mutex_lock_interruptible(&session->report_mutex))
352 return -ERESTARTSYS;
353
354 /* Set up our wait, and send the report request to the device. */
355 session->waiting_report_type = report_type & HIDP_DATA_RTYPE_MASK;
356 session->waiting_report_number = numbered_reports ? report_number : -1;
357 set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
358 data[0] = report_number;
David Herrmann794d1752011-08-26 14:06:02 +0200359 ret = hidp_send_ctrl_message(hid->driver_data, report_type, data, 1);
360 if (ret)
361 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500362
363 /* Wait for the return of the report. The returned report
364 gets put in session->report_return. */
365 while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
366 int res;
367
368 res = wait_event_interruptible_timeout(session->report_queue,
369 !test_bit(HIDP_WAITING_FOR_RETURN, &session->flags),
370 5*HZ);
371 if (res == 0) {
372 /* timeout */
David Herrmann794d1752011-08-26 14:06:02 +0200373 ret = -EIO;
374 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500375 }
376 if (res < 0) {
377 /* signal */
David Herrmann794d1752011-08-26 14:06:02 +0200378 ret = -ERESTARTSYS;
379 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500380 }
381 }
382
383 skb = session->report_return;
384 if (skb) {
385 len = skb->len < count ? skb->len : count;
386 memcpy(data, skb->data, len);
387
388 kfree_skb(skb);
389 session->report_return = NULL;
390 } else {
391 /* Device returned a HANDSHAKE, indicating protocol error. */
392 len = -EIO;
393 }
394
395 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
396 mutex_unlock(&session->report_mutex);
397
398 return len;
399
David Herrmann794d1752011-08-26 14:06:02 +0200400err:
Alan Ott0ff17312011-01-18 03:04:40 -0500401 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
402 mutex_unlock(&session->report_mutex);
David Herrmann794d1752011-08-26 14:06:02 +0200403 return ret;
Alan Ott0ff17312011-01-18 03:04:40 -0500404}
405
Linus Torvalds1da177e2005-04-16 15:20:36 -0700406static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
Jiri Kosina2da31932009-11-26 16:20:56 +0100407 unsigned char report_type)
408{
Alan Ott08254112011-01-18 03:04:38 -0500409 struct hidp_session *session = hid->driver_data;
410 int ret;
411
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100412 switch (report_type) {
413 case HID_FEATURE_REPORT:
414 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
415 break;
416 case HID_OUTPUT_REPORT:
Antonio Ospite97e1efb2011-02-20 18:26:46 +0100417 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100418 break;
419 default:
420 return -EINVAL;
421 }
422
Alan Ott08254112011-01-18 03:04:38 -0500423 if (mutex_lock_interruptible(&session->report_mutex))
424 return -ERESTARTSYS;
425
426 /* Set up our wait, and send the report request to the device. */
427 set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
David Herrmann794d1752011-08-26 14:06:02 +0200428 ret = hidp_send_ctrl_message(hid->driver_data, report_type, data,
429 count);
430 if (ret)
Alan Ott08254112011-01-18 03:04:38 -0500431 goto err;
Alan Ott08254112011-01-18 03:04:38 -0500432
433 /* Wait for the ACK from the device. */
434 while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
435 int res;
436
437 res = wait_event_interruptible_timeout(session->report_queue,
438 !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags),
439 10*HZ);
440 if (res == 0) {
441 /* timeout */
442 ret = -EIO;
443 goto err;
444 }
445 if (res < 0) {
446 /* signal */
447 ret = -ERESTARTSYS;
448 goto err;
449 }
450 }
451
452 if (!session->output_report_success) {
453 ret = -EIO;
454 goto err;
455 }
456
457 ret = count;
458
459err:
460 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
461 mutex_unlock(&session->report_mutex);
462 return ret;
Jiri Kosina2da31932009-11-26 16:20:56 +0100463}
464
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465static void hidp_idle_timeout(unsigned long arg)
466{
467 struct hidp_session *session = (struct hidp_session *) arg;
468
Peter Hurley7bb59df2011-06-30 13:53:53 -0400469 atomic_inc(&session->terminate);
470 wake_up_process(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471}
472
Andrew Morton91f5cca2008-02-05 03:07:58 -0800473static void hidp_set_timer(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474{
475 if (session->idle_to > 0)
476 mod_timer(&session->timer, jiffies + HZ * session->idle_to);
477}
478
479static inline void hidp_del_timer(struct hidp_session *session)
480{
481 if (session->idle_to > 0)
482 del_timer(&session->timer);
483}
484
Andrew Morton91f5cca2008-02-05 03:07:58 -0800485static void hidp_process_handshake(struct hidp_session *session,
486 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487{
488 BT_DBG("session %p param 0x%02x", session, param);
Alan Ott08254112011-01-18 03:04:38 -0500489 session->output_report_success = 0; /* default condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490
491 switch (param) {
492 case HIDP_HSHK_SUCCESSFUL:
493 /* FIXME: Call into SET_ GET_ handlers here */
Alan Ott08254112011-01-18 03:04:38 -0500494 session->output_report_success = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495 break;
496
497 case HIDP_HSHK_NOT_READY:
498 case HIDP_HSHK_ERR_INVALID_REPORT_ID:
499 case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
500 case HIDP_HSHK_ERR_INVALID_PARAMETER:
Alan Ott0ff17312011-01-18 03:04:40 -0500501 if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
502 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
503 wake_up_interruptible(&session->report_queue);
504 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700505 /* FIXME: Call into SET_ GET_ handlers here */
506 break;
507
508 case HIDP_HSHK_ERR_UNKNOWN:
509 break;
510
511 case HIDP_HSHK_ERR_FATAL:
512 /* Device requests a reboot, as this is the only way this error
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900513 * can be recovered. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 __hidp_send_ctrl_message(session,
515 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
516 break;
517
518 default:
519 __hidp_send_ctrl_message(session,
520 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
521 break;
522 }
Alan Ott08254112011-01-18 03:04:38 -0500523
524 /* Wake up the waiting thread. */
525 if (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
526 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
527 wake_up_interruptible(&session->report_queue);
528 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529}
530
Andrew Morton91f5cca2008-02-05 03:07:58 -0800531static void hidp_process_hid_control(struct hidp_session *session,
532 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533{
534 BT_DBG("session %p param 0x%02x", session, param);
535
Dave Youngeff001e2008-02-05 03:07:14 -0800536 if (param == HIDP_CTRL_VIRTUAL_CABLE_UNPLUG) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700537 /* Flush the transmit queues */
538 skb_queue_purge(&session->ctrl_transmit);
539 skb_queue_purge(&session->intr_transmit);
540
Peter Hurley7bb59df2011-06-30 13:53:53 -0400541 atomic_inc(&session->terminate);
542 wake_up_process(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700543 }
544}
545
Alan Ott0ff17312011-01-18 03:04:40 -0500546/* Returns true if the passed-in skb should be freed by the caller. */
547static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800548 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549{
Alan Ott0ff17312011-01-18 03:04:40 -0500550 int done_with_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
552
553 switch (param) {
554 case HIDP_DATA_RTYPE_INPUT:
555 hidp_set_timer(session);
556
557 if (session->input)
558 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100559
560 if (session->hid)
561 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562 break;
563
564 case HIDP_DATA_RTYPE_OTHER:
565 case HIDP_DATA_RTYPE_OUPUT:
566 case HIDP_DATA_RTYPE_FEATURE:
567 break;
568
569 default:
570 __hidp_send_ctrl_message(session,
571 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
572 }
Alan Ott0ff17312011-01-18 03:04:40 -0500573
574 if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
575 param == session->waiting_report_type) {
576 if (session->waiting_report_number < 0 ||
577 session->waiting_report_number == skb->data[0]) {
578 /* hidp_get_raw_report() is waiting on this report. */
579 session->report_return = skb;
580 done_with_skb = 0;
581 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
582 wake_up_interruptible(&session->report_queue);
583 }
584 }
585
586 return done_with_skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587}
588
Andrew Morton91f5cca2008-02-05 03:07:58 -0800589static void hidp_recv_ctrl_frame(struct hidp_session *session,
590 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591{
592 unsigned char hdr, type, param;
Alan Ott0ff17312011-01-18 03:04:40 -0500593 int free_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594
595 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
596
597 hdr = skb->data[0];
598 skb_pull(skb, 1);
599
600 type = hdr & HIDP_HEADER_TRANS_MASK;
601 param = hdr & HIDP_HEADER_PARAM_MASK;
602
603 switch (type) {
604 case HIDP_TRANS_HANDSHAKE:
605 hidp_process_handshake(session, param);
606 break;
607
608 case HIDP_TRANS_HID_CONTROL:
609 hidp_process_hid_control(session, param);
610 break;
611
612 case HIDP_TRANS_DATA:
Alan Ott0ff17312011-01-18 03:04:40 -0500613 free_skb = hidp_process_data(session, skb, param);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 break;
615
616 default:
617 __hidp_send_ctrl_message(session,
618 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
619 break;
620 }
621
Alan Ott0ff17312011-01-18 03:04:40 -0500622 if (free_skb)
623 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624}
625
Andrew Morton91f5cca2008-02-05 03:07:58 -0800626static void hidp_recv_intr_frame(struct hidp_session *session,
627 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628{
629 unsigned char hdr;
630
631 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
632
633 hdr = skb->data[0];
634 skb_pull(skb, 1);
635
636 if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
637 hidp_set_timer(session);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100638
Linus Torvalds1da177e2005-04-16 15:20:36 -0700639 if (session->input)
640 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100641
642 if (session->hid) {
643 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
644 BT_DBG("report len %d", skb->len);
645 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700646 } else {
647 BT_DBG("Unsupported protocol header 0x%02x", hdr);
648 }
649
650 kfree_skb(skb);
651}
652
653static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
654{
655 struct kvec iv = { data, len };
656 struct msghdr msg;
657
658 BT_DBG("sock %p data %p len %d", sock, data, len);
659
660 if (!len)
661 return 0;
662
663 memset(&msg, 0, sizeof(msg));
664
665 return kernel_sendmsg(sock, &msg, &iv, 1, len);
666}
667
David S. Millerb03efcf2005-07-08 14:57:23 -0700668static void hidp_process_transmit(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700669{
670 struct sk_buff *skb;
671
672 BT_DBG("session %p", session);
673
674 while ((skb = skb_dequeue(&session->ctrl_transmit))) {
675 if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
676 skb_queue_head(&session->ctrl_transmit, skb);
677 break;
678 }
679
680 hidp_set_timer(session);
681 kfree_skb(skb);
682 }
683
684 while ((skb = skb_dequeue(&session->intr_transmit))) {
685 if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
686 skb_queue_head(&session->intr_transmit, skb);
687 break;
688 }
689
690 hidp_set_timer(session);
691 kfree_skb(skb);
692 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693}
694
695static int hidp_session(void *arg)
696{
697 struct hidp_session *session = arg;
698 struct sock *ctrl_sk = session->ctrl_sock->sk;
699 struct sock *intr_sk = session->intr_sock->sk;
700 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 wait_queue_t ctrl_wait, intr_wait;
702
703 BT_DBG("session %p", session);
704
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 set_user_nice(current, -15);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706
707 init_waitqueue_entry(&ctrl_wait, current);
708 init_waitqueue_entry(&intr_wait, current);
Eric Dumazetaa395142010-04-20 13:03:51 +0000709 add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
710 add_wait_queue(sk_sleep(intr_sk), &intr_wait);
Alan Ott0f69dca2011-01-18 03:04:37 -0500711 session->waiting_for_startup = 0;
712 wake_up_interruptible(&session->startup_queue);
Peter Hurley7bb59df2011-06-30 13:53:53 -0400713 set_current_state(TASK_INTERRUPTIBLE);
714 while (!atomic_read(&session->terminate)) {
Szymon Janc17f09a72011-03-21 14:20:01 +0100715 if (ctrl_sk->sk_state != BT_CONNECTED ||
716 intr_sk->sk_state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 break;
718
719 while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
720 skb_orphan(skb);
Mat Martineau44935722011-07-22 14:53:58 -0700721 if (!skb_linearize(skb))
722 hidp_recv_ctrl_frame(session, skb);
723 else
724 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725 }
726
727 while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
728 skb_orphan(skb);
Mat Martineau44935722011-07-22 14:53:58 -0700729 if (!skb_linearize(skb))
730 hidp_recv_intr_frame(session, skb);
731 else
732 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 }
734
735 hidp_process_transmit(session);
736
737 schedule();
Peter Hurley7bb59df2011-06-30 13:53:53 -0400738 set_current_state(TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 }
740 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +0000741 remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
742 remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
David Herrmann794d1752011-08-26 14:06:02 +0200744 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
745 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
746 wake_up_interruptible(&session->report_queue);
747
Linus Torvalds1da177e2005-04-16 15:20:36 -0700748 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
Peter Hurley1c97e942011-08-05 10:51:34 -0400779 kfree(session->rd_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700780 kfree(session);
781 return 0;
782}
783
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200784static struct device *hidp_get_device(struct hidp_session *session)
785{
786 bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
787 bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700788 struct device *device = NULL;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200789 struct hci_dev *hdev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200790
791 hdev = hci_get_route(dst, src);
792 if (!hdev)
793 return NULL;
794
Marcel Holtmannedad6382009-08-22 14:22:15 -0700795 session->conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
796 if (session->conn)
797 device = &session->conn->dev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200798
799 hci_dev_put(hdev);
800
Marcel Holtmannedad6382009-08-22 14:22:15 -0700801 return device;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200802}
803
Andrew Morton91f5cca2008-02-05 03:07:58 -0800804static int hidp_setup_input(struct hidp_session *session,
805 struct hidp_connadd_req *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700806{
Jiri Slabyc500c972008-05-16 11:49:16 +0200807 struct input_dev *input;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700808 int err, i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809
Jiri Slabyc500c972008-05-16 11:49:16 +0200810 input = input_allocate_device();
811 if (!input)
812 return -ENOMEM;
813
814 session->input = input;
815
Marcel Holtmann5be39462007-05-09 09:15:30 +0200816 input_set_drvdata(input, session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700817
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500818 input->name = "Bluetooth HID Boot Protocol Device";
819
Linus Torvalds1da177e2005-04-16 15:20:36 -0700820 input->id.bustype = BUS_BLUETOOTH;
821 input->id.vendor = req->vendor;
822 input->id.product = req->product;
823 input->id.version = req->version;
824
825 if (req->subclass & 0x40) {
826 set_bit(EV_KEY, input->evbit);
827 set_bit(EV_LED, input->evbit);
828 set_bit(EV_REP, input->evbit);
829
830 set_bit(LED_NUML, input->ledbit);
831 set_bit(LED_CAPSL, input->ledbit);
832 set_bit(LED_SCROLLL, input->ledbit);
833 set_bit(LED_COMPOSE, input->ledbit);
834 set_bit(LED_KANA, input->ledbit);
835
836 for (i = 0; i < sizeof(hidp_keycode); i++)
837 set_bit(hidp_keycode[i], input->keybit);
838 clear_bit(0, input->keybit);
839 }
840
841 if (req->subclass & 0x80) {
Jiri Slaby7b19ada2007-10-18 23:40:32 -0700842 input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
843 input->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
844 BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
845 input->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
846 input->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |
847 BIT_MASK(BTN_EXTRA);
848 input->relbit[0] |= BIT_MASK(REL_WHEEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 }
850
Marcel Holtmann5be39462007-05-09 09:15:30 +0200851 input->dev.parent = hidp_get_device(session);
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200852
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 input->event = hidp_input_event;
854
Marcel Holtmannedad6382009-08-22 14:22:15 -0700855 err = input_register_device(input);
856 if (err < 0) {
Peter Hurley615aedd2011-08-05 10:51:50 -0400857 input_free_device(input);
858 session->input = NULL;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700859 return err;
860 }
861
862 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700863}
864
Marcel Holtmannf5ffd462007-02-17 23:58:53 +0100865static int hidp_open(struct hid_device *hid)
866{
867 return 0;
868}
869
870static void hidp_close(struct hid_device *hid)
871{
872}
873
Jiri Slabyc500c972008-05-16 11:49:16 +0200874static int hidp_parse(struct hid_device *hid)
875{
876 struct hidp_session *session = hid->driver_data;
Jiri Slabyc500c972008-05-16 11:49:16 +0200877
Michael Poole15c697c2010-02-05 12:23:43 -0500878 return hid_parse_report(session->hid, session->rd_data,
879 session->rd_size);
Jiri Slabyc500c972008-05-16 11:49:16 +0200880}
881
882static int hidp_start(struct hid_device *hid)
883{
884 struct hidp_session *session = hid->driver_data;
885 struct hid_report *report;
886
David Herrmann142c69c2011-08-26 13:27:12 +0200887 if (hid->quirks & HID_QUIRK_NO_INIT_REPORTS)
888 return 0;
889
Jiri Slabyc500c972008-05-16 11:49:16 +0200890 list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].
891 report_list, list)
892 hidp_send_report(session, report);
893
894 list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].
895 report_list, list)
896 hidp_send_report(session, report);
897
Jiri Slabyc500c972008-05-16 11:49:16 +0200898 return 0;
899}
900
901static void hidp_stop(struct hid_device *hid)
902{
903 struct hidp_session *session = hid->driver_data;
904
905 skb_queue_purge(&session->ctrl_transmit);
906 skb_queue_purge(&session->intr_transmit);
907
Jiri Slabyc500c972008-05-16 11:49:16 +0200908 hid->claimed = 0;
909}
910
911static struct hid_ll_driver hidp_hid_driver = {
912 .parse = hidp_parse,
913 .start = hidp_start,
914 .stop = hidp_stop,
915 .open = hidp_open,
916 .close = hidp_close,
917 .hidinput_input_event = hidp_hidinput_event,
918};
919
Alan Ott0f69dca2011-01-18 03:04:37 -0500920/* This function sets up the hid device. It does not add it
921 to the HID system. That is done in hidp_add_connection(). */
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200922static int hidp_setup_hid(struct hidp_session *session,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800923 struct hidp_connadd_req *req)
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100924{
Jiri Slabyc500c972008-05-16 11:49:16 +0200925 struct hid_device *hid;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700926 int err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100927
Michael Poole15c697c2010-02-05 12:23:43 -0500928 session->rd_data = kzalloc(req->rd_size, GFP_KERNEL);
929 if (!session->rd_data)
930 return -ENOMEM;
931
932 if (copy_from_user(session->rd_data, req->rd_data, req->rd_size)) {
933 err = -EFAULT;
934 goto fault;
935 }
936 session->rd_size = req->rd_size;
937
Jiri Slabyc500c972008-05-16 11:49:16 +0200938 hid = hid_allocate_device();
Michael Poole15c697c2010-02-05 12:23:43 -0500939 if (IS_ERR(hid)) {
940 err = PTR_ERR(hid);
941 goto fault;
942 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100943
Jiri Slabyc500c972008-05-16 11:49:16 +0200944 session->hid = hid;
Michael Poole15c697c2010-02-05 12:23:43 -0500945
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100946 hid->driver_data = session;
947
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100948 hid->bus = BUS_BLUETOOTH;
949 hid->vendor = req->vendor;
950 hid->product = req->product;
951 hid->version = req->version;
Jiri Slabyc500c972008-05-16 11:49:16 +0200952 hid->country = req->country;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100953
954 strncpy(hid->name, req->name, 128);
Gustavo F. Padovand6b2eb22010-09-03 18:29:46 -0300955 strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64);
956 strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100957
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200958 hid->dev.parent = hidp_get_device(session);
Jiri Slabyc500c972008-05-16 11:49:16 +0200959 hid->ll_driver = &hidp_hid_driver;
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200960
Alan Ott0ff17312011-01-18 03:04:40 -0500961 hid->hid_get_raw_report = hidp_get_raw_report;
Jiri Kosina2da31932009-11-26 16:20:56 +0100962 hid->hid_output_raw_report = hidp_output_raw_report;
963
Jiri Slabyc500c972008-05-16 11:49:16 +0200964 return 0;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700965
Michael Poole15c697c2010-02-05 12:23:43 -0500966fault:
967 kfree(session->rd_data);
968 session->rd_data = NULL;
969
Marcel Holtmannedad6382009-08-22 14:22:15 -0700970 return err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100971}
972
Linus Torvalds1da177e2005-04-16 15:20:36 -0700973int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
974{
975 struct hidp_session *session, *s;
Szymon Jancaabf6f82011-04-05 15:37:45 +0200976 int vendor, product;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 int err;
978
979 BT_DBG("");
980
981 if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
982 bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
983 return -ENOTUNIQ;
984
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200985 session = kzalloc(sizeof(struct hidp_session), GFP_KERNEL);
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500986 if (!session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100989 BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
990
Linus Torvalds1da177e2005-04-16 15:20:36 -0700991 down_write(&hidp_session_sem);
992
993 s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
994 if (s && s->state == BT_CONNECTED) {
995 err = -EEXIST;
996 goto failed;
997 }
998
999 bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
1000
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -03001001 session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->chan->omtu,
1002 l2cap_pi(ctrl_sock->sk)->chan->imtu);
1003 session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->chan->omtu,
1004 l2cap_pi(intr_sock->sk)->chan->imtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005
1006 BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
1007
1008 session->ctrl_sock = ctrl_sock;
1009 session->intr_sock = intr_sock;
1010 session->state = BT_CONNECTED;
1011
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001012 setup_timer(&session->timer, hidp_idle_timeout, (unsigned long)session);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013
1014 skb_queue_head_init(&session->ctrl_transmit);
1015 skb_queue_head_init(&session->intr_transmit);
1016
Alan Ott0ff17312011-01-18 03:04:40 -05001017 mutex_init(&session->report_mutex);
1018 init_waitqueue_head(&session->report_queue);
Alan Ott0f69dca2011-01-18 03:04:37 -05001019 init_waitqueue_head(&session->startup_queue);
1020 session->waiting_for_startup = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001021 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
1022 session->idle_to = req->idle_to;
1023
Jiri Slabyc500c972008-05-16 11:49:16 +02001024 if (req->rd_size > 0) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001025 err = hidp_setup_hid(session, req);
Jiri Slabyd458a9d2008-05-16 11:49:20 +02001026 if (err && err != -ENODEV)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001027 goto purge;
Jiri Slabyc500c972008-05-16 11:49:16 +02001028 }
1029
1030 if (!session->hid) {
1031 err = hidp_setup_input(session, req);
1032 if (err < 0)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001033 goto purge;
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001034 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001035
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 __hidp_link_session(session);
1037
1038 hidp_set_timer(session);
1039
Szymon Jancaabf6f82011-04-05 15:37:45 +02001040 if (session->hid) {
1041 vendor = session->hid->vendor;
1042 product = session->hid->product;
1043 } else if (session->input) {
1044 vendor = session->input->id.vendor;
1045 product = session->input->id.product;
1046 } else {
1047 vendor = 0x0000;
1048 product = 0x0000;
1049 }
1050
1051 session->task = kthread_run(hidp_session, session, "khidpd_%04x%04x",
1052 vendor, product);
1053 if (IS_ERR(session->task)) {
1054 err = PTR_ERR(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001055 goto unlink;
Szymon Jancaabf6f82011-04-05 15:37:45 +02001056 }
1057
Alan Ott0f69dca2011-01-18 03:04:37 -05001058 while (session->waiting_for_startup) {
1059 wait_event_interruptible(session->startup_queue,
1060 !session->waiting_for_startup);
1061 }
1062
1063 err = hid_add_device(session->hid);
Peter Hurleye9d5cb52011-08-05 10:51:26 -04001064 if (err < 0) {
1065 atomic_inc(&session->terminate);
1066 wake_up_process(session->task);
1067 up_write(&hidp_session_sem);
1068 return err;
1069 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070
1071 if (session->input) {
1072 hidp_send_ctrl_message(session,
1073 HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
1074 session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
1075
1076 session->leds = 0xff;
1077 hidp_input_event(session->input, EV_LED, 0, 0);
1078 }
1079
1080 up_write(&hidp_session_sem);
1081 return 0;
1082
1083unlink:
1084 hidp_del_timer(session);
1085
1086 __hidp_unlink_session(session);
1087
Marcel Holtmannedad6382009-08-22 14:22:15 -07001088 if (session->input) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001089 input_unregister_device(session->input);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001090 session->input = NULL;
1091 }
1092
1093 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001094 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001095 session->hid = NULL;
1096 }
1097
Michael Poole15c697c2010-02-05 12:23:43 -05001098 kfree(session->rd_data);
1099 session->rd_data = NULL;
1100
Marcel Holtmannedad6382009-08-22 14:22:15 -07001101purge:
Jiri Slabyc500c972008-05-16 11:49:16 +02001102 skb_queue_purge(&session->ctrl_transmit);
1103 skb_queue_purge(&session->intr_transmit);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001104
Jiri Slabyc500c972008-05-16 11:49:16 +02001105failed:
1106 up_write(&hidp_session_sem);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001107
Linus Torvalds1da177e2005-04-16 15:20:36 -07001108 kfree(session);
1109 return err;
1110}
1111
1112int hidp_del_connection(struct hidp_conndel_req *req)
1113{
1114 struct hidp_session *session;
1115 int err = 0;
1116
1117 BT_DBG("");
1118
1119 down_read(&hidp_session_sem);
1120
1121 session = __hidp_get_session(&req->bdaddr);
1122 if (session) {
1123 if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
1124 hidp_send_ctrl_message(session,
1125 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
1126 } else {
1127 /* Flush the transmit queues */
1128 skb_queue_purge(&session->ctrl_transmit);
1129 skb_queue_purge(&session->intr_transmit);
1130
Peter Hurley7bb59df2011-06-30 13:53:53 -04001131 atomic_inc(&session->terminate);
1132 wake_up_process(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 }
1134 } else
1135 err = -ENOENT;
1136
1137 up_read(&hidp_session_sem);
1138 return err;
1139}
1140
1141int hidp_get_connlist(struct hidp_connlist_req *req)
1142{
1143 struct list_head *p;
1144 int err = 0, n = 0;
1145
1146 BT_DBG("");
1147
1148 down_read(&hidp_session_sem);
1149
1150 list_for_each(p, &hidp_session_list) {
1151 struct hidp_session *session;
1152 struct hidp_conninfo ci;
1153
1154 session = list_entry(p, struct hidp_session, list);
1155
1156 __hidp_copy_session(session, &ci);
1157
1158 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
1159 err = -EFAULT;
1160 break;
1161 }
1162
1163 if (++n >= req->cnum)
1164 break;
1165
1166 req->ci++;
1167 }
1168 req->cnum = n;
1169
1170 up_read(&hidp_session_sem);
1171 return err;
1172}
1173
1174int hidp_get_conninfo(struct hidp_conninfo *ci)
1175{
1176 struct hidp_session *session;
1177 int err = 0;
1178
1179 down_read(&hidp_session_sem);
1180
1181 session = __hidp_get_session(&ci->bdaddr);
1182 if (session)
1183 __hidp_copy_session(session, ci);
1184 else
1185 err = -ENOENT;
1186
1187 up_read(&hidp_session_sem);
1188 return err;
1189}
1190
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001191static const struct hid_device_id hidp_table[] = {
1192 { HID_BLUETOOTH_DEVICE(HID_ANY_ID, HID_ANY_ID) },
1193 { }
1194};
1195
1196static struct hid_driver hidp_driver = {
1197 .name = "generic-bluetooth",
1198 .id_table = hidp_table,
1199};
1200
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201static int __init hidp_init(void)
1202{
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001203 int ret;
1204
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205 BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
1206
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001207 ret = hid_register_driver(&hidp_driver);
1208 if (ret)
1209 goto err;
1210
1211 ret = hidp_init_sockets();
1212 if (ret)
1213 goto err_drv;
1214
1215 return 0;
1216err_drv:
1217 hid_unregister_driver(&hidp_driver);
1218err:
1219 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001220}
1221
1222static void __exit hidp_exit(void)
1223{
1224 hidp_cleanup_sockets();
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001225 hid_unregister_driver(&hidp_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001226}
1227
1228module_init(hidp_init);
1229module_exit(hidp_exit);
1230
1231MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
1232MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
1233MODULE_VERSION(VERSION);
1234MODULE_LICENSE("GPL");
1235MODULE_ALIAS("bt-proto-6");