core.c revision cb3fecc2f29056e89658e7eb371e7f9be66cda6d
1469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg/*
2469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg   HIDP implementation for Linux Bluetooth stack (BlueZ).
3469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg   Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
4469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
5469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg   This program is free software; you can redistribute it and/or modify
6469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg   it under the terms of the GNU General Public License version 2 as
7469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg   published by the Free Software Foundation;
8469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
9469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
10469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg   OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
12469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg   IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
13469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg   CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
14469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg   WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg   ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
165a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo   OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
18469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg   ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
19469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg   COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
20469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg   SOFTWARE IS DISCLAIMED.
21469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg*/
22469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
23469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <linux/module.h>
24469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
25469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <linux/types.h>
262448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg#include <linux/errno.h>
27469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <linux/kernel.h>
28469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <linux/sched.h>
29469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <linux/slab.h>
30469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <linux/poll.h>
31469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <linux/fcntl.h>
32469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <linux/skbuff.h>
33469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <linux/socket.h>
344a332a385a86e31bfe181d969a8cb5579798fe03Alina Friedrichsen#include <linux/ioctl.h>
35469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <linux/file.h>
36469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <linux/init.h>
37469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <linux/wait.h>
38469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <net/sock.h>
39469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
40469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <linux/input.h>
41469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <linux/hid.h>
42469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
43469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <net/bluetooth/bluetooth.h>
44469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <net/bluetooth/hci_core.h>
45469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <net/bluetooth/l2cap.h>
46469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
47469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include "hidp.h"
48469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
49469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#ifndef CONFIG_BT_HIDP_DEBUG
50469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#undef  BT_DBG
51469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#define BT_DBG(D...)
52469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#endif
53469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
54469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#define VERSION "1.2"
55469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
56469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic DECLARE_RWSEM(hidp_session_sem);
57469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic LIST_HEAD(hidp_session_list);
58469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
59469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic unsigned char hidp_keycode[256] = {
60469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	  0,  0,  0,  0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38,
61fffd0934b9390f34bec45762192b7edd3b12b4b5Johannes Berg	 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44,  2,  3,
62469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	  4,  5,  6,  7,  8,  9, 10, 11, 28,  1, 14, 15, 57, 12, 13, 26,
63469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64,
64af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106,
65af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71,
66af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190,
67b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg	191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113,
68af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	115,114,  0,  0,  0,121,  0, 89, 93,124, 92, 94, 95,  0,  0,  0,
69469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	122,123, 90, 91, 85,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
70469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
71469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
72b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
73469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
74469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113,
75469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	150,158,159,128,136,177,178,176,142,152,173,140
76469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg};
77f446d10f214091408b7300f15c9adf60569edf28Johannes Berg
7857c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Bergstatic unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
79b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg
802448798133d747ad339e57099e32a1d1e68aca1cJohannes Bergstatic struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr)
812448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg{
822448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg	struct hidp_session *session;
83469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct list_head *p;
84af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
85af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	BT_DBG("");
86af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
87af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	list_for_each(p, &hidp_session_list) {
88af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		session = list_entry(p, struct hidp_session, list);
89af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		if (!bacmp(bdaddr, &session->bdaddr))
90af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg			return session;
91469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
92af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	return NULL;
93af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg}
94469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
9549b5c7f473f1bbcb30275dcaee2c06dfb8ec2279Johannes Bergstatic void __hidp_link_session(struct hidp_session *session)
9649b5c7f473f1bbcb30275dcaee2c06dfb8ec2279Johannes Berg{
9749b5c7f473f1bbcb30275dcaee2c06dfb8ec2279Johannes Berg	__module_get(THIS_MODULE);
9849b5c7f473f1bbcb30275dcaee2c06dfb8ec2279Johannes Berg	list_add(&session->list, &hidp_session_list);
9949b5c7f473f1bbcb30275dcaee2c06dfb8ec2279Johannes Berg}
10049b5c7f473f1bbcb30275dcaee2c06dfb8ec2279Johannes Berg
101469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic void __hidp_unlink_session(struct hidp_session *session)
102469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
103af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	list_del(&session->list);
104469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	module_put(THIS_MODULE);
105af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg}
1060aaffa9b9699894aab3266195a529baf9f96ac29Johannes Berg
107af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Bergstatic void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
10857c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg{
109af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	bacpy(&ci->bdaddr, &session->bdaddr);
110469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
111b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg	ci->flags = session->flags;
112b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg	ci->state = session->state;
113b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg
114b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg	ci->vendor  = 0x0000;
115b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg	ci->product = 0x0000;
116b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg	ci->version = 0x0000;
117b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg	memset(ci->name, 0, 128);
118b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg
119b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg	if (session->input) {
120b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg		ci->vendor  = session->input->id.vendor;
121469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		ci->product = session->input->id.product;
122af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		ci->version = session->input->id.version;
123469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		if (session->input->name)
124469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			strncpy(ci->name, session->input->name, 128);
125469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		else
126469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			strncpy(ci->name, "HID Boot Device", 128);
12747846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg	}
128469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
12957c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg	if (session->hid) {
130707c1b4e68a2811ff2c9e75750a98a3310789a2dSujith		ci->vendor  = session->hid->vendor;
131469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		ci->product = session->hid->product;
132469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		ci->version = session->hid->version;
133469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		strncpy(ci->name, session->hid->name, 128);
134469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
135469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
136469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
137469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline int hidp_queue_event(struct hidp_session *session, struct input_dev *dev,
138b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg					unsigned int type, unsigned int code, int value)
139469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
140469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	unsigned char newleds;
141469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct sk_buff *skb;
142469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
143469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	BT_DBG("session %p type %d code %d value %d", session, type, code, value);
144469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
145469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (type != EV_LED)
146469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		return -1;
147469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
148469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	newleds = (!!test_bit(LED_KANA,    dev->led) << 3) |
149469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		  (!!test_bit(LED_COMPOSE, dev->led) << 3) |
150af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		  (!!test_bit(LED_SCROLLL, dev->led) << 2) |
151469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		  (!!test_bit(LED_CAPSL,   dev->led) << 1) |
152469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		  (!!test_bit(LED_NUML,    dev->led));
153469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
154469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (session->leds == newleds)
155469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		return 0;
156469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
157469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	session->leds = newleds;
158469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
159469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (!(skb = alloc_skb(3, GFP_ATOMIC))) {
160b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg		BT_ERR("Can't allocate memory for new frame");
161b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg		return -ENOMEM;
162469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
163469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
164469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	*skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
165469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	*skb_put(skb, 1) = 0x01;
166469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	*skb_put(skb, 1) = newleds;
167469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
168af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	skb_queue_tail(&session->intr_transmit, skb);
169af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
170af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	hidp_schedule(session);
171af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
172af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	return 0;
173469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
1742d0ddec5b2b859f06116f631fc0ffe94fbceb556Johannes Berg
1752d0ddec5b2b859f06116f631fc0ffe94fbceb556Johannes Bergstatic int hidp_hidinput_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
1762d0ddec5b2b859f06116f631fc0ffe94fbceb556Johannes Berg{
1772d0ddec5b2b859f06116f631fc0ffe94fbceb556Johannes Berg	struct hid_device *hid = dev->private;
1782d0ddec5b2b859f06116f631fc0ffe94fbceb556Johannes Berg	struct hidp_session *session = hid->driver_data;
1792d0ddec5b2b859f06116f631fc0ffe94fbceb556Johannes Berg
1808fc214ba958648ab111a173f2db7b0e1dfed5b11Johannes Berg	return hidp_queue_event(session, dev, type, code, value);
1818fc214ba958648ab111a173f2db7b0e1dfed5b11Johannes Berg}
1822d0ddec5b2b859f06116f631fc0ffe94fbceb556Johannes Berg
183469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
184b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg{
185469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct hidp_session *session = dev->private;
186469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
187af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	return hidp_queue_event(session, dev, type, code, value);
188af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg}
189469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
190f446d10f214091408b7300f15c9adf60569edf28Johannes Bergstatic void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
191f446d10f214091408b7300f15c9adf60569edf28Johannes Berg{
192f446d10f214091408b7300f15c9adf60569edf28Johannes Berg	struct input_dev *dev = session->input;
193af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	unsigned char *keys = session->keys;
194469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	unsigned char *udata = skb->data + 1;
195469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	signed char *sdata = skb->data + 1;
196af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	int i, size = skb->len - 1;
197af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
198469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	switch (skb->data[0]) {
1990c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg	case 0x01:	/* Keyboard report */
2000c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg		for (i = 0; i < 8; i++)
201b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg			input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
202b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg
203b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg		/* If all the key codes have been set to 0x01, it means
2040c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg		 * too many keys were pressed at the same time. */
20557c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg		if (!memcmp(udata + 2, hidp_mkeyspat, 6))
20657c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg			break;
20757c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg
20857c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg		for (i = 2; i < 8; i++) {
2090c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg			if (keys[i] > 3 && memscan(udata + 2, keys[i], 6) == udata + 8) {
210b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg				if (hidp_keycode[keys[i]])
211b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg					input_report_key(dev, hidp_keycode[keys[i]], 0);
212b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg				else
213b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg					BT_ERR("Unknown key (scancode %#x) released.", keys[i]);
214b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg			}
215b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg
216b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg			if (udata[i] > 3 && memscan(keys + 2, udata[i], 6) == keys + 8) {
217b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg				if (hidp_keycode[udata[i]])
218b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg					input_report_key(dev, hidp_keycode[udata[i]], 1);
219b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg				else
220b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg					BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]);
221b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg			}
222b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg		}
223b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg
224b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg		memcpy(keys, udata, 8);
225b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg		break;
2260c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg
22757c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg	case 0x02:	/* Mouse report */
2280c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg		input_report_key(dev, BTN_LEFT,   sdata[0] & 0x01);
229b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg		input_report_key(dev, BTN_RIGHT,  sdata[0] & 0x02);
2300c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg		input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
2310c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg		input_report_key(dev, BTN_SIDE,   sdata[0] & 0x08);
232469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		input_report_key(dev, BTN_EXTRA,  sdata[0] & 0x10);
233469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
234469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		input_report_rel(dev, REL_X, sdata[1]);
235469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		input_report_rel(dev, REL_Y, sdata[2]);
236469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
237469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		if (size > 3)
238469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			input_report_rel(dev, REL_WHEEL, sdata[3]);
239469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		break;
240469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
241469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
242469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	input_sync(dev);
2430c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg}
244469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
245469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline int hidp_queue_report(struct hidp_session *session, unsigned char *data, int size)
246469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
247469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct sk_buff *skb;
248469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
249469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	BT_DBG("session %p hid %p data %p size %d", session, device, data, size);
250469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
251469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
252469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		BT_ERR("Can't allocate memory for new frame");
253469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		return -ENOMEM;
254469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
255469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
256469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	*skb_put(skb, 1) = 0xa2;
257469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (size > 0)
258469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		memcpy(skb_put(skb, size), data, size);
259469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
260469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	skb_queue_tail(&session->intr_transmit, skb);
261469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
262469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hidp_schedule(session);
263469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
264469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	return 0;
265469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
266469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
267abe60632f311d515b082b450504ee24006023951Johannes Bergstatic int hidp_send_report(struct hidp_session *session, struct hid_report *report)
268469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
269469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	unsigned char buf[32];
270469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	int rsize;
271469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
272469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	rsize = ((report->size - 1) >> 3) + 1 + (report->id > 0);
273469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (rsize > sizeof(buf))
274469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		return -EIO;
275469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
27609a08cff3d13315c948e6aee5cf912f8f1db54e7Bruno Randolf	hid_output_report(report, buf);
277469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
278469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	return hidp_queue_report(session, buf, rsize);
27909a08cff3d13315c948e6aee5cf912f8f1db54e7Bruno Randolf}
28009a08cff3d13315c948e6aee5cf912f8f1db54e7Bruno Randolf
28109a08cff3d13315c948e6aee5cf912f8f1db54e7Bruno Randolfstatic void hidp_idle_timeout(unsigned long arg)
28209a08cff3d13315c948e6aee5cf912f8f1db54e7Bruno Randolf{
283469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct hidp_session *session = (struct hidp_session *) arg;
28409a08cff3d13315c948e6aee5cf912f8f1db54e7Bruno Randolf
28509a08cff3d13315c948e6aee5cf912f8f1db54e7Bruno Randolf	atomic_inc(&session->terminate);
28634e895075e21be3e21e71d6317440d1ee7969ad0Johannes Berg	hidp_schedule(session);
28734e895075e21be3e21e71d6317440d1ee7969ad0Johannes Berg}
28834e895075e21be3e21e71d6317440d1ee7969ad0Johannes Berg
28934e895075e21be3e21e71d6317440d1ee7969ad0Johannes Bergstatic inline void hidp_set_timer(struct hidp_session *session)
29034e895075e21be3e21e71d6317440d1ee7969ad0Johannes Berg{
29134e895075e21be3e21e71d6317440d1ee7969ad0Johannes Berg	if (session->idle_to > 0)
292469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		mod_timer(&session->timer, jiffies + HZ * session->idle_to);
293469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
294469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
295469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline void hidp_del_timer(struct hidp_session *session)
296469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
297469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (session->idle_to > 0)
298469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		del_timer(&session->timer);
2990c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg}
3000c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg
301469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic int __hidp_send_ctrl_message(struct hidp_session *session,
3020c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg			unsigned char hdr, unsigned char *data, int size)
303469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
304469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct sk_buff *skb;
305469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
306469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	BT_DBG("session %p data %p size %d", session, data, size);
307a98bfec2985221d8e0904a526cbe88590eaad2a6Benoit Papillault
308469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) {
309469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		BT_ERR("Can't allocate memory for new frame");
310469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		return -ENOMEM;
3110c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg	}
312469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
313469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	*skb_put(skb, 1) = hdr;
314469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (data && size > 0)
3150c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg		memcpy(skb_put(skb, size), data, size);
316469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
317469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	skb_queue_tail(&session->ctrl_transmit, skb);
318469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
319469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	return 0;
320469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
321469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
322469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline int hidp_send_ctrl_message(struct hidp_session *session,
323469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			unsigned char hdr, unsigned char *data, int size)
32434e8f08231388f9e16c6f1e2461f53afaf7f1e5eAlina Friedrichsen{
3250c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg	int err;
32634e8f08231388f9e16c6f1e2461f53afaf7f1e5eAlina Friedrichsen
32734e8f08231388f9e16c6f1e2461f53afaf7f1e5eAlina Friedrichsen	err = __hidp_send_ctrl_message(session, hdr, data, size);
328469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
329469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hidp_schedule(session);
330469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
331469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	return err;
332469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
333469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
334469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline void hidp_process_handshake(struct hidp_session *session, unsigned char param)
335469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
336469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	BT_DBG("session %p param 0x%02x", session, param);
337469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
338469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	switch (param) {
339469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	case HIDP_HSHK_SUCCESSFUL:
340469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		/* FIXME: Call into SET_ GET_ handlers here */
341469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		break;
342469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
343469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	case HIDP_HSHK_NOT_READY:
344469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	case HIDP_HSHK_ERR_INVALID_REPORT_ID:
345469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
346469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	case HIDP_HSHK_ERR_INVALID_PARAMETER:
347469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		/* FIXME: Call into SET_ GET_ handlers here */
348469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		break;
349469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
350469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	case HIDP_HSHK_ERR_UNKNOWN:
351469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		break;
3522448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg
3532448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg	case HIDP_HSHK_ERR_FATAL:
3542448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg		/* Device requests a reboot, as this is the only way this error
3552448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg		 * can be recovered. */
3562448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg		__hidp_send_ctrl_message(session,
3572448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg			HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
3582448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg		break;
359469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
360469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	default:
361469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		__hidp_send_ctrl_message(session,
362469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
363469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		break;
364469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
365469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
366469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
367469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline void hidp_process_hid_control(struct hidp_session *session, unsigned char param)
368469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
369469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	BT_DBG("session %p param 0x%02x", session, param);
3704a332a385a86e31bfe181d969a8cb5579798fe03Alina Friedrichsen
3714a332a385a86e31bfe181d969a8cb5579798fe03Alina Friedrichsen	switch (param) {
3724a332a385a86e31bfe181d969a8cb5579798fe03Alina Friedrichsen	case HIDP_CTRL_NOP:
3734a332a385a86e31bfe181d969a8cb5579798fe03Alina Friedrichsen		break;
374469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
375469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	case HIDP_CTRL_VIRTUAL_CABLE_UNPLUG:
376469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		/* Flush the transmit queues */
377469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		skb_queue_purge(&session->ctrl_transmit);
37847846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg		skb_queue_purge(&session->intr_transmit);
379469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
380469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		/* Kill session thread */
38109a08cff3d13315c948e6aee5cf912f8f1db54e7Bruno Randolf		atomic_inc(&session->terminate);
38234e895075e21be3e21e71d6317440d1ee7969ad0Johannes Berg		break;
38334e895075e21be3e21e71d6317440d1ee7969ad0Johannes Berg
384469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	case HIDP_CTRL_HARD_RESET:
385469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	case HIDP_CTRL_SOFT_RESET:
386469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	case HIDP_CTRL_SUSPEND:
387469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	case HIDP_CTRL_EXIT_SUSPEND:
388469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		/* FIXME: We have to parse these and return no error */
389469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		break;
390469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
391469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	default:
392469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		__hidp_send_ctrl_message(session,
393469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
394469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		break;
395469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
39634e895075e21be3e21e71d6317440d1ee7969ad0Johannes Berg}
39734e895075e21be3e21e71d6317440d1ee7969ad0Johannes Berg
398469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline void hidp_process_data(struct hidp_session *session, struct sk_buff *skb, unsigned char param)
3992e10d330f8d5f039fa1e00baf59435ab0f11c722Felix Fietkau{
400469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
401469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
402469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	switch (param) {
403469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	case HIDP_DATA_RTYPE_INPUT:
404af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		hidp_set_timer(session);
405af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
406af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		if (session->input)
407af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg			hidp_input_report(session, skb);
408469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
409af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		if (session->hid)
410af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg			hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 0);
41147846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg
412469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		break;
413469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
414469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	case HIDP_DATA_RTYPE_OTHER:
4152e10d330f8d5f039fa1e00baf59435ab0f11c722Felix Fietkau	case HIDP_DATA_RTYPE_OUPUT:
4162e10d330f8d5f039fa1e00baf59435ab0f11c722Felix Fietkau	case HIDP_DATA_RTYPE_FEATURE:
4172e10d330f8d5f039fa1e00baf59435ab0f11c722Felix Fietkau		break;
418469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
419469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	default:
420469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		__hidp_send_ctrl_message(session,
421469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
422469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
42347846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg}
424469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
425469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline void hidp_recv_ctrl_frame(struct hidp_session *session, struct sk_buff *skb)
42634e895075e21be3e21e71d6317440d1ee7969ad0Johannes Berg{
427469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	unsigned char hdr, type, param;
428469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
429469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
430469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
431469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hdr = skb->data[0];
432469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	skb_pull(skb, 1);
433469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
434469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	type = hdr & HIDP_HEADER_TRANS_MASK;
435469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	param = hdr & HIDP_HEADER_PARAM_MASK;
436469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
437469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	switch (type) {
43834e895075e21be3e21e71d6317440d1ee7969ad0Johannes Berg	case HIDP_TRANS_HANDSHAKE:
439469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		hidp_process_handshake(session, param);
44034e895075e21be3e21e71d6317440d1ee7969ad0Johannes Berg		break;
441469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
442469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	case HIDP_TRANS_HID_CONTROL:
443469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		hidp_process_hid_control(session, param);
444469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		break;
445469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
446469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	case HIDP_TRANS_DATA:
447469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		hidp_process_data(session, skb, param);
448469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		break;
449469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
450469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	default:
451469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		__hidp_send_ctrl_message(session,
452469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
453469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		break;
454469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
455469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
456469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	kfree_skb(skb);
457469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
458469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
459469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline void hidp_recv_intr_frame(struct hidp_session *session, struct sk_buff *skb)
460469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
461469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	unsigned char hdr;
462469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
463469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
464469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
465469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hdr = skb->data[0];
466ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault	skb_pull(skb, 1);
467ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault
468ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault	if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
469469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		hidp_set_timer(session);
470469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
471469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		if (session->input)
472469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			hidp_input_report(session, skb);
473469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
474af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		if (session->hid) {
475af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg			hid_input_report(session->hid, HID_INPUT_REPORT, skb->data, skb->len, 1);
476469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			BT_DBG("report len %d", skb->len);
477469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		}
478af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	} else {
479450aae3d7b60a970f266349a837dfb30a539198bSujith		BT_DBG("Unsupported protocol header 0x%02x", hdr);
480450aae3d7b60a970f266349a837dfb30a539198bSujith	}
481450aae3d7b60a970f266349a837dfb30a539198bSujith
482450aae3d7b60a970f266349a837dfb30a539198bSujith	kfree_skb(skb);
483469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
484469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
485469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
486af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg{
487469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct kvec iv = { data, len };
488469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct msghdr msg;
489469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
49047846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg	BT_DBG("sock %p data %p len %d", sock, data, len);
491469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
492be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg	if (!len)
493be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg		return 0;
494be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg
495469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	memset(&msg, 0, sizeof(msg));
496469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
497af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	return kernel_sendmsg(sock, &msg, &iv, 1, len);
498469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
499469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
500469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic void hidp_process_transmit(struct hidp_session *session)
501469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
502469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct sk_buff *skb;
503469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
504469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	BT_DBG("session %p", session);
505469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
506af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	while ((skb = skb_dequeue(&session->ctrl_transmit))) {
507469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) {
508469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			skb_queue_head(&session->ctrl_transmit, skb);
509469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			break;
510469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		}
511469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
512469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		hidp_set_timer(session);
513469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		kfree_skb(skb);
51447846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg	}
515469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
516469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	while ((skb = skb_dequeue(&session->intr_transmit))) {
517469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) {
518469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			skb_queue_head(&session->intr_transmit, skb);
519469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			break;
52047846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg		}
521469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
522af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		hidp_set_timer(session);
523469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		kfree_skb(skb);
524469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
525469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
526fffd0934b9390f34bec45762192b7edd3b12b4b5Johannes Berg
527469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic int hidp_session(void *arg)
528469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
529469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct hidp_session *session = arg;
530469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct sock *ctrl_sk = session->ctrl_sock->sk;
53157c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg	struct sock *intr_sk = session->intr_sock->sk;
532b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg	struct sk_buff *skb;
533b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg	int vendor = 0x0000, product = 0x0000;
534469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	wait_queue_t ctrl_wait, intr_wait;
535469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
536ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault	BT_DBG("session %p", session);
537ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault
538ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault	if (session->input) {
539ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault		vendor  = session->input->id.vendor;
540af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		product = session->input->id.product;
541469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
542469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
543469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (session->hid) {
5440c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg		vendor  = session->hid->vendor;
545af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		product = session->hid->product;
546469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
547469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
548e0d61887c2ee19bb63f6a8c0e2c149184e879501Johannes Berg	daemonize("khidpd_%04x%04x", vendor, product);
549469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	set_user_nice(current, -15);
550469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	current->flags |= PF_NOFREEZE;
551469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
552469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	init_waitqueue_entry(&ctrl_wait, current);
55347846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg	init_waitqueue_entry(&intr_wait, current);
554469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	add_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait);
555469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	add_wait_queue(intr_sk->sk_sleep, &intr_wait);
556469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	while (!atomic_read(&session->terminate)) {
557af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		set_current_state(TASK_INTERRUPTIBLE);
558469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
559e0d61887c2ee19bb63f6a8c0e2c149184e879501Johannes Berg		if (ctrl_sk->sk_state != BT_CONNECTED || intr_sk->sk_state != BT_CONNECTED)
560fffd0934b9390f34bec45762192b7edd3b12b4b5Johannes Berg			break;
561e0d61887c2ee19bb63f6a8c0e2c149184e879501Johannes Berg
562af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
563af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg			skb_orphan(skb);
564af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg			hidp_recv_ctrl_frame(session, skb);
565af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		}
566af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
567469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
5680c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg			skb_orphan(skb);
5690c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg			hidp_recv_intr_frame(session, skb);
5700c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg		}
5710c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg
5720c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg		hidp_process_transmit(session);
5730c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg
5740c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg		schedule();
575469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
5760c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg	set_current_state(TASK_RUNNING);
577469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	remove_wait_queue(intr_sk->sk_sleep, &intr_wait);
578469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	remove_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait);
5790c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg
580469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	down_write(&hidp_session_sem);
581469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
582469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hidp_del_timer(session);
583469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
5840c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg	fput(session->intr_sock->file);
585469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
586af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	wait_event_timeout(*(ctrl_sk->sk_sleep),
587469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		(ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500));
588af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
589d419b9f0fa69e79ccba3e5e79a58a52ae0c2ed6aReinette Chatre	fput(session->ctrl_sock->file);
590469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
591469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	__hidp_unlink_session(session);
592469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
593469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (session->input) {
594469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		input_unregister_device(session->input);
595469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		session->input = NULL;
596ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault	}
597469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
598469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (session->hid) {
59947846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg		if (session->hid->claimed & HID_CLAIMED_INPUT)
600469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			hidinput_disconnect(session->hid);
601be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg		hid_free_device(session->hid);
602be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg	}
603be4a4b6a5d2f76393f545a2545fbaa1b65577e13Johannes Berg
604ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault	up_write(&hidp_session_sem);
605469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
606469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	kfree(session);
607469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	return 0;
608469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
609af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
610af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Bergstatic struct device *hidp_get_device(struct hidp_session *session)
611af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg{
612af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
613469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
61447846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg	struct hci_dev *hdev;
615469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct hci_conn *conn;
616469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
617469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hdev = hci_get_route(dst, src);
618469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (!hdev)
619469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		return NULL;
620469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
621469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst);
622af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
623af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	hci_dev_put(hdev);
624469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
625469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	return conn ? &conn->dev : NULL;
626469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
627469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
628469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req)
629469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
630469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct input_dev *input = session->input;
631469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	int i;
632469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
633469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	input->private = session;
634469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
635469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	input->name = "Bluetooth HID Boot Protocol Device";
636469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
637469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	input->id.bustype = BUS_BLUETOOTH;
638469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	input->id.vendor  = req->vendor;
639af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	input->id.product = req->product;
640469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	input->id.version = req->version;
641469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
6422448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg	if (req->subclass & 0x40) {
643469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		set_bit(EV_KEY, input->evbit);
644469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		set_bit(EV_LED, input->evbit);
645469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		set_bit(EV_REP, input->evbit);
646469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
64747846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg		set_bit(LED_NUML,    input->ledbit);
648469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		set_bit(LED_CAPSL,   input->ledbit);
649469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		set_bit(LED_SCROLLL, input->ledbit);
650469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		set_bit(LED_COMPOSE, input->ledbit);
651469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		set_bit(LED_KANA,    input->ledbit);
652469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
653469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		for (i = 0; i < sizeof(hidp_keycode); i++)
654469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			set_bit(hidp_keycode[i], input->keybit);
655469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		clear_bit(0, input->keybit);
656469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
657469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
658469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (req->subclass & 0x80) {
659469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		input->evbit[0] = BIT(EV_KEY) | BIT(EV_REL);
660469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		input->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE);
661469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		input->relbit[0] = BIT(REL_X) | BIT(REL_Y);
662469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		input->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA);
663469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		input->relbit[0] |= BIT(REL_WHEEL);
664469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
66547846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg
666469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	input->cdev.dev = hidp_get_device(session);
667469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
668469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	input->event = hidp_input_event;
669469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
670469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	input_register_device(input);
6710da780c269957783d341fc3559e6b4c9912af7b4Benoit Papillault}
672469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
673469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic int hidp_open(struct hid_device *hid)
674469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
675469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	return 0;
676469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
677af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
678469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic void hidp_close(struct hid_device *hid)
679469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
680469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
681469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
682469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic const struct {
683469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	__u16 idVendor;
684469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	__u16 idProduct;
68547846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg	unsigned quirks;
686469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} hidp_blacklist[] = {
68762ae67be31c2346b6d74653a148ddbd1b9a94424Johannes Berg	/* Apple wireless Mighty Mouse */
68862ae67be31c2346b6d74653a148ddbd1b9a94424Johannes Berg	{ 0x05ac, 0x030c, HID_QUIRK_MIGHTYMOUSE | HID_QUIRK_INVERT_HWHEEL },
689469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
690469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	{ }	/* Terminating entry */
691469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg};
692469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
693469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic void hidp_setup_quirks(struct hid_device *hid)
694469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
695469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	unsigned int n;
696469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
697469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	for (n = 0; hidp_blacklist[n].idVendor; n++)
698469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		if (hidp_blacklist[n].idVendor == le16_to_cpu(hid->vendor) &&
69947846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg				hidp_blacklist[n].idProduct == le16_to_cpu(hid->product))
700469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			hid->quirks = hidp_blacklist[n].quirks;
701469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
702469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
703469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline void hidp_setup_hid(struct hidp_session *session, struct hidp_connadd_req *req)
704469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
705469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct hid_device *hid = session->hid;
706469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct hid_report *report;
707469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	bdaddr_t src, dst;
708469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
709469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	baswap(&src, &bt_sk(session->ctrl_sock->sk)->src);
710469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	baswap(&dst, &bt_sk(session->ctrl_sock->sk)->dst);
711469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
712469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hid->driver_data = session;
713469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
714469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hid->country = req->country;
715469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
716469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hid->bus     = BUS_BLUETOOTH;
717469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hid->vendor  = req->vendor;
718469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hid->product = req->product;
719469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hid->version = req->version;
720469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
721469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	strncpy(hid->name, req->name, 128);
722469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	strncpy(hid->phys, batostr(&src), 64);
723469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	strncpy(hid->uniq, batostr(&dst), 64);
724469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
725469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hid->dev = hidp_get_device(session);
726469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
727469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hid->hid_open  = hidp_open;
728469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hid->hid_close = hidp_close;
729469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
730469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hid->hidinput_input_event = hidp_hidinput_event;
731469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
732469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hidp_setup_quirks(hid);
733469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
734469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
735469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		hidp_send_report(session, report);
736469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
737f1d58c2521eb160178b2151d6326d8dc5d7c8560Johannes Berg	list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
738469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		hidp_send_report(session, report);
739469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
740469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (hidinput_connect(hid) == 0) {
741469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		hid->claimed |= HID_CLAIMED_INPUT;
742469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		hid_ff_init(hid);
743469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
744469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}
745469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
746469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergint hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
747469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
748469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct hidp_session *session, *s;
749469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	int err;
750469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
751469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	BT_DBG("");
752469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
753469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) ||
754469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst))
755469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		return -ENOTUNIQ;
756469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
757469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	session = kzalloc(sizeof(struct hidp_session), GFP_KERNEL);
758469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (!session)
759469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		return -ENOMEM;
760469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
761469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	BT_DBG("rd_data %p rd_size %d", req->rd_data, req->rd_size);
762469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
763469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (req->rd_size > 0) {
764469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		unsigned char *buf = kmalloc(req->rd_size, GFP_KERNEL);
765469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
766469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		if (!buf) {
767469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			kfree(session);
768469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			return -ENOMEM;
7695bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg		}
7705bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg
7715bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg		if (copy_from_user(buf, req->rd_data, req->rd_size)) {
7729607e6b66a0d25ca63b70d54a4283fa13d8f7c9dJohannes Berg			kfree(buf);
773469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			kfree(session);
774469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			return -EFAULT;
775fbe9c429f195111bbf7f1630efa19aee295fd8e7Helmut Schaa		}
776469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
777469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		session->hid = hid_parse_report(buf, req->rd_size);
778469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
779469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		kfree(buf);
780469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
781469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		if (!session->hid) {
782469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			kfree(session);
783469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			return -EINVAL;
784469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		}
785469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
786469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
787469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (!session->hid) {
788469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		session->input = input_allocate_device();
789469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		if (!session->input) {
790469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			kfree(session);
791469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			return -ENOMEM;
792469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		}
793469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
794469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
795469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	down_write(&hidp_session_sem);
796469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
797469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst);
798469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (s && s->state == BT_CONNECTED) {
799469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		err = -EEXIST;
800469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		goto failed;
8013a4d4aa2d38e5305b5e93dffdc9dd2f975129328Johannes Berg	}
8023a4d4aa2d38e5305b5e93dffdc9dd2f975129328Johannes Berg
8033a4d4aa2d38e5305b5e93dffdc9dd2f975129328Johannes Berg	bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst);
8043a4d4aa2d38e5305b5e93dffdc9dd2f975129328Johannes Berg
8053a4d4aa2d38e5305b5e93dffdc9dd2f975129328Johannes Berg	session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->omtu, l2cap_pi(ctrl_sock->sk)->imtu);
8063a4d4aa2d38e5305b5e93dffdc9dd2f975129328Johannes Berg	session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->omtu, l2cap_pi(intr_sock->sk)->imtu);
8073a4d4aa2d38e5305b5e93dffdc9dd2f975129328Johannes Berg
8083a4d4aa2d38e5305b5e93dffdc9dd2f975129328Johannes Berg	BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu);
8093a4d4aa2d38e5305b5e93dffdc9dd2f975129328Johannes Berg
810469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	session->ctrl_sock = ctrl_sock;
811469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	session->intr_sock = intr_sock;
812469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	session->state     = BT_CONNECTED;
813469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
814469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	init_timer(&session->timer);
815469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
816469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	session->timer.function = hidp_idle_timeout;
8175bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg	session->timer.data     = (unsigned long) session;
8185bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg
8195bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg	skb_queue_head_init(&session->ctrl_transmit);
8205bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg	skb_queue_head_init(&session->intr_transmit);
8215bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg
8223a4d4aa2d38e5305b5e93dffdc9dd2f975129328Johannes Berg	session->flags   = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
823469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	session->idle_to = req->idle_to;
824469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
8255bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg	if (session->input)
8265bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg		hidp_setup_input(session, req);
8275bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg
8285bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg	if (session->hid)
8295bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg		hidp_setup_hid(session, req);
8305bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg
8315bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg	__hidp_link_session(session);
8325bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg
8335bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg	hidp_set_timer(session);
8345bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg
8355bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg	err = kernel_thread(hidp_session, session, CLONE_KERNEL);
8365bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg	if (err < 0)
8375bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg		goto unlink;
8385bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg
8395bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg	if (session->input) {
8405bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg		hidp_send_ctrl_message(session,
8415bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg			HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0);
8425bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg		session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE);
8435bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg
8445bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg		session->leds = 0xff;
8455bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg		hidp_input_event(session->input, EV_LED, 0, 0);
846469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	}
847469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
848469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	up_write(&hidp_session_sem);
849469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	return 0;
850469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
851469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergunlink:
852469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	hidp_del_timer(session);
853469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
854469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	__hidp_unlink_session(session);
855469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
856469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (session->input) {
857469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		input_unregister_device(session->input);
858469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		session->input = NULL; /* don't try to free it here */
859af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	}
860469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
86129b4a4f7c7b588b5568edd0da42f38623b81fc66Johannes Bergfailed:
86229b4a4f7c7b588b5568edd0da42f38623b81fc66Johannes Berg	up_write(&hidp_session_sem);
8639607e6b66a0d25ca63b70d54a4283fa13d8f7c9dJohannes Berg
8640e41f715c04f85a40ae6531d660be2241717be1cJohannes Berg	if (session->hid)
865af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		hid_free_device(session->hid);
866af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
8670e41f715c04f85a40ae6531d660be2241717be1cJohannes Berg	kfree(session->input);
8680e41f715c04f85a40ae6531d660be2241717be1cJohannes Berg	kfree(session);
869af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	return err;
8703a4d4aa2d38e5305b5e93dffdc9dd2f975129328Johannes Berg}
871469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
87229b4a4f7c7b588b5568edd0da42f38623b81fc66Johannes Bergint hidp_del_connection(struct hidp_conndel_req *req)
873469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{
874469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	struct hidp_session *session;
875469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	int err = 0;
876f1d58c2521eb160178b2151d6326d8dc5d7c8560Johannes Berg
877469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	BT_DBG("");
878469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
879469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	down_read(&hidp_session_sem);
880469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
881469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	session = __hidp_get_session(&req->bdaddr);
882469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	if (session) {
883469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) {
884469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			hidp_send_ctrl_message(session,
885469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg				HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0);
886469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		} else {
887469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			/* Flush the transmit queues */
888469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			skb_queue_purge(&session->ctrl_transmit);
889469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			skb_queue_purge(&session->intr_transmit);
890469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
891469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			/* Kill session thread */
892469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			atomic_inc(&session->terminate);
893469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg			hidp_schedule(session);
89442935ecaf4e784d0815afa9a7e5fe7e141157ca3Luis R. Rodriguez		}
895469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	} else
896469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg		err = -ENOENT;
897469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg
898469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	up_read(&hidp_session_sem);
899469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg	return err;
900af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg}
901af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
902af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Bergint hidp_get_connlist(struct hidp_connlist_req *req)
903af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg{
904af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	struct list_head *p;
905af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	int err = 0, n = 0;
906af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
907af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	BT_DBG("");
908af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
909af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	down_read(&hidp_session_sem);
910af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
911af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	list_for_each(p, &hidp_session_list) {
912fffd0934b9390f34bec45762192b7edd3b12b4b5Johannes Berg		struct hidp_session *session;
913fffd0934b9390f34bec45762192b7edd3b12b4b5Johannes Berg		struct hidp_conninfo ci;
91457c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg
91557c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg		session = list_entry(p, struct hidp_session, list);
916af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
917af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		__hidp_copy_session(session, &ci);
918af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
919adfba3c7c026a6a5560d2a43fefc9b198cb74462Johannes Berg		if (copy_to_user(req->ci, &ci, sizeof(ci))) {
920adfba3c7c026a6a5560d2a43fefc9b198cb74462Johannes Berg			err = -EFAULT;
921adfba3c7c026a6a5560d2a43fefc9b198cb74462Johannes Berg			break;
9220aaffa9b9699894aab3266195a529baf9f96ac29Johannes Berg		}
9230aaffa9b9699894aab3266195a529baf9f96ac29Johannes Berg
924adfba3c7c026a6a5560d2a43fefc9b198cb74462Johannes Berg		if (++n >= req->cnum)
925adfba3c7c026a6a5560d2a43fefc9b198cb74462Johannes Berg			break;
926af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
927af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		req->ci++;
928af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	}
929af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	req->cnum = n;
930af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
931af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	up_read(&hidp_session_sem);
932af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	return err;
933af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg}
934af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
935af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Bergint hidp_get_conninfo(struct hidp_conninfo *ci)
936af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg{
937af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	struct hidp_session *session;
938af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	int err = 0;
939af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
940af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	down_read(&hidp_session_sem);
941af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
942af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	session = __hidp_get_session(&ci->bdaddr);
943af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	if (session)
944af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg		__hidp_copy_session(session, ci);
945af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	else
9460e41f715c04f85a40ae6531d660be2241717be1cJohannes Berg		err = -ENOENT;
9470e41f715c04f85a40ae6531d660be2241717be1cJohannes Berg
9480e41f715c04f85a40ae6531d660be2241717be1cJohannes Berg	up_read(&hidp_session_sem);
9490e41f715c04f85a40ae6531d660be2241717be1cJohannes Berg	return err;
9500e41f715c04f85a40ae6531d660be2241717be1cJohannes Berg}
9510e41f715c04f85a40ae6531d660be2241717be1cJohannes Berg
9520e41f715c04f85a40ae6531d660be2241717be1cJohannes Bergstatic int __init hidp_init(void)
9530e41f715c04f85a40ae6531d660be2241717be1cJohannes Berg{
9540e41f715c04f85a40ae6531d660be2241717be1cJohannes Berg	l2cap_load();
9550e41f715c04f85a40ae6531d660be2241717be1cJohannes Berg
9560e41f715c04f85a40ae6531d660be2241717be1cJohannes Berg	BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
9575cff20e6c5a6591a79d3b027af222870f52bb550Johannes Berg
9585cff20e6c5a6591a79d3b027af222870f52bb550Johannes Berg	return hidp_init_sockets();
959af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg}
96042935ecaf4e784d0815afa9a7e5fe7e141157ca3Luis R. Rodriguez
961af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Bergstatic void __exit hidp_exit(void)
962af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg{
963af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg	hidp_cleanup_sockets();
964af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg}
965af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
966af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Bergmodule_init(hidp_init);
967af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Bergmodule_exit(hidp_exit);
968af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg
969af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes BergMODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
970af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes BergMODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
971af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes BergMODULE_VERSION(VERSION);
972af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes BergMODULE_LICENSE("GPL");
973af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes BergMODULE_ALIAS("bt-proto-6");
974af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg