blob: f2bec4981b76939f17da2042f02acd4b6c629dfb [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;
Linus Torvalds1da177e2005-04-16 15:20:36 -070084
85 BT_DBG("");
86
Gustavo F. Padovancd11cdd2011-10-06 17:35:31 -030087 list_for_each_entry(session, &hidp_session_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 if (!bacmp(bdaddr, &session->bdaddr))
89 return session;
90 }
91 return NULL;
92}
93
94static void __hidp_link_session(struct hidp_session *session)
95{
96 __module_get(THIS_MODULE);
97 list_add(&session->list, &hidp_session_list);
Marcel Holtmannedad6382009-08-22 14:22:15 -070098
99 hci_conn_hold_device(session->conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100}
101
102static void __hidp_unlink_session(struct hidp_session *session)
103{
Marcel Holtmannedad6382009-08-22 14:22:15 -0700104 hci_conn_put_device(session->conn);
105
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106 list_del(&session->list);
107 module_put(THIS_MODULE);
108}
109
110static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
111{
Vasiliy Kulikovd31dbf62010-10-30 18:26:31 +0400112 memset(ci, 0, sizeof(*ci));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113 bacpy(&ci->bdaddr, &session->bdaddr);
114
115 ci->flags = session->flags;
116 ci->state = session->state;
117
118 ci->vendor = 0x0000;
119 ci->product = 0x0000;
120 ci->version = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121
122 if (session->input) {
123 ci->vendor = session->input->id.vendor;
124 ci->product = session->input->id.product;
125 ci->version = session->input->id.version;
126 if (session->input->name)
127 strncpy(ci->name, session->input->name, 128);
128 else
129 strncpy(ci->name, "HID Boot Device", 128);
130 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100131
132 if (session->hid) {
133 ci->vendor = session->hid->vendor;
134 ci->product = session->hid->product;
135 ci->version = session->hid->version;
136 strncpy(ci->name, session->hid->name, 128);
137 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138}
139
Andrew Morton91f5cca2008-02-05 03:07:58 -0800140static int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
141 unsigned int type, unsigned int code, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143 unsigned char newleds;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100144 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700145
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100146 BT_DBG("session %p type %d code %d value %d", session, type, code, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147
148 if (type != EV_LED)
149 return -1;
150
151 newleds = (!!test_bit(LED_KANA, dev->led) << 3) |
152 (!!test_bit(LED_COMPOSE, dev->led) << 3) |
153 (!!test_bit(LED_SCROLLL, dev->led) << 2) |
154 (!!test_bit(LED_CAPSL, dev->led) << 1) |
155 (!!test_bit(LED_NUML, dev->led));
156
157 if (session->leds == newleds)
158 return 0;
159
160 session->leds = newleds;
161
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200162 skb = alloc_skb(3, GFP_ATOMIC);
163 if (!skb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700164 BT_ERR("Can't allocate memory for new frame");
165 return -ENOMEM;
166 }
167
168 *skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
169 *skb_put(skb, 1) = 0x01;
170 *skb_put(skb, 1) = newleds;
171
172 skb_queue_tail(&session->intr_transmit, skb);
173
174 hidp_schedule(session);
175
176 return 0;
177}
178
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100179static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
180{
Marcel Holtmann5be39462007-05-09 09:15:30 +0200181 struct hid_device *hid = input_get_drvdata(dev);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100182 struct hidp_session *session = hid->driver_data;
183
184 return hidp_queue_event(session, dev, type, code, value);
185}
186
187static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
188{
Marcel Holtmann5be39462007-05-09 09:15:30 +0200189 struct hidp_session *session = input_get_drvdata(dev);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100190
191 return hidp_queue_event(session, dev, type, code, value);
192}
193
Linus Torvalds1da177e2005-04-16 15:20:36 -0700194static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
195{
196 struct input_dev *dev = session->input;
197 unsigned char *keys = session->keys;
198 unsigned char *udata = skb->data + 1;
199 signed char *sdata = skb->data + 1;
200 int i, size = skb->len - 1;
201
202 switch (skb->data[0]) {
203 case 0x01: /* Keyboard report */
204 for (i = 0; i < 8; i++)
205 input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
206
207 /* If all the key codes have been set to 0x01, it means
208 * too many keys were pressed at the same time. */
209 if (!memcmp(udata + 2, hidp_mkeyspat, 6))
210 break;
211
212 for (i = 2; i < 8; i++) {
213 if (keys[i] > 3 && memscan(udata + 2, keys[i], 6) == udata + 8) {
214 if (hidp_keycode[keys[i]])
215 input_report_key(dev, hidp_keycode[keys[i]], 0);
216 else
217 BT_ERR("Unknown key (scancode %#x) released.", keys[i]);
218 }
219
220 if (udata[i] > 3 && memscan(keys + 2, udata[i], 6) == keys + 8) {
221 if (hidp_keycode[udata[i]])
222 input_report_key(dev, hidp_keycode[udata[i]], 1);
223 else
224 BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]);
225 }
226 }
227
228 memcpy(keys, udata, 8);
229 break;
230
231 case 0x02: /* Mouse report */
232 input_report_key(dev, BTN_LEFT, sdata[0] & 0x01);
233 input_report_key(dev, BTN_RIGHT, sdata[0] & 0x02);
234 input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
235 input_report_key(dev, BTN_SIDE, sdata[0] & 0x08);
236 input_report_key(dev, BTN_EXTRA, sdata[0] & 0x10);
237
238 input_report_rel(dev, REL_X, sdata[1]);
239 input_report_rel(dev, REL_Y, sdata[2]);
240
241 if (size > 3)
242 input_report_rel(dev, REL_WHEEL, sdata[3]);
243 break;
244 }
245
246 input_sync(dev);
247}
248
Bastien Nocera6bf82682010-01-20 12:00:42 +0000249static int __hidp_send_ctrl_message(struct hidp_session *session,
250 unsigned char hdr, unsigned char *data, int size)
251{
252 struct sk_buff *skb;
253
254 BT_DBG("session %p data %p size %d", session, data, size);
255
David Herrmann794d1752011-08-26 14:06:02 +0200256 if (atomic_read(&session->terminate))
257 return -EIO;
258
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200259 skb = alloc_skb(size + 1, GFP_ATOMIC);
260 if (!skb) {
Bastien Nocera6bf82682010-01-20 12:00:42 +0000261 BT_ERR("Can't allocate memory for new frame");
262 return -ENOMEM;
263 }
264
265 *skb_put(skb, 1) = hdr;
266 if (data && size > 0)
267 memcpy(skb_put(skb, size), data, size);
268
269 skb_queue_tail(&session->ctrl_transmit, skb);
270
271 return 0;
272}
273
274static inline int hidp_send_ctrl_message(struct hidp_session *session,
275 unsigned char hdr, unsigned char *data, int size)
276{
277 int err;
278
279 err = __hidp_send_ctrl_message(session, hdr, data, size);
280
281 hidp_schedule(session);
282
283 return err;
284}
285
Andrew Morton91f5cca2008-02-05 03:07:58 -0800286static int hidp_queue_report(struct hidp_session *session,
287 unsigned char *data, int size)
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100288{
289 struct sk_buff *skb;
290
Dave Young6792b5e2007-10-20 14:15:39 +0200291 BT_DBG("session %p hid %p data %p size %d", session, session->hid, data, size);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100292
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200293 skb = alloc_skb(size + 1, GFP_ATOMIC);
294 if (!skb) {
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100295 BT_ERR("Can't allocate memory for new frame");
296 return -ENOMEM;
297 }
298
299 *skb_put(skb, 1) = 0xa2;
300 if (size > 0)
301 memcpy(skb_put(skb, size), data, size);
302
303 skb_queue_tail(&session->intr_transmit, skb);
304
305 hidp_schedule(session);
306
307 return 0;
308}
309
310static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
311{
312 unsigned char buf[32];
313 int rsize;
314
315 rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
316 if (rsize > sizeof(buf))
317 return -EIO;
318
319 hid_output_report(report, buf);
320
321 return hidp_queue_report(session, buf, rsize);
322}
323
Alan Ott0ff17312011-01-18 03:04:40 -0500324static int hidp_get_raw_report(struct hid_device *hid,
325 unsigned char report_number,
326 unsigned char *data, size_t count,
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100327 unsigned char report_type)
Jiri Kosina2da31932009-11-26 16:20:56 +0100328{
Alan Ott0ff17312011-01-18 03:04:40 -0500329 struct hidp_session *session = hid->driver_data;
330 struct sk_buff *skb;
331 size_t len;
332 int numbered_reports = hid->report_enum[report_type].numbered;
David Herrmann794d1752011-08-26 14:06:02 +0200333 int ret;
Alan Ott0ff17312011-01-18 03:04:40 -0500334
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100335 switch (report_type) {
336 case HID_FEATURE_REPORT:
Alan Ott0ff17312011-01-18 03:04:40 -0500337 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
338 break;
339 case HID_INPUT_REPORT:
340 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_INPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100341 break;
342 case HID_OUTPUT_REPORT:
Alan Ott0ff17312011-01-18 03:04:40 -0500343 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_OUPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100344 break;
345 default:
346 return -EINVAL;
347 }
348
Alan Ott0ff17312011-01-18 03:04:40 -0500349 if (mutex_lock_interruptible(&session->report_mutex))
350 return -ERESTARTSYS;
351
352 /* Set up our wait, and send the report request to the device. */
353 session->waiting_report_type = report_type & HIDP_DATA_RTYPE_MASK;
354 session->waiting_report_number = numbered_reports ? report_number : -1;
355 set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
356 data[0] = report_number;
David Herrmann794d1752011-08-26 14:06:02 +0200357 ret = hidp_send_ctrl_message(hid->driver_data, report_type, data, 1);
358 if (ret)
359 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500360
361 /* Wait for the return of the report. The returned report
362 gets put in session->report_return. */
363 while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
364 int res;
365
366 res = wait_event_interruptible_timeout(session->report_queue,
367 !test_bit(HIDP_WAITING_FOR_RETURN, &session->flags),
368 5*HZ);
369 if (res == 0) {
370 /* timeout */
David Herrmann794d1752011-08-26 14:06:02 +0200371 ret = -EIO;
372 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500373 }
374 if (res < 0) {
375 /* signal */
David Herrmann794d1752011-08-26 14:06:02 +0200376 ret = -ERESTARTSYS;
377 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500378 }
379 }
380
381 skb = session->report_return;
382 if (skb) {
383 len = skb->len < count ? skb->len : count;
384 memcpy(data, skb->data, len);
385
386 kfree_skb(skb);
387 session->report_return = NULL;
388 } else {
389 /* Device returned a HANDSHAKE, indicating protocol error. */
390 len = -EIO;
391 }
392
393 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
394 mutex_unlock(&session->report_mutex);
395
396 return len;
397
David Herrmann794d1752011-08-26 14:06:02 +0200398err:
Alan Ott0ff17312011-01-18 03:04:40 -0500399 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
400 mutex_unlock(&session->report_mutex);
David Herrmann794d1752011-08-26 14:06:02 +0200401 return ret;
Alan Ott0ff17312011-01-18 03:04:40 -0500402}
403
Linus Torvalds1da177e2005-04-16 15:20:36 -0700404static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
Jiri Kosina2da31932009-11-26 16:20:56 +0100405 unsigned char report_type)
406{
Alan Ott08254112011-01-18 03:04:38 -0500407 struct hidp_session *session = hid->driver_data;
408 int ret;
409
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100410 switch (report_type) {
411 case HID_FEATURE_REPORT:
412 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
413 break;
414 case HID_OUTPUT_REPORT:
Antonio Ospite97e1efb2011-02-20 18:26:46 +0100415 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100416 break;
417 default:
418 return -EINVAL;
419 }
420
Alan Ott08254112011-01-18 03:04:38 -0500421 if (mutex_lock_interruptible(&session->report_mutex))
422 return -ERESTARTSYS;
423
424 /* Set up our wait, and send the report request to the device. */
425 set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
David Herrmann794d1752011-08-26 14:06:02 +0200426 ret = hidp_send_ctrl_message(hid->driver_data, report_type, data,
427 count);
428 if (ret)
Alan Ott08254112011-01-18 03:04:38 -0500429 goto err;
Alan Ott08254112011-01-18 03:04:38 -0500430
431 /* Wait for the ACK from the device. */
432 while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
433 int res;
434
435 res = wait_event_interruptible_timeout(session->report_queue,
436 !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags),
437 10*HZ);
438 if (res == 0) {
439 /* timeout */
440 ret = -EIO;
441 goto err;
442 }
443 if (res < 0) {
444 /* signal */
445 ret = -ERESTARTSYS;
446 goto err;
447 }
448 }
449
450 if (!session->output_report_success) {
451 ret = -EIO;
452 goto err;
453 }
454
455 ret = count;
456
457err:
458 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
459 mutex_unlock(&session->report_mutex);
460 return ret;
Jiri Kosina2da31932009-11-26 16:20:56 +0100461}
462
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463static void hidp_idle_timeout(unsigned long arg)
464{
465 struct hidp_session *session = (struct hidp_session *) arg;
466
Peter Hurley7bb59df2011-06-30 13:53:53 -0400467 atomic_inc(&session->terminate);
468 wake_up_process(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700469}
470
Andrew Morton91f5cca2008-02-05 03:07:58 -0800471static void hidp_set_timer(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472{
473 if (session->idle_to > 0)
474 mod_timer(&session->timer, jiffies + HZ * session->idle_to);
475}
476
477static inline void hidp_del_timer(struct hidp_session *session)
478{
479 if (session->idle_to > 0)
480 del_timer(&session->timer);
481}
482
Andrew Morton91f5cca2008-02-05 03:07:58 -0800483static void hidp_process_handshake(struct hidp_session *session,
484 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485{
486 BT_DBG("session %p param 0x%02x", session, param);
Alan Ott08254112011-01-18 03:04:38 -0500487 session->output_report_success = 0; /* default condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488
489 switch (param) {
490 case HIDP_HSHK_SUCCESSFUL:
491 /* FIXME: Call into SET_ GET_ handlers here */
Alan Ott08254112011-01-18 03:04:38 -0500492 session->output_report_success = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 break;
494
495 case HIDP_HSHK_NOT_READY:
496 case HIDP_HSHK_ERR_INVALID_REPORT_ID:
497 case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
498 case HIDP_HSHK_ERR_INVALID_PARAMETER:
Gustavo F. Padovanab88f712011-10-06 22:05:37 -0300499 if (test_and_clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags))
Alan Ott0ff17312011-01-18 03:04:40 -0500500 wake_up_interruptible(&session->report_queue);
Gustavo F. Padovanab88f712011-10-06 22:05:37 -0300501
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. */
Gustavo F. Padovanab88f712011-10-06 22:05:37 -0300522 if (test_and_clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags))
Alan Ott08254112011-01-18 03:04:38 -0500523 wake_up_interruptible(&session->report_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524}
525
Andrew Morton91f5cca2008-02-05 03:07:58 -0800526static void hidp_process_hid_control(struct hidp_session *session,
527 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528{
529 BT_DBG("session %p param 0x%02x", session, param);
530
Dave Youngeff001e2008-02-05 03:07:14 -0800531 if (param == HIDP_CTRL_VIRTUAL_CABLE_UNPLUG) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700532 /* Flush the transmit queues */
533 skb_queue_purge(&session->ctrl_transmit);
534 skb_queue_purge(&session->intr_transmit);
535
Peter Hurley7bb59df2011-06-30 13:53:53 -0400536 atomic_inc(&session->terminate);
537 wake_up_process(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700538 }
539}
540
Alan Ott0ff17312011-01-18 03:04:40 -0500541/* Returns true if the passed-in skb should be freed by the caller. */
542static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800543 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700544{
Alan Ott0ff17312011-01-18 03:04:40 -0500545 int done_with_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700546 BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
547
548 switch (param) {
549 case HIDP_DATA_RTYPE_INPUT:
550 hidp_set_timer(session);
551
552 if (session->input)
553 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100554
555 if (session->hid)
556 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 break;
558
559 case HIDP_DATA_RTYPE_OTHER:
560 case HIDP_DATA_RTYPE_OUPUT:
561 case HIDP_DATA_RTYPE_FEATURE:
562 break;
563
564 default:
565 __hidp_send_ctrl_message(session,
566 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
567 }
Alan Ott0ff17312011-01-18 03:04:40 -0500568
569 if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
570 param == session->waiting_report_type) {
571 if (session->waiting_report_number < 0 ||
572 session->waiting_report_number == skb->data[0]) {
573 /* hidp_get_raw_report() is waiting on this report. */
574 session->report_return = skb;
575 done_with_skb = 0;
576 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
577 wake_up_interruptible(&session->report_queue);
578 }
579 }
580
581 return done_with_skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582}
583
Andrew Morton91f5cca2008-02-05 03:07:58 -0800584static void hidp_recv_ctrl_frame(struct hidp_session *session,
585 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700586{
587 unsigned char hdr, type, param;
Alan Ott0ff17312011-01-18 03:04:40 -0500588 int free_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589
590 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
591
592 hdr = skb->data[0];
593 skb_pull(skb, 1);
594
595 type = hdr & HIDP_HEADER_TRANS_MASK;
596 param = hdr & HIDP_HEADER_PARAM_MASK;
597
598 switch (type) {
599 case HIDP_TRANS_HANDSHAKE:
600 hidp_process_handshake(session, param);
601 break;
602
603 case HIDP_TRANS_HID_CONTROL:
604 hidp_process_hid_control(session, param);
605 break;
606
607 case HIDP_TRANS_DATA:
Alan Ott0ff17312011-01-18 03:04:40 -0500608 free_skb = hidp_process_data(session, skb, param);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700609 break;
610
611 default:
612 __hidp_send_ctrl_message(session,
613 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
614 break;
615 }
616
Alan Ott0ff17312011-01-18 03:04:40 -0500617 if (free_skb)
618 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619}
620
Andrew Morton91f5cca2008-02-05 03:07:58 -0800621static void hidp_recv_intr_frame(struct hidp_session *session,
622 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623{
624 unsigned char hdr;
625
626 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
627
628 hdr = skb->data[0];
629 skb_pull(skb, 1);
630
631 if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
632 hidp_set_timer(session);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100633
Linus Torvalds1da177e2005-04-16 15:20:36 -0700634 if (session->input)
635 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100636
637 if (session->hid) {
638 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
639 BT_DBG("report len %d", skb->len);
640 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641 } else {
642 BT_DBG("Unsupported protocol header 0x%02x", hdr);
643 }
644
645 kfree_skb(skb);
646}
647
648static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
649{
650 struct kvec iv = { data, len };
651 struct msghdr msg;
652
653 BT_DBG("sock %p data %p len %d", sock, data, len);
654
655 if (!len)
656 return 0;
657
658 memset(&msg, 0, sizeof(msg));
659
660 return kernel_sendmsg(sock, &msg, &iv, 1, len);
661}
662
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300663static void hidp_process_intr_transmit(struct hidp_session *session)
664{
665 struct sk_buff *skb;
666
667 BT_DBG("session %p", session);
668
669 while ((skb = skb_dequeue(&session->intr_transmit))) {
670 if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
671 skb_queue_head(&session->intr_transmit, skb);
672 break;
673 }
674
675 hidp_set_timer(session);
676 kfree_skb(skb);
677 }
678}
679
680static void hidp_process_ctrl_transmit(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681{
682 struct sk_buff *skb;
683
684 BT_DBG("session %p", session);
685
686 while ((skb = skb_dequeue(&session->ctrl_transmit))) {
687 if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
688 skb_queue_head(&session->ctrl_transmit, skb);
689 break;
690 }
691
692 hidp_set_timer(session);
693 kfree_skb(skb);
694 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700695}
696
697static int hidp_session(void *arg)
698{
699 struct hidp_session *session = arg;
700 struct sock *ctrl_sk = session->ctrl_sock->sk;
701 struct sock *intr_sk = session->intr_sock->sk;
702 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 wait_queue_t ctrl_wait, intr_wait;
704
705 BT_DBG("session %p", session);
706
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 set_user_nice(current, -15);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708
709 init_waitqueue_entry(&ctrl_wait, current);
710 init_waitqueue_entry(&intr_wait, current);
Eric Dumazetaa395142010-04-20 13:03:51 +0000711 add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
712 add_wait_queue(sk_sleep(intr_sk), &intr_wait);
Alan Ott0f69dca2011-01-18 03:04:37 -0500713 session->waiting_for_startup = 0;
714 wake_up_interruptible(&session->startup_queue);
Peter Hurley7bb59df2011-06-30 13:53:53 -0400715 set_current_state(TASK_INTERRUPTIBLE);
716 while (!atomic_read(&session->terminate)) {
Szymon Janc17f09a72011-03-21 14:20:01 +0100717 if (ctrl_sk->sk_state != BT_CONNECTED ||
718 intr_sk->sk_state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719 break;
720
Linus Torvalds1da177e2005-04-16 15:20:36 -0700721 while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
722 skb_orphan(skb);
Mat Martineau44935722011-07-22 14:53:58 -0700723 if (!skb_linearize(skb))
724 hidp_recv_intr_frame(session, skb);
725 else
726 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 }
728
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300729 hidp_process_intr_transmit(session);
730
Gustavo F. Padovandc0da5c2011-10-06 18:02:13 -0300731 while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
732 skb_orphan(skb);
733 if (!skb_linearize(skb))
734 hidp_recv_ctrl_frame(session, skb);
735 else
736 kfree_skb(skb);
737 }
738
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300739 hidp_process_ctrl_transmit(session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740
741 schedule();
Peter Hurley7bb59df2011-06-30 13:53:53 -0400742 set_current_state(TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 }
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
David Herrmann794d1752011-08-26 14:06:02 +0200748 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
749 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
750 wake_up_interruptible(&session->report_queue);
751
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752 down_write(&hidp_session_sem);
753
754 hidp_del_timer(session);
755
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 if (session->input) {
757 input_unregister_device(session->input);
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500758 session->input = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 }
760
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100761 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200762 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -0700763 session->hid = NULL;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100764 }
765
Marcel Holtmannec8dab32008-07-14 20:13:53 +0200766 /* Wakeup user-space polling for socket errors */
767 session->intr_sock->sk->sk_err = EUNATCH;
768 session->ctrl_sock->sk->sk_err = EUNATCH;
769
770 hidp_schedule(session);
771
David Woodhouse1c398582007-07-07 14:58:39 -0400772 fput(session->intr_sock->file);
773
Eric Dumazetaa395142010-04-20 13:03:51 +0000774 wait_event_timeout(*(sk_sleep(ctrl_sk)),
David Woodhouse1c398582007-07-07 14:58:39 -0400775 (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
776
777 fput(session->ctrl_sock->file);
778
779 __hidp_unlink_session(session);
780
Linus Torvalds1da177e2005-04-16 15:20:36 -0700781 up_write(&hidp_session_sem);
782
Peter Hurley1c97e942011-08-05 10:51:34 -0400783 kfree(session->rd_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 kfree(session);
785 return 0;
786}
787
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200788static struct device *hidp_get_device(struct hidp_session *session)
789{
790 bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
791 bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700792 struct device *device = NULL;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200793 struct hci_dev *hdev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200794
795 hdev = hci_get_route(dst, src);
796 if (!hdev)
797 return NULL;
798
Marcel Holtmannedad6382009-08-22 14:22:15 -0700799 session->conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
800 if (session->conn)
801 device = &session->conn->dev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200802
803 hci_dev_put(hdev);
804
Marcel Holtmannedad6382009-08-22 14:22:15 -0700805 return device;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200806}
807
Andrew Morton91f5cca2008-02-05 03:07:58 -0800808static int hidp_setup_input(struct hidp_session *session,
809 struct hidp_connadd_req *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810{
Jiri Slabyc500c972008-05-16 11:49:16 +0200811 struct input_dev *input;
Gustavo F. Padovan3415a5f2011-10-06 21:17:32 -0300812 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813
Jiri Slabyc500c972008-05-16 11:49:16 +0200814 input = input_allocate_device();
815 if (!input)
816 return -ENOMEM;
817
818 session->input = input;
819
Marcel Holtmann5be39462007-05-09 09:15:30 +0200820 input_set_drvdata(input, session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700821
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500822 input->name = "Bluetooth HID Boot Protocol Device";
823
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824 input->id.bustype = BUS_BLUETOOTH;
825 input->id.vendor = req->vendor;
826 input->id.product = req->product;
827 input->id.version = req->version;
828
829 if (req->subclass & 0x40) {
830 set_bit(EV_KEY, input->evbit);
831 set_bit(EV_LED, input->evbit);
832 set_bit(EV_REP, input->evbit);
833
834 set_bit(LED_NUML, input->ledbit);
835 set_bit(LED_CAPSL, input->ledbit);
836 set_bit(LED_SCROLLL, input->ledbit);
837 set_bit(LED_COMPOSE, input->ledbit);
838 set_bit(LED_KANA, input->ledbit);
839
840 for (i = 0; i < sizeof(hidp_keycode); i++)
841 set_bit(hidp_keycode[i], input->keybit);
842 clear_bit(0, input->keybit);
843 }
844
845 if (req->subclass & 0x80) {
Jiri Slaby7b19ada2007-10-18 23:40:32 -0700846 input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
847 input->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
848 BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
849 input->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
850 input->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |
851 BIT_MASK(BTN_EXTRA);
852 input->relbit[0] |= BIT_MASK(REL_WHEEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 }
854
Marcel Holtmann5be39462007-05-09 09:15:30 +0200855 input->dev.parent = hidp_get_device(session);
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200856
Linus Torvalds1da177e2005-04-16 15:20:36 -0700857 input->event = hidp_input_event;
858
Marcel Holtmannedad6382009-08-22 14:22:15 -0700859 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860}
861
Marcel Holtmannf5ffd462007-02-17 23:58:53 +0100862static int hidp_open(struct hid_device *hid)
863{
864 return 0;
865}
866
867static void hidp_close(struct hid_device *hid)
868{
869}
870
Jiri Slabyc500c972008-05-16 11:49:16 +0200871static int hidp_parse(struct hid_device *hid)
872{
873 struct hidp_session *session = hid->driver_data;
Jiri Slabyc500c972008-05-16 11:49:16 +0200874
Michael Poole15c697c2010-02-05 12:23:43 -0500875 return hid_parse_report(session->hid, session->rd_data,
876 session->rd_size);
Jiri Slabyc500c972008-05-16 11:49:16 +0200877}
878
879static int hidp_start(struct hid_device *hid)
880{
881 struct hidp_session *session = hid->driver_data;
882 struct hid_report *report;
883
David Herrmann142c69c2011-08-26 13:27:12 +0200884 if (hid->quirks & HID_QUIRK_NO_INIT_REPORTS)
885 return 0;
886
Jiri Slabyc500c972008-05-16 11:49:16 +0200887 list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].
888 report_list, list)
889 hidp_send_report(session, report);
890
891 list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].
892 report_list, list)
893 hidp_send_report(session, report);
894
Jiri Slabyc500c972008-05-16 11:49:16 +0200895 return 0;
896}
897
898static void hidp_stop(struct hid_device *hid)
899{
900 struct hidp_session *session = hid->driver_data;
901
902 skb_queue_purge(&session->ctrl_transmit);
903 skb_queue_purge(&session->intr_transmit);
904
Jiri Slabyc500c972008-05-16 11:49:16 +0200905 hid->claimed = 0;
906}
907
908static struct hid_ll_driver hidp_hid_driver = {
909 .parse = hidp_parse,
910 .start = hidp_start,
911 .stop = hidp_stop,
912 .open = hidp_open,
913 .close = hidp_close,
914 .hidinput_input_event = hidp_hidinput_event,
915};
916
Alan Ott0f69dca2011-01-18 03:04:37 -0500917/* This function sets up the hid device. It does not add it
918 to the HID system. That is done in hidp_add_connection(). */
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200919static int hidp_setup_hid(struct hidp_session *session,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800920 struct hidp_connadd_req *req)
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100921{
Jiri Slabyc500c972008-05-16 11:49:16 +0200922 struct hid_device *hid;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700923 int err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100924
Michael Poole15c697c2010-02-05 12:23:43 -0500925 session->rd_data = kzalloc(req->rd_size, GFP_KERNEL);
926 if (!session->rd_data)
927 return -ENOMEM;
928
929 if (copy_from_user(session->rd_data, req->rd_data, req->rd_size)) {
930 err = -EFAULT;
931 goto fault;
932 }
933 session->rd_size = req->rd_size;
934
Jiri Slabyc500c972008-05-16 11:49:16 +0200935 hid = hid_allocate_device();
Michael Poole15c697c2010-02-05 12:23:43 -0500936 if (IS_ERR(hid)) {
937 err = PTR_ERR(hid);
938 goto fault;
939 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100940
Jiri Slabyc500c972008-05-16 11:49:16 +0200941 session->hid = hid;
Michael Poole15c697c2010-02-05 12:23:43 -0500942
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100943 hid->driver_data = session;
944
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100945 hid->bus = BUS_BLUETOOTH;
946 hid->vendor = req->vendor;
947 hid->product = req->product;
948 hid->version = req->version;
Jiri Slabyc500c972008-05-16 11:49:16 +0200949 hid->country = req->country;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100950
951 strncpy(hid->name, req->name, 128);
Gustavo F. Padovand6b2eb22010-09-03 18:29:46 -0300952 strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64);
953 strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100954
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200955 hid->dev.parent = hidp_get_device(session);
Jiri Slabyc500c972008-05-16 11:49:16 +0200956 hid->ll_driver = &hidp_hid_driver;
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200957
Alan Ott0ff17312011-01-18 03:04:40 -0500958 hid->hid_get_raw_report = hidp_get_raw_report;
Jiri Kosina2da31932009-11-26 16:20:56 +0100959 hid->hid_output_raw_report = hidp_output_raw_report;
960
Jiri Slabyc500c972008-05-16 11:49:16 +0200961 return 0;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700962
Michael Poole15c697c2010-02-05 12:23:43 -0500963fault:
964 kfree(session->rd_data);
965 session->rd_data = NULL;
966
Marcel Holtmannedad6382009-08-22 14:22:15 -0700967 return err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100968}
969
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
971{
972 struct hidp_session *session, *s;
Szymon Jancaabf6f82011-04-05 15:37:45 +0200973 int vendor, product;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974 int err;
975
976 BT_DBG("");
977
978 if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
979 bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
980 return -ENOTUNIQ;
981
Marcel Holtmann25ea6db2006-07-06 15:40:09 +0200982 session = kzalloc(sizeof(struct hidp_session), GFP_KERNEL);
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500983 if (!session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700984 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700985
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100986 BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
987
Linus Torvalds1da177e2005-04-16 15:20:36 -0700988 down_write(&hidp_session_sem);
989
990 s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
991 if (s && s->state == BT_CONNECTED) {
992 err = -EEXIST;
993 goto failed;
994 }
995
996 bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
997
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300998 session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->chan->omtu,
999 l2cap_pi(ctrl_sock->sk)->chan->imtu);
1000 session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->chan->omtu,
1001 l2cap_pi(intr_sock->sk)->chan->imtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002
1003 BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
1004
1005 session->ctrl_sock = ctrl_sock;
1006 session->intr_sock = intr_sock;
1007 session->state = BT_CONNECTED;
1008
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001009 setup_timer(&session->timer, hidp_idle_timeout, (unsigned long)session);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001010
1011 skb_queue_head_init(&session->ctrl_transmit);
1012 skb_queue_head_init(&session->intr_transmit);
1013
Alan Ott0ff17312011-01-18 03:04:40 -05001014 mutex_init(&session->report_mutex);
1015 init_waitqueue_head(&session->report_queue);
Alan Ott0f69dca2011-01-18 03:04:37 -05001016 init_waitqueue_head(&session->startup_queue);
1017 session->waiting_for_startup = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001018 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
1019 session->idle_to = req->idle_to;
1020
Jiri Slabyc500c972008-05-16 11:49:16 +02001021 if (req->rd_size > 0) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001022 err = hidp_setup_hid(session, req);
Gustavo F. Padovan192893c2011-10-06 21:27:56 -03001023 if (err)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001024 goto purge;
Jiri Slabyc500c972008-05-16 11:49:16 +02001025 }
1026
1027 if (!session->hid) {
1028 err = hidp_setup_input(session, req);
1029 if (err < 0)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001030 goto purge;
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001031 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001032
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 __hidp_link_session(session);
1034
1035 hidp_set_timer(session);
1036
Szymon Jancaabf6f82011-04-05 15:37:45 +02001037 if (session->hid) {
1038 vendor = session->hid->vendor;
1039 product = session->hid->product;
1040 } else if (session->input) {
1041 vendor = session->input->id.vendor;
1042 product = session->input->id.product;
1043 } else {
1044 vendor = 0x0000;
1045 product = 0x0000;
1046 }
1047
1048 session->task = kthread_run(hidp_session, session, "khidpd_%04x%04x",
1049 vendor, product);
1050 if (IS_ERR(session->task)) {
1051 err = PTR_ERR(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001052 goto unlink;
Szymon Jancaabf6f82011-04-05 15:37:45 +02001053 }
1054
Alan Ott0f69dca2011-01-18 03:04:37 -05001055 while (session->waiting_for_startup) {
1056 wait_event_interruptible(session->startup_queue,
1057 !session->waiting_for_startup);
1058 }
1059
Gustavo F. Padovan3415a5f2011-10-06 21:17:32 -03001060 if (session->hid)
1061 err = hid_add_device(session->hid);
1062 else
1063 err = input_register_device(session->input);
1064
Peter Hurleye9d5cb52011-08-05 10:51:26 -04001065 if (err < 0) {
1066 atomic_inc(&session->terminate);
1067 wake_up_process(session->task);
1068 up_write(&hidp_session_sem);
1069 return err;
1070 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001071
1072 if (session->input) {
1073 hidp_send_ctrl_message(session,
1074 HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
1075 session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
1076
1077 session->leds = 0xff;
1078 hidp_input_event(session->input, EV_LED, 0, 0);
1079 }
1080
1081 up_write(&hidp_session_sem);
1082 return 0;
1083
1084unlink:
1085 hidp_del_timer(session);
1086
1087 __hidp_unlink_session(session);
1088
Marcel Holtmannedad6382009-08-22 14:22:15 -07001089 if (session->input) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 input_unregister_device(session->input);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001091 session->input = NULL;
1092 }
1093
1094 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001095 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001096 session->hid = NULL;
1097 }
1098
Michael Poole15c697c2010-02-05 12:23:43 -05001099 kfree(session->rd_data);
1100 session->rd_data = NULL;
1101
Marcel Holtmannedad6382009-08-22 14:22:15 -07001102purge:
Jiri Slabyc500c972008-05-16 11:49:16 +02001103 skb_queue_purge(&session->ctrl_transmit);
1104 skb_queue_purge(&session->intr_transmit);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001105
Jiri Slabyc500c972008-05-16 11:49:16 +02001106failed:
1107 up_write(&hidp_session_sem);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001108
Linus Torvalds1da177e2005-04-16 15:20:36 -07001109 kfree(session);
1110 return err;
1111}
1112
1113int hidp_del_connection(struct hidp_conndel_req *req)
1114{
1115 struct hidp_session *session;
1116 int err = 0;
1117
1118 BT_DBG("");
1119
1120 down_read(&hidp_session_sem);
1121
1122 session = __hidp_get_session(&req->bdaddr);
1123 if (session) {
1124 if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
1125 hidp_send_ctrl_message(session,
1126 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
1127 } else {
1128 /* Flush the transmit queues */
1129 skb_queue_purge(&session->ctrl_transmit);
1130 skb_queue_purge(&session->intr_transmit);
1131
Peter Hurley7bb59df2011-06-30 13:53:53 -04001132 atomic_inc(&session->terminate);
1133 wake_up_process(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001134 }
1135 } else
1136 err = -ENOENT;
1137
1138 up_read(&hidp_session_sem);
1139 return err;
1140}
1141
1142int hidp_get_connlist(struct hidp_connlist_req *req)
1143{
Gustavo F. Padovancd11cdd2011-10-06 17:35:31 -03001144 struct hidp_session *session;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 int err = 0, n = 0;
1146
1147 BT_DBG("");
1148
1149 down_read(&hidp_session_sem);
1150
Gustavo F. Padovancd11cdd2011-10-06 17:35:31 -03001151 list_for_each_entry(session, &hidp_session_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001152 struct hidp_conninfo ci;
1153
Linus Torvalds1da177e2005-04-16 15:20:36 -07001154 __hidp_copy_session(session, &ci);
1155
1156 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
1157 err = -EFAULT;
1158 break;
1159 }
1160
1161 if (++n >= req->cnum)
1162 break;
1163
1164 req->ci++;
1165 }
1166 req->cnum = n;
1167
1168 up_read(&hidp_session_sem);
1169 return err;
1170}
1171
1172int hidp_get_conninfo(struct hidp_conninfo *ci)
1173{
1174 struct hidp_session *session;
1175 int err = 0;
1176
1177 down_read(&hidp_session_sem);
1178
1179 session = __hidp_get_session(&ci->bdaddr);
1180 if (session)
1181 __hidp_copy_session(session, ci);
1182 else
1183 err = -ENOENT;
1184
1185 up_read(&hidp_session_sem);
1186 return err;
1187}
1188
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001189static const struct hid_device_id hidp_table[] = {
1190 { HID_BLUETOOTH_DEVICE(HID_ANY_ID, HID_ANY_ID) },
1191 { }
1192};
1193
1194static struct hid_driver hidp_driver = {
1195 .name = "generic-bluetooth",
1196 .id_table = hidp_table,
1197};
1198
Linus Torvalds1da177e2005-04-16 15:20:36 -07001199static int __init hidp_init(void)
1200{
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001201 int ret;
1202
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203 BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
1204
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001205 ret = hid_register_driver(&hidp_driver);
1206 if (ret)
1207 goto err;
1208
1209 ret = hidp_init_sockets();
1210 if (ret)
1211 goto err_drv;
1212
1213 return 0;
1214err_drv:
1215 hid_unregister_driver(&hidp_driver);
1216err:
1217 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001218}
1219
1220static void __exit hidp_exit(void)
1221{
1222 hidp_cleanup_sockets();
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001223 hid_unregister_driver(&hidp_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001224}
1225
1226module_init(hidp_init);
1227module_exit(hidp_exit);
1228
1229MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
1230MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
1231MODULE_VERSION(VERSION);
1232MODULE_LICENSE("GPL");
1233MODULE_ALIAS("bt-proto-6");