blob: 2342327f3335c69ab1bb7de610db392d8731810f [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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070024#include <linux/file.h>
Szymon Jancaabf6f82011-04-05 15:37:45 +020025#include <linux/kthread.h>
Marcel Holtmann364f6352009-08-22 14:15:53 -070026#include <linux/hidraw.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070027
28#include <net/bluetooth/bluetooth.h>
Marcel Holtmann0a85b962006-07-06 13:09:02 +020029#include <net/bluetooth/hci_core.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070030#include <net/bluetooth/l2cap.h>
31
32#include "hidp.h"
33
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +010034#define VERSION "1.2"
Linus Torvalds1da177e2005-04-16 15:20:36 -070035
36static DECLARE_RWSEM(hidp_session_sem);
37static LIST_HEAD(hidp_session_list);
38
39static unsigned char hidp_keycode[256] = {
Szymon Janc17f09a72011-03-21 14:20:01 +010040 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36,
41 37, 38, 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45,
42 21, 44, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 28, 1,
43 14, 15, 57, 12, 13, 26, 27, 43, 43, 39, 40, 41, 51, 52,
44 53, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 87, 88,
45 99, 70, 119, 110, 102, 104, 111, 107, 109, 106, 105, 108, 103, 69,
46 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 72, 73,
47 82, 83, 86, 127, 116, 117, 183, 184, 185, 186, 187, 188, 189, 190,
48 191, 192, 193, 194, 134, 138, 130, 132, 128, 129, 131, 137, 133, 135,
49 136, 113, 115, 114, 0, 0, 0, 121, 0, 89, 93, 124, 92, 94,
50 95, 0, 0, 0, 122, 123, 90, 91, 85, 0, 0, 0, 0, 0,
51 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
52 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
53 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
54 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
55 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
56 29, 42, 56, 125, 97, 54, 100, 126, 164, 166, 165, 163, 161, 115,
57 114, 113, 150, 158, 159, 128, 136, 177, 178, 176, 142, 152, 173, 140
Linus Torvalds1da177e2005-04-16 15:20:36 -070058};
59
60static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
61
62static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
63{
64 struct hidp_session *session;
Linus Torvalds1da177e2005-04-16 15:20:36 -070065
66 BT_DBG("");
67
Gustavo F. Padovancd11cdd2011-10-06 17:35:31 -030068 list_for_each_entry(session, &hidp_session_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070069 if (!bacmp(bdaddr, &session->bdaddr))
70 return session;
71 }
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +020072
Linus Torvalds1da177e2005-04-16 15:20:36 -070073 return NULL;
74}
75
76static void __hidp_link_session(struct hidp_session *session)
77{
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 list_add(&session->list, &hidp_session_list);
79}
80
81static void __hidp_unlink_session(struct hidp_session *session)
82{
Marcel Holtmannedad6382009-08-22 14:22:15 -070083 hci_conn_put_device(session->conn);
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085 list_del(&session->list);
Linus Torvalds1da177e2005-04-16 15:20:36 -070086}
87
88static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
89{
Vasiliy Kulikovd31dbf62010-10-30 18:26:31 +040090 memset(ci, 0, sizeof(*ci));
Linus Torvalds1da177e2005-04-16 15:20:36 -070091 bacpy(&ci->bdaddr, &session->bdaddr);
92
93 ci->flags = session->flags;
94 ci->state = session->state;
95
96 ci->vendor = 0x0000;
97 ci->product = 0x0000;
98 ci->version = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -070099
100 if (session->input) {
101 ci->vendor = session->input->id.vendor;
102 ci->product = session->input->id.product;
103 ci->version = session->input->id.version;
104 if (session->input->name)
105 strncpy(ci->name, session->input->name, 128);
106 else
107 strncpy(ci->name, "HID Boot Device", 128);
108 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100109
110 if (session->hid) {
111 ci->vendor = session->hid->vendor;
112 ci->product = session->hid->product;
113 ci->version = session->hid->version;
114 strncpy(ci->name, session->hid->name, 128);
115 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700116}
117
Andrew Morton91f5cca2008-02-05 03:07:58 -0800118static int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
119 unsigned int type, unsigned int code, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700121 unsigned char newleds;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100122 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100124 BT_DBG("session %p type %d code %d value %d", session, type, code, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
126 if (type != EV_LED)
127 return -1;
128
129 newleds = (!!test_bit(LED_KANA, dev->led) << 3) |
130 (!!test_bit(LED_COMPOSE, dev->led) << 3) |
131 (!!test_bit(LED_SCROLLL, dev->led) << 2) |
132 (!!test_bit(LED_CAPSL, dev->led) << 1) |
133 (!!test_bit(LED_NUML, dev->led));
134
135 if (session->leds == newleds)
136 return 0;
137
138 session->leds = newleds;
139
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200140 skb = alloc_skb(3, GFP_ATOMIC);
141 if (!skb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700142 BT_ERR("Can't allocate memory for new frame");
143 return -ENOMEM;
144 }
145
146 *skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
147 *skb_put(skb, 1) = 0x01;
148 *skb_put(skb, 1) = newleds;
149
150 skb_queue_tail(&session->intr_transmit, skb);
151
152 hidp_schedule(session);
153
154 return 0;
155}
156
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100157static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
158{
Marcel Holtmann5be39462007-05-09 09:15:30 +0200159 struct hid_device *hid = input_get_drvdata(dev);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100160 struct hidp_session *session = hid->driver_data;
161
162 return hidp_queue_event(session, dev, type, code, value);
163}
164
165static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
166{
Marcel Holtmann5be39462007-05-09 09:15:30 +0200167 struct hidp_session *session = input_get_drvdata(dev);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100168
169 return hidp_queue_event(session, dev, type, code, value);
170}
171
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
173{
174 struct input_dev *dev = session->input;
175 unsigned char *keys = session->keys;
176 unsigned char *udata = skb->data + 1;
177 signed char *sdata = skb->data + 1;
178 int i, size = skb->len - 1;
179
180 switch (skb->data[0]) {
181 case 0x01: /* Keyboard report */
182 for (i = 0; i < 8; i++)
183 input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
184
185 /* If all the key codes have been set to 0x01, it means
186 * too many keys were pressed at the same time. */
187 if (!memcmp(udata + 2, hidp_mkeyspat, 6))
188 break;
189
190 for (i = 2; i < 8; i++) {
191 if (keys[i] > 3 && memscan(udata + 2, keys[i], 6) == udata + 8) {
192 if (hidp_keycode[keys[i]])
193 input_report_key(dev, hidp_keycode[keys[i]], 0);
194 else
195 BT_ERR("Unknown key (scancode %#x) released.", keys[i]);
196 }
197
198 if (udata[i] > 3 && memscan(keys + 2, udata[i], 6) == keys + 8) {
199 if (hidp_keycode[udata[i]])
200 input_report_key(dev, hidp_keycode[udata[i]], 1);
201 else
202 BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]);
203 }
204 }
205
206 memcpy(keys, udata, 8);
207 break;
208
209 case 0x02: /* Mouse report */
210 input_report_key(dev, BTN_LEFT, sdata[0] & 0x01);
211 input_report_key(dev, BTN_RIGHT, sdata[0] & 0x02);
212 input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
213 input_report_key(dev, BTN_SIDE, sdata[0] & 0x08);
214 input_report_key(dev, BTN_EXTRA, sdata[0] & 0x10);
215
216 input_report_rel(dev, REL_X, sdata[1]);
217 input_report_rel(dev, REL_Y, sdata[2]);
218
219 if (size > 3)
220 input_report_rel(dev, REL_WHEEL, sdata[3]);
221 break;
222 }
223
224 input_sync(dev);
225}
226
Bastien Nocera6bf82682010-01-20 12:00:42 +0000227static int __hidp_send_ctrl_message(struct hidp_session *session,
Gustavo Padovan1d0c4da2012-06-09 19:22:42 -0300228 unsigned char hdr, unsigned char *data,
229 int size)
Bastien Nocera6bf82682010-01-20 12:00:42 +0000230{
231 struct sk_buff *skb;
232
233 BT_DBG("session %p data %p size %d", session, data, size);
234
David Herrmann794d1752011-08-26 14:06:02 +0200235 if (atomic_read(&session->terminate))
236 return -EIO;
237
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200238 skb = alloc_skb(size + 1, GFP_ATOMIC);
239 if (!skb) {
Bastien Nocera6bf82682010-01-20 12:00:42 +0000240 BT_ERR("Can't allocate memory for new frame");
241 return -ENOMEM;
242 }
243
244 *skb_put(skb, 1) = hdr;
245 if (data && size > 0)
246 memcpy(skb_put(skb, size), data, size);
247
248 skb_queue_tail(&session->ctrl_transmit, skb);
249
250 return 0;
251}
252
Gustavo Padovan6039aa72012-05-23 04:04:18 -0300253static int hidp_send_ctrl_message(struct hidp_session *session,
Bastien Nocera6bf82682010-01-20 12:00:42 +0000254 unsigned char hdr, unsigned char *data, int size)
255{
256 int err;
257
258 err = __hidp_send_ctrl_message(session, hdr, data, size);
259
260 hidp_schedule(session);
261
262 return err;
263}
264
Andrew Morton91f5cca2008-02-05 03:07:58 -0800265static int hidp_queue_report(struct hidp_session *session,
266 unsigned char *data, int size)
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100267{
268 struct sk_buff *skb;
269
Dave Young6792b5e2007-10-20 14:15:39 +0200270 BT_DBG("session %p hid %p data %p size %d", session, session->hid, data, size);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100271
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200272 skb = alloc_skb(size + 1, GFP_ATOMIC);
273 if (!skb) {
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100274 BT_ERR("Can't allocate memory for new frame");
275 return -ENOMEM;
276 }
277
278 *skb_put(skb, 1) = 0xa2;
279 if (size > 0)
280 memcpy(skb_put(skb, size), data, size);
281
282 skb_queue_tail(&session->intr_transmit, skb);
283
284 hidp_schedule(session);
285
286 return 0;
287}
288
289static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
290{
291 unsigned char buf[32];
292 int rsize;
293
294 rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
295 if (rsize > sizeof(buf))
296 return -EIO;
297
298 hid_output_report(report, buf);
299
300 return hidp_queue_report(session, buf, rsize);
301}
302
Alan Ott0ff17312011-01-18 03:04:40 -0500303static int hidp_get_raw_report(struct hid_device *hid,
304 unsigned char report_number,
305 unsigned char *data, size_t count,
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100306 unsigned char report_type)
Jiri Kosina2da31932009-11-26 16:20:56 +0100307{
Alan Ott0ff17312011-01-18 03:04:40 -0500308 struct hidp_session *session = hid->driver_data;
309 struct sk_buff *skb;
310 size_t len;
311 int numbered_reports = hid->report_enum[report_type].numbered;
David Herrmann794d1752011-08-26 14:06:02 +0200312 int ret;
Alan Ott0ff17312011-01-18 03:04:40 -0500313
Karl Reltonfd86c9b2013-02-20 18:16:19 +0000314 if (atomic_read(&session->terminate))
315 return -EIO;
316
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100317 switch (report_type) {
318 case HID_FEATURE_REPORT:
Alan Ott0ff17312011-01-18 03:04:40 -0500319 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
320 break;
321 case HID_INPUT_REPORT:
322 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_INPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100323 break;
324 case HID_OUTPUT_REPORT:
Alan Ott0ff17312011-01-18 03:04:40 -0500325 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_OUPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100326 break;
327 default:
328 return -EINVAL;
329 }
330
Alan Ott0ff17312011-01-18 03:04:40 -0500331 if (mutex_lock_interruptible(&session->report_mutex))
332 return -ERESTARTSYS;
333
334 /* Set up our wait, and send the report request to the device. */
335 session->waiting_report_type = report_type & HIDP_DATA_RTYPE_MASK;
336 session->waiting_report_number = numbered_reports ? report_number : -1;
337 set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
338 data[0] = report_number;
David Herrmann794d1752011-08-26 14:06:02 +0200339 ret = hidp_send_ctrl_message(hid->driver_data, report_type, data, 1);
340 if (ret)
341 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500342
343 /* Wait for the return of the report. The returned report
344 gets put in session->report_return. */
345 while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
346 int res;
347
348 res = wait_event_interruptible_timeout(session->report_queue,
349 !test_bit(HIDP_WAITING_FOR_RETURN, &session->flags),
350 5*HZ);
351 if (res == 0) {
352 /* timeout */
David Herrmann794d1752011-08-26 14:06:02 +0200353 ret = -EIO;
354 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500355 }
356 if (res < 0) {
357 /* signal */
David Herrmann794d1752011-08-26 14:06:02 +0200358 ret = -ERESTARTSYS;
359 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500360 }
361 }
362
363 skb = session->report_return;
364 if (skb) {
365 len = skb->len < count ? skb->len : count;
366 memcpy(data, skb->data, len);
367
368 kfree_skb(skb);
369 session->report_return = NULL;
370 } else {
371 /* Device returned a HANDSHAKE, indicating protocol error. */
372 len = -EIO;
373 }
374
375 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
376 mutex_unlock(&session->report_mutex);
377
378 return len;
379
David Herrmann794d1752011-08-26 14:06:02 +0200380err:
Alan Ott0ff17312011-01-18 03:04:40 -0500381 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
382 mutex_unlock(&session->report_mutex);
David Herrmann794d1752011-08-26 14:06:02 +0200383 return ret;
Alan Ott0ff17312011-01-18 03:04:40 -0500384}
385
Linus Torvalds1da177e2005-04-16 15:20:36 -0700386static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
Jiri Kosina2da31932009-11-26 16:20:56 +0100387 unsigned char report_type)
388{
Alan Ott08254112011-01-18 03:04:38 -0500389 struct hidp_session *session = hid->driver_data;
390 int ret;
391
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100392 switch (report_type) {
393 case HID_FEATURE_REPORT:
394 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
395 break;
396 case HID_OUTPUT_REPORT:
Antonio Ospite97e1efb2011-02-20 18:26:46 +0100397 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100398 break;
399 default:
400 return -EINVAL;
401 }
402
Alan Ott08254112011-01-18 03:04:38 -0500403 if (mutex_lock_interruptible(&session->report_mutex))
404 return -ERESTARTSYS;
405
406 /* Set up our wait, and send the report request to the device. */
407 set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
David Herrmann794d1752011-08-26 14:06:02 +0200408 ret = hidp_send_ctrl_message(hid->driver_data, report_type, data,
409 count);
410 if (ret)
Alan Ott08254112011-01-18 03:04:38 -0500411 goto err;
Alan Ott08254112011-01-18 03:04:38 -0500412
413 /* Wait for the ACK from the device. */
414 while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
415 int res;
416
417 res = wait_event_interruptible_timeout(session->report_queue,
418 !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags),
419 10*HZ);
420 if (res == 0) {
421 /* timeout */
422 ret = -EIO;
423 goto err;
424 }
425 if (res < 0) {
426 /* signal */
427 ret = -ERESTARTSYS;
428 goto err;
429 }
430 }
431
432 if (!session->output_report_success) {
433 ret = -EIO;
434 goto err;
435 }
436
437 ret = count;
438
439err:
440 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
441 mutex_unlock(&session->report_mutex);
442 return ret;
Jiri Kosina2da31932009-11-26 16:20:56 +0100443}
444
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445static void hidp_idle_timeout(unsigned long arg)
446{
447 struct hidp_session *session = (struct hidp_session *) arg;
448
Peter Hurley7bb59df2011-06-30 13:53:53 -0400449 atomic_inc(&session->terminate);
450 wake_up_process(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451}
452
Andrew Morton91f5cca2008-02-05 03:07:58 -0800453static void hidp_set_timer(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454{
455 if (session->idle_to > 0)
456 mod_timer(&session->timer, jiffies + HZ * session->idle_to);
457}
458
Gustavo Padovan6039aa72012-05-23 04:04:18 -0300459static void hidp_del_timer(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460{
461 if (session->idle_to > 0)
462 del_timer(&session->timer);
463}
464
Andrew Morton91f5cca2008-02-05 03:07:58 -0800465static void hidp_process_handshake(struct hidp_session *session,
466 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467{
468 BT_DBG("session %p param 0x%02x", session, param);
Alan Ott08254112011-01-18 03:04:38 -0500469 session->output_report_success = 0; /* default condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470
471 switch (param) {
472 case HIDP_HSHK_SUCCESSFUL:
473 /* FIXME: Call into SET_ GET_ handlers here */
Alan Ott08254112011-01-18 03:04:38 -0500474 session->output_report_success = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 break;
476
477 case HIDP_HSHK_NOT_READY:
478 case HIDP_HSHK_ERR_INVALID_REPORT_ID:
479 case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
480 case HIDP_HSHK_ERR_INVALID_PARAMETER:
Gustavo F. Padovanab88f712011-10-06 22:05:37 -0300481 if (test_and_clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags))
Alan Ott0ff17312011-01-18 03:04:40 -0500482 wake_up_interruptible(&session->report_queue);
Gustavo F. Padovanab88f712011-10-06 22:05:37 -0300483
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 /* FIXME: Call into SET_ GET_ handlers here */
485 break;
486
487 case HIDP_HSHK_ERR_UNKNOWN:
488 break;
489
490 case HIDP_HSHK_ERR_FATAL:
491 /* Device requests a reboot, as this is the only way this error
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900492 * can be recovered. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700493 __hidp_send_ctrl_message(session,
494 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
495 break;
496
497 default:
498 __hidp_send_ctrl_message(session,
499 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
500 break;
501 }
Alan Ott08254112011-01-18 03:04:38 -0500502
503 /* Wake up the waiting thread. */
Gustavo F. Padovanab88f712011-10-06 22:05:37 -0300504 if (test_and_clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags))
Alan Ott08254112011-01-18 03:04:38 -0500505 wake_up_interruptible(&session->report_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506}
507
Andrew Morton91f5cca2008-02-05 03:07:58 -0800508static void hidp_process_hid_control(struct hidp_session *session,
509 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700510{
511 BT_DBG("session %p param 0x%02x", session, param);
512
Dave Youngeff001e2008-02-05 03:07:14 -0800513 if (param == HIDP_CTRL_VIRTUAL_CABLE_UNPLUG) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 /* Flush the transmit queues */
515 skb_queue_purge(&session->ctrl_transmit);
516 skb_queue_purge(&session->intr_transmit);
517
Peter Hurley7bb59df2011-06-30 13:53:53 -0400518 atomic_inc(&session->terminate);
519 wake_up_process(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700520 }
521}
522
Alan Ott0ff17312011-01-18 03:04:40 -0500523/* Returns true if the passed-in skb should be freed by the caller. */
524static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800525 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700526{
Alan Ott0ff17312011-01-18 03:04:40 -0500527 int done_with_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528 BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
529
530 switch (param) {
531 case HIDP_DATA_RTYPE_INPUT:
532 hidp_set_timer(session);
533
534 if (session->input)
535 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100536
537 if (session->hid)
538 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 break;
540
541 case HIDP_DATA_RTYPE_OTHER:
542 case HIDP_DATA_RTYPE_OUPUT:
543 case HIDP_DATA_RTYPE_FEATURE:
544 break;
545
546 default:
547 __hidp_send_ctrl_message(session,
548 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
549 }
Alan Ott0ff17312011-01-18 03:04:40 -0500550
551 if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
552 param == session->waiting_report_type) {
553 if (session->waiting_report_number < 0 ||
554 session->waiting_report_number == skb->data[0]) {
555 /* hidp_get_raw_report() is waiting on this report. */
556 session->report_return = skb;
557 done_with_skb = 0;
558 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
559 wake_up_interruptible(&session->report_queue);
560 }
561 }
562
563 return done_with_skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564}
565
Andrew Morton91f5cca2008-02-05 03:07:58 -0800566static void hidp_recv_ctrl_frame(struct hidp_session *session,
567 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568{
569 unsigned char hdr, type, param;
Alan Ott0ff17312011-01-18 03:04:40 -0500570 int free_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571
572 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
573
574 hdr = skb->data[0];
575 skb_pull(skb, 1);
576
577 type = hdr & HIDP_HEADER_TRANS_MASK;
578 param = hdr & HIDP_HEADER_PARAM_MASK;
579
580 switch (type) {
581 case HIDP_TRANS_HANDSHAKE:
582 hidp_process_handshake(session, param);
583 break;
584
585 case HIDP_TRANS_HID_CONTROL:
586 hidp_process_hid_control(session, param);
587 break;
588
589 case HIDP_TRANS_DATA:
Alan Ott0ff17312011-01-18 03:04:40 -0500590 free_skb = hidp_process_data(session, skb, param);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700591 break;
592
593 default:
594 __hidp_send_ctrl_message(session,
595 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
596 break;
597 }
598
Alan Ott0ff17312011-01-18 03:04:40 -0500599 if (free_skb)
600 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700601}
602
Andrew Morton91f5cca2008-02-05 03:07:58 -0800603static void hidp_recv_intr_frame(struct hidp_session *session,
604 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605{
606 unsigned char hdr;
607
608 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
609
610 hdr = skb->data[0];
611 skb_pull(skb, 1);
612
613 if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
614 hidp_set_timer(session);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100615
Linus Torvalds1da177e2005-04-16 15:20:36 -0700616 if (session->input)
617 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100618
619 if (session->hid) {
620 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
621 BT_DBG("report len %d", skb->len);
622 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700623 } else {
624 BT_DBG("Unsupported protocol header 0x%02x", hdr);
625 }
626
627 kfree_skb(skb);
628}
629
630static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
631{
632 struct kvec iv = { data, len };
633 struct msghdr msg;
634
635 BT_DBG("sock %p data %p len %d", sock, data, len);
636
637 if (!len)
638 return 0;
639
640 memset(&msg, 0, sizeof(msg));
641
642 return kernel_sendmsg(sock, &msg, &iv, 1, len);
643}
644
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300645static void hidp_process_intr_transmit(struct hidp_session *session)
646{
647 struct sk_buff *skb;
648
649 BT_DBG("session %p", session);
650
651 while ((skb = skb_dequeue(&session->intr_transmit))) {
652 if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
653 skb_queue_head(&session->intr_transmit, skb);
654 break;
655 }
656
657 hidp_set_timer(session);
658 kfree_skb(skb);
659 }
660}
661
662static void hidp_process_ctrl_transmit(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663{
664 struct sk_buff *skb;
665
666 BT_DBG("session %p", session);
667
668 while ((skb = skb_dequeue(&session->ctrl_transmit))) {
669 if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
670 skb_queue_head(&session->ctrl_transmit, skb);
671 break;
672 }
673
674 hidp_set_timer(session);
675 kfree_skb(skb);
676 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677}
678
679static int hidp_session(void *arg)
680{
681 struct hidp_session *session = arg;
682 struct sock *ctrl_sk = session->ctrl_sock->sk;
683 struct sock *intr_sk = session->intr_sock->sk;
684 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700685 wait_queue_t ctrl_wait, intr_wait;
686
687 BT_DBG("session %p", session);
688
David Herrmann25df0842011-11-01 17:27:50 +0100689 __module_get(THIS_MODULE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 set_user_nice(current, -15);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691
692 init_waitqueue_entry(&ctrl_wait, current);
693 init_waitqueue_entry(&intr_wait, current);
Eric Dumazetaa395142010-04-20 13:03:51 +0000694 add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
695 add_wait_queue(sk_sleep(intr_sk), &intr_wait);
Alan Ott0f69dca2011-01-18 03:04:37 -0500696 session->waiting_for_startup = 0;
697 wake_up_interruptible(&session->startup_queue);
Peter Hurley7bb59df2011-06-30 13:53:53 -0400698 set_current_state(TASK_INTERRUPTIBLE);
699 while (!atomic_read(&session->terminate)) {
Szymon Janc17f09a72011-03-21 14:20:01 +0100700 if (ctrl_sk->sk_state != BT_CONNECTED ||
701 intr_sk->sk_state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700702 break;
703
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704 while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
705 skb_orphan(skb);
Mat Martineau44935722011-07-22 14:53:58 -0700706 if (!skb_linearize(skb))
707 hidp_recv_intr_frame(session, skb);
708 else
709 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 }
711
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300712 hidp_process_intr_transmit(session);
713
Gustavo F. Padovandc0da5c2011-10-06 18:02:13 -0300714 while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
715 skb_orphan(skb);
716 if (!skb_linearize(skb))
717 hidp_recv_ctrl_frame(session, skb);
718 else
719 kfree_skb(skb);
720 }
721
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300722 hidp_process_ctrl_transmit(session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723
724 schedule();
Peter Hurley7bb59df2011-06-30 13:53:53 -0400725 set_current_state(TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700726 }
727 set_current_state(TASK_RUNNING);
Karl Reltonfd86c9b2013-02-20 18:16:19 +0000728 atomic_inc(&session->terminate);
Eric Dumazetaa395142010-04-20 13:03:51 +0000729 remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
730 remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731
David Herrmann794d1752011-08-26 14:06:02 +0200732 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
733 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
734 wake_up_interruptible(&session->report_queue);
735
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 down_write(&hidp_session_sem);
737
738 hidp_del_timer(session);
739
Linus Torvalds1da177e2005-04-16 15:20:36 -0700740 if (session->input) {
741 input_unregister_device(session->input);
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500742 session->input = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700743 }
744
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100745 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200746 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -0700747 session->hid = NULL;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100748 }
749
Marcel Holtmannec8dab32008-07-14 20:13:53 +0200750 /* Wakeup user-space polling for socket errors */
751 session->intr_sock->sk->sk_err = EUNATCH;
752 session->ctrl_sock->sk->sk_err = EUNATCH;
753
754 hidp_schedule(session);
755
David Woodhouse1c398582007-07-07 14:58:39 -0400756 fput(session->intr_sock->file);
757
Eric Dumazetaa395142010-04-20 13:03:51 +0000758 wait_event_timeout(*(sk_sleep(ctrl_sk)),
David Woodhouse1c398582007-07-07 14:58:39 -0400759 (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
760
761 fput(session->ctrl_sock->file);
762
763 __hidp_unlink_session(session);
764
Linus Torvalds1da177e2005-04-16 15:20:36 -0700765 up_write(&hidp_session_sem);
766
Peter Hurley1c97e942011-08-05 10:51:34 -0400767 kfree(session->rd_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700768 kfree(session);
David Herrmann25df0842011-11-01 17:27:50 +0100769 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700770 return 0;
771}
772
Gustavo F. Padovan3e90dc82011-10-07 01:29:51 -0300773static struct hci_conn *hidp_get_connection(struct hidp_session *session)
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200774{
775 bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
776 bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
Peter Hurley1785dbf2011-08-30 11:53:35 -0400777 struct hci_conn *conn;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200778 struct hci_dev *hdev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200779
780 hdev = hci_get_route(dst, src);
781 if (!hdev)
782 return NULL;
783
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300784 hci_dev_lock(hdev);
Peter Hurley1785dbf2011-08-30 11:53:35 -0400785 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
786 if (conn)
787 hci_conn_hold_device(conn);
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300788 hci_dev_unlock(hdev);
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200789
790 hci_dev_put(hdev);
791
Peter Hurley1785dbf2011-08-30 11:53:35 -0400792 return conn;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200793}
794
Andrew Morton91f5cca2008-02-05 03:07:58 -0800795static int hidp_setup_input(struct hidp_session *session,
796 struct hidp_connadd_req *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797{
Jiri Slabyc500c972008-05-16 11:49:16 +0200798 struct input_dev *input;
Gustavo F. Padovan3415a5f2011-10-06 21:17:32 -0300799 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800
Jiri Slabyc500c972008-05-16 11:49:16 +0200801 input = input_allocate_device();
802 if (!input)
803 return -ENOMEM;
804
805 session->input = input;
806
Marcel Holtmann5be39462007-05-09 09:15:30 +0200807 input_set_drvdata(input, session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500809 input->name = "Bluetooth HID Boot Protocol Device";
810
Linus Torvalds1da177e2005-04-16 15:20:36 -0700811 input->id.bustype = BUS_BLUETOOTH;
812 input->id.vendor = req->vendor;
813 input->id.product = req->product;
814 input->id.version = req->version;
815
816 if (req->subclass & 0x40) {
817 set_bit(EV_KEY, input->evbit);
818 set_bit(EV_LED, input->evbit);
819 set_bit(EV_REP, input->evbit);
820
821 set_bit(LED_NUML, input->ledbit);
822 set_bit(LED_CAPSL, input->ledbit);
823 set_bit(LED_SCROLLL, input->ledbit);
824 set_bit(LED_COMPOSE, input->ledbit);
825 set_bit(LED_KANA, input->ledbit);
826
827 for (i = 0; i < sizeof(hidp_keycode); i++)
828 set_bit(hidp_keycode[i], input->keybit);
829 clear_bit(0, input->keybit);
830 }
831
832 if (req->subclass & 0x80) {
Jiri Slaby7b19ada2007-10-18 23:40:32 -0700833 input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
834 input->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
835 BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
836 input->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
837 input->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |
838 BIT_MASK(BTN_EXTRA);
839 input->relbit[0] |= BIT_MASK(REL_WHEEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 }
841
Peter Hurley1785dbf2011-08-30 11:53:35 -0400842 input->dev.parent = &session->conn->dev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200843
Linus Torvalds1da177e2005-04-16 15:20:36 -0700844 input->event = hidp_input_event;
845
Marcel Holtmannedad6382009-08-22 14:22:15 -0700846 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847}
848
Marcel Holtmannf5ffd462007-02-17 23:58:53 +0100849static int hidp_open(struct hid_device *hid)
850{
851 return 0;
852}
853
854static void hidp_close(struct hid_device *hid)
855{
856}
857
Jiri Slabyc500c972008-05-16 11:49:16 +0200858static int hidp_parse(struct hid_device *hid)
859{
860 struct hidp_session *session = hid->driver_data;
Jiri Slabyc500c972008-05-16 11:49:16 +0200861
Michael Poole15c697c2010-02-05 12:23:43 -0500862 return hid_parse_report(session->hid, session->rd_data,
863 session->rd_size);
Jiri Slabyc500c972008-05-16 11:49:16 +0200864}
865
866static int hidp_start(struct hid_device *hid)
867{
868 struct hidp_session *session = hid->driver_data;
869 struct hid_report *report;
870
David Herrmann142c69c2011-08-26 13:27:12 +0200871 if (hid->quirks & HID_QUIRK_NO_INIT_REPORTS)
872 return 0;
873
Jiri Slabyc500c972008-05-16 11:49:16 +0200874 list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].
875 report_list, list)
876 hidp_send_report(session, report);
877
878 list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].
879 report_list, list)
880 hidp_send_report(session, report);
881
Jiri Slabyc500c972008-05-16 11:49:16 +0200882 return 0;
883}
884
885static void hidp_stop(struct hid_device *hid)
886{
887 struct hidp_session *session = hid->driver_data;
888
889 skb_queue_purge(&session->ctrl_transmit);
890 skb_queue_purge(&session->intr_transmit);
891
Jiri Slabyc500c972008-05-16 11:49:16 +0200892 hid->claimed = 0;
893}
894
895static struct hid_ll_driver hidp_hid_driver = {
896 .parse = hidp_parse,
897 .start = hidp_start,
898 .stop = hidp_stop,
899 .open = hidp_open,
900 .close = hidp_close,
901 .hidinput_input_event = hidp_hidinput_event,
902};
903
Alan Ott0f69dca2011-01-18 03:04:37 -0500904/* This function sets up the hid device. It does not add it
905 to the HID system. That is done in hidp_add_connection(). */
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200906static int hidp_setup_hid(struct hidp_session *session,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800907 struct hidp_connadd_req *req)
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100908{
Jiri Slabyc500c972008-05-16 11:49:16 +0200909 struct hid_device *hid;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700910 int err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100911
Michael Poole15c697c2010-02-05 12:23:43 -0500912 session->rd_data = kzalloc(req->rd_size, GFP_KERNEL);
913 if (!session->rd_data)
914 return -ENOMEM;
915
916 if (copy_from_user(session->rd_data, req->rd_data, req->rd_size)) {
917 err = -EFAULT;
918 goto fault;
919 }
920 session->rd_size = req->rd_size;
921
Jiri Slabyc500c972008-05-16 11:49:16 +0200922 hid = hid_allocate_device();
Michael Poole15c697c2010-02-05 12:23:43 -0500923 if (IS_ERR(hid)) {
924 err = PTR_ERR(hid);
925 goto fault;
926 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100927
Jiri Slabyc500c972008-05-16 11:49:16 +0200928 session->hid = hid;
Michael Poole15c697c2010-02-05 12:23:43 -0500929
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100930 hid->driver_data = session;
931
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100932 hid->bus = BUS_BLUETOOTH;
933 hid->vendor = req->vendor;
934 hid->product = req->product;
935 hid->version = req->version;
Jiri Slabyc500c972008-05-16 11:49:16 +0200936 hid->country = req->country;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100937
Anderson Lizardo0a9ab9b2013-01-06 18:28:53 -0400938 strncpy(hid->name, req->name, sizeof(req->name) - 1);
Andrei Emeltchenkofcb73332012-09-25 12:49:44 +0300939
940 snprintf(hid->phys, sizeof(hid->phys), "%pMR",
941 &bt_sk(session->ctrl_sock->sk)->src);
942
943 snprintf(hid->uniq, sizeof(hid->uniq), "%pMR",
944 &bt_sk(session->ctrl_sock->sk)->dst);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100945
Peter Hurley1785dbf2011-08-30 11:53:35 -0400946 hid->dev.parent = &session->conn->dev;
Jiri Slabyc500c972008-05-16 11:49:16 +0200947 hid->ll_driver = &hidp_hid_driver;
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200948
Alan Ott0ff17312011-01-18 03:04:40 -0500949 hid->hid_get_raw_report = hidp_get_raw_report;
Jiri Kosina2da31932009-11-26 16:20:56 +0100950 hid->hid_output_raw_report = hidp_output_raw_report;
951
Lamarque V. Souza4529eef2012-12-06 12:39:55 -0200952 /* True if device is blacklisted in drivers/hid/hid-core.c */
953 if (hid_ignore(hid)) {
954 hid_destroy_device(session->hid);
955 session->hid = NULL;
956 return -ENODEV;
957 }
958
Jiri Slabyc500c972008-05-16 11:49:16 +0200959 return 0;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700960
Michael Poole15c697c2010-02-05 12:23:43 -0500961fault:
962 kfree(session->rd_data);
963 session->rd_data = NULL;
964
Marcel Holtmannedad6382009-08-22 14:22:15 -0700965 return err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100966}
967
Linus Torvalds1da177e2005-04-16 15:20:36 -0700968int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
969{
970 struct hidp_session *session, *s;
Szymon Jancaabf6f82011-04-05 15:37:45 +0200971 int vendor, product;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700972 int err;
973
974 BT_DBG("");
975
976 if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
977 bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
978 return -ENOTUNIQ;
979
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100980 BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
981
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 down_write(&hidp_session_sem);
983
984 s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
985 if (s && s->state == BT_CONNECTED) {
Gustavo F. Padovan81b25cd2011-10-06 23:32:29 -0300986 up_write(&hidp_session_sem);
987 return -EEXIST;
988 }
989
990 session = kzalloc(sizeof(struct hidp_session), GFP_KERNEL);
991 if (!session) {
992 up_write(&hidp_session_sem);
993 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700994 }
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
Gustavo F. Padovan3c32fa92011-10-20 17:21:34 -02001009 session->conn = hidp_get_connection(session);
1010 if (!session->conn) {
1011 err = -ENOTCONN;
1012 goto failed;
1013 }
1014
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001015 setup_timer(&session->timer, hidp_idle_timeout, (unsigned long)session);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016
1017 skb_queue_head_init(&session->ctrl_transmit);
1018 skb_queue_head_init(&session->intr_transmit);
1019
Alan Ott0ff17312011-01-18 03:04:40 -05001020 mutex_init(&session->report_mutex);
1021 init_waitqueue_head(&session->report_queue);
Alan Ott0f69dca2011-01-18 03:04:37 -05001022 init_waitqueue_head(&session->startup_queue);
1023 session->waiting_for_startup = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
1025 session->idle_to = req->idle_to;
1026
Peter Hurley1785dbf2011-08-30 11:53:35 -04001027 __hidp_link_session(session);
1028
Jiri Slabyc500c972008-05-16 11:49:16 +02001029 if (req->rd_size > 0) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001030 err = hidp_setup_hid(session, req);
Lamarque V. Souza4529eef2012-12-06 12:39:55 -02001031 if (err && err != -ENODEV)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001032 goto purge;
Jiri Slabyc500c972008-05-16 11:49:16 +02001033 }
1034
1035 if (!session->hid) {
1036 err = hidp_setup_input(session, req);
1037 if (err < 0)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001038 goto purge;
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001039 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001040
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 hidp_set_timer(session);
1042
Szymon Jancaabf6f82011-04-05 15:37:45 +02001043 if (session->hid) {
1044 vendor = session->hid->vendor;
1045 product = session->hid->product;
1046 } else if (session->input) {
1047 vendor = session->input->id.vendor;
1048 product = session->input->id.product;
1049 } else {
1050 vendor = 0x0000;
1051 product = 0x0000;
1052 }
1053
1054 session->task = kthread_run(hidp_session, session, "khidpd_%04x%04x",
1055 vendor, product);
1056 if (IS_ERR(session->task)) {
1057 err = PTR_ERR(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 goto unlink;
Szymon Jancaabf6f82011-04-05 15:37:45 +02001059 }
1060
Alan Ott0f69dca2011-01-18 03:04:37 -05001061 while (session->waiting_for_startup) {
1062 wait_event_interruptible(session->startup_queue,
1063 !session->waiting_for_startup);
1064 }
1065
Gustavo F. Padovan3415a5f2011-10-06 21:17:32 -03001066 if (session->hid)
1067 err = hid_add_device(session->hid);
1068 else
1069 err = input_register_device(session->input);
1070
Peter Hurleye9d5cb52011-08-05 10:51:26 -04001071 if (err < 0) {
1072 atomic_inc(&session->terminate);
1073 wake_up_process(session->task);
1074 up_write(&hidp_session_sem);
1075 return err;
1076 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077
1078 if (session->input) {
1079 hidp_send_ctrl_message(session,
1080 HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
1081 session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
1082
1083 session->leds = 0xff;
1084 hidp_input_event(session->input, EV_LED, 0, 0);
1085 }
1086
1087 up_write(&hidp_session_sem);
1088 return 0;
1089
1090unlink:
1091 hidp_del_timer(session);
1092
Marcel Holtmannedad6382009-08-22 14:22:15 -07001093 if (session->input) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 input_unregister_device(session->input);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001095 session->input = NULL;
1096 }
1097
1098 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001099 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001100 session->hid = NULL;
1101 }
1102
Michael Poole15c697c2010-02-05 12:23:43 -05001103 kfree(session->rd_data);
1104 session->rd_data = NULL;
1105
Marcel Holtmannedad6382009-08-22 14:22:15 -07001106purge:
Peter Hurley1785dbf2011-08-30 11:53:35 -04001107 __hidp_unlink_session(session);
1108
Jiri Slabyc500c972008-05-16 11:49:16 +02001109 skb_queue_purge(&session->ctrl_transmit);
1110 skb_queue_purge(&session->intr_transmit);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001111
Jiri Slabyc500c972008-05-16 11:49:16 +02001112failed:
1113 up_write(&hidp_session_sem);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001114
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 kfree(session);
1116 return err;
1117}
1118
1119int hidp_del_connection(struct hidp_conndel_req *req)
1120{
1121 struct hidp_session *session;
1122 int err = 0;
1123
1124 BT_DBG("");
1125
1126 down_read(&hidp_session_sem);
1127
1128 session = __hidp_get_session(&req->bdaddr);
1129 if (session) {
1130 if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
1131 hidp_send_ctrl_message(session,
1132 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
1133 } else {
1134 /* Flush the transmit queues */
1135 skb_queue_purge(&session->ctrl_transmit);
1136 skb_queue_purge(&session->intr_transmit);
1137
Peter Hurley7bb59df2011-06-30 13:53:53 -04001138 atomic_inc(&session->terminate);
1139 wake_up_process(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 }
1141 } else
1142 err = -ENOENT;
1143
1144 up_read(&hidp_session_sem);
1145 return err;
1146}
1147
1148int hidp_get_connlist(struct hidp_connlist_req *req)
1149{
Gustavo F. Padovancd11cdd2011-10-06 17:35:31 -03001150 struct hidp_session *session;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 int err = 0, n = 0;
1152
1153 BT_DBG("");
1154
1155 down_read(&hidp_session_sem);
1156
Gustavo F. Padovancd11cdd2011-10-06 17:35:31 -03001157 list_for_each_entry(session, &hidp_session_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 struct hidp_conninfo ci;
1159
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 __hidp_copy_session(session, &ci);
1161
1162 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
1163 err = -EFAULT;
1164 break;
1165 }
1166
1167 if (++n >= req->cnum)
1168 break;
1169
1170 req->ci++;
1171 }
1172 req->cnum = n;
1173
1174 up_read(&hidp_session_sem);
1175 return err;
1176}
1177
1178int hidp_get_conninfo(struct hidp_conninfo *ci)
1179{
1180 struct hidp_session *session;
1181 int err = 0;
1182
1183 down_read(&hidp_session_sem);
1184
1185 session = __hidp_get_session(&ci->bdaddr);
1186 if (session)
1187 __hidp_copy_session(session, ci);
1188 else
1189 err = -ENOENT;
1190
1191 up_read(&hidp_session_sem);
1192 return err;
1193}
1194
1195static int __init hidp_init(void)
1196{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
1198
Henrik Rydberg8215d552012-04-23 12:07:07 +02001199 return hidp_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200}
1201
1202static void __exit hidp_exit(void)
1203{
1204 hidp_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205}
1206
1207module_init(hidp_init);
1208module_exit(hidp_exit);
1209
1210MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
1211MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
1212MODULE_VERSION(VERSION);
1213MODULE_LICENSE("GPL");
1214MODULE_ALIAS("bt-proto-6");