blob: ccd985da65180656d7df83a986655c4b82258220 [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 Padovan6039aa732012-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
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100314 switch (report_type) {
315 case HID_FEATURE_REPORT:
Alan Ott0ff17312011-01-18 03:04:40 -0500316 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
317 break;
318 case HID_INPUT_REPORT:
319 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_INPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100320 break;
321 case HID_OUTPUT_REPORT:
Alan Ott0ff17312011-01-18 03:04:40 -0500322 report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_OUPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100323 break;
324 default:
325 return -EINVAL;
326 }
327
Alan Ott0ff17312011-01-18 03:04:40 -0500328 if (mutex_lock_interruptible(&session->report_mutex))
329 return -ERESTARTSYS;
330
331 /* Set up our wait, and send the report request to the device. */
332 session->waiting_report_type = report_type & HIDP_DATA_RTYPE_MASK;
333 session->waiting_report_number = numbered_reports ? report_number : -1;
334 set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
335 data[0] = report_number;
David Herrmann794d1752011-08-26 14:06:02 +0200336 ret = hidp_send_ctrl_message(hid->driver_data, report_type, data, 1);
337 if (ret)
338 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500339
340 /* Wait for the return of the report. The returned report
341 gets put in session->report_return. */
342 while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)) {
343 int res;
344
345 res = wait_event_interruptible_timeout(session->report_queue,
346 !test_bit(HIDP_WAITING_FOR_RETURN, &session->flags),
347 5*HZ);
348 if (res == 0) {
349 /* timeout */
David Herrmann794d1752011-08-26 14:06:02 +0200350 ret = -EIO;
351 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500352 }
353 if (res < 0) {
354 /* signal */
David Herrmann794d1752011-08-26 14:06:02 +0200355 ret = -ERESTARTSYS;
356 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500357 }
358 }
359
360 skb = session->report_return;
361 if (skb) {
362 len = skb->len < count ? skb->len : count;
363 memcpy(data, skb->data, len);
364
365 kfree_skb(skb);
366 session->report_return = NULL;
367 } else {
368 /* Device returned a HANDSHAKE, indicating protocol error. */
369 len = -EIO;
370 }
371
372 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
373 mutex_unlock(&session->report_mutex);
374
375 return len;
376
David Herrmann794d1752011-08-26 14:06:02 +0200377err:
Alan Ott0ff17312011-01-18 03:04:40 -0500378 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
379 mutex_unlock(&session->report_mutex);
David Herrmann794d1752011-08-26 14:06:02 +0200380 return ret;
Alan Ott0ff17312011-01-18 03:04:40 -0500381}
382
Linus Torvalds1da177e2005-04-16 15:20:36 -0700383static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
Jiri Kosina2da31932009-11-26 16:20:56 +0100384 unsigned char report_type)
385{
Alan Ott08254112011-01-18 03:04:38 -0500386 struct hidp_session *session = hid->driver_data;
387 int ret;
388
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100389 switch (report_type) {
390 case HID_FEATURE_REPORT:
391 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
392 break;
393 case HID_OUTPUT_REPORT:
Antonio Ospite97e1efb2011-02-20 18:26:46 +0100394 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100395 break;
396 default:
397 return -EINVAL;
398 }
399
Alan Ott08254112011-01-18 03:04:38 -0500400 if (mutex_lock_interruptible(&session->report_mutex))
401 return -ERESTARTSYS;
402
403 /* Set up our wait, and send the report request to the device. */
404 set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
David Herrmann794d1752011-08-26 14:06:02 +0200405 ret = hidp_send_ctrl_message(hid->driver_data, report_type, data,
406 count);
407 if (ret)
Alan Ott08254112011-01-18 03:04:38 -0500408 goto err;
Alan Ott08254112011-01-18 03:04:38 -0500409
410 /* Wait for the ACK from the device. */
411 while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)) {
412 int res;
413
414 res = wait_event_interruptible_timeout(session->report_queue,
415 !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags),
416 10*HZ);
417 if (res == 0) {
418 /* timeout */
419 ret = -EIO;
420 goto err;
421 }
422 if (res < 0) {
423 /* signal */
424 ret = -ERESTARTSYS;
425 goto err;
426 }
427 }
428
429 if (!session->output_report_success) {
430 ret = -EIO;
431 goto err;
432 }
433
434 ret = count;
435
436err:
437 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
438 mutex_unlock(&session->report_mutex);
439 return ret;
Jiri Kosina2da31932009-11-26 16:20:56 +0100440}
441
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442static void hidp_idle_timeout(unsigned long arg)
443{
444 struct hidp_session *session = (struct hidp_session *) arg;
445
Peter Hurley7bb59df2011-06-30 13:53:53 -0400446 atomic_inc(&session->terminate);
447 wake_up_process(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448}
449
Andrew Morton91f5cca2008-02-05 03:07:58 -0800450static void hidp_set_timer(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451{
452 if (session->idle_to > 0)
453 mod_timer(&session->timer, jiffies + HZ * session->idle_to);
454}
455
Gustavo Padovan6039aa732012-05-23 04:04:18 -0300456static void hidp_del_timer(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700457{
458 if (session->idle_to > 0)
459 del_timer(&session->timer);
460}
461
Andrew Morton91f5cca2008-02-05 03:07:58 -0800462static void hidp_process_handshake(struct hidp_session *session,
463 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464{
465 BT_DBG("session %p param 0x%02x", session, param);
Alan Ott08254112011-01-18 03:04:38 -0500466 session->output_report_success = 0; /* default condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467
468 switch (param) {
469 case HIDP_HSHK_SUCCESSFUL:
470 /* FIXME: Call into SET_ GET_ handlers here */
Alan Ott08254112011-01-18 03:04:38 -0500471 session->output_report_success = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472 break;
473
474 case HIDP_HSHK_NOT_READY:
475 case HIDP_HSHK_ERR_INVALID_REPORT_ID:
476 case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
477 case HIDP_HSHK_ERR_INVALID_PARAMETER:
Gustavo F. Padovanab88f712011-10-06 22:05:37 -0300478 if (test_and_clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags))
Alan Ott0ff17312011-01-18 03:04:40 -0500479 wake_up_interruptible(&session->report_queue);
Gustavo F. Padovanab88f712011-10-06 22:05:37 -0300480
Linus Torvalds1da177e2005-04-16 15:20:36 -0700481 /* FIXME: Call into SET_ GET_ handlers here */
482 break;
483
484 case HIDP_HSHK_ERR_UNKNOWN:
485 break;
486
487 case HIDP_HSHK_ERR_FATAL:
488 /* Device requests a reboot, as this is the only way this error
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900489 * can be recovered. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700490 __hidp_send_ctrl_message(session,
491 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
492 break;
493
494 default:
495 __hidp_send_ctrl_message(session,
496 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
497 break;
498 }
Alan Ott08254112011-01-18 03:04:38 -0500499
500 /* Wake up the waiting thread. */
Gustavo F. Padovanab88f712011-10-06 22:05:37 -0300501 if (test_and_clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags))
Alan Ott08254112011-01-18 03:04:38 -0500502 wake_up_interruptible(&session->report_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503}
504
Andrew Morton91f5cca2008-02-05 03:07:58 -0800505static void hidp_process_hid_control(struct hidp_session *session,
506 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507{
508 BT_DBG("session %p param 0x%02x", session, param);
509
Dave Youngeff001e2008-02-05 03:07:14 -0800510 if (param == HIDP_CTRL_VIRTUAL_CABLE_UNPLUG) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511 /* Flush the transmit queues */
512 skb_queue_purge(&session->ctrl_transmit);
513 skb_queue_purge(&session->intr_transmit);
514
Peter Hurley7bb59df2011-06-30 13:53:53 -0400515 atomic_inc(&session->terminate);
516 wake_up_process(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517 }
518}
519
Alan Ott0ff17312011-01-18 03:04:40 -0500520/* Returns true if the passed-in skb should be freed by the caller. */
521static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800522 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700523{
Alan Ott0ff17312011-01-18 03:04:40 -0500524 int done_with_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700525 BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
526
527 switch (param) {
528 case HIDP_DATA_RTYPE_INPUT:
529 hidp_set_timer(session);
530
531 if (session->input)
532 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100533
534 if (session->hid)
535 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700536 break;
537
538 case HIDP_DATA_RTYPE_OTHER:
539 case HIDP_DATA_RTYPE_OUPUT:
540 case HIDP_DATA_RTYPE_FEATURE:
541 break;
542
543 default:
544 __hidp_send_ctrl_message(session,
545 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
546 }
Alan Ott0ff17312011-01-18 03:04:40 -0500547
548 if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
549 param == session->waiting_report_type) {
550 if (session->waiting_report_number < 0 ||
551 session->waiting_report_number == skb->data[0]) {
552 /* hidp_get_raw_report() is waiting on this report. */
553 session->report_return = skb;
554 done_with_skb = 0;
555 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
556 wake_up_interruptible(&session->report_queue);
557 }
558 }
559
560 return done_with_skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561}
562
Andrew Morton91f5cca2008-02-05 03:07:58 -0800563static void hidp_recv_ctrl_frame(struct hidp_session *session,
564 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565{
566 unsigned char hdr, type, param;
Alan Ott0ff17312011-01-18 03:04:40 -0500567 int free_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568
569 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
570
571 hdr = skb->data[0];
572 skb_pull(skb, 1);
573
574 type = hdr & HIDP_HEADER_TRANS_MASK;
575 param = hdr & HIDP_HEADER_PARAM_MASK;
576
577 switch (type) {
578 case HIDP_TRANS_HANDSHAKE:
579 hidp_process_handshake(session, param);
580 break;
581
582 case HIDP_TRANS_HID_CONTROL:
583 hidp_process_hid_control(session, param);
584 break;
585
586 case HIDP_TRANS_DATA:
Alan Ott0ff17312011-01-18 03:04:40 -0500587 free_skb = hidp_process_data(session, skb, param);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588 break;
589
590 default:
591 __hidp_send_ctrl_message(session,
592 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
593 break;
594 }
595
Alan Ott0ff17312011-01-18 03:04:40 -0500596 if (free_skb)
597 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598}
599
Andrew Morton91f5cca2008-02-05 03:07:58 -0800600static void hidp_recv_intr_frame(struct hidp_session *session,
601 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602{
603 unsigned char hdr;
604
605 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
606
607 hdr = skb->data[0];
608 skb_pull(skb, 1);
609
610 if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
611 hidp_set_timer(session);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100612
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 if (session->input)
614 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100615
616 if (session->hid) {
617 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
618 BT_DBG("report len %d", skb->len);
619 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700620 } else {
621 BT_DBG("Unsupported protocol header 0x%02x", hdr);
622 }
623
624 kfree_skb(skb);
625}
626
627static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
628{
629 struct kvec iv = { data, len };
630 struct msghdr msg;
631
632 BT_DBG("sock %p data %p len %d", sock, data, len);
633
634 if (!len)
635 return 0;
636
637 memset(&msg, 0, sizeof(msg));
638
639 return kernel_sendmsg(sock, &msg, &iv, 1, len);
640}
641
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300642static void hidp_process_intr_transmit(struct hidp_session *session)
643{
644 struct sk_buff *skb;
645
646 BT_DBG("session %p", session);
647
648 while ((skb = skb_dequeue(&session->intr_transmit))) {
649 if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
650 skb_queue_head(&session->intr_transmit, skb);
651 break;
652 }
653
654 hidp_set_timer(session);
655 kfree_skb(skb);
656 }
657}
658
659static void hidp_process_ctrl_transmit(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660{
661 struct sk_buff *skb;
662
663 BT_DBG("session %p", session);
664
665 while ((skb = skb_dequeue(&session->ctrl_transmit))) {
666 if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
667 skb_queue_head(&session->ctrl_transmit, skb);
668 break;
669 }
670
671 hidp_set_timer(session);
672 kfree_skb(skb);
673 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700674}
675
676static int hidp_session(void *arg)
677{
678 struct hidp_session *session = arg;
679 struct sock *ctrl_sk = session->ctrl_sock->sk;
680 struct sock *intr_sk = session->intr_sock->sk;
681 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682 wait_queue_t ctrl_wait, intr_wait;
683
684 BT_DBG("session %p", session);
685
David Herrmann25df0842011-11-01 17:27:50 +0100686 __module_get(THIS_MODULE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687 set_user_nice(current, -15);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688
689 init_waitqueue_entry(&ctrl_wait, current);
690 init_waitqueue_entry(&intr_wait, current);
Eric Dumazetaa395142010-04-20 13:03:51 +0000691 add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
692 add_wait_queue(sk_sleep(intr_sk), &intr_wait);
Alan Ott0f69dca2011-01-18 03:04:37 -0500693 session->waiting_for_startup = 0;
694 wake_up_interruptible(&session->startup_queue);
Peter Hurley7bb59df2011-06-30 13:53:53 -0400695 set_current_state(TASK_INTERRUPTIBLE);
696 while (!atomic_read(&session->terminate)) {
Szymon Janc17f09a72011-03-21 14:20:01 +0100697 if (ctrl_sk->sk_state != BT_CONNECTED ||
698 intr_sk->sk_state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 break;
700
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
702 skb_orphan(skb);
Mat Martineau44935722011-07-22 14:53:58 -0700703 if (!skb_linearize(skb))
704 hidp_recv_intr_frame(session, skb);
705 else
706 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700707 }
708
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300709 hidp_process_intr_transmit(session);
710
Gustavo F. Padovandc0da5c2011-10-06 18:02:13 -0300711 while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
712 skb_orphan(skb);
713 if (!skb_linearize(skb))
714 hidp_recv_ctrl_frame(session, skb);
715 else
716 kfree_skb(skb);
717 }
718
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300719 hidp_process_ctrl_transmit(session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700720
721 schedule();
Peter Hurley7bb59df2011-06-30 13:53:53 -0400722 set_current_state(TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700723 }
724 set_current_state(TASK_RUNNING);
Eric Dumazetaa395142010-04-20 13:03:51 +0000725 remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
726 remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727
David Herrmann794d1752011-08-26 14:06:02 +0200728 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
729 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
730 wake_up_interruptible(&session->report_queue);
731
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732 down_write(&hidp_session_sem);
733
734 hidp_del_timer(session);
735
Linus Torvalds1da177e2005-04-16 15:20:36 -0700736 if (session->input) {
737 input_unregister_device(session->input);
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500738 session->input = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700739 }
740
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100741 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200742 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -0700743 session->hid = NULL;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100744 }
745
Marcel Holtmannec8dab32008-07-14 20:13:53 +0200746 /* Wakeup user-space polling for socket errors */
747 session->intr_sock->sk->sk_err = EUNATCH;
748 session->ctrl_sock->sk->sk_err = EUNATCH;
749
750 hidp_schedule(session);
751
David Woodhouse1c398582007-07-07 14:58:39 -0400752 fput(session->intr_sock->file);
753
Eric Dumazetaa395142010-04-20 13:03:51 +0000754 wait_event_timeout(*(sk_sleep(ctrl_sk)),
David Woodhouse1c398582007-07-07 14:58:39 -0400755 (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
756
757 fput(session->ctrl_sock->file);
758
759 __hidp_unlink_session(session);
760
Linus Torvalds1da177e2005-04-16 15:20:36 -0700761 up_write(&hidp_session_sem);
762
Peter Hurley1c97e942011-08-05 10:51:34 -0400763 kfree(session->rd_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700764 kfree(session);
David Herrmann25df0842011-11-01 17:27:50 +0100765 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 return 0;
767}
768
Gustavo F. Padovan3e90dc82011-10-07 01:29:51 -0300769static struct hci_conn *hidp_get_connection(struct hidp_session *session)
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200770{
771 bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
772 bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
Peter Hurley1785dbf2011-08-30 11:53:35 -0400773 struct hci_conn *conn;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200774 struct hci_dev *hdev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200775
776 hdev = hci_get_route(dst, src);
777 if (!hdev)
778 return NULL;
779
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300780 hci_dev_lock(hdev);
Peter Hurley1785dbf2011-08-30 11:53:35 -0400781 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
782 if (conn)
783 hci_conn_hold_device(conn);
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300784 hci_dev_unlock(hdev);
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200785
786 hci_dev_put(hdev);
787
Peter Hurley1785dbf2011-08-30 11:53:35 -0400788 return conn;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200789}
790
Andrew Morton91f5cca2008-02-05 03:07:58 -0800791static int hidp_setup_input(struct hidp_session *session,
792 struct hidp_connadd_req *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700793{
Jiri Slabyc500c972008-05-16 11:49:16 +0200794 struct input_dev *input;
Gustavo F. Padovan3415a5f2011-10-06 21:17:32 -0300795 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796
Jiri Slabyc500c972008-05-16 11:49:16 +0200797 input = input_allocate_device();
798 if (!input)
799 return -ENOMEM;
800
801 session->input = input;
802
Marcel Holtmann5be39462007-05-09 09:15:30 +0200803 input_set_drvdata(input, session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700804
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500805 input->name = "Bluetooth HID Boot Protocol Device";
806
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807 input->id.bustype = BUS_BLUETOOTH;
808 input->id.vendor = req->vendor;
809 input->id.product = req->product;
810 input->id.version = req->version;
811
812 if (req->subclass & 0x40) {
813 set_bit(EV_KEY, input->evbit);
814 set_bit(EV_LED, input->evbit);
815 set_bit(EV_REP, input->evbit);
816
817 set_bit(LED_NUML, input->ledbit);
818 set_bit(LED_CAPSL, input->ledbit);
819 set_bit(LED_SCROLLL, input->ledbit);
820 set_bit(LED_COMPOSE, input->ledbit);
821 set_bit(LED_KANA, input->ledbit);
822
823 for (i = 0; i < sizeof(hidp_keycode); i++)
824 set_bit(hidp_keycode[i], input->keybit);
825 clear_bit(0, input->keybit);
826 }
827
828 if (req->subclass & 0x80) {
Jiri Slaby7b19ada2007-10-18 23:40:32 -0700829 input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
830 input->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
831 BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
832 input->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
833 input->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |
834 BIT_MASK(BTN_EXTRA);
835 input->relbit[0] |= BIT_MASK(REL_WHEEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700836 }
837
Peter Hurley1785dbf2011-08-30 11:53:35 -0400838 input->dev.parent = &session->conn->dev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200839
Linus Torvalds1da177e2005-04-16 15:20:36 -0700840 input->event = hidp_input_event;
841
Marcel Holtmannedad6382009-08-22 14:22:15 -0700842 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843}
844
Marcel Holtmannf5ffd462007-02-17 23:58:53 +0100845static int hidp_open(struct hid_device *hid)
846{
847 return 0;
848}
849
850static void hidp_close(struct hid_device *hid)
851{
852}
853
Jiri Slabyc500c972008-05-16 11:49:16 +0200854static int hidp_parse(struct hid_device *hid)
855{
856 struct hidp_session *session = hid->driver_data;
Jiri Slabyc500c972008-05-16 11:49:16 +0200857
Michael Poole15c697c2010-02-05 12:23:43 -0500858 return hid_parse_report(session->hid, session->rd_data,
859 session->rd_size);
Jiri Slabyc500c972008-05-16 11:49:16 +0200860}
861
862static int hidp_start(struct hid_device *hid)
863{
864 struct hidp_session *session = hid->driver_data;
865 struct hid_report *report;
866
David Herrmann142c69c2011-08-26 13:27:12 +0200867 if (hid->quirks & HID_QUIRK_NO_INIT_REPORTS)
868 return 0;
869
Jiri Slabyc500c972008-05-16 11:49:16 +0200870 list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].
871 report_list, list)
872 hidp_send_report(session, report);
873
874 list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].
875 report_list, list)
876 hidp_send_report(session, report);
877
Jiri Slabyc500c972008-05-16 11:49:16 +0200878 return 0;
879}
880
881static void hidp_stop(struct hid_device *hid)
882{
883 struct hidp_session *session = hid->driver_data;
884
885 skb_queue_purge(&session->ctrl_transmit);
886 skb_queue_purge(&session->intr_transmit);
887
Jiri Slabyc500c972008-05-16 11:49:16 +0200888 hid->claimed = 0;
889}
890
891static struct hid_ll_driver hidp_hid_driver = {
892 .parse = hidp_parse,
893 .start = hidp_start,
894 .stop = hidp_stop,
895 .open = hidp_open,
896 .close = hidp_close,
897 .hidinput_input_event = hidp_hidinput_event,
898};
899
Alan Ott0f69dca2011-01-18 03:04:37 -0500900/* This function sets up the hid device. It does not add it
901 to the HID system. That is done in hidp_add_connection(). */
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200902static int hidp_setup_hid(struct hidp_session *session,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800903 struct hidp_connadd_req *req)
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100904{
Jiri Slabyc500c972008-05-16 11:49:16 +0200905 struct hid_device *hid;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700906 int err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100907
Michael Poole15c697c2010-02-05 12:23:43 -0500908 session->rd_data = kzalloc(req->rd_size, GFP_KERNEL);
909 if (!session->rd_data)
910 return -ENOMEM;
911
912 if (copy_from_user(session->rd_data, req->rd_data, req->rd_size)) {
913 err = -EFAULT;
914 goto fault;
915 }
916 session->rd_size = req->rd_size;
917
Jiri Slabyc500c972008-05-16 11:49:16 +0200918 hid = hid_allocate_device();
Michael Poole15c697c2010-02-05 12:23:43 -0500919 if (IS_ERR(hid)) {
920 err = PTR_ERR(hid);
921 goto fault;
922 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100923
Jiri Slabyc500c972008-05-16 11:49:16 +0200924 session->hid = hid;
Michael Poole15c697c2010-02-05 12:23:43 -0500925
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100926 hid->driver_data = session;
927
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100928 hid->bus = BUS_BLUETOOTH;
929 hid->vendor = req->vendor;
930 hid->product = req->product;
931 hid->version = req->version;
Jiri Slabyc500c972008-05-16 11:49:16 +0200932 hid->country = req->country;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100933
934 strncpy(hid->name, req->name, 128);
Gustavo F. Padovand6b2eb22010-09-03 18:29:46 -0300935 strncpy(hid->phys, batostr(&bt_sk(session->ctrl_sock->sk)->src), 64);
936 strncpy(hid->uniq, batostr(&bt_sk(session->ctrl_sock->sk)->dst), 64);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100937
Peter Hurley1785dbf2011-08-30 11:53:35 -0400938 hid->dev.parent = &session->conn->dev;
Jiri Slabyc500c972008-05-16 11:49:16 +0200939 hid->ll_driver = &hidp_hid_driver;
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200940
Alan Ott0ff17312011-01-18 03:04:40 -0500941 hid->hid_get_raw_report = hidp_get_raw_report;
Jiri Kosina2da31932009-11-26 16:20:56 +0100942 hid->hid_output_raw_report = hidp_output_raw_report;
943
Jiri Slabyc500c972008-05-16 11:49:16 +0200944 return 0;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700945
Michael Poole15c697c2010-02-05 12:23:43 -0500946fault:
947 kfree(session->rd_data);
948 session->rd_data = NULL;
949
Marcel Holtmannedad6382009-08-22 14:22:15 -0700950 return err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100951}
952
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
954{
955 struct hidp_session *session, *s;
Szymon Jancaabf6f82011-04-05 15:37:45 +0200956 int vendor, product;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700957 int err;
958
959 BT_DBG("");
960
961 if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
962 bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
963 return -ENOTUNIQ;
964
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100965 BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
966
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967 down_write(&hidp_session_sem);
968
969 s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
970 if (s && s->state == BT_CONNECTED) {
Gustavo F. Padovan81b25cd2011-10-06 23:32:29 -0300971 up_write(&hidp_session_sem);
972 return -EEXIST;
973 }
974
975 session = kzalloc(sizeof(struct hidp_session), GFP_KERNEL);
976 if (!session) {
977 up_write(&hidp_session_sem);
978 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700979 }
980
981 bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
982
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300983 session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->chan->omtu,
984 l2cap_pi(ctrl_sock->sk)->chan->imtu);
985 session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->chan->omtu,
986 l2cap_pi(intr_sock->sk)->chan->imtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987
988 BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
989
990 session->ctrl_sock = ctrl_sock;
991 session->intr_sock = intr_sock;
992 session->state = BT_CONNECTED;
993
Gustavo F. Padovan3c32fa92011-10-20 17:21:34 -0200994 session->conn = hidp_get_connection(session);
995 if (!session->conn) {
996 err = -ENOTCONN;
997 goto failed;
998 }
999
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001000 setup_timer(&session->timer, hidp_idle_timeout, (unsigned long)session);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001001
1002 skb_queue_head_init(&session->ctrl_transmit);
1003 skb_queue_head_init(&session->intr_transmit);
1004
Alan Ott0ff17312011-01-18 03:04:40 -05001005 mutex_init(&session->report_mutex);
1006 init_waitqueue_head(&session->report_queue);
Alan Ott0f69dca2011-01-18 03:04:37 -05001007 init_waitqueue_head(&session->startup_queue);
1008 session->waiting_for_startup = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001009 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
1010 session->idle_to = req->idle_to;
1011
Peter Hurley1785dbf2011-08-30 11:53:35 -04001012 __hidp_link_session(session);
1013
Jiri Slabyc500c972008-05-16 11:49:16 +02001014 if (req->rd_size > 0) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001015 err = hidp_setup_hid(session, req);
Gustavo F. Padovan192893c2011-10-06 21:27:56 -03001016 if (err)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001017 goto purge;
Jiri Slabyc500c972008-05-16 11:49:16 +02001018 }
1019
1020 if (!session->hid) {
1021 err = hidp_setup_input(session, req);
1022 if (err < 0)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001023 goto purge;
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001024 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001025
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 hidp_set_timer(session);
1027
Szymon Jancaabf6f82011-04-05 15:37:45 +02001028 if (session->hid) {
1029 vendor = session->hid->vendor;
1030 product = session->hid->product;
1031 } else if (session->input) {
1032 vendor = session->input->id.vendor;
1033 product = session->input->id.product;
1034 } else {
1035 vendor = 0x0000;
1036 product = 0x0000;
1037 }
1038
1039 session->task = kthread_run(hidp_session, session, "khidpd_%04x%04x",
1040 vendor, product);
1041 if (IS_ERR(session->task)) {
1042 err = PTR_ERR(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001043 goto unlink;
Szymon Jancaabf6f82011-04-05 15:37:45 +02001044 }
1045
Alan Ott0f69dca2011-01-18 03:04:37 -05001046 while (session->waiting_for_startup) {
1047 wait_event_interruptible(session->startup_queue,
1048 !session->waiting_for_startup);
1049 }
1050
Gustavo F. Padovan3415a5f2011-10-06 21:17:32 -03001051 if (session->hid)
1052 err = hid_add_device(session->hid);
1053 else
1054 err = input_register_device(session->input);
1055
Peter Hurleye9d5cb52011-08-05 10:51:26 -04001056 if (err < 0) {
1057 atomic_inc(&session->terminate);
1058 wake_up_process(session->task);
1059 up_write(&hidp_session_sem);
1060 return err;
1061 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062
1063 if (session->input) {
1064 hidp_send_ctrl_message(session,
1065 HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
1066 session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
1067
1068 session->leds = 0xff;
1069 hidp_input_event(session->input, EV_LED, 0, 0);
1070 }
1071
1072 up_write(&hidp_session_sem);
1073 return 0;
1074
1075unlink:
1076 hidp_del_timer(session);
1077
Marcel Holtmannedad6382009-08-22 14:22:15 -07001078 if (session->input) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079 input_unregister_device(session->input);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001080 session->input = NULL;
1081 }
1082
1083 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001084 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001085 session->hid = NULL;
1086 }
1087
Michael Poole15c697c2010-02-05 12:23:43 -05001088 kfree(session->rd_data);
1089 session->rd_data = NULL;
1090
Marcel Holtmannedad6382009-08-22 14:22:15 -07001091purge:
Peter Hurley1785dbf2011-08-30 11:53:35 -04001092 __hidp_unlink_session(session);
1093
Jiri Slabyc500c972008-05-16 11:49:16 +02001094 skb_queue_purge(&session->ctrl_transmit);
1095 skb_queue_purge(&session->intr_transmit);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001096
Jiri Slabyc500c972008-05-16 11:49:16 +02001097failed:
1098 up_write(&hidp_session_sem);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001099
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 kfree(session);
1101 return err;
1102}
1103
1104int hidp_del_connection(struct hidp_conndel_req *req)
1105{
1106 struct hidp_session *session;
1107 int err = 0;
1108
1109 BT_DBG("");
1110
1111 down_read(&hidp_session_sem);
1112
1113 session = __hidp_get_session(&req->bdaddr);
1114 if (session) {
1115 if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
1116 hidp_send_ctrl_message(session,
1117 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
1118 } else {
1119 /* Flush the transmit queues */
1120 skb_queue_purge(&session->ctrl_transmit);
1121 skb_queue_purge(&session->intr_transmit);
1122
Peter Hurley7bb59df2011-06-30 13:53:53 -04001123 atomic_inc(&session->terminate);
1124 wake_up_process(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001125 }
1126 } else
1127 err = -ENOENT;
1128
1129 up_read(&hidp_session_sem);
1130 return err;
1131}
1132
1133int hidp_get_connlist(struct hidp_connlist_req *req)
1134{
Gustavo F. Padovancd11cdd2011-10-06 17:35:31 -03001135 struct hidp_session *session;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001136 int err = 0, n = 0;
1137
1138 BT_DBG("");
1139
1140 down_read(&hidp_session_sem);
1141
Gustavo F. Padovancd11cdd2011-10-06 17:35:31 -03001142 list_for_each_entry(session, &hidp_session_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001143 struct hidp_conninfo ci;
1144
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145 __hidp_copy_session(session, &ci);
1146
1147 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
1148 err = -EFAULT;
1149 break;
1150 }
1151
1152 if (++n >= req->cnum)
1153 break;
1154
1155 req->ci++;
1156 }
1157 req->cnum = n;
1158
1159 up_read(&hidp_session_sem);
1160 return err;
1161}
1162
1163int hidp_get_conninfo(struct hidp_conninfo *ci)
1164{
1165 struct hidp_session *session;
1166 int err = 0;
1167
1168 down_read(&hidp_session_sem);
1169
1170 session = __hidp_get_session(&ci->bdaddr);
1171 if (session)
1172 __hidp_copy_session(session, ci);
1173 else
1174 err = -ENOENT;
1175
1176 up_read(&hidp_session_sem);
1177 return err;
1178}
1179
1180static int __init hidp_init(void)
1181{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001182 BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
1183
Henrik Rydberg8215d552012-04-23 12:07:07 +02001184 return hidp_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185}
1186
1187static void __exit hidp_exit(void)
1188{
1189 hidp_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190}
1191
1192module_init(hidp_init);
1193module_exit(hidp_exit);
1194
1195MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
1196MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
1197MODULE_VERSION(VERSION);
1198MODULE_LICENSE("GPL");
1199MODULE_ALIAS("bt-proto-6");