blob: 9734136d64311f7632115b509a1c28d1ae0e443c [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
Linus Torvalds1da177e2005-04-16 15:20:36 -070076static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
77{
Vasiliy Kulikovd31dbf62010-10-30 18:26:31 +040078 memset(ci, 0, sizeof(*ci));
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 bacpy(&ci->bdaddr, &session->bdaddr);
80
81 ci->flags = session->flags;
82 ci->state = session->state;
83
84 ci->vendor = 0x0000;
85 ci->product = 0x0000;
86 ci->version = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -070087
88 if (session->input) {
89 ci->vendor = session->input->id.vendor;
90 ci->product = session->input->id.product;
91 ci->version = session->input->id.version;
92 if (session->input->name)
93 strncpy(ci->name, session->input->name, 128);
94 else
95 strncpy(ci->name, "HID Boot Device", 128);
96 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +010097
98 if (session->hid) {
99 ci->vendor = session->hid->vendor;
100 ci->product = session->hid->product;
101 ci->version = session->hid->version;
102 strncpy(ci->name, session->hid->name, 128);
103 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700104}
105
Andrew Morton91f5cca2008-02-05 03:07:58 -0800106static int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
107 unsigned int type, unsigned int code, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700108{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 unsigned char newleds;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100110 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700111
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100112 BT_DBG("session %p type %d code %d value %d", session, type, code, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113
114 if (type != EV_LED)
115 return -1;
116
117 newleds = (!!test_bit(LED_KANA, dev->led) << 3) |
118 (!!test_bit(LED_COMPOSE, dev->led) << 3) |
119 (!!test_bit(LED_SCROLLL, dev->led) << 2) |
120 (!!test_bit(LED_CAPSL, dev->led) << 1) |
121 (!!test_bit(LED_NUML, dev->led));
122
123 if (session->leds == newleds)
124 return 0;
125
126 session->leds = newleds;
127
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200128 skb = alloc_skb(3, GFP_ATOMIC);
129 if (!skb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700130 BT_ERR("Can't allocate memory for new frame");
131 return -ENOMEM;
132 }
133
134 *skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
135 *skb_put(skb, 1) = 0x01;
136 *skb_put(skb, 1) = newleds;
137
138 skb_queue_tail(&session->intr_transmit, skb);
139
140 hidp_schedule(session);
141
142 return 0;
143}
144
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100145static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
146{
Marcel Holtmann5be39462007-05-09 09:15:30 +0200147 struct hid_device *hid = input_get_drvdata(dev);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100148 struct hidp_session *session = hid->driver_data;
149
150 return hidp_queue_event(session, dev, type, code, value);
151}
152
153static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
154{
Marcel Holtmann5be39462007-05-09 09:15:30 +0200155 struct hidp_session *session = input_get_drvdata(dev);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100156
157 return hidp_queue_event(session, dev, type, code, value);
158}
159
Linus Torvalds1da177e2005-04-16 15:20:36 -0700160static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
161{
162 struct input_dev *dev = session->input;
163 unsigned char *keys = session->keys;
164 unsigned char *udata = skb->data + 1;
165 signed char *sdata = skb->data + 1;
166 int i, size = skb->len - 1;
167
168 switch (skb->data[0]) {
169 case 0x01: /* Keyboard report */
170 for (i = 0; i < 8; i++)
171 input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
172
173 /* If all the key codes have been set to 0x01, it means
174 * too many keys were pressed at the same time. */
175 if (!memcmp(udata + 2, hidp_mkeyspat, 6))
176 break;
177
178 for (i = 2; i < 8; i++) {
179 if (keys[i] > 3 && memscan(udata + 2, keys[i], 6) == udata + 8) {
180 if (hidp_keycode[keys[i]])
181 input_report_key(dev, hidp_keycode[keys[i]], 0);
182 else
183 BT_ERR("Unknown key (scancode %#x) released.", keys[i]);
184 }
185
186 if (udata[i] > 3 && memscan(keys + 2, udata[i], 6) == keys + 8) {
187 if (hidp_keycode[udata[i]])
188 input_report_key(dev, hidp_keycode[udata[i]], 1);
189 else
190 BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]);
191 }
192 }
193
194 memcpy(keys, udata, 8);
195 break;
196
197 case 0x02: /* Mouse report */
198 input_report_key(dev, BTN_LEFT, sdata[0] & 0x01);
199 input_report_key(dev, BTN_RIGHT, sdata[0] & 0x02);
200 input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
201 input_report_key(dev, BTN_SIDE, sdata[0] & 0x08);
202 input_report_key(dev, BTN_EXTRA, sdata[0] & 0x10);
203
204 input_report_rel(dev, REL_X, sdata[1]);
205 input_report_rel(dev, REL_Y, sdata[2]);
206
207 if (size > 3)
208 input_report_rel(dev, REL_WHEEL, sdata[3]);
209 break;
210 }
211
212 input_sync(dev);
213}
214
Bastien Nocera6bf82682010-01-20 12:00:42 +0000215static int __hidp_send_ctrl_message(struct hidp_session *session,
Gustavo Padovan1d0c4da2012-06-09 19:22:42 -0300216 unsigned char hdr, unsigned char *data,
217 int size)
Bastien Nocera6bf82682010-01-20 12:00:42 +0000218{
219 struct sk_buff *skb;
220
221 BT_DBG("session %p data %p size %d", session, data, size);
222
David Herrmann794d1752011-08-26 14:06:02 +0200223 if (atomic_read(&session->terminate))
224 return -EIO;
225
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200226 skb = alloc_skb(size + 1, GFP_ATOMIC);
227 if (!skb) {
Bastien Nocera6bf82682010-01-20 12:00:42 +0000228 BT_ERR("Can't allocate memory for new frame");
229 return -ENOMEM;
230 }
231
232 *skb_put(skb, 1) = hdr;
233 if (data && size > 0)
234 memcpy(skb_put(skb, size), data, size);
235
236 skb_queue_tail(&session->ctrl_transmit, skb);
237
238 return 0;
239}
240
Gustavo Padovan6039aa72012-05-23 04:04:18 -0300241static int hidp_send_ctrl_message(struct hidp_session *session,
Bastien Nocera6bf82682010-01-20 12:00:42 +0000242 unsigned char hdr, unsigned char *data, int size)
243{
244 int err;
245
246 err = __hidp_send_ctrl_message(session, hdr, data, size);
247
248 hidp_schedule(session);
249
250 return err;
251}
252
Andrew Morton91f5cca2008-02-05 03:07:58 -0800253static int hidp_queue_report(struct hidp_session *session,
254 unsigned char *data, int size)
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100255{
256 struct sk_buff *skb;
257
Dave Young6792b5e2007-10-20 14:15:39 +0200258 BT_DBG("session %p hid %p data %p size %d", session, session->hid, data, size);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100259
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200260 skb = alloc_skb(size + 1, GFP_ATOMIC);
261 if (!skb) {
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100262 BT_ERR("Can't allocate memory for new frame");
263 return -ENOMEM;
264 }
265
266 *skb_put(skb, 1) = 0xa2;
267 if (size > 0)
268 memcpy(skb_put(skb, size), data, size);
269
270 skb_queue_tail(&session->intr_transmit, skb);
271
272 hidp_schedule(session);
273
274 return 0;
275}
276
277static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
278{
279 unsigned char buf[32];
280 int rsize;
281
282 rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
283 if (rsize > sizeof(buf))
284 return -EIO;
285
286 hid_output_report(report, buf);
287
288 return hidp_queue_report(session, buf, rsize);
289}
290
Alan Ott0ff17312011-01-18 03:04:40 -0500291static int hidp_get_raw_report(struct hid_device *hid,
292 unsigned char report_number,
293 unsigned char *data, size_t count,
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100294 unsigned char report_type)
Jiri Kosina2da31932009-11-26 16:20:56 +0100295{
Alan Ott0ff17312011-01-18 03:04:40 -0500296 struct hidp_session *session = hid->driver_data;
297 struct sk_buff *skb;
298 size_t len;
299 int numbered_reports = hid->report_enum[report_type].numbered;
David Herrmann794d1752011-08-26 14:06:02 +0200300 int ret;
Alan Ott0ff17312011-01-18 03:04:40 -0500301
Karl Reltonfd86c9b2013-02-20 18:16:19 +0000302 if (atomic_read(&session->terminate))
303 return -EIO;
304
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100305 switch (report_type) {
306 case HID_FEATURE_REPORT:
Alan Ott0ff17312011-01-18 03:04:40 -0500307 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
308 break;
309 case HID_INPUT_REPORT:
310 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_INPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100311 break;
312 case HID_OUTPUT_REPORT:
Alan Ott0ff17312011-01-18 03:04:40 -0500313 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_OUPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100314 break;
315 default:
316 return -EINVAL;
317 }
318
Alan Ott0ff17312011-01-18 03:04:40 -0500319 if (mutex_lock_interruptible(&session->report_mutex))
320 return -ERESTARTSYS;
321
322 /* Set up our wait, and send the report request to the device. */
323 session->waiting_report_type = report_type & HIDP_DATA_RTYPE_MASK;
324 session->waiting_report_number = numbered_reports ? report_number : -1;
325 set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
326 data[0] = report_number;
David Herrmann794d1752011-08-26 14:06:02 +0200327 ret = hidp_send_ctrl_message(hid->driver_data, report_type, data, 1);
328 if (ret)
329 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500330
331 /* Wait for the return of the report. The returned report
332 gets put in session->report_return. */
333 while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
334 int res;
335
336 res = wait_event_interruptible_timeout(session->report_queue,
337 !test_bit(HIDP_WAITING_FOR_RETURN, &session->flags),
338 5*HZ);
339 if (res == 0) {
340 /* timeout */
David Herrmann794d1752011-08-26 14:06:02 +0200341 ret = -EIO;
342 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500343 }
344 if (res < 0) {
345 /* signal */
David Herrmann794d1752011-08-26 14:06:02 +0200346 ret = -ERESTARTSYS;
347 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500348 }
349 }
350
351 skb = session->report_return;
352 if (skb) {
353 len = skb->len < count ? skb->len : count;
354 memcpy(data, skb->data, len);
355
356 kfree_skb(skb);
357 session->report_return = NULL;
358 } else {
359 /* Device returned a HANDSHAKE, indicating protocol error. */
360 len = -EIO;
361 }
362
363 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
364 mutex_unlock(&session->report_mutex);
365
366 return len;
367
David Herrmann794d1752011-08-26 14:06:02 +0200368err:
Alan Ott0ff17312011-01-18 03:04:40 -0500369 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
370 mutex_unlock(&session->report_mutex);
David Herrmann794d1752011-08-26 14:06:02 +0200371 return ret;
Alan Ott0ff17312011-01-18 03:04:40 -0500372}
373
Linus Torvalds1da177e2005-04-16 15:20:36 -0700374static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
Jiri Kosina2da31932009-11-26 16:20:56 +0100375 unsigned char report_type)
376{
Alan Ott08254112011-01-18 03:04:38 -0500377 struct hidp_session *session = hid->driver_data;
378 int ret;
379
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100380 switch (report_type) {
381 case HID_FEATURE_REPORT:
382 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
383 break;
384 case HID_OUTPUT_REPORT:
Antonio Ospite97e1efb2011-02-20 18:26:46 +0100385 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100386 break;
387 default:
388 return -EINVAL;
389 }
390
Alan Ott08254112011-01-18 03:04:38 -0500391 if (mutex_lock_interruptible(&session->report_mutex))
392 return -ERESTARTSYS;
393
394 /* Set up our wait, and send the report request to the device. */
395 set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
David Herrmann794d1752011-08-26 14:06:02 +0200396 ret = hidp_send_ctrl_message(hid->driver_data, report_type, data,
397 count);
398 if (ret)
Alan Ott08254112011-01-18 03:04:38 -0500399 goto err;
Alan Ott08254112011-01-18 03:04:38 -0500400
401 /* Wait for the ACK from the device. */
402 while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
403 int res;
404
405 res = wait_event_interruptible_timeout(session->report_queue,
406 !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags),
407 10*HZ);
408 if (res == 0) {
409 /* timeout */
410 ret = -EIO;
411 goto err;
412 }
413 if (res < 0) {
414 /* signal */
415 ret = -ERESTARTSYS;
416 goto err;
417 }
418 }
419
420 if (!session->output_report_success) {
421 ret = -EIO;
422 goto err;
423 }
424
425 ret = count;
426
427err:
428 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
429 mutex_unlock(&session->report_mutex);
430 return ret;
Jiri Kosina2da31932009-11-26 16:20:56 +0100431}
432
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433static void hidp_idle_timeout(unsigned long arg)
434{
435 struct hidp_session *session = (struct hidp_session *) arg;
436
Peter Hurley7bb59df2011-06-30 13:53:53 -0400437 atomic_inc(&session->terminate);
438 wake_up_process(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439}
440
Andrew Morton91f5cca2008-02-05 03:07:58 -0800441static void hidp_set_timer(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442{
443 if (session->idle_to > 0)
444 mod_timer(&session->timer, jiffies + HZ * session->idle_to);
445}
446
Gustavo Padovan6039aa72012-05-23 04:04:18 -0300447static void hidp_del_timer(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448{
449 if (session->idle_to > 0)
450 del_timer(&session->timer);
451}
452
Andrew Morton91f5cca2008-02-05 03:07:58 -0800453static void hidp_process_handshake(struct hidp_session *session,
454 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455{
456 BT_DBG("session %p param 0x%02x", session, param);
Alan Ott08254112011-01-18 03:04:38 -0500457 session->output_report_success = 0; /* default condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458
459 switch (param) {
460 case HIDP_HSHK_SUCCESSFUL:
461 /* FIXME: Call into SET_ GET_ handlers here */
Alan Ott08254112011-01-18 03:04:38 -0500462 session->output_report_success = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463 break;
464
465 case HIDP_HSHK_NOT_READY:
466 case HIDP_HSHK_ERR_INVALID_REPORT_ID:
467 case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
468 case HIDP_HSHK_ERR_INVALID_PARAMETER:
Gustavo F. Padovanab88f712011-10-06 22:05:37 -0300469 if (test_and_clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags))
Alan Ott0ff17312011-01-18 03:04:40 -0500470 wake_up_interruptible(&session->report_queue);
Gustavo F. Padovanab88f712011-10-06 22:05:37 -0300471
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 /* FIXME: Call into SET_ GET_ handlers here */
473 break;
474
475 case HIDP_HSHK_ERR_UNKNOWN:
476 break;
477
478 case HIDP_HSHK_ERR_FATAL:
479 /* Device requests a reboot, as this is the only way this error
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900480 * can be recovered. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 __hidp_send_ctrl_message(session,
482 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
483 break;
484
485 default:
486 __hidp_send_ctrl_message(session,
487 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
488 break;
489 }
Alan Ott08254112011-01-18 03:04:38 -0500490
491 /* Wake up the waiting thread. */
Gustavo F. Padovanab88f712011-10-06 22:05:37 -0300492 if (test_and_clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags))
Alan Ott08254112011-01-18 03:04:38 -0500493 wake_up_interruptible(&session->report_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494}
495
Andrew Morton91f5cca2008-02-05 03:07:58 -0800496static void hidp_process_hid_control(struct hidp_session *session,
497 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498{
499 BT_DBG("session %p param 0x%02x", session, param);
500
Dave Youngeff001e2008-02-05 03:07:14 -0800501 if (param == HIDP_CTRL_VIRTUAL_CABLE_UNPLUG) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700502 /* Flush the transmit queues */
503 skb_queue_purge(&session->ctrl_transmit);
504 skb_queue_purge(&session->intr_transmit);
505
Peter Hurley7bb59df2011-06-30 13:53:53 -0400506 atomic_inc(&session->terminate);
507 wake_up_process(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700508 }
509}
510
Alan Ott0ff17312011-01-18 03:04:40 -0500511/* Returns true if the passed-in skb should be freed by the caller. */
512static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800513 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514{
Alan Ott0ff17312011-01-18 03:04:40 -0500515 int done_with_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700516 BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
517
518 switch (param) {
519 case HIDP_DATA_RTYPE_INPUT:
520 hidp_set_timer(session);
521
522 if (session->input)
523 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100524
525 if (session->hid)
526 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527 break;
528
529 case HIDP_DATA_RTYPE_OTHER:
530 case HIDP_DATA_RTYPE_OUPUT:
531 case HIDP_DATA_RTYPE_FEATURE:
532 break;
533
534 default:
535 __hidp_send_ctrl_message(session,
536 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
537 }
Alan Ott0ff17312011-01-18 03:04:40 -0500538
539 if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
540 param == session->waiting_report_type) {
541 if (session->waiting_report_number < 0 ||
542 session->waiting_report_number == skb->data[0]) {
543 /* hidp_get_raw_report() is waiting on this report. */
544 session->report_return = skb;
545 done_with_skb = 0;
546 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
547 wake_up_interruptible(&session->report_queue);
548 }
549 }
550
551 return done_with_skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552}
553
Andrew Morton91f5cca2008-02-05 03:07:58 -0800554static void hidp_recv_ctrl_frame(struct hidp_session *session,
555 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556{
557 unsigned char hdr, type, param;
Alan Ott0ff17312011-01-18 03:04:40 -0500558 int free_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559
560 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
561
562 hdr = skb->data[0];
563 skb_pull(skb, 1);
564
565 type = hdr & HIDP_HEADER_TRANS_MASK;
566 param = hdr & HIDP_HEADER_PARAM_MASK;
567
568 switch (type) {
569 case HIDP_TRANS_HANDSHAKE:
570 hidp_process_handshake(session, param);
571 break;
572
573 case HIDP_TRANS_HID_CONTROL:
574 hidp_process_hid_control(session, param);
575 break;
576
577 case HIDP_TRANS_DATA:
Alan Ott0ff17312011-01-18 03:04:40 -0500578 free_skb = hidp_process_data(session, skb, param);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579 break;
580
581 default:
582 __hidp_send_ctrl_message(session,
583 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
584 break;
585 }
586
Alan Ott0ff17312011-01-18 03:04:40 -0500587 if (free_skb)
588 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700589}
590
Andrew Morton91f5cca2008-02-05 03:07:58 -0800591static void hidp_recv_intr_frame(struct hidp_session *session,
592 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700593{
594 unsigned char hdr;
595
596 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
597
598 hdr = skb->data[0];
599 skb_pull(skb, 1);
600
601 if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
602 hidp_set_timer(session);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100603
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604 if (session->input)
605 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100606
607 if (session->hid) {
608 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
609 BT_DBG("report len %d", skb->len);
610 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 } else {
612 BT_DBG("Unsupported protocol header 0x%02x", hdr);
613 }
614
615 kfree_skb(skb);
616}
617
618static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
619{
620 struct kvec iv = { data, len };
621 struct msghdr msg;
622
623 BT_DBG("sock %p data %p len %d", sock, data, len);
624
625 if (!len)
626 return 0;
627
628 memset(&msg, 0, sizeof(msg));
629
630 return kernel_sendmsg(sock, &msg, &iv, 1, len);
631}
632
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300633static void hidp_process_intr_transmit(struct hidp_session *session)
634{
635 struct sk_buff *skb;
636
637 BT_DBG("session %p", session);
638
639 while ((skb = skb_dequeue(&session->intr_transmit))) {
640 if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
641 skb_queue_head(&session->intr_transmit, skb);
642 break;
643 }
644
645 hidp_set_timer(session);
646 kfree_skb(skb);
647 }
648}
649
650static void hidp_process_ctrl_transmit(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700651{
652 struct sk_buff *skb;
653
654 BT_DBG("session %p", session);
655
656 while ((skb = skb_dequeue(&session->ctrl_transmit))) {
657 if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
658 skb_queue_head(&session->ctrl_transmit, skb);
659 break;
660 }
661
662 hidp_set_timer(session);
663 kfree_skb(skb);
664 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665}
666
667static int hidp_session(void *arg)
668{
669 struct hidp_session *session = arg;
670 struct sock *ctrl_sk = session->ctrl_sock->sk;
671 struct sock *intr_sk = session->intr_sock->sk;
672 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700673 wait_queue_t ctrl_wait, intr_wait;
674
675 BT_DBG("session %p", session);
676
David Herrmann25df0842011-11-01 17:27:50 +0100677 __module_get(THIS_MODULE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 set_user_nice(current, -15);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700679
680 init_waitqueue_entry(&ctrl_wait, current);
681 init_waitqueue_entry(&intr_wait, current);
Eric Dumazetaa395142010-04-20 13:03:51 +0000682 add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
683 add_wait_queue(sk_sleep(intr_sk), &intr_wait);
Alan Ott0f69dca2011-01-18 03:04:37 -0500684 session->waiting_for_startup = 0;
685 wake_up_interruptible(&session->startup_queue);
Peter Hurley7bb59df2011-06-30 13:53:53 -0400686 set_current_state(TASK_INTERRUPTIBLE);
687 while (!atomic_read(&session->terminate)) {
Szymon Janc17f09a72011-03-21 14:20:01 +0100688 if (ctrl_sk->sk_state != BT_CONNECTED ||
689 intr_sk->sk_state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700690 break;
691
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
693 skb_orphan(skb);
Mat Martineau44935722011-07-22 14:53:58 -0700694 if (!skb_linearize(skb))
695 hidp_recv_intr_frame(session, skb);
696 else
697 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698 }
699
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300700 hidp_process_intr_transmit(session);
701
Gustavo F. Padovandc0da5c2011-10-06 18:02:13 -0300702 while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
703 skb_orphan(skb);
704 if (!skb_linearize(skb))
705 hidp_recv_ctrl_frame(session, skb);
706 else
707 kfree_skb(skb);
708 }
709
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300710 hidp_process_ctrl_transmit(session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
712 schedule();
Peter Hurley7bb59df2011-06-30 13:53:53 -0400713 set_current_state(TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700714 }
715 set_current_state(TASK_RUNNING);
Karl Reltonfd86c9b2013-02-20 18:16:19 +0000716 atomic_inc(&session->terminate);
Eric Dumazetaa395142010-04-20 13:03:51 +0000717 remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
718 remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700719
David Herrmann794d1752011-08-26 14:06:02 +0200720 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
721 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
722 wake_up_interruptible(&session->report_queue);
723
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724 down_write(&hidp_session_sem);
725
726 hidp_del_timer(session);
727
Linus Torvalds1da177e2005-04-16 15:20:36 -0700728 if (session->input) {
729 input_unregister_device(session->input);
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500730 session->input = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700731 }
732
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100733 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200734 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -0700735 session->hid = NULL;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100736 }
737
Marcel Holtmannec8dab32008-07-14 20:13:53 +0200738 /* Wakeup user-space polling for socket errors */
739 session->intr_sock->sk->sk_err = EUNATCH;
740 session->ctrl_sock->sk->sk_err = EUNATCH;
741
742 hidp_schedule(session);
743
David Woodhouse1c398582007-07-07 14:58:39 -0400744 fput(session->intr_sock->file);
745
Eric Dumazetaa395142010-04-20 13:03:51 +0000746 wait_event_timeout(*(sk_sleep(ctrl_sk)),
David Woodhouse1c398582007-07-07 14:58:39 -0400747 (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
748
749 fput(session->ctrl_sock->file);
750
David Herrmannfc225c32013-04-06 20:28:38 +0200751 list_del(&session->list);
David Woodhouse1c398582007-07-07 14:58:39 -0400752
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 up_write(&hidp_session_sem);
754
Peter Hurley1c97e942011-08-05 10:51:34 -0400755 kfree(session->rd_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 kfree(session);
David Herrmann25df0842011-11-01 17:27:50 +0100757 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700758 return 0;
759}
760
Gustavo F. Padovan3e90dc82011-10-07 01:29:51 -0300761static struct hci_conn *hidp_get_connection(struct hidp_session *session)
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200762{
763 bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
764 bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
Peter Hurley1785dbf2011-08-30 11:53:35 -0400765 struct hci_conn *conn;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200766 struct hci_dev *hdev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200767
768 hdev = hci_get_route(dst, src);
769 if (!hdev)
770 return NULL;
771
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300772 hci_dev_lock(hdev);
Peter Hurley1785dbf2011-08-30 11:53:35 -0400773 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300774 hci_dev_unlock(hdev);
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200775
776 hci_dev_put(hdev);
777
Peter Hurley1785dbf2011-08-30 11:53:35 -0400778 return conn;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200779}
780
Andrew Morton91f5cca2008-02-05 03:07:58 -0800781static int hidp_setup_input(struct hidp_session *session,
782 struct hidp_connadd_req *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700783{
Jiri Slabyc500c972008-05-16 11:49:16 +0200784 struct input_dev *input;
Gustavo F. Padovan3415a5f2011-10-06 21:17:32 -0300785 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786
Jiri Slabyc500c972008-05-16 11:49:16 +0200787 input = input_allocate_device();
788 if (!input)
789 return -ENOMEM;
790
791 session->input = input;
792
Marcel Holtmann5be39462007-05-09 09:15:30 +0200793 input_set_drvdata(input, session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700794
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500795 input->name = "Bluetooth HID Boot Protocol Device";
796
Linus Torvalds1da177e2005-04-16 15:20:36 -0700797 input->id.bustype = BUS_BLUETOOTH;
798 input->id.vendor = req->vendor;
799 input->id.product = req->product;
800 input->id.version = req->version;
801
802 if (req->subclass & 0x40) {
803 set_bit(EV_KEY, input->evbit);
804 set_bit(EV_LED, input->evbit);
805 set_bit(EV_REP, input->evbit);
806
807 set_bit(LED_NUML, input->ledbit);
808 set_bit(LED_CAPSL, input->ledbit);
809 set_bit(LED_SCROLLL, input->ledbit);
810 set_bit(LED_COMPOSE, input->ledbit);
811 set_bit(LED_KANA, input->ledbit);
812
813 for (i = 0; i < sizeof(hidp_keycode); i++)
814 set_bit(hidp_keycode[i], input->keybit);
815 clear_bit(0, input->keybit);
816 }
817
818 if (req->subclass & 0x80) {
Jiri Slaby7b19ada2007-10-18 23:40:32 -0700819 input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
820 input->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
821 BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
822 input->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
823 input->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |
824 BIT_MASK(BTN_EXTRA);
825 input->relbit[0] |= BIT_MASK(REL_WHEEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700826 }
827
Peter Hurley1785dbf2011-08-30 11:53:35 -0400828 input->dev.parent = &session->conn->dev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200829
Linus Torvalds1da177e2005-04-16 15:20:36 -0700830 input->event = hidp_input_event;
831
Marcel Holtmannedad6382009-08-22 14:22:15 -0700832 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700833}
834
Marcel Holtmannf5ffd462007-02-17 23:58:53 +0100835static int hidp_open(struct hid_device *hid)
836{
837 return 0;
838}
839
840static void hidp_close(struct hid_device *hid)
841{
842}
843
Jiri Slabyc500c972008-05-16 11:49:16 +0200844static int hidp_parse(struct hid_device *hid)
845{
846 struct hidp_session *session = hid->driver_data;
Jiri Slabyc500c972008-05-16 11:49:16 +0200847
Michael Poole15c697c2010-02-05 12:23:43 -0500848 return hid_parse_report(session->hid, session->rd_data,
849 session->rd_size);
Jiri Slabyc500c972008-05-16 11:49:16 +0200850}
851
852static int hidp_start(struct hid_device *hid)
853{
854 struct hidp_session *session = hid->driver_data;
855 struct hid_report *report;
856
David Herrmann142c69c2011-08-26 13:27:12 +0200857 if (hid->quirks & HID_QUIRK_NO_INIT_REPORTS)
858 return 0;
859
Jiri Slabyc500c972008-05-16 11:49:16 +0200860 list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].
861 report_list, list)
862 hidp_send_report(session, report);
863
864 list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].
865 report_list, list)
866 hidp_send_report(session, report);
867
Jiri Slabyc500c972008-05-16 11:49:16 +0200868 return 0;
869}
870
871static void hidp_stop(struct hid_device *hid)
872{
873 struct hidp_session *session = hid->driver_data;
874
875 skb_queue_purge(&session->ctrl_transmit);
876 skb_queue_purge(&session->intr_transmit);
877
Jiri Slabyc500c972008-05-16 11:49:16 +0200878 hid->claimed = 0;
879}
880
881static struct hid_ll_driver hidp_hid_driver = {
882 .parse = hidp_parse,
883 .start = hidp_start,
884 .stop = hidp_stop,
885 .open = hidp_open,
886 .close = hidp_close,
887 .hidinput_input_event = hidp_hidinput_event,
888};
889
Alan Ott0f69dca2011-01-18 03:04:37 -0500890/* This function sets up the hid device. It does not add it
891 to the HID system. That is done in hidp_add_connection(). */
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200892static int hidp_setup_hid(struct hidp_session *session,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800893 struct hidp_connadd_req *req)
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100894{
Jiri Slabyc500c972008-05-16 11:49:16 +0200895 struct hid_device *hid;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700896 int err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100897
Michael Poole15c697c2010-02-05 12:23:43 -0500898 session->rd_data = kzalloc(req->rd_size, GFP_KERNEL);
899 if (!session->rd_data)
900 return -ENOMEM;
901
902 if (copy_from_user(session->rd_data, req->rd_data, req->rd_size)) {
903 err = -EFAULT;
904 goto fault;
905 }
906 session->rd_size = req->rd_size;
907
Jiri Slabyc500c972008-05-16 11:49:16 +0200908 hid = hid_allocate_device();
Michael Poole15c697c2010-02-05 12:23:43 -0500909 if (IS_ERR(hid)) {
910 err = PTR_ERR(hid);
911 goto fault;
912 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100913
Jiri Slabyc500c972008-05-16 11:49:16 +0200914 session->hid = hid;
Michael Poole15c697c2010-02-05 12:23:43 -0500915
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100916 hid->driver_data = session;
917
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100918 hid->bus = BUS_BLUETOOTH;
919 hid->vendor = req->vendor;
920 hid->product = req->product;
921 hid->version = req->version;
Jiri Slabyc500c972008-05-16 11:49:16 +0200922 hid->country = req->country;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100923
Anderson Lizardo0a9ab9b2013-01-06 18:28:53 -0400924 strncpy(hid->name, req->name, sizeof(req->name) - 1);
Andrei Emeltchenkofcb73332012-09-25 12:49:44 +0300925
926 snprintf(hid->phys, sizeof(hid->phys), "%pMR",
927 &bt_sk(session->ctrl_sock->sk)->src);
928
929 snprintf(hid->uniq, sizeof(hid->uniq), "%pMR",
930 &bt_sk(session->ctrl_sock->sk)->dst);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100931
Peter Hurley1785dbf2011-08-30 11:53:35 -0400932 hid->dev.parent = &session->conn->dev;
Jiri Slabyc500c972008-05-16 11:49:16 +0200933 hid->ll_driver = &hidp_hid_driver;
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200934
Alan Ott0ff17312011-01-18 03:04:40 -0500935 hid->hid_get_raw_report = hidp_get_raw_report;
Jiri Kosina2da31932009-11-26 16:20:56 +0100936 hid->hid_output_raw_report = hidp_output_raw_report;
937
Lamarque V. Souza4529eef2012-12-06 12:39:55 -0200938 /* True if device is blacklisted in drivers/hid/hid-core.c */
939 if (hid_ignore(hid)) {
940 hid_destroy_device(session->hid);
941 session->hid = NULL;
942 return -ENODEV;
943 }
944
Jiri Slabyc500c972008-05-16 11:49:16 +0200945 return 0;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700946
Michael Poole15c697c2010-02-05 12:23:43 -0500947fault:
948 kfree(session->rd_data);
949 session->rd_data = NULL;
950
Marcel Holtmannedad6382009-08-22 14:22:15 -0700951 return err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100952}
953
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
955{
956 struct hidp_session *session, *s;
Szymon Jancaabf6f82011-04-05 15:37:45 +0200957 int vendor, product;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700958 int err;
959
960 BT_DBG("");
961
David Herrmannb3916db2013-04-05 14:57:34 +0200962 if (!l2cap_is_socket(ctrl_sock) || !l2cap_is_socket(intr_sock))
963 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700964 if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
965 bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
966 return -ENOTUNIQ;
967
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100968 BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
969
Linus Torvalds1da177e2005-04-16 15:20:36 -0700970 down_write(&hidp_session_sem);
971
972 s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
973 if (s && s->state == BT_CONNECTED) {
Gustavo F. Padovan81b25cd2011-10-06 23:32:29 -0300974 up_write(&hidp_session_sem);
975 return -EEXIST;
976 }
977
978 session = kzalloc(sizeof(struct hidp_session), GFP_KERNEL);
979 if (!session) {
980 up_write(&hidp_session_sem);
981 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700982 }
983
984 bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
985
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300986 session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->chan->omtu,
987 l2cap_pi(ctrl_sock->sk)->chan->imtu);
988 session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->chan->omtu,
989 l2cap_pi(intr_sock->sk)->chan->imtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700990
991 BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
992
993 session->ctrl_sock = ctrl_sock;
994 session->intr_sock = intr_sock;
995 session->state = BT_CONNECTED;
996
Gustavo F. Padovan3c32fa92011-10-20 17:21:34 -0200997 session->conn = hidp_get_connection(session);
998 if (!session->conn) {
999 err = -ENOTCONN;
1000 goto failed;
1001 }
1002
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001003 setup_timer(&session->timer, hidp_idle_timeout, (unsigned long)session);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004
1005 skb_queue_head_init(&session->ctrl_transmit);
1006 skb_queue_head_init(&session->intr_transmit);
1007
Alan Ott0ff17312011-01-18 03:04:40 -05001008 mutex_init(&session->report_mutex);
1009 init_waitqueue_head(&session->report_queue);
Alan Ott0f69dca2011-01-18 03:04:37 -05001010 init_waitqueue_head(&session->startup_queue);
1011 session->waiting_for_startup = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001012 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
1013 session->idle_to = req->idle_to;
1014
David Herrmannfc225c32013-04-06 20:28:38 +02001015 list_add(&session->list, &hidp_session_list);
Peter Hurley1785dbf2011-08-30 11:53:35 -04001016
Jiri Slabyc500c972008-05-16 11:49:16 +02001017 if (req->rd_size > 0) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001018 err = hidp_setup_hid(session, req);
Lamarque V. Souza4529eef2012-12-06 12:39:55 -02001019 if (err && err != -ENODEV)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001020 goto purge;
Jiri Slabyc500c972008-05-16 11:49:16 +02001021 }
1022
1023 if (!session->hid) {
1024 err = hidp_setup_input(session, req);
1025 if (err < 0)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001026 goto purge;
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001027 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001028
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 hidp_set_timer(session);
1030
Szymon Jancaabf6f82011-04-05 15:37:45 +02001031 if (session->hid) {
1032 vendor = session->hid->vendor;
1033 product = session->hid->product;
1034 } else if (session->input) {
1035 vendor = session->input->id.vendor;
1036 product = session->input->id.product;
1037 } else {
1038 vendor = 0x0000;
1039 product = 0x0000;
1040 }
1041
1042 session->task = kthread_run(hidp_session, session, "khidpd_%04x%04x",
1043 vendor, product);
1044 if (IS_ERR(session->task)) {
1045 err = PTR_ERR(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 goto unlink;
Szymon Jancaabf6f82011-04-05 15:37:45 +02001047 }
1048
Alan Ott0f69dca2011-01-18 03:04:37 -05001049 while (session->waiting_for_startup) {
1050 wait_event_interruptible(session->startup_queue,
1051 !session->waiting_for_startup);
1052 }
1053
Gustavo F. Padovan3415a5f2011-10-06 21:17:32 -03001054 if (session->hid)
1055 err = hid_add_device(session->hid);
1056 else
1057 err = input_register_device(session->input);
1058
Peter Hurleye9d5cb52011-08-05 10:51:26 -04001059 if (err < 0) {
1060 atomic_inc(&session->terminate);
1061 wake_up_process(session->task);
1062 up_write(&hidp_session_sem);
1063 return err;
1064 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065
1066 if (session->input) {
1067 hidp_send_ctrl_message(session,
1068 HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
1069 session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
1070
1071 session->leds = 0xff;
1072 hidp_input_event(session->input, EV_LED, 0, 0);
1073 }
1074
1075 up_write(&hidp_session_sem);
1076 return 0;
1077
1078unlink:
1079 hidp_del_timer(session);
1080
Marcel Holtmannedad6382009-08-22 14:22:15 -07001081 if (session->input) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082 input_unregister_device(session->input);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001083 session->input = NULL;
1084 }
1085
1086 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001087 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001088 session->hid = NULL;
1089 }
1090
Michael Poole15c697c2010-02-05 12:23:43 -05001091 kfree(session->rd_data);
1092 session->rd_data = NULL;
1093
Marcel Holtmannedad6382009-08-22 14:22:15 -07001094purge:
David Herrmannfc225c32013-04-06 20:28:38 +02001095 list_del(&session->list);
Peter Hurley1785dbf2011-08-30 11:53:35 -04001096
Jiri Slabyc500c972008-05-16 11:49:16 +02001097 skb_queue_purge(&session->ctrl_transmit);
1098 skb_queue_purge(&session->intr_transmit);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001099
Jiri Slabyc500c972008-05-16 11:49:16 +02001100failed:
1101 up_write(&hidp_session_sem);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001102
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103 kfree(session);
1104 return err;
1105}
1106
1107int hidp_del_connection(struct hidp_conndel_req *req)
1108{
1109 struct hidp_session *session;
1110 int err = 0;
1111
1112 BT_DBG("");
1113
1114 down_read(&hidp_session_sem);
1115
1116 session = __hidp_get_session(&req->bdaddr);
1117 if (session) {
1118 if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
1119 hidp_send_ctrl_message(session,
1120 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
1121 } else {
1122 /* Flush the transmit queues */
1123 skb_queue_purge(&session->ctrl_transmit);
1124 skb_queue_purge(&session->intr_transmit);
1125
Peter Hurley7bb59df2011-06-30 13:53:53 -04001126 atomic_inc(&session->terminate);
1127 wake_up_process(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128 }
1129 } else
1130 err = -ENOENT;
1131
1132 up_read(&hidp_session_sem);
1133 return err;
1134}
1135
1136int hidp_get_connlist(struct hidp_connlist_req *req)
1137{
Gustavo F. Padovancd11cdd2011-10-06 17:35:31 -03001138 struct hidp_session *session;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001139 int err = 0, n = 0;
1140
1141 BT_DBG("");
1142
1143 down_read(&hidp_session_sem);
1144
Gustavo F. Padovancd11cdd2011-10-06 17:35:31 -03001145 list_for_each_entry(session, &hidp_session_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146 struct hidp_conninfo ci;
1147
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148 __hidp_copy_session(session, &ci);
1149
1150 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
1151 err = -EFAULT;
1152 break;
1153 }
1154
1155 if (++n >= req->cnum)
1156 break;
1157
1158 req->ci++;
1159 }
1160 req->cnum = n;
1161
1162 up_read(&hidp_session_sem);
1163 return err;
1164}
1165
1166int hidp_get_conninfo(struct hidp_conninfo *ci)
1167{
1168 struct hidp_session *session;
1169 int err = 0;
1170
1171 down_read(&hidp_session_sem);
1172
1173 session = __hidp_get_session(&ci->bdaddr);
1174 if (session)
1175 __hidp_copy_session(session, ci);
1176 else
1177 err = -ENOENT;
1178
1179 up_read(&hidp_session_sem);
1180 return err;
1181}
1182
1183static int __init hidp_init(void)
1184{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
1186
Henrik Rydberg8215d552012-04-23 12:07:07 +02001187 return hidp_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188}
1189
1190static void __exit hidp_exit(void)
1191{
1192 hidp_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001193}
1194
1195module_init(hidp_init);
1196module_exit(hidp_exit);
1197
1198MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
1199MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
1200MODULE_VERSION(VERSION);
1201MODULE_LICENSE("GPL");
1202MODULE_ALIAS("bt-proto-6");