blob: cef1021d540391c1960a35468a99281fc366f69c [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
David Herrmann3764eaa2013-04-06 20:28:43 +020062static inline void hidp_schedule(struct hidp_session *session)
63{
64 struct sock *ctrl_sk = session->ctrl_sock->sk;
65 struct sock *intr_sk = session->intr_sock->sk;
66
67 wake_up_interruptible(sk_sleep(ctrl_sk));
68 wake_up_interruptible(sk_sleep(intr_sk));
69}
70
Linus Torvalds1da177e2005-04-16 15:20:36 -070071static struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
72{
73 struct hidp_session *session;
Linus Torvalds1da177e2005-04-16 15:20:36 -070074
75 BT_DBG("");
76
Gustavo F. Padovancd11cdd2011-10-06 17:35:31 -030077 list_for_each_entry(session, &hidp_session_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -070078 if (!bacmp(bdaddr, &session->bdaddr))
79 return session;
80 }
Luiz Augusto von Dentz8035ded2011-11-01 10:58:56 +020081
Linus Torvalds1da177e2005-04-16 15:20:36 -070082 return NULL;
83}
84
Linus Torvalds1da177e2005-04-16 15:20:36 -070085static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
86{
Vasiliy Kulikovd31dbf62010-10-30 18:26:31 +040087 memset(ci, 0, sizeof(*ci));
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 bacpy(&ci->bdaddr, &session->bdaddr);
89
90 ci->flags = session->flags;
David Herrmanndcc07642013-04-06 20:28:40 +020091 ci->state = BT_CONNECTED;
Linus Torvalds1da177e2005-04-16 15:20:36 -070092
93 ci->vendor = 0x0000;
94 ci->product = 0x0000;
95 ci->version = 0x0000;
Linus Torvalds1da177e2005-04-16 15:20:36 -070096
97 if (session->input) {
98 ci->vendor = session->input->id.vendor;
99 ci->product = session->input->id.product;
100 ci->version = session->input->id.version;
101 if (session->input->name)
102 strncpy(ci->name, session->input->name, 128);
103 else
104 strncpy(ci->name, "HID Boot Device", 128);
105 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100106
107 if (session->hid) {
108 ci->vendor = session->hid->vendor;
109 ci->product = session->hid->product;
110 ci->version = session->hid->version;
111 strncpy(ci->name, session->hid->name, 128);
112 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113}
114
Andrew Morton91f5cca2008-02-05 03:07:58 -0800115static int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
116 unsigned int type, unsigned int code, int value)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700117{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 unsigned char newleds;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100119 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100121 BT_DBG("session %p type %d code %d value %d", session, type, code, value);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700122
123 if (type != EV_LED)
124 return -1;
125
126 newleds = (!!test_bit(LED_KANA, dev->led) << 3) |
127 (!!test_bit(LED_COMPOSE, dev->led) << 3) |
128 (!!test_bit(LED_SCROLLL, dev->led) << 2) |
129 (!!test_bit(LED_CAPSL, dev->led) << 1) |
130 (!!test_bit(LED_NUML, dev->led));
131
132 if (session->leds == newleds)
133 return 0;
134
135 session->leds = newleds;
136
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200137 skb = alloc_skb(3, GFP_ATOMIC);
138 if (!skb) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139 BT_ERR("Can't allocate memory for new frame");
140 return -ENOMEM;
141 }
142
143 *skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
144 *skb_put(skb, 1) = 0x01;
145 *skb_put(skb, 1) = newleds;
146
147 skb_queue_tail(&session->intr_transmit, skb);
148
149 hidp_schedule(session);
150
151 return 0;
152}
153
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100154static int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
155{
Marcel Holtmann5be39462007-05-09 09:15:30 +0200156 struct hid_device *hid = input_get_drvdata(dev);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100157 struct hidp_session *session = hid->driver_data;
158
159 return hidp_queue_event(session, dev, type, code, value);
160}
161
162static int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
163{
Marcel Holtmann5be39462007-05-09 09:15:30 +0200164 struct hidp_session *session = input_get_drvdata(dev);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100165
166 return hidp_queue_event(session, dev, type, code, value);
167}
168
Linus Torvalds1da177e2005-04-16 15:20:36 -0700169static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
170{
171 struct input_dev *dev = session->input;
172 unsigned char *keys = session->keys;
173 unsigned char *udata = skb->data + 1;
174 signed char *sdata = skb->data + 1;
175 int i, size = skb->len - 1;
176
177 switch (skb->data[0]) {
178 case 0x01: /* Keyboard report */
179 for (i = 0; i < 8; i++)
180 input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
181
182 /* If all the key codes have been set to 0x01, it means
183 * too many keys were pressed at the same time. */
184 if (!memcmp(udata + 2, hidp_mkeyspat, 6))
185 break;
186
187 for (i = 2; i < 8; i++) {
188 if (keys[i] > 3 && memscan(udata + 2, keys[i], 6) == udata + 8) {
189 if (hidp_keycode[keys[i]])
190 input_report_key(dev, hidp_keycode[keys[i]], 0);
191 else
192 BT_ERR("Unknown key (scancode %#x) released.", keys[i]);
193 }
194
195 if (udata[i] > 3 && memscan(keys + 2, udata[i], 6) == keys + 8) {
196 if (hidp_keycode[udata[i]])
197 input_report_key(dev, hidp_keycode[udata[i]], 1);
198 else
199 BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]);
200 }
201 }
202
203 memcpy(keys, udata, 8);
204 break;
205
206 case 0x02: /* Mouse report */
207 input_report_key(dev, BTN_LEFT, sdata[0] & 0x01);
208 input_report_key(dev, BTN_RIGHT, sdata[0] & 0x02);
209 input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
210 input_report_key(dev, BTN_SIDE, sdata[0] & 0x08);
211 input_report_key(dev, BTN_EXTRA, sdata[0] & 0x10);
212
213 input_report_rel(dev, REL_X, sdata[1]);
214 input_report_rel(dev, REL_Y, sdata[2]);
215
216 if (size > 3)
217 input_report_rel(dev, REL_WHEEL, sdata[3]);
218 break;
219 }
220
221 input_sync(dev);
222}
223
Bastien Nocera6bf82682010-01-20 12:00:42 +0000224static int __hidp_send_ctrl_message(struct hidp_session *session,
Gustavo Padovan1d0c4da2012-06-09 19:22:42 -0300225 unsigned char hdr, unsigned char *data,
226 int size)
Bastien Nocera6bf82682010-01-20 12:00:42 +0000227{
228 struct sk_buff *skb;
229
230 BT_DBG("session %p data %p size %d", session, data, size);
231
David Herrmann794d1752011-08-26 14:06:02 +0200232 if (atomic_read(&session->terminate))
233 return -EIO;
234
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200235 skb = alloc_skb(size + 1, GFP_ATOMIC);
236 if (!skb) {
Bastien Nocera6bf82682010-01-20 12:00:42 +0000237 BT_ERR("Can't allocate memory for new frame");
238 return -ENOMEM;
239 }
240
241 *skb_put(skb, 1) = hdr;
242 if (data && size > 0)
243 memcpy(skb_put(skb, size), data, size);
244
245 skb_queue_tail(&session->ctrl_transmit, skb);
246
247 return 0;
248}
249
Gustavo Padovan6039aa72012-05-23 04:04:18 -0300250static int hidp_send_ctrl_message(struct hidp_session *session,
Bastien Nocera6bf82682010-01-20 12:00:42 +0000251 unsigned char hdr, unsigned char *data, int size)
252{
253 int err;
254
255 err = __hidp_send_ctrl_message(session, hdr, data, size);
256
257 hidp_schedule(session);
258
259 return err;
260}
261
Andrew Morton91f5cca2008-02-05 03:07:58 -0800262static int hidp_queue_report(struct hidp_session *session,
263 unsigned char *data, int size)
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100264{
265 struct sk_buff *skb;
266
Dave Young6792b5e2007-10-20 14:15:39 +0200267 BT_DBG("session %p hid %p data %p size %d", session, session->hid, data, size);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100268
Andrei Emeltchenko5a08ecc2011-01-11 17:20:20 +0200269 skb = alloc_skb(size + 1, GFP_ATOMIC);
270 if (!skb) {
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100271 BT_ERR("Can't allocate memory for new frame");
272 return -ENOMEM;
273 }
274
275 *skb_put(skb, 1) = 0xa2;
276 if (size > 0)
277 memcpy(skb_put(skb, size), data, size);
278
279 skb_queue_tail(&session->intr_transmit, skb);
280
281 hidp_schedule(session);
282
283 return 0;
284}
285
286static int hidp_send_report(struct hidp_session *session, struct hid_report *report)
287{
288 unsigned char buf[32];
289 int rsize;
290
291 rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
292 if (rsize > sizeof(buf))
293 return -EIO;
294
295 hid_output_report(report, buf);
296
297 return hidp_queue_report(session, buf, rsize);
298}
299
Alan Ott0ff17312011-01-18 03:04:40 -0500300static int hidp_get_raw_report(struct hid_device *hid,
301 unsigned char report_number,
302 unsigned char *data, size_t count,
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100303 unsigned char report_type)
Jiri Kosina2da31932009-11-26 16:20:56 +0100304{
Alan Ott0ff17312011-01-18 03:04:40 -0500305 struct hidp_session *session = hid->driver_data;
306 struct sk_buff *skb;
307 size_t len;
308 int numbered_reports = hid->report_enum[report_type].numbered;
David Herrmann794d1752011-08-26 14:06:02 +0200309 int ret;
Alan Ott0ff17312011-01-18 03:04:40 -0500310
Karl Reltonfd86c9b2013-02-20 18:16:19 +0000311 if (atomic_read(&session->terminate))
312 return -EIO;
313
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. */
David Herrmanne3492dc2013-04-06 20:28:41 +0200342 while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
343 !atomic_read(&session->terminate)) {
Alan Ott0ff17312011-01-18 03:04:40 -0500344 int res;
345
346 res = wait_event_interruptible_timeout(session->report_queue,
David Herrmanne3492dc2013-04-06 20:28:41 +0200347 !test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)
348 || atomic_read(&session->terminate),
Alan Ott0ff17312011-01-18 03:04:40 -0500349 5*HZ);
350 if (res == 0) {
351 /* timeout */
David Herrmann794d1752011-08-26 14:06:02 +0200352 ret = -EIO;
353 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500354 }
355 if (res < 0) {
356 /* signal */
David Herrmann794d1752011-08-26 14:06:02 +0200357 ret = -ERESTARTSYS;
358 goto err;
Alan Ott0ff17312011-01-18 03:04:40 -0500359 }
360 }
361
362 skb = session->report_return;
363 if (skb) {
364 len = skb->len < count ? skb->len : count;
365 memcpy(data, skb->data, len);
366
367 kfree_skb(skb);
368 session->report_return = NULL;
369 } else {
370 /* Device returned a HANDSHAKE, indicating protocol error. */
371 len = -EIO;
372 }
373
374 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
375 mutex_unlock(&session->report_mutex);
376
377 return len;
378
David Herrmann794d1752011-08-26 14:06:02 +0200379err:
Alan Ott0ff17312011-01-18 03:04:40 -0500380 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
381 mutex_unlock(&session->report_mutex);
David Herrmann794d1752011-08-26 14:06:02 +0200382 return ret;
Alan Ott0ff17312011-01-18 03:04:40 -0500383}
384
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385static int hidp_output_raw_report(struct hid_device *hid, unsigned char *data, size_t count,
Jiri Kosina2da31932009-11-26 16:20:56 +0100386 unsigned char report_type)
387{
Alan Ott08254112011-01-18 03:04:38 -0500388 struct hidp_session *session = hid->driver_data;
389 int ret;
390
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100391 switch (report_type) {
392 case HID_FEATURE_REPORT:
393 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
394 break;
395 case HID_OUTPUT_REPORT:
Antonio Ospite97e1efb2011-02-20 18:26:46 +0100396 report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
Jiri Kosinad4bfa032010-01-29 15:03:36 +0100397 break;
398 default:
399 return -EINVAL;
400 }
401
Alan Ott08254112011-01-18 03:04:38 -0500402 if (mutex_lock_interruptible(&session->report_mutex))
403 return -ERESTARTSYS;
404
405 /* Set up our wait, and send the report request to the device. */
406 set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
David Herrmann794d1752011-08-26 14:06:02 +0200407 ret = hidp_send_ctrl_message(hid->driver_data, report_type, data,
408 count);
409 if (ret)
Alan Ott08254112011-01-18 03:04:38 -0500410 goto err;
Alan Ott08254112011-01-18 03:04:38 -0500411
412 /* Wait for the ACK from the device. */
David Herrmanne3492dc2013-04-06 20:28:41 +0200413 while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags) &&
414 !atomic_read(&session->terminate)) {
Alan Ott08254112011-01-18 03:04:38 -0500415 int res;
416
417 res = wait_event_interruptible_timeout(session->report_queue,
David Herrmanne3492dc2013-04-06 20:28:41 +0200418 !test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)
419 || atomic_read(&session->terminate),
Alan Ott08254112011-01-18 03:04:38 -0500420 10*HZ);
421 if (res == 0) {
422 /* timeout */
423 ret = -EIO;
424 goto err;
425 }
426 if (res < 0) {
427 /* signal */
428 ret = -ERESTARTSYS;
429 goto err;
430 }
431 }
432
433 if (!session->output_report_success) {
434 ret = -EIO;
435 goto err;
436 }
437
438 ret = count;
439
440err:
441 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
442 mutex_unlock(&session->report_mutex);
443 return ret;
Jiri Kosina2da31932009-11-26 16:20:56 +0100444}
445
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446static void hidp_idle_timeout(unsigned long arg)
447{
448 struct hidp_session *session = (struct hidp_session *) arg;
449
Peter Hurley7bb59df2011-06-30 13:53:53 -0400450 atomic_inc(&session->terminate);
451 wake_up_process(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452}
453
Andrew Morton91f5cca2008-02-05 03:07:58 -0800454static void hidp_set_timer(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700455{
456 if (session->idle_to > 0)
457 mod_timer(&session->timer, jiffies + HZ * session->idle_to);
458}
459
Gustavo Padovan6039aa72012-05-23 04:04:18 -0300460static void hidp_del_timer(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461{
462 if (session->idle_to > 0)
463 del_timer(&session->timer);
464}
465
Andrew Morton91f5cca2008-02-05 03:07:58 -0800466static void hidp_process_handshake(struct hidp_session *session,
467 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468{
469 BT_DBG("session %p param 0x%02x", session, param);
Alan Ott08254112011-01-18 03:04:38 -0500470 session->output_report_success = 0; /* default condition */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471
472 switch (param) {
473 case HIDP_HSHK_SUCCESSFUL:
474 /* FIXME: Call into SET_ GET_ handlers here */
Alan Ott08254112011-01-18 03:04:38 -0500475 session->output_report_success = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700476 break;
477
478 case HIDP_HSHK_NOT_READY:
479 case HIDP_HSHK_ERR_INVALID_REPORT_ID:
480 case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
481 case HIDP_HSHK_ERR_INVALID_PARAMETER:
Gustavo F. Padovanab88f712011-10-06 22:05:37 -0300482 if (test_and_clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags))
Alan Ott0ff17312011-01-18 03:04:40 -0500483 wake_up_interruptible(&session->report_queue);
Gustavo F. Padovanab88f712011-10-06 22:05:37 -0300484
Linus Torvalds1da177e2005-04-16 15:20:36 -0700485 /* FIXME: Call into SET_ GET_ handlers here */
486 break;
487
488 case HIDP_HSHK_ERR_UNKNOWN:
489 break;
490
491 case HIDP_HSHK_ERR_FATAL:
492 /* Device requests a reboot, as this is the only way this error
YOSHIFUJI Hideaki8e87d142007-02-09 23:24:33 +0900493 * can be recovered. */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 __hidp_send_ctrl_message(session,
495 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
496 break;
497
498 default:
499 __hidp_send_ctrl_message(session,
500 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
501 break;
502 }
Alan Ott08254112011-01-18 03:04:38 -0500503
504 /* Wake up the waiting thread. */
Gustavo F. Padovanab88f712011-10-06 22:05:37 -0300505 if (test_and_clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags))
Alan Ott08254112011-01-18 03:04:38 -0500506 wake_up_interruptible(&session->report_queue);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700507}
508
Andrew Morton91f5cca2008-02-05 03:07:58 -0800509static void hidp_process_hid_control(struct hidp_session *session,
510 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700511{
512 BT_DBG("session %p param 0x%02x", session, param);
513
Dave Youngeff001e2008-02-05 03:07:14 -0800514 if (param == HIDP_CTRL_VIRTUAL_CABLE_UNPLUG) {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700515 /* Flush the transmit queues */
516 skb_queue_purge(&session->ctrl_transmit);
517 skb_queue_purge(&session->intr_transmit);
518
Peter Hurley7bb59df2011-06-30 13:53:53 -0400519 atomic_inc(&session->terminate);
520 wake_up_process(current);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700521 }
522}
523
Alan Ott0ff17312011-01-18 03:04:40 -0500524/* Returns true if the passed-in skb should be freed by the caller. */
525static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800526 unsigned char param)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700527{
Alan Ott0ff17312011-01-18 03:04:40 -0500528 int done_with_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700529 BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
530
531 switch (param) {
532 case HIDP_DATA_RTYPE_INPUT:
533 hidp_set_timer(session);
534
535 if (session->input)
536 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100537
538 if (session->hid)
539 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540 break;
541
542 case HIDP_DATA_RTYPE_OTHER:
543 case HIDP_DATA_RTYPE_OUPUT:
544 case HIDP_DATA_RTYPE_FEATURE:
545 break;
546
547 default:
548 __hidp_send_ctrl_message(session,
549 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
550 }
Alan Ott0ff17312011-01-18 03:04:40 -0500551
552 if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
553 param == session->waiting_report_type) {
554 if (session->waiting_report_number < 0 ||
555 session->waiting_report_number == skb->data[0]) {
556 /* hidp_get_raw_report() is waiting on this report. */
557 session->report_return = skb;
558 done_with_skb = 0;
559 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
560 wake_up_interruptible(&session->report_queue);
561 }
562 }
563
564 return done_with_skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565}
566
Andrew Morton91f5cca2008-02-05 03:07:58 -0800567static void hidp_recv_ctrl_frame(struct hidp_session *session,
568 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569{
570 unsigned char hdr, type, param;
Alan Ott0ff17312011-01-18 03:04:40 -0500571 int free_skb = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572
573 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
574
575 hdr = skb->data[0];
576 skb_pull(skb, 1);
577
578 type = hdr & HIDP_HEADER_TRANS_MASK;
579 param = hdr & HIDP_HEADER_PARAM_MASK;
580
581 switch (type) {
582 case HIDP_TRANS_HANDSHAKE:
583 hidp_process_handshake(session, param);
584 break;
585
586 case HIDP_TRANS_HID_CONTROL:
587 hidp_process_hid_control(session, param);
588 break;
589
590 case HIDP_TRANS_DATA:
Alan Ott0ff17312011-01-18 03:04:40 -0500591 free_skb = hidp_process_data(session, skb, param);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 break;
593
594 default:
595 __hidp_send_ctrl_message(session,
596 HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
597 break;
598 }
599
Alan Ott0ff17312011-01-18 03:04:40 -0500600 if (free_skb)
601 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602}
603
Andrew Morton91f5cca2008-02-05 03:07:58 -0800604static void hidp_recv_intr_frame(struct hidp_session *session,
605 struct sk_buff *skb)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700606{
607 unsigned char hdr;
608
609 BT_DBG("session %p skb %p len %d", session, skb, skb->len);
610
611 hdr = skb->data[0];
612 skb_pull(skb, 1);
613
614 if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
615 hidp_set_timer(session);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100616
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617 if (session->input)
618 hidp_input_report(session, skb);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100619
620 if (session->hid) {
621 hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
622 BT_DBG("report len %d", skb->len);
623 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 } else {
625 BT_DBG("Unsupported protocol header 0x%02x", hdr);
626 }
627
628 kfree_skb(skb);
629}
630
631static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
632{
633 struct kvec iv = { data, len };
634 struct msghdr msg;
635
636 BT_DBG("sock %p data %p len %d", sock, data, len);
637
638 if (!len)
639 return 0;
640
641 memset(&msg, 0, sizeof(msg));
642
643 return kernel_sendmsg(sock, &msg, &iv, 1, len);
644}
645
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300646static void hidp_process_intr_transmit(struct hidp_session *session)
647{
648 struct sk_buff *skb;
649
650 BT_DBG("session %p", session);
651
652 while ((skb = skb_dequeue(&session->intr_transmit))) {
653 if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
654 skb_queue_head(&session->intr_transmit, skb);
655 break;
656 }
657
658 hidp_set_timer(session);
659 kfree_skb(skb);
660 }
661}
662
663static void hidp_process_ctrl_transmit(struct hidp_session *session)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700664{
665 struct sk_buff *skb;
666
667 BT_DBG("session %p", session);
668
669 while ((skb = skb_dequeue(&session->ctrl_transmit))) {
670 if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
671 skb_queue_head(&session->ctrl_transmit, skb);
672 break;
673 }
674
675 hidp_set_timer(session);
676 kfree_skb(skb);
677 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678}
679
680static int hidp_session(void *arg)
681{
682 struct hidp_session *session = arg;
683 struct sock *ctrl_sk = session->ctrl_sock->sk;
684 struct sock *intr_sk = session->intr_sock->sk;
685 struct sk_buff *skb;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700686 wait_queue_t ctrl_wait, intr_wait;
687
688 BT_DBG("session %p", session);
689
David Herrmann25df0842011-11-01 17:27:50 +0100690 __module_get(THIS_MODULE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691 set_user_nice(current, -15);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692
693 init_waitqueue_entry(&ctrl_wait, current);
694 init_waitqueue_entry(&intr_wait, current);
Eric Dumazetaa395142010-04-20 13:03:51 +0000695 add_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
696 add_wait_queue(sk_sleep(intr_sk), &intr_wait);
Alan Ott0f69dca2011-01-18 03:04:37 -0500697 session->waiting_for_startup = 0;
698 wake_up_interruptible(&session->startup_queue);
Peter Hurley7bb59df2011-06-30 13:53:53 -0400699 set_current_state(TASK_INTERRUPTIBLE);
700 while (!atomic_read(&session->terminate)) {
Szymon Janc17f09a72011-03-21 14:20:01 +0100701 if (ctrl_sk->sk_state != BT_CONNECTED ||
702 intr_sk->sk_state != BT_CONNECTED)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703 break;
704
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
706 skb_orphan(skb);
Mat Martineau44935722011-07-22 14:53:58 -0700707 if (!skb_linearize(skb))
708 hidp_recv_intr_frame(session, skb);
709 else
710 kfree_skb(skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711 }
712
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300713 hidp_process_intr_transmit(session);
714
Gustavo F. Padovandc0da5c2011-10-06 18:02:13 -0300715 while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
716 skb_orphan(skb);
717 if (!skb_linearize(skb))
718 hidp_recv_ctrl_frame(session, skb);
719 else
720 kfree_skb(skb);
721 }
722
Gustavo F. Padovan679344e2011-10-06 20:51:37 -0300723 hidp_process_ctrl_transmit(session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724
725 schedule();
Peter Hurley7bb59df2011-06-30 13:53:53 -0400726 set_current_state(TASK_INTERRUPTIBLE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700727 }
728 set_current_state(TASK_RUNNING);
Karl Reltonfd86c9b2013-02-20 18:16:19 +0000729 atomic_inc(&session->terminate);
Eric Dumazetaa395142010-04-20 13:03:51 +0000730 remove_wait_queue(sk_sleep(intr_sk), &intr_wait);
731 remove_wait_queue(sk_sleep(ctrl_sk), &ctrl_wait);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
David Herrmann794d1752011-08-26 14:06:02 +0200733 clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
734 clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
735 wake_up_interruptible(&session->report_queue);
736
Linus Torvalds1da177e2005-04-16 15:20:36 -0700737 down_write(&hidp_session_sem);
738
739 hidp_del_timer(session);
740
Linus Torvalds1da177e2005-04-16 15:20:36 -0700741 if (session->input) {
742 input_unregister_device(session->input);
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500743 session->input = NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 }
745
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100746 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200747 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -0700748 session->hid = NULL;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100749 }
750
Marcel Holtmannec8dab32008-07-14 20:13:53 +0200751 /* Wakeup user-space polling for socket errors */
752 session->intr_sock->sk->sk_err = EUNATCH;
753 session->ctrl_sock->sk->sk_err = EUNATCH;
754
755 hidp_schedule(session);
756
David Woodhouse1c398582007-07-07 14:58:39 -0400757 fput(session->intr_sock->file);
758
Eric Dumazetaa395142010-04-20 13:03:51 +0000759 wait_event_timeout(*(sk_sleep(ctrl_sk)),
David Woodhouse1c398582007-07-07 14:58:39 -0400760 (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
761
762 fput(session->ctrl_sock->file);
763
David Herrmannfc225c32013-04-06 20:28:38 +0200764 list_del(&session->list);
David Woodhouse1c398582007-07-07 14:58:39 -0400765
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 up_write(&hidp_session_sem);
767
Peter Hurley1c97e942011-08-05 10:51:34 -0400768 kfree(session->rd_data);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769 kfree(session);
David Herrmann25df0842011-11-01 17:27:50 +0100770 module_put_and_exit(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700771 return 0;
772}
773
Gustavo F. Padovan3e90dc82011-10-07 01:29:51 -0300774static struct hci_conn *hidp_get_connection(struct hidp_session *session)
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200775{
776 bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
777 bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
Peter Hurley1785dbf2011-08-30 11:53:35 -0400778 struct hci_conn *conn;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200779 struct hci_dev *hdev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200780
781 hdev = hci_get_route(dst, src);
782 if (!hdev)
783 return NULL;
784
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300785 hci_dev_lock(hdev);
Peter Hurley1785dbf2011-08-30 11:53:35 -0400786 conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
Gustavo F. Padovan09fd0de2011-06-17 13:03:21 -0300787 hci_dev_unlock(hdev);
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200788
789 hci_dev_put(hdev);
790
Peter Hurley1785dbf2011-08-30 11:53:35 -0400791 return conn;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200792}
793
Andrew Morton91f5cca2008-02-05 03:07:58 -0800794static int hidp_setup_input(struct hidp_session *session,
795 struct hidp_connadd_req *req)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700796{
Jiri Slabyc500c972008-05-16 11:49:16 +0200797 struct input_dev *input;
Gustavo F. Padovan3415a5f2011-10-06 21:17:32 -0300798 int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700799
Jiri Slabyc500c972008-05-16 11:49:16 +0200800 input = input_allocate_device();
801 if (!input)
802 return -ENOMEM;
803
804 session->input = input;
805
Marcel Holtmann5be39462007-05-09 09:15:30 +0200806 input_set_drvdata(input, session);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700807
Dmitry Torokhov34abf912005-09-15 02:01:40 -0500808 input->name = "Bluetooth HID Boot Protocol Device";
809
Linus Torvalds1da177e2005-04-16 15:20:36 -0700810 input->id.bustype = BUS_BLUETOOTH;
811 input->id.vendor = req->vendor;
812 input->id.product = req->product;
813 input->id.version = req->version;
814
815 if (req->subclass & 0x40) {
816 set_bit(EV_KEY, input->evbit);
817 set_bit(EV_LED, input->evbit);
818 set_bit(EV_REP, input->evbit);
819
820 set_bit(LED_NUML, input->ledbit);
821 set_bit(LED_CAPSL, input->ledbit);
822 set_bit(LED_SCROLLL, input->ledbit);
823 set_bit(LED_COMPOSE, input->ledbit);
824 set_bit(LED_KANA, input->ledbit);
825
826 for (i = 0; i < sizeof(hidp_keycode); i++)
827 set_bit(hidp_keycode[i], input->keybit);
828 clear_bit(0, input->keybit);
829 }
830
831 if (req->subclass & 0x80) {
Jiri Slaby7b19ada2007-10-18 23:40:32 -0700832 input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
833 input->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
834 BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
835 input->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
836 input->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |
837 BIT_MASK(BTN_EXTRA);
838 input->relbit[0] |= BIT_MASK(REL_WHEEL);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700839 }
840
Peter Hurley1785dbf2011-08-30 11:53:35 -0400841 input->dev.parent = &session->conn->dev;
Marcel Holtmann0a85b962006-07-06 13:09:02 +0200842
Linus Torvalds1da177e2005-04-16 15:20:36 -0700843 input->event = hidp_input_event;
844
Marcel Holtmannedad6382009-08-22 14:22:15 -0700845 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700846}
847
Marcel Holtmannf5ffd462007-02-17 23:58:53 +0100848static int hidp_open(struct hid_device *hid)
849{
850 return 0;
851}
852
853static void hidp_close(struct hid_device *hid)
854{
855}
856
Jiri Slabyc500c972008-05-16 11:49:16 +0200857static int hidp_parse(struct hid_device *hid)
858{
859 struct hidp_session *session = hid->driver_data;
Jiri Slabyc500c972008-05-16 11:49:16 +0200860
Michael Poole15c697c2010-02-05 12:23:43 -0500861 return hid_parse_report(session->hid, session->rd_data,
862 session->rd_size);
Jiri Slabyc500c972008-05-16 11:49:16 +0200863}
864
865static int hidp_start(struct hid_device *hid)
866{
867 struct hidp_session *session = hid->driver_data;
868 struct hid_report *report;
869
David Herrmann142c69c2011-08-26 13:27:12 +0200870 if (hid->quirks & HID_QUIRK_NO_INIT_REPORTS)
871 return 0;
872
Jiri Slabyc500c972008-05-16 11:49:16 +0200873 list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].
874 report_list, list)
875 hidp_send_report(session, report);
876
877 list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].
878 report_list, list)
879 hidp_send_report(session, report);
880
Jiri Slabyc500c972008-05-16 11:49:16 +0200881 return 0;
882}
883
884static void hidp_stop(struct hid_device *hid)
885{
886 struct hidp_session *session = hid->driver_data;
887
888 skb_queue_purge(&session->ctrl_transmit);
889 skb_queue_purge(&session->intr_transmit);
890
Jiri Slabyc500c972008-05-16 11:49:16 +0200891 hid->claimed = 0;
892}
893
894static struct hid_ll_driver hidp_hid_driver = {
895 .parse = hidp_parse,
896 .start = hidp_start,
897 .stop = hidp_stop,
898 .open = hidp_open,
899 .close = hidp_close,
900 .hidinput_input_event = hidp_hidinput_event,
901};
902
Alan Ott0f69dca2011-01-18 03:04:37 -0500903/* This function sets up the hid device. It does not add it
904 to the HID system. That is done in hidp_add_connection(). */
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200905static int hidp_setup_hid(struct hidp_session *session,
Andrew Morton91f5cca2008-02-05 03:07:58 -0800906 struct hidp_connadd_req *req)
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100907{
Jiri Slabyc500c972008-05-16 11:49:16 +0200908 struct hid_device *hid;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700909 int err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100910
Michael Poole15c697c2010-02-05 12:23:43 -0500911 session->rd_data = kzalloc(req->rd_size, GFP_KERNEL);
912 if (!session->rd_data)
913 return -ENOMEM;
914
915 if (copy_from_user(session->rd_data, req->rd_data, req->rd_size)) {
916 err = -EFAULT;
917 goto fault;
918 }
919 session->rd_size = req->rd_size;
920
Jiri Slabyc500c972008-05-16 11:49:16 +0200921 hid = hid_allocate_device();
Michael Poole15c697c2010-02-05 12:23:43 -0500922 if (IS_ERR(hid)) {
923 err = PTR_ERR(hid);
924 goto fault;
925 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100926
Jiri Slabyc500c972008-05-16 11:49:16 +0200927 session->hid = hid;
Michael Poole15c697c2010-02-05 12:23:43 -0500928
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100929 hid->driver_data = session;
930
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100931 hid->bus = BUS_BLUETOOTH;
932 hid->vendor = req->vendor;
933 hid->product = req->product;
934 hid->version = req->version;
Jiri Slabyc500c972008-05-16 11:49:16 +0200935 hid->country = req->country;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100936
Anderson Lizardo0a9ab9b2013-01-06 18:28:53 -0400937 strncpy(hid->name, req->name, sizeof(req->name) - 1);
Andrei Emeltchenkofcb73332012-09-25 12:49:44 +0300938
939 snprintf(hid->phys, sizeof(hid->phys), "%pMR",
940 &bt_sk(session->ctrl_sock->sk)->src);
941
942 snprintf(hid->uniq, sizeof(hid->uniq), "%pMR",
943 &bt_sk(session->ctrl_sock->sk)->dst);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100944
Peter Hurley1785dbf2011-08-30 11:53:35 -0400945 hid->dev.parent = &session->conn->dev;
Jiri Slabyc500c972008-05-16 11:49:16 +0200946 hid->ll_driver = &hidp_hid_driver;
Jiri Slaby85cdaf52008-05-16 11:49:15 +0200947
Alan Ott0ff17312011-01-18 03:04:40 -0500948 hid->hid_get_raw_report = hidp_get_raw_report;
Jiri Kosina2da31932009-11-26 16:20:56 +0100949 hid->hid_output_raw_report = hidp_output_raw_report;
950
Lamarque V. Souza4529eef2012-12-06 12:39:55 -0200951 /* True if device is blacklisted in drivers/hid/hid-core.c */
952 if (hid_ignore(hid)) {
953 hid_destroy_device(session->hid);
954 session->hid = NULL;
955 return -ENODEV;
956 }
957
Jiri Slabyc500c972008-05-16 11:49:16 +0200958 return 0;
Marcel Holtmannedad6382009-08-22 14:22:15 -0700959
Michael Poole15c697c2010-02-05 12:23:43 -0500960fault:
961 kfree(session->rd_data);
962 session->rd_data = NULL;
963
Marcel Holtmannedad6382009-08-22 14:22:15 -0700964 return err;
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100965}
966
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
968{
969 struct hidp_session *session, *s;
Szymon Jancaabf6f82011-04-05 15:37:45 +0200970 int vendor, product;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700971 int err;
972
973 BT_DBG("");
974
David Herrmannb3916db2013-04-05 14:57:34 +0200975 if (!l2cap_is_socket(ctrl_sock) || !l2cap_is_socket(intr_sock))
976 return -EINVAL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977 if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
978 bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
979 return -ENOTUNIQ;
980
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +0100981 BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
982
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983 down_write(&hidp_session_sem);
984
985 s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
David Herrmanndcc07642013-04-06 20:28:40 +0200986 if (s) {
Gustavo F. Padovan81b25cd2011-10-06 23:32:29 -0300987 up_write(&hidp_session_sem);
988 return -EEXIST;
989 }
990
991 session = kzalloc(sizeof(struct hidp_session), GFP_KERNEL);
992 if (!session) {
993 up_write(&hidp_session_sem);
994 return -ENOMEM;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 }
996
997 bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
998
Gustavo F. Padovan0c1bc5c2011-04-13 17:20:49 -0300999 session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->chan->omtu,
1000 l2cap_pi(ctrl_sock->sk)->chan->imtu);
1001 session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->chan->omtu,
1002 l2cap_pi(intr_sock->sk)->chan->imtu);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001003
1004 BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
1005
1006 session->ctrl_sock = ctrl_sock;
1007 session->intr_sock = intr_sock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001008
Gustavo F. Padovan3c32fa92011-10-20 17:21:34 -02001009 session->conn = hidp_get_connection(session);
1010 if (!session->conn) {
1011 err = -ENOTCONN;
1012 goto failed;
1013 }
1014
Pavel Emelyanovb24b8a22008-01-23 21:20:07 -08001015 setup_timer(&session->timer, hidp_idle_timeout, (unsigned long)session);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001016
1017 skb_queue_head_init(&session->ctrl_transmit);
1018 skb_queue_head_init(&session->intr_transmit);
1019
Alan Ott0ff17312011-01-18 03:04:40 -05001020 mutex_init(&session->report_mutex);
1021 init_waitqueue_head(&session->report_queue);
Alan Ott0f69dca2011-01-18 03:04:37 -05001022 init_waitqueue_head(&session->startup_queue);
1023 session->waiting_for_startup = 1;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001024 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
1025 session->idle_to = req->idle_to;
1026
David Herrmannfc225c32013-04-06 20:28:38 +02001027 list_add(&session->list, &hidp_session_list);
Peter Hurley1785dbf2011-08-30 11:53:35 -04001028
Jiri Slabyc500c972008-05-16 11:49:16 +02001029 if (req->rd_size > 0) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001030 err = hidp_setup_hid(session, req);
Lamarque V. Souza4529eef2012-12-06 12:39:55 -02001031 if (err && err != -ENODEV)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001032 goto purge;
Jiri Slabyc500c972008-05-16 11:49:16 +02001033 }
1034
1035 if (!session->hid) {
1036 err = hidp_setup_input(session, req);
1037 if (err < 0)
Marcel Holtmannedad6382009-08-22 14:22:15 -07001038 goto purge;
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001039 }
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001040
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 hidp_set_timer(session);
1042
Szymon Jancaabf6f82011-04-05 15:37:45 +02001043 if (session->hid) {
1044 vendor = session->hid->vendor;
1045 product = session->hid->product;
1046 } else if (session->input) {
1047 vendor = session->input->id.vendor;
1048 product = session->input->id.product;
1049 } else {
1050 vendor = 0x0000;
1051 product = 0x0000;
1052 }
1053
1054 session->task = kthread_run(hidp_session, session, "khidpd_%04x%04x",
1055 vendor, product);
1056 if (IS_ERR(session->task)) {
1057 err = PTR_ERR(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001058 goto unlink;
Szymon Jancaabf6f82011-04-05 15:37:45 +02001059 }
1060
Alan Ott0f69dca2011-01-18 03:04:37 -05001061 while (session->waiting_for_startup) {
1062 wait_event_interruptible(session->startup_queue,
1063 !session->waiting_for_startup);
1064 }
1065
Gustavo F. Padovan3415a5f2011-10-06 21:17:32 -03001066 if (session->hid)
1067 err = hid_add_device(session->hid);
1068 else
1069 err = input_register_device(session->input);
1070
Peter Hurleye9d5cb52011-08-05 10:51:26 -04001071 if (err < 0) {
1072 atomic_inc(&session->terminate);
1073 wake_up_process(session->task);
1074 up_write(&hidp_session_sem);
1075 return err;
1076 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001077
1078 if (session->input) {
1079 hidp_send_ctrl_message(session,
1080 HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
1081 session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
1082
1083 session->leds = 0xff;
1084 hidp_input_event(session->input, EV_LED, 0, 0);
1085 }
1086
1087 up_write(&hidp_session_sem);
1088 return 0;
1089
1090unlink:
1091 hidp_del_timer(session);
1092
Marcel Holtmannedad6382009-08-22 14:22:15 -07001093 if (session->input) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094 input_unregister_device(session->input);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001095 session->input = NULL;
1096 }
1097
1098 if (session->hid) {
Jiri Slaby85cdaf52008-05-16 11:49:15 +02001099 hid_destroy_device(session->hid);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001100 session->hid = NULL;
1101 }
1102
Michael Poole15c697c2010-02-05 12:23:43 -05001103 kfree(session->rd_data);
1104 session->rd_data = NULL;
1105
Marcel Holtmannedad6382009-08-22 14:22:15 -07001106purge:
David Herrmannfc225c32013-04-06 20:28:38 +02001107 list_del(&session->list);
Peter Hurley1785dbf2011-08-30 11:53:35 -04001108
Jiri Slabyc500c972008-05-16 11:49:16 +02001109 skb_queue_purge(&session->ctrl_transmit);
1110 skb_queue_purge(&session->intr_transmit);
Marcel Holtmannedad6382009-08-22 14:22:15 -07001111
Jiri Slabyc500c972008-05-16 11:49:16 +02001112failed:
1113 up_write(&hidp_session_sem);
Marcel Holtmanne1aaadd2007-02-17 23:58:49 +01001114
Linus Torvalds1da177e2005-04-16 15:20:36 -07001115 kfree(session);
1116 return err;
1117}
1118
1119int hidp_del_connection(struct hidp_conndel_req *req)
1120{
1121 struct hidp_session *session;
1122 int err = 0;
1123
1124 BT_DBG("");
1125
1126 down_read(&hidp_session_sem);
1127
1128 session = __hidp_get_session(&req->bdaddr);
1129 if (session) {
1130 if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
1131 hidp_send_ctrl_message(session,
1132 HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
1133 } else {
1134 /* Flush the transmit queues */
1135 skb_queue_purge(&session->ctrl_transmit);
1136 skb_queue_purge(&session->intr_transmit);
1137
Peter Hurley7bb59df2011-06-30 13:53:53 -04001138 atomic_inc(&session->terminate);
1139 wake_up_process(session->task);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001140 }
1141 } else
1142 err = -ENOENT;
1143
1144 up_read(&hidp_session_sem);
1145 return err;
1146}
1147
1148int hidp_get_connlist(struct hidp_connlist_req *req)
1149{
Gustavo F. Padovancd11cdd2011-10-06 17:35:31 -03001150 struct hidp_session *session;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151 int err = 0, n = 0;
1152
1153 BT_DBG("");
1154
1155 down_read(&hidp_session_sem);
1156
Gustavo F. Padovancd11cdd2011-10-06 17:35:31 -03001157 list_for_each_entry(session, &hidp_session_list, list) {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158 struct hidp_conninfo ci;
1159
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160 __hidp_copy_session(session, &ci);
1161
1162 if (copy_to_user(req->ci, &ci, sizeof(ci))) {
1163 err = -EFAULT;
1164 break;
1165 }
1166
1167 if (++n >= req->cnum)
1168 break;
1169
1170 req->ci++;
1171 }
1172 req->cnum = n;
1173
1174 up_read(&hidp_session_sem);
1175 return err;
1176}
1177
1178int hidp_get_conninfo(struct hidp_conninfo *ci)
1179{
1180 struct hidp_session *session;
1181 int err = 0;
1182
1183 down_read(&hidp_session_sem);
1184
1185 session = __hidp_get_session(&ci->bdaddr);
1186 if (session)
1187 __hidp_copy_session(session, ci);
1188 else
1189 err = -ENOENT;
1190
1191 up_read(&hidp_session_sem);
1192 return err;
1193}
1194
1195static int __init hidp_init(void)
1196{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
1198
Henrik Rydberg8215d552012-04-23 12:07:07 +02001199 return hidp_init_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200}
1201
1202static void __exit hidp_exit(void)
1203{
1204 hidp_cleanup_sockets();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001205}
1206
1207module_init(hidp_init);
1208module_exit(hidp_exit);
1209
1210MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
1211MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
1212MODULE_VERSION(VERSION);
1213MODULE_LICENSE("GPL");
1214MODULE_ALIAS("bt-proto-6");