blob: 8d99a17c478c89ba6c90889872f7050a7d9d5c6d [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:
Alan Ott0ff17312011-01-18 03:04:40 -0500499 if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
500 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
501 wake_up_interruptible(&session->report_queue);
502 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503 /* FIXME: Call into SET_ GET_ handlers here */
504 break;
505
506 case HIDP_HSHK_ERR_UNKNOWN:
507 break;
508
509 case HIDP_HSHK_ERR_FATAL:
510 /* Device requests a reboot, as this is the only way this error
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900511 * can be recovered. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700512 __hidp_send_ctrl_message(session,
513 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
514 break;
515
516 default:
517 __hidp_send_ctrl_message(session,
518 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
519 break;
520 }
Alan Ott08254112011-01-18 03:04:38 -0500521
522 /* Wake up the waiting thread. */
523 if (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
524 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
525 wake_up_interruptible(&session->report_queue);
526 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527}
528
Andrew Morton91f5cca2008-02-05 03:07:58 -0800529static void hidp_process_hid_control(struct hidp_session *session,
530 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531{
532 BT_DBG("session %p param 0x%02x", session, param);
533
Dave Youngeff001e2008-02-05 03:07:14 -0800534 if (param == HIDP_CTRL_VIRTUAL_CABLE_UNPLUG) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 /* Flush the transmit queues */
536 skb_queue_purge(&session->ctrl_transmit);
537 skb_queue_purge(&session->intr_transmit);
538
Peter Hurley7bb59df2011-06-30 13:53:53 -0400539 atomic_inc(&session->terminate);
540 wake_up_process(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700541 }
542}
543
Alan Ott0ff17312011-01-18 03:04:40 -0500544/* Returns true if the passed-in skb should be freed by the caller. */
545static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800546 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547{
Alan Ott0ff17312011-01-18 03:04:40 -0500548 int done_with_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549 BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
550
551 switch (param) {
552 case HIDP_DATA_RTYPE_INPUT:
553 hidp_set_timer(session);
554
555 if (session->input)
556 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100557
558 if (session->hid)
559 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 break;
561
562 case HIDP_DATA_RTYPE_OTHER:
563 case HIDP_DATA_RTYPE_OUPUT:
564 case HIDP_DATA_RTYPE_FEATURE:
565 break;
566
567 default:
568 __hidp_send_ctrl_message(session,
569 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
570 }
Alan Ott0ff17312011-01-18 03:04:40 -0500571
572 if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
573 param == session->waiting_report_type) {
574 if (session->waiting_report_number < 0 ||
575 session->waiting_report_number == skb->data[0]) {
576 /* hidp_get_raw_report() is waiting on this report. */
577 session->report_return = skb;
578 done_with_skb = 0;
579 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
580 wake_up_interruptible(&session->report_queue);
581 }
582 }
583
584 return done_with_skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585}
586
Andrew Morton91f5cca2008-02-05 03:07:58 -0800587static void hidp_recv_ctrl_frame(struct hidp_session *session,
588 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589{
590 unsigned char hdr, type, param;
Alan Ott0ff17312011-01-18 03:04:40 -0500591 int free_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592
593 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
594
595 hdr = skb->data[0];
596 skb_pull(skb, 1);
597
598 type = hdr & HIDP_HEADER_TRANS_MASK;
599 param = hdr & HIDP_HEADER_PARAM_MASK;
600
601 switch (type) {
602 case HIDP_TRANS_HANDSHAKE:
603 hidp_process_handshake(session, param);
604 break;
605
606 case HIDP_TRANS_HID_CONTROL:
607 hidp_process_hid_control(session, param);
608 break;
609
610 case HIDP_TRANS_DATA:
Alan Ott0ff17312011-01-18 03:04:40 -0500611 free_skb = hidp_process_data(session, skb, param);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700612 break;
613
614 default:
615 __hidp_send_ctrl_message(session,
616 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
617 break;
618 }
619
Alan Ott0ff17312011-01-18 03:04:40 -0500620 if (free_skb)
621 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700622}
623
Andrew Morton91f5cca2008-02-05 03:07:58 -0800624static void hidp_recv_intr_frame(struct hidp_session *session,
625 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626{
627 unsigned char hdr;
628
629 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
630
631 hdr = skb->data[0];
632 skb_pull(skb, 1);
633
634 if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
635 hidp_set_timer(session);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100636
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 if (session->input)
638 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100639
640 if (session->hid) {
641 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
642 BT_DBG("report len %d", skb->len);
643 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 } else {
645 BT_DBG("Unsupported protocol header 0x%02x", hdr);
646 }
647
648 kfree_skb(skb);
649}
650
651static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
652{
653 struct kvec iv = { data, len };
654 struct msghdr msg;
655
656 BT_DBG("sock %p data %p len %d", sock, data, len);
657
658 if (!len)
659 return 0;
660
661 memset(&msg, 0, sizeof(msg));
662
663 return kernel_sendmsg(sock, &msg, &iv, 1, len);
664}
665
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300666static void hidp_process_intr_transmit(struct hidp_session *session)
667{
668 struct sk_buff *skb;
669
670 BT_DBG("session %p", session);
671
672 while ((skb = skb_dequeue(&session->intr_transmit))) {
673 if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
674 skb_queue_head(&session->intr_transmit, skb);
675 break;
676 }
677
678 hidp_set_timer(session);
679 kfree_skb(skb);
680 }
681}
682
683static void hidp_process_ctrl_transmit(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684{
685 struct sk_buff *skb;
686
687 BT_DBG("session %p", session);
688
689 while ((skb = skb_dequeue(&session->ctrl_transmit))) {
690 if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
691 skb_queue_head(&session->ctrl_transmit, skb);
692 break;
693 }
694
695 hidp_set_timer(session);
696 kfree_skb(skb);
697 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698}
699
700static int hidp_session(void *arg)
701{
702 struct hidp_session *session = arg;
703 struct sock *ctrl_sk = session->ctrl_sock->sk;
704 struct sock *intr_sk = session->intr_sock->sk;
705 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 wait_queue_t ctrl_wait, intr_wait;
707
708 BT_DBG("session %p", session);
709
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 set_user_nice(current, -15);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
712 init_waitqueue_entry(&ctrl_wait, current);
713 init_waitqueue_entry(&intr_wait, current);
Eric Dumazetaa395142010-04-20 13:03:51 +0000714 add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
715 add_wait_queue(sk_sleep(intr_sk), &intr_wait);
Alan Ott0f69dca2011-01-18 03:04:37 -0500716 session->waiting_for_startup = 0;
717 wake_up_interruptible(&session->startup_queue);
Peter Hurley7bb59df2011-06-30 13:53:53 -0400718 set_current_state(TASK_INTERRUPTIBLE);
719 while (!atomic_read(&session->terminate)) {
Szymon Janc17f09a72011-03-21 14:20:01 +0100720 if (ctrl_sk->sk_state != BT_CONNECTED ||
721 intr_sk->sk_state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700722 break;
723
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
725 skb_orphan(skb);
Mat Martineau44935722011-07-22 14:53:58 -0700726 if (!skb_linearize(skb))
727 hidp_recv_intr_frame(session, skb);
728 else
729 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700730 }
731
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300732 hidp_process_intr_transmit(session);
733
Gustavo F. Padovandc0da5c2011-10-06 18:02:13 -0300734 while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
735 skb_orphan(skb);
736 if (!skb_linearize(skb))
737 hidp_recv_ctrl_frame(session, skb);
738 else
739 kfree_skb(skb);
740 }
741
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300742 hidp_process_ctrl_transmit(session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743
744 schedule();
Peter Hurley7bb59df2011-06-30 13:53:53 -0400745 set_current_state(TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700746 }
747 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +0000748 remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
749 remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700750
David Herrmann794d1752011-08-26 14:06:02 +0200751 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
752 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
753 wake_up_interruptible(&session->report_queue);
754
Linus Torvalds1da177e2005-04-16 15:20:36 -0700755 down_write(&hidp_session_sem);
756
757 hidp_del_timer(session);
758
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759 if (session->input) {
760 input_unregister_device(session->input);
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500761 session->input = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700762 }
763
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100764 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200765 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -0700766 session->hid = NULL;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100767 }
768
Marcel Holtmannec8dab32008-07-14 20:13:53 +0200769 /* Wakeup user-space polling for socket errors */
770 session->intr_sock->sk->sk_err = EUNATCH;
771 session->ctrl_sock->sk->sk_err = EUNATCH;
772
773 hidp_schedule(session);
774
David Woodhouse1c398582007-07-07 14:58:39 -0400775 fput(session->intr_sock->file);
776
Eric Dumazetaa395142010-04-20 13:03:51 +0000777 wait_event_timeout(*(sk_sleep(ctrl_sk)),
David Woodhouse1c398582007-07-07 14:58:39 -0400778 (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
779
780 fput(session->ctrl_sock->file);
781
782 __hidp_unlink_session(session);
783
Linus Torvalds1da177e2005-04-16 15:20:36 -0700784 up_write(&hidp_session_sem);
785
Peter Hurley1c97e942011-08-05 10:51:34 -0400786 kfree(session->rd_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700787 kfree(session);
788 return 0;
789}
790
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200791static struct device *hidp_get_device(struct hidp_session *session)
792{
793 bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
794 bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700795 struct device *device = NULL;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200796 struct hci_dev *hdev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200797
798 hdev = hci_get_route(dst, src);
799 if (!hdev)
800 return NULL;
801
Marcel Holtmannedad6382009-08-22 14:22:15 -0700802 session->conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
803 if (session->conn)
804 device = &session->conn->dev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200805
806 hci_dev_put(hdev);
807
Marcel Holtmannedad6382009-08-22 14:22:15 -0700808 return device;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200809}
810
Andrew Morton91f5cca2008-02-05 03:07:58 -0800811static int hidp_setup_input(struct hidp_session *session,
812 struct hidp_connadd_req *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700813{
Jiri Slabyc500c972008-05-16 11:49:16 +0200814 struct input_dev *input;
Gustavo F. Padovan3415a5f2011-10-06 21:17:32 -0300815 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816
Jiri Slabyc500c972008-05-16 11:49:16 +0200817 input = input_allocate_device();
818 if (!input)
819 return -ENOMEM;
820
821 session->input = input;
822
Marcel Holtmann5be39462007-05-09 09:15:30 +0200823 input_set_drvdata(input, session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500825 input->name = "Bluetooth HID Boot Protocol Device";
826
Linus Torvalds1da177e2005-04-16 15:20:36 -0700827 input->id.bustype = BUS_BLUETOOTH;
828 input->id.vendor = req->vendor;
829 input->id.product = req->product;
830 input->id.version = req->version;
831
832 if (req->subclass & 0x40) {
833 set_bit(EV_KEY, input->evbit);
834 set_bit(EV_LED, input->evbit);
835 set_bit(EV_REP, input->evbit);
836
837 set_bit(LED_NUML, input->ledbit);
838 set_bit(LED_CAPSL, input->ledbit);
839 set_bit(LED_SCROLLL, input->ledbit);
840 set_bit(LED_COMPOSE, input->ledbit);
841 set_bit(LED_KANA, input->ledbit);
842
843 for (i = 0; i < sizeof(hidp_keycode); i++)
844 set_bit(hidp_keycode[i], input->keybit);
845 clear_bit(0, input->keybit);
846 }
847
848 if (req->subclass & 0x80) {
Jiri Slaby7b19ada2007-10-18 23:40:32 -0700849 input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
850 input->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
851 BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
852 input->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
853 input->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |
854 BIT_MASK(BTN_EXTRA);
855 input->relbit[0] |= BIT_MASK(REL_WHEEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700856 }
857
Marcel Holtmann5be39462007-05-09 09:15:30 +0200858 input->dev.parent = hidp_get_device(session);
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200859
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 input->event = hidp_input_event;
861
Marcel Holtmannedad6382009-08-22 14:22:15 -0700862 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
Gustavo F. Padovan3415a5f2011-10-06 21:17:32 -03001063 if (session->hid)
1064 err = hid_add_device(session->hid);
1065 else
1066 err = input_register_device(session->input);
1067
Peter Hurleye9d5cb52011-08-05 10:51:26 -04001068 if (err < 0) {
1069 atomic_inc(&session->terminate);
1070 wake_up_process(session->task);
1071 up_write(&hidp_session_sem);
1072 return err;
1073 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001074
1075 if (session->input) {
1076 hidp_send_ctrl_message(session,
1077 HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
1078 session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
1079
1080 session->leds = 0xff;
1081 hidp_input_event(session->input, EV_LED, 0, 0);
1082 }
1083
1084 up_write(&hidp_session_sem);
1085 return 0;
1086
1087unlink:
1088 hidp_del_timer(session);
1089
1090 __hidp_unlink_session(session);
1091
Marcel Holtmannedad6382009-08-22 14:22:15 -07001092 if (session->input) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001093 input_unregister_device(session->input);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001094 session->input = NULL;
1095 }
1096
1097 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001098 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001099 session->hid = NULL;
1100 }
1101
Michael Poole15c697c2010-02-05 12:23:43 -05001102 kfree(session->rd_data);
1103 session->rd_data = NULL;
1104
Marcel Holtmannedad6382009-08-22 14:22:15 -07001105purge:
Jiri Slabyc500c972008-05-16 11:49:16 +02001106 skb_queue_purge(&session->ctrl_transmit);
1107 skb_queue_purge(&session->intr_transmit);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001108
Jiri Slabyc500c972008-05-16 11:49:16 +02001109failed:
1110 up_write(&hidp_session_sem);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001111
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112 kfree(session);
1113 return err;
1114}
1115
1116int hidp_del_connection(struct hidp_conndel_req *req)
1117{
1118 struct hidp_session *session;
1119 int err = 0;
1120
1121 BT_DBG("");
1122
1123 down_read(&hidp_session_sem);
1124
1125 session = __hidp_get_session(&req->bdaddr);
1126 if (session) {
1127 if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
1128 hidp_send_ctrl_message(session,
1129 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
1130 } else {
1131 /* Flush the transmit queues */
1132 skb_queue_purge(&session->ctrl_transmit);
1133 skb_queue_purge(&session->intr_transmit);
1134
Peter Hurley7bb59df2011-06-30 13:53:53 -04001135 atomic_inc(&session->terminate);
1136 wake_up_process(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001137 }
1138 } else
1139 err = -ENOENT;
1140
1141 up_read(&hidp_session_sem);
1142 return err;
1143}
1144
1145int hidp_get_connlist(struct hidp_connlist_req *req)
1146{
Gustavo F. Padovancd11cdd2011-10-06 17:35:31 -03001147 struct hidp_session *session;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 int err = 0, n = 0;
1149
1150 BT_DBG("");
1151
1152 down_read(&hidp_session_sem);
1153
Gustavo F. Padovancd11cdd2011-10-06 17:35:31 -03001154 list_for_each_entry(session, &hidp_session_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155 struct hidp_conninfo ci;
1156
Linus Torvalds1da177e2005-04-16 15:20:36 -07001157 __hidp_copy_session(session, &ci);
1158
1159 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
1160 err = -EFAULT;
1161 break;
1162 }
1163
1164 if (++n >= req->cnum)
1165 break;
1166
1167 req->ci++;
1168 }
1169 req->cnum = n;
1170
1171 up_read(&hidp_session_sem);
1172 return err;
1173}
1174
1175int hidp_get_conninfo(struct hidp_conninfo *ci)
1176{
1177 struct hidp_session *session;
1178 int err = 0;
1179
1180 down_read(&hidp_session_sem);
1181
1182 session = __hidp_get_session(&ci->bdaddr);
1183 if (session)
1184 __hidp_copy_session(session, ci);
1185 else
1186 err = -ENOENT;
1187
1188 up_read(&hidp_session_sem);
1189 return err;
1190}
1191
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001192static const struct hid_device_id hidp_table[] = {
1193 { HID_BLUETOOTH_DEVICE(HID_ANY_ID, HID_ANY_ID) },
1194 { }
1195};
1196
1197static struct hid_driver hidp_driver = {
1198 .name = "generic-bluetooth",
1199 .id_table = hidp_table,
1200};
1201
Linus Torvalds1da177e2005-04-16 15:20:36 -07001202static int __init hidp_init(void)
1203{
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001204 int ret;
1205
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
1207
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001208 ret = hid_register_driver(&hidp_driver);
1209 if (ret)
1210 goto err;
1211
1212 ret = hidp_init_sockets();
1213 if (ret)
1214 goto err_drv;
1215
1216 return 0;
1217err_drv:
1218 hid_unregister_driver(&hidp_driver);
1219err:
1220 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221}
1222
1223static void __exit hidp_exit(void)
1224{
1225 hidp_cleanup_sockets();
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001226 hid_unregister_driver(&hidp_driver);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001227}
1228
1229module_init(hidp_init);
1230module_exit(hidp_exit);
1231
1232MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
1233MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
1234MODULE_VERSION(VERSION);
1235MODULE_LICENSE("GPL");
1236MODULE_ALIAS("bt-proto-6");