xref: /OK3568_Linux_fs/kernel/net/bluetooth/hidp/core.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun    HIDP implementation for Linux Bluetooth stack (BlueZ).
3*4882a593Smuzhiyun    Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
4*4882a593Smuzhiyun    Copyright (C) 2013 David Herrmann <dh.herrmann@gmail.com>
5*4882a593Smuzhiyun 
6*4882a593Smuzhiyun    This program is free software; you can redistribute it and/or modify
7*4882a593Smuzhiyun    it under the terms of the GNU General Public License version 2 as
8*4882a593Smuzhiyun    published by the Free Software Foundation;
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
11*4882a593Smuzhiyun    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*4882a593Smuzhiyun    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
13*4882a593Smuzhiyun    IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
14*4882a593Smuzhiyun    CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
15*4882a593Smuzhiyun    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16*4882a593Smuzhiyun    ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17*4882a593Smuzhiyun    OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun    ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
20*4882a593Smuzhiyun    COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
21*4882a593Smuzhiyun    SOFTWARE IS DISCLAIMED.
22*4882a593Smuzhiyun */
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #include <linux/kref.h>
25*4882a593Smuzhiyun #include <linux/module.h>
26*4882a593Smuzhiyun #include <linux/file.h>
27*4882a593Smuzhiyun #include <linux/kthread.h>
28*4882a593Smuzhiyun #include <linux/hidraw.h>
29*4882a593Smuzhiyun 
30*4882a593Smuzhiyun #include <net/bluetooth/bluetooth.h>
31*4882a593Smuzhiyun #include <net/bluetooth/hci_core.h>
32*4882a593Smuzhiyun #include <net/bluetooth/l2cap.h>
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun #include "hidp.h"
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #define VERSION "1.2"
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun static DECLARE_RWSEM(hidp_session_sem);
39*4882a593Smuzhiyun static DECLARE_WAIT_QUEUE_HEAD(hidp_session_wq);
40*4882a593Smuzhiyun static LIST_HEAD(hidp_session_list);
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun static unsigned char hidp_keycode[256] = {
43*4882a593Smuzhiyun 	  0,   0,   0,   0,  30,  48,  46,  32,  18,  33,  34,  35,  23,  36,
44*4882a593Smuzhiyun 	 37,  38,  50,  49,  24,  25,  16,  19,  31,  20,  22,  47,  17,  45,
45*4882a593Smuzhiyun 	 21,  44,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  28,   1,
46*4882a593Smuzhiyun 	 14,  15,  57,  12,  13,  26,  27,  43,  43,  39,  40,  41,  51,  52,
47*4882a593Smuzhiyun 	 53,  58,  59,  60,  61,  62,  63,  64,  65,  66,  67,  68,  87,  88,
48*4882a593Smuzhiyun 	 99,  70, 119, 110, 102, 104, 111, 107, 109, 106, 105, 108, 103,  69,
49*4882a593Smuzhiyun 	 98,  55,  74,  78,  96,  79,  80,  81,  75,  76,  77,  71,  72,  73,
50*4882a593Smuzhiyun 	 82,  83,  86, 127, 116, 117, 183, 184, 185, 186, 187, 188, 189, 190,
51*4882a593Smuzhiyun 	191, 192, 193, 194, 134, 138, 130, 132, 128, 129, 131, 137, 133, 135,
52*4882a593Smuzhiyun 	136, 113, 115, 114,   0,   0,   0, 121,   0,  89,  93, 124,  92,  94,
53*4882a593Smuzhiyun 	 95,   0,   0,   0, 122, 123,  90,  91,  85,   0,   0,   0,   0,   0,
54*4882a593Smuzhiyun 	  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
55*4882a593Smuzhiyun 	  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
56*4882a593Smuzhiyun 	  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
57*4882a593Smuzhiyun 	  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
58*4882a593Smuzhiyun 	  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
59*4882a593Smuzhiyun 	 29,  42,  56, 125,  97,  54, 100, 126, 164, 166, 165, 163, 161, 115,
60*4882a593Smuzhiyun 	114, 113, 150, 158, 159, 128, 136, 177, 178, 176, 142, 152, 173, 140
61*4882a593Smuzhiyun };
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun static int hidp_session_probe(struct l2cap_conn *conn,
66*4882a593Smuzhiyun 			      struct l2cap_user *user);
67*4882a593Smuzhiyun static void hidp_session_remove(struct l2cap_conn *conn,
68*4882a593Smuzhiyun 				struct l2cap_user *user);
69*4882a593Smuzhiyun static int hidp_session_thread(void *arg);
70*4882a593Smuzhiyun static void hidp_session_terminate(struct hidp_session *s);
71*4882a593Smuzhiyun 
hidp_copy_session(struct hidp_session * session,struct hidp_conninfo * ci)72*4882a593Smuzhiyun static void hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	u32 valid_flags = 0;
75*4882a593Smuzhiyun 	memset(ci, 0, sizeof(*ci));
76*4882a593Smuzhiyun 	bacpy(&ci->bdaddr, &session->bdaddr);
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun 	ci->flags = session->flags & valid_flags;
79*4882a593Smuzhiyun 	ci->state = BT_CONNECTED;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	if (session->input) {
82*4882a593Smuzhiyun 		ci->vendor  = session->input->id.vendor;
83*4882a593Smuzhiyun 		ci->product = session->input->id.product;
84*4882a593Smuzhiyun 		ci->version = session->input->id.version;
85*4882a593Smuzhiyun 		if (session->input->name)
86*4882a593Smuzhiyun 			strlcpy(ci->name, session->input->name, 128);
87*4882a593Smuzhiyun 		else
88*4882a593Smuzhiyun 			strlcpy(ci->name, "HID Boot Device", 128);
89*4882a593Smuzhiyun 	} else if (session->hid) {
90*4882a593Smuzhiyun 		ci->vendor  = session->hid->vendor;
91*4882a593Smuzhiyun 		ci->product = session->hid->product;
92*4882a593Smuzhiyun 		ci->version = session->hid->version;
93*4882a593Smuzhiyun 		strlcpy(ci->name, session->hid->name, 128);
94*4882a593Smuzhiyun 	}
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun /* assemble skb, queue message on @transmit and wake up the session thread */
hidp_send_message(struct hidp_session * session,struct socket * sock,struct sk_buff_head * transmit,unsigned char hdr,const unsigned char * data,int size)98*4882a593Smuzhiyun static int hidp_send_message(struct hidp_session *session, struct socket *sock,
99*4882a593Smuzhiyun 			     struct sk_buff_head *transmit, unsigned char hdr,
100*4882a593Smuzhiyun 			     const unsigned char *data, int size)
101*4882a593Smuzhiyun {
102*4882a593Smuzhiyun 	struct sk_buff *skb;
103*4882a593Smuzhiyun 	struct sock *sk = sock->sk;
104*4882a593Smuzhiyun 	int ret;
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun 	BT_DBG("session %p data %p size %d", session, data, size);
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	if (atomic_read(&session->terminate))
109*4882a593Smuzhiyun 		return -EIO;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun 	skb = alloc_skb(size + 1, GFP_ATOMIC);
112*4882a593Smuzhiyun 	if (!skb) {
113*4882a593Smuzhiyun 		BT_ERR("Can't allocate memory for new frame");
114*4882a593Smuzhiyun 		return -ENOMEM;
115*4882a593Smuzhiyun 	}
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	skb_put_u8(skb, hdr);
118*4882a593Smuzhiyun 	if (data && size > 0) {
119*4882a593Smuzhiyun 		skb_put_data(skb, data, size);
120*4882a593Smuzhiyun 		ret = size;
121*4882a593Smuzhiyun 	} else {
122*4882a593Smuzhiyun 		ret = 0;
123*4882a593Smuzhiyun 	}
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun 	skb_queue_tail(transmit, skb);
126*4882a593Smuzhiyun 	wake_up_interruptible(sk_sleep(sk));
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	return ret;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun 
hidp_send_ctrl_message(struct hidp_session * session,unsigned char hdr,const unsigned char * data,int size)131*4882a593Smuzhiyun static int hidp_send_ctrl_message(struct hidp_session *session,
132*4882a593Smuzhiyun 				  unsigned char hdr, const unsigned char *data,
133*4882a593Smuzhiyun 				  int size)
134*4882a593Smuzhiyun {
135*4882a593Smuzhiyun 	return hidp_send_message(session, session->ctrl_sock,
136*4882a593Smuzhiyun 				 &session->ctrl_transmit, hdr, data, size);
137*4882a593Smuzhiyun }
138*4882a593Smuzhiyun 
hidp_send_intr_message(struct hidp_session * session,unsigned char hdr,const unsigned char * data,int size)139*4882a593Smuzhiyun static int hidp_send_intr_message(struct hidp_session *session,
140*4882a593Smuzhiyun 				  unsigned char hdr, const unsigned char *data,
141*4882a593Smuzhiyun 				  int size)
142*4882a593Smuzhiyun {
143*4882a593Smuzhiyun 	return hidp_send_message(session, session->intr_sock,
144*4882a593Smuzhiyun 				 &session->intr_transmit, hdr, data, size);
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun 
hidp_input_event(struct input_dev * dev,unsigned int type,unsigned int code,int value)147*4882a593Smuzhiyun static int hidp_input_event(struct input_dev *dev, unsigned int type,
148*4882a593Smuzhiyun 			    unsigned int code, int value)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun 	struct hidp_session *session = input_get_drvdata(dev);
151*4882a593Smuzhiyun 	unsigned char newleds;
152*4882a593Smuzhiyun 	unsigned char hdr, data[2];
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	BT_DBG("session %p type %d code %d value %d",
155*4882a593Smuzhiyun 	       session, type, code, value);
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	if (type != EV_LED)
158*4882a593Smuzhiyun 		return -1;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	newleds = (!!test_bit(LED_KANA,    dev->led) << 3) |
161*4882a593Smuzhiyun 		  (!!test_bit(LED_COMPOSE, dev->led) << 3) |
162*4882a593Smuzhiyun 		  (!!test_bit(LED_SCROLLL, dev->led) << 2) |
163*4882a593Smuzhiyun 		  (!!test_bit(LED_CAPSL,   dev->led) << 1) |
164*4882a593Smuzhiyun 		  (!!test_bit(LED_NUML,    dev->led) << 0);
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun 	if (session->leds == newleds)
167*4882a593Smuzhiyun 		return 0;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun 	session->leds = newleds;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	hdr = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT;
172*4882a593Smuzhiyun 	data[0] = 0x01;
173*4882a593Smuzhiyun 	data[1] = newleds;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	return hidp_send_intr_message(session, hdr, data, 2);
176*4882a593Smuzhiyun }
177*4882a593Smuzhiyun 
hidp_input_report(struct hidp_session * session,struct sk_buff * skb)178*4882a593Smuzhiyun static void hidp_input_report(struct hidp_session *session, struct sk_buff *skb)
179*4882a593Smuzhiyun {
180*4882a593Smuzhiyun 	struct input_dev *dev = session->input;
181*4882a593Smuzhiyun 	unsigned char *keys = session->keys;
182*4882a593Smuzhiyun 	unsigned char *udata = skb->data + 1;
183*4882a593Smuzhiyun 	signed char *sdata = skb->data + 1;
184*4882a593Smuzhiyun 	int i, size = skb->len - 1;
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun 	switch (skb->data[0]) {
187*4882a593Smuzhiyun 	case 0x01:	/* Keyboard report */
188*4882a593Smuzhiyun 		for (i = 0; i < 8; i++)
189*4882a593Smuzhiyun 			input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun 		/* If all the key codes have been set to 0x01, it means
192*4882a593Smuzhiyun 		 * too many keys were pressed at the same time. */
193*4882a593Smuzhiyun 		if (!memcmp(udata + 2, hidp_mkeyspat, 6))
194*4882a593Smuzhiyun 			break;
195*4882a593Smuzhiyun 
196*4882a593Smuzhiyun 		for (i = 2; i < 8; i++) {
197*4882a593Smuzhiyun 			if (keys[i] > 3 && memscan(udata + 2, keys[i], 6) == udata + 8) {
198*4882a593Smuzhiyun 				if (hidp_keycode[keys[i]])
199*4882a593Smuzhiyun 					input_report_key(dev, hidp_keycode[keys[i]], 0);
200*4882a593Smuzhiyun 				else
201*4882a593Smuzhiyun 					BT_ERR("Unknown key (scancode %#x) released.", keys[i]);
202*4882a593Smuzhiyun 			}
203*4882a593Smuzhiyun 
204*4882a593Smuzhiyun 			if (udata[i] > 3 && memscan(keys + 2, udata[i], 6) == keys + 8) {
205*4882a593Smuzhiyun 				if (hidp_keycode[udata[i]])
206*4882a593Smuzhiyun 					input_report_key(dev, hidp_keycode[udata[i]], 1);
207*4882a593Smuzhiyun 				else
208*4882a593Smuzhiyun 					BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]);
209*4882a593Smuzhiyun 			}
210*4882a593Smuzhiyun 		}
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 		memcpy(keys, udata, 8);
213*4882a593Smuzhiyun 		break;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	case 0x02:	/* Mouse report */
216*4882a593Smuzhiyun 		input_report_key(dev, BTN_LEFT,   sdata[0] & 0x01);
217*4882a593Smuzhiyun 		input_report_key(dev, BTN_RIGHT,  sdata[0] & 0x02);
218*4882a593Smuzhiyun 		input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
219*4882a593Smuzhiyun 		input_report_key(dev, BTN_SIDE,   sdata[0] & 0x08);
220*4882a593Smuzhiyun 		input_report_key(dev, BTN_EXTRA,  sdata[0] & 0x10);
221*4882a593Smuzhiyun 
222*4882a593Smuzhiyun 		input_report_rel(dev, REL_X, sdata[1]);
223*4882a593Smuzhiyun 		input_report_rel(dev, REL_Y, sdata[2]);
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 		if (size > 3)
226*4882a593Smuzhiyun 			input_report_rel(dev, REL_WHEEL, sdata[3]);
227*4882a593Smuzhiyun 		break;
228*4882a593Smuzhiyun 	}
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	input_sync(dev);
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun 
hidp_get_raw_report(struct hid_device * hid,unsigned char report_number,unsigned char * data,size_t count,unsigned char report_type)233*4882a593Smuzhiyun static int hidp_get_raw_report(struct hid_device *hid,
234*4882a593Smuzhiyun 		unsigned char report_number,
235*4882a593Smuzhiyun 		unsigned char *data, size_t count,
236*4882a593Smuzhiyun 		unsigned char report_type)
237*4882a593Smuzhiyun {
238*4882a593Smuzhiyun 	struct hidp_session *session = hid->driver_data;
239*4882a593Smuzhiyun 	struct sk_buff *skb;
240*4882a593Smuzhiyun 	size_t len;
241*4882a593Smuzhiyun 	int numbered_reports = hid->report_enum[report_type].numbered;
242*4882a593Smuzhiyun 	int ret;
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun 	if (atomic_read(&session->terminate))
245*4882a593Smuzhiyun 		return -EIO;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	switch (report_type) {
248*4882a593Smuzhiyun 	case HID_FEATURE_REPORT:
249*4882a593Smuzhiyun 		report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_FEATURE;
250*4882a593Smuzhiyun 		break;
251*4882a593Smuzhiyun 	case HID_INPUT_REPORT:
252*4882a593Smuzhiyun 		report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_INPUT;
253*4882a593Smuzhiyun 		break;
254*4882a593Smuzhiyun 	case HID_OUTPUT_REPORT:
255*4882a593Smuzhiyun 		report_type = HIDP_TRANS_GET_REPORT | HIDP_DATA_RTYPE_OUPUT;
256*4882a593Smuzhiyun 		break;
257*4882a593Smuzhiyun 	default:
258*4882a593Smuzhiyun 		return -EINVAL;
259*4882a593Smuzhiyun 	}
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	if (mutex_lock_interruptible(&session->report_mutex))
262*4882a593Smuzhiyun 		return -ERESTARTSYS;
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	/* Set up our wait, and send the report request to the device. */
265*4882a593Smuzhiyun 	session->waiting_report_type = report_type & HIDP_DATA_RTYPE_MASK;
266*4882a593Smuzhiyun 	session->waiting_report_number = numbered_reports ? report_number : -1;
267*4882a593Smuzhiyun 	set_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
268*4882a593Smuzhiyun 	data[0] = report_number;
269*4882a593Smuzhiyun 	ret = hidp_send_ctrl_message(session, report_type, data, 1);
270*4882a593Smuzhiyun 	if (ret < 0)
271*4882a593Smuzhiyun 		goto err;
272*4882a593Smuzhiyun 
273*4882a593Smuzhiyun 	/* Wait for the return of the report. The returned report
274*4882a593Smuzhiyun 	   gets put in session->report_return.  */
275*4882a593Smuzhiyun 	while (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
276*4882a593Smuzhiyun 	       !atomic_read(&session->terminate)) {
277*4882a593Smuzhiyun 		int res;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun 		res = wait_event_interruptible_timeout(session->report_queue,
280*4882a593Smuzhiyun 			!test_bit(HIDP_WAITING_FOR_RETURN, &session->flags)
281*4882a593Smuzhiyun 				|| atomic_read(&session->terminate),
282*4882a593Smuzhiyun 			5*HZ);
283*4882a593Smuzhiyun 		if (res == 0) {
284*4882a593Smuzhiyun 			/* timeout */
285*4882a593Smuzhiyun 			ret = -EIO;
286*4882a593Smuzhiyun 			goto err;
287*4882a593Smuzhiyun 		}
288*4882a593Smuzhiyun 		if (res < 0) {
289*4882a593Smuzhiyun 			/* signal */
290*4882a593Smuzhiyun 			ret = -ERESTARTSYS;
291*4882a593Smuzhiyun 			goto err;
292*4882a593Smuzhiyun 		}
293*4882a593Smuzhiyun 	}
294*4882a593Smuzhiyun 
295*4882a593Smuzhiyun 	skb = session->report_return;
296*4882a593Smuzhiyun 	if (skb) {
297*4882a593Smuzhiyun 		len = skb->len < count ? skb->len : count;
298*4882a593Smuzhiyun 		memcpy(data, skb->data, len);
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 		kfree_skb(skb);
301*4882a593Smuzhiyun 		session->report_return = NULL;
302*4882a593Smuzhiyun 	} else {
303*4882a593Smuzhiyun 		/* Device returned a HANDSHAKE, indicating  protocol error. */
304*4882a593Smuzhiyun 		len = -EIO;
305*4882a593Smuzhiyun 	}
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun 	clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
308*4882a593Smuzhiyun 	mutex_unlock(&session->report_mutex);
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	return len;
311*4882a593Smuzhiyun 
312*4882a593Smuzhiyun err:
313*4882a593Smuzhiyun 	clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
314*4882a593Smuzhiyun 	mutex_unlock(&session->report_mutex);
315*4882a593Smuzhiyun 	return ret;
316*4882a593Smuzhiyun }
317*4882a593Smuzhiyun 
hidp_set_raw_report(struct hid_device * hid,unsigned char reportnum,unsigned char * data,size_t count,unsigned char report_type)318*4882a593Smuzhiyun static int hidp_set_raw_report(struct hid_device *hid, unsigned char reportnum,
319*4882a593Smuzhiyun 			       unsigned char *data, size_t count,
320*4882a593Smuzhiyun 			       unsigned char report_type)
321*4882a593Smuzhiyun {
322*4882a593Smuzhiyun 	struct hidp_session *session = hid->driver_data;
323*4882a593Smuzhiyun 	int ret;
324*4882a593Smuzhiyun 
325*4882a593Smuzhiyun 	switch (report_type) {
326*4882a593Smuzhiyun 	case HID_FEATURE_REPORT:
327*4882a593Smuzhiyun 		report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_FEATURE;
328*4882a593Smuzhiyun 		break;
329*4882a593Smuzhiyun 	case HID_INPUT_REPORT:
330*4882a593Smuzhiyun 		report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_INPUT;
331*4882a593Smuzhiyun 		break;
332*4882a593Smuzhiyun 	case HID_OUTPUT_REPORT:
333*4882a593Smuzhiyun 		report_type = HIDP_TRANS_SET_REPORT | HIDP_DATA_RTYPE_OUPUT;
334*4882a593Smuzhiyun 		break;
335*4882a593Smuzhiyun 	default:
336*4882a593Smuzhiyun 		return -EINVAL;
337*4882a593Smuzhiyun 	}
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	if (mutex_lock_interruptible(&session->report_mutex))
340*4882a593Smuzhiyun 		return -ERESTARTSYS;
341*4882a593Smuzhiyun 
342*4882a593Smuzhiyun 	/* Set up our wait, and send the report request to the device. */
343*4882a593Smuzhiyun 	data[0] = reportnum;
344*4882a593Smuzhiyun 	set_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
345*4882a593Smuzhiyun 	ret = hidp_send_ctrl_message(session, report_type, data, count);
346*4882a593Smuzhiyun 	if (ret < 0)
347*4882a593Smuzhiyun 		goto err;
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 	/* Wait for the ACK from the device. */
350*4882a593Smuzhiyun 	while (test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags) &&
351*4882a593Smuzhiyun 	       !atomic_read(&session->terminate)) {
352*4882a593Smuzhiyun 		int res;
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun 		res = wait_event_interruptible_timeout(session->report_queue,
355*4882a593Smuzhiyun 			!test_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags)
356*4882a593Smuzhiyun 				|| atomic_read(&session->terminate),
357*4882a593Smuzhiyun 			10*HZ);
358*4882a593Smuzhiyun 		if (res == 0) {
359*4882a593Smuzhiyun 			/* timeout */
360*4882a593Smuzhiyun 			ret = -EIO;
361*4882a593Smuzhiyun 			goto err;
362*4882a593Smuzhiyun 		}
363*4882a593Smuzhiyun 		if (res < 0) {
364*4882a593Smuzhiyun 			/* signal */
365*4882a593Smuzhiyun 			ret = -ERESTARTSYS;
366*4882a593Smuzhiyun 			goto err;
367*4882a593Smuzhiyun 		}
368*4882a593Smuzhiyun 	}
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	if (!session->output_report_success) {
371*4882a593Smuzhiyun 		ret = -EIO;
372*4882a593Smuzhiyun 		goto err;
373*4882a593Smuzhiyun 	}
374*4882a593Smuzhiyun 
375*4882a593Smuzhiyun 	ret = count;
376*4882a593Smuzhiyun 
377*4882a593Smuzhiyun err:
378*4882a593Smuzhiyun 	clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags);
379*4882a593Smuzhiyun 	mutex_unlock(&session->report_mutex);
380*4882a593Smuzhiyun 	return ret;
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun 
hidp_output_report(struct hid_device * hid,__u8 * data,size_t count)383*4882a593Smuzhiyun static int hidp_output_report(struct hid_device *hid, __u8 *data, size_t count)
384*4882a593Smuzhiyun {
385*4882a593Smuzhiyun 	struct hidp_session *session = hid->driver_data;
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	return hidp_send_intr_message(session,
388*4882a593Smuzhiyun 				      HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT,
389*4882a593Smuzhiyun 				      data, count);
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun 
hidp_raw_request(struct hid_device * hid,unsigned char reportnum,__u8 * buf,size_t len,unsigned char rtype,int reqtype)392*4882a593Smuzhiyun static int hidp_raw_request(struct hid_device *hid, unsigned char reportnum,
393*4882a593Smuzhiyun 			    __u8 *buf, size_t len, unsigned char rtype,
394*4882a593Smuzhiyun 			    int reqtype)
395*4882a593Smuzhiyun {
396*4882a593Smuzhiyun 	switch (reqtype) {
397*4882a593Smuzhiyun 	case HID_REQ_GET_REPORT:
398*4882a593Smuzhiyun 		return hidp_get_raw_report(hid, reportnum, buf, len, rtype);
399*4882a593Smuzhiyun 	case HID_REQ_SET_REPORT:
400*4882a593Smuzhiyun 		return hidp_set_raw_report(hid, reportnum, buf, len, rtype);
401*4882a593Smuzhiyun 	default:
402*4882a593Smuzhiyun 		return -EIO;
403*4882a593Smuzhiyun 	}
404*4882a593Smuzhiyun }
405*4882a593Smuzhiyun 
hidp_idle_timeout(struct timer_list * t)406*4882a593Smuzhiyun static void hidp_idle_timeout(struct timer_list *t)
407*4882a593Smuzhiyun {
408*4882a593Smuzhiyun 	struct hidp_session *session = from_timer(session, t, timer);
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	/* The HIDP user-space API only contains calls to add and remove
411*4882a593Smuzhiyun 	 * devices. There is no way to forward events of any kind. Therefore,
412*4882a593Smuzhiyun 	 * we have to forcefully disconnect a device on idle-timeouts. This is
413*4882a593Smuzhiyun 	 * unfortunate and weird API design, but it is spec-compliant and
414*4882a593Smuzhiyun 	 * required for backwards-compatibility. Hence, on idle-timeout, we
415*4882a593Smuzhiyun 	 * signal driver-detach events, so poll() will be woken up with an
416*4882a593Smuzhiyun 	 * error-condition on both sockets.
417*4882a593Smuzhiyun 	 */
418*4882a593Smuzhiyun 
419*4882a593Smuzhiyun 	session->intr_sock->sk->sk_err = EUNATCH;
420*4882a593Smuzhiyun 	session->ctrl_sock->sk->sk_err = EUNATCH;
421*4882a593Smuzhiyun 	wake_up_interruptible(sk_sleep(session->intr_sock->sk));
422*4882a593Smuzhiyun 	wake_up_interruptible(sk_sleep(session->ctrl_sock->sk));
423*4882a593Smuzhiyun 
424*4882a593Smuzhiyun 	hidp_session_terminate(session);
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun 
hidp_set_timer(struct hidp_session * session)427*4882a593Smuzhiyun static void hidp_set_timer(struct hidp_session *session)
428*4882a593Smuzhiyun {
429*4882a593Smuzhiyun 	if (session->idle_to > 0)
430*4882a593Smuzhiyun 		mod_timer(&session->timer, jiffies + HZ * session->idle_to);
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun 
hidp_del_timer(struct hidp_session * session)433*4882a593Smuzhiyun static void hidp_del_timer(struct hidp_session *session)
434*4882a593Smuzhiyun {
435*4882a593Smuzhiyun 	if (session->idle_to > 0)
436*4882a593Smuzhiyun 		del_timer(&session->timer);
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun 
hidp_process_report(struct hidp_session * session,int type,const u8 * data,unsigned int len,int intr)439*4882a593Smuzhiyun static void hidp_process_report(struct hidp_session *session, int type,
440*4882a593Smuzhiyun 				const u8 *data, unsigned int len, int intr)
441*4882a593Smuzhiyun {
442*4882a593Smuzhiyun 	if (len > HID_MAX_BUFFER_SIZE)
443*4882a593Smuzhiyun 		len = HID_MAX_BUFFER_SIZE;
444*4882a593Smuzhiyun 
445*4882a593Smuzhiyun 	memcpy(session->input_buf, data, len);
446*4882a593Smuzhiyun 	hid_input_report(session->hid, type, session->input_buf, len, intr);
447*4882a593Smuzhiyun }
448*4882a593Smuzhiyun 
hidp_process_handshake(struct hidp_session * session,unsigned char param)449*4882a593Smuzhiyun static void hidp_process_handshake(struct hidp_session *session,
450*4882a593Smuzhiyun 					unsigned char param)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun 	BT_DBG("session %p param 0x%02x", session, param);
453*4882a593Smuzhiyun 	session->output_report_success = 0; /* default condition */
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	switch (param) {
456*4882a593Smuzhiyun 	case HIDP_HSHK_SUCCESSFUL:
457*4882a593Smuzhiyun 		/* FIXME: Call into SET_ GET_ handlers here */
458*4882a593Smuzhiyun 		session->output_report_success = 1;
459*4882a593Smuzhiyun 		break;
460*4882a593Smuzhiyun 
461*4882a593Smuzhiyun 	case HIDP_HSHK_NOT_READY:
462*4882a593Smuzhiyun 	case HIDP_HSHK_ERR_INVALID_REPORT_ID:
463*4882a593Smuzhiyun 	case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST:
464*4882a593Smuzhiyun 	case HIDP_HSHK_ERR_INVALID_PARAMETER:
465*4882a593Smuzhiyun 		if (test_and_clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags))
466*4882a593Smuzhiyun 			wake_up_interruptible(&session->report_queue);
467*4882a593Smuzhiyun 
468*4882a593Smuzhiyun 		/* FIXME: Call into SET_ GET_ handlers here */
469*4882a593Smuzhiyun 		break;
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun 	case HIDP_HSHK_ERR_UNKNOWN:
472*4882a593Smuzhiyun 		break;
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 	case HIDP_HSHK_ERR_FATAL:
475*4882a593Smuzhiyun 		/* Device requests a reboot, as this is the only way this error
476*4882a593Smuzhiyun 		 * can be recovered. */
477*4882a593Smuzhiyun 		hidp_send_ctrl_message(session,
478*4882a593Smuzhiyun 			HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0);
479*4882a593Smuzhiyun 		break;
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	default:
482*4882a593Smuzhiyun 		hidp_send_ctrl_message(session,
483*4882a593Smuzhiyun 			HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
484*4882a593Smuzhiyun 		break;
485*4882a593Smuzhiyun 	}
486*4882a593Smuzhiyun 
487*4882a593Smuzhiyun 	/* Wake up the waiting thread. */
488*4882a593Smuzhiyun 	if (test_and_clear_bit(HIDP_WAITING_FOR_SEND_ACK, &session->flags))
489*4882a593Smuzhiyun 		wake_up_interruptible(&session->report_queue);
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun 
hidp_process_hid_control(struct hidp_session * session,unsigned char param)492*4882a593Smuzhiyun static void hidp_process_hid_control(struct hidp_session *session,
493*4882a593Smuzhiyun 					unsigned char param)
494*4882a593Smuzhiyun {
495*4882a593Smuzhiyun 	BT_DBG("session %p param 0x%02x", session, param);
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	if (param == HIDP_CTRL_VIRTUAL_CABLE_UNPLUG) {
498*4882a593Smuzhiyun 		/* Flush the transmit queues */
499*4882a593Smuzhiyun 		skb_queue_purge(&session->ctrl_transmit);
500*4882a593Smuzhiyun 		skb_queue_purge(&session->intr_transmit);
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 		hidp_session_terminate(session);
503*4882a593Smuzhiyun 	}
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun 
506*4882a593Smuzhiyun /* Returns true if the passed-in skb should be freed by the caller. */
hidp_process_data(struct hidp_session * session,struct sk_buff * skb,unsigned char param)507*4882a593Smuzhiyun static int hidp_process_data(struct hidp_session *session, struct sk_buff *skb,
508*4882a593Smuzhiyun 				unsigned char param)
509*4882a593Smuzhiyun {
510*4882a593Smuzhiyun 	int done_with_skb = 1;
511*4882a593Smuzhiyun 	BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param);
512*4882a593Smuzhiyun 
513*4882a593Smuzhiyun 	switch (param) {
514*4882a593Smuzhiyun 	case HIDP_DATA_RTYPE_INPUT:
515*4882a593Smuzhiyun 		hidp_set_timer(session);
516*4882a593Smuzhiyun 
517*4882a593Smuzhiyun 		if (session->input)
518*4882a593Smuzhiyun 			hidp_input_report(session, skb);
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 		if (session->hid)
521*4882a593Smuzhiyun 			hidp_process_report(session, HID_INPUT_REPORT,
522*4882a593Smuzhiyun 					    skb->data, skb->len, 0);
523*4882a593Smuzhiyun 		break;
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	case HIDP_DATA_RTYPE_OTHER:
526*4882a593Smuzhiyun 	case HIDP_DATA_RTYPE_OUPUT:
527*4882a593Smuzhiyun 	case HIDP_DATA_RTYPE_FEATURE:
528*4882a593Smuzhiyun 		break;
529*4882a593Smuzhiyun 
530*4882a593Smuzhiyun 	default:
531*4882a593Smuzhiyun 		hidp_send_ctrl_message(session,
532*4882a593Smuzhiyun 			HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0);
533*4882a593Smuzhiyun 	}
534*4882a593Smuzhiyun 
535*4882a593Smuzhiyun 	if (test_bit(HIDP_WAITING_FOR_RETURN, &session->flags) &&
536*4882a593Smuzhiyun 				param == session->waiting_report_type) {
537*4882a593Smuzhiyun 		if (session->waiting_report_number < 0 ||
538*4882a593Smuzhiyun 		    session->waiting_report_number == skb->data[0]) {
539*4882a593Smuzhiyun 			/* hidp_get_raw_report() is waiting on this report. */
540*4882a593Smuzhiyun 			session->report_return = skb;
541*4882a593Smuzhiyun 			done_with_skb = 0;
542*4882a593Smuzhiyun 			clear_bit(HIDP_WAITING_FOR_RETURN, &session->flags);
543*4882a593Smuzhiyun 			wake_up_interruptible(&session->report_queue);
544*4882a593Smuzhiyun 		}
545*4882a593Smuzhiyun 	}
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun 	return done_with_skb;
548*4882a593Smuzhiyun }
549*4882a593Smuzhiyun 
hidp_recv_ctrl_frame(struct hidp_session * session,struct sk_buff * skb)550*4882a593Smuzhiyun static void hidp_recv_ctrl_frame(struct hidp_session *session,
551*4882a593Smuzhiyun 					struct sk_buff *skb)
552*4882a593Smuzhiyun {
553*4882a593Smuzhiyun 	unsigned char hdr, type, param;
554*4882a593Smuzhiyun 	int free_skb = 1;
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun 	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	hdr = skb->data[0];
559*4882a593Smuzhiyun 	skb_pull(skb, 1);
560*4882a593Smuzhiyun 
561*4882a593Smuzhiyun 	type = hdr & HIDP_HEADER_TRANS_MASK;
562*4882a593Smuzhiyun 	param = hdr & HIDP_HEADER_PARAM_MASK;
563*4882a593Smuzhiyun 
564*4882a593Smuzhiyun 	switch (type) {
565*4882a593Smuzhiyun 	case HIDP_TRANS_HANDSHAKE:
566*4882a593Smuzhiyun 		hidp_process_handshake(session, param);
567*4882a593Smuzhiyun 		break;
568*4882a593Smuzhiyun 
569*4882a593Smuzhiyun 	case HIDP_TRANS_HID_CONTROL:
570*4882a593Smuzhiyun 		hidp_process_hid_control(session, param);
571*4882a593Smuzhiyun 		break;
572*4882a593Smuzhiyun 
573*4882a593Smuzhiyun 	case HIDP_TRANS_DATA:
574*4882a593Smuzhiyun 		free_skb = hidp_process_data(session, skb, param);
575*4882a593Smuzhiyun 		break;
576*4882a593Smuzhiyun 
577*4882a593Smuzhiyun 	default:
578*4882a593Smuzhiyun 		hidp_send_ctrl_message(session,
579*4882a593Smuzhiyun 			HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0);
580*4882a593Smuzhiyun 		break;
581*4882a593Smuzhiyun 	}
582*4882a593Smuzhiyun 
583*4882a593Smuzhiyun 	if (free_skb)
584*4882a593Smuzhiyun 		kfree_skb(skb);
585*4882a593Smuzhiyun }
586*4882a593Smuzhiyun 
hidp_recv_intr_frame(struct hidp_session * session,struct sk_buff * skb)587*4882a593Smuzhiyun static void hidp_recv_intr_frame(struct hidp_session *session,
588*4882a593Smuzhiyun 				struct sk_buff *skb)
589*4882a593Smuzhiyun {
590*4882a593Smuzhiyun 	unsigned char hdr;
591*4882a593Smuzhiyun 
592*4882a593Smuzhiyun 	BT_DBG("session %p skb %p len %d", session, skb, skb->len);
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	hdr = skb->data[0];
595*4882a593Smuzhiyun 	skb_pull(skb, 1);
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) {
598*4882a593Smuzhiyun 		hidp_set_timer(session);
599*4882a593Smuzhiyun 
600*4882a593Smuzhiyun 		if (session->input)
601*4882a593Smuzhiyun 			hidp_input_report(session, skb);
602*4882a593Smuzhiyun 
603*4882a593Smuzhiyun 		if (session->hid) {
604*4882a593Smuzhiyun 			hidp_process_report(session, HID_INPUT_REPORT,
605*4882a593Smuzhiyun 					    skb->data, skb->len, 1);
606*4882a593Smuzhiyun 			BT_DBG("report len %d", skb->len);
607*4882a593Smuzhiyun 		}
608*4882a593Smuzhiyun 	} else {
609*4882a593Smuzhiyun 		BT_DBG("Unsupported protocol header 0x%02x", hdr);
610*4882a593Smuzhiyun 	}
611*4882a593Smuzhiyun 
612*4882a593Smuzhiyun 	kfree_skb(skb);
613*4882a593Smuzhiyun }
614*4882a593Smuzhiyun 
hidp_send_frame(struct socket * sock,unsigned char * data,int len)615*4882a593Smuzhiyun static int hidp_send_frame(struct socket *sock, unsigned char *data, int len)
616*4882a593Smuzhiyun {
617*4882a593Smuzhiyun 	struct kvec iv = { data, len };
618*4882a593Smuzhiyun 	struct msghdr msg;
619*4882a593Smuzhiyun 
620*4882a593Smuzhiyun 	BT_DBG("sock %p data %p len %d", sock, data, len);
621*4882a593Smuzhiyun 
622*4882a593Smuzhiyun 	if (!len)
623*4882a593Smuzhiyun 		return 0;
624*4882a593Smuzhiyun 
625*4882a593Smuzhiyun 	memset(&msg, 0, sizeof(msg));
626*4882a593Smuzhiyun 
627*4882a593Smuzhiyun 	return kernel_sendmsg(sock, &msg, &iv, 1, len);
628*4882a593Smuzhiyun }
629*4882a593Smuzhiyun 
630*4882a593Smuzhiyun /* dequeue message from @transmit and send via @sock */
hidp_process_transmit(struct hidp_session * session,struct sk_buff_head * transmit,struct socket * sock)631*4882a593Smuzhiyun static void hidp_process_transmit(struct hidp_session *session,
632*4882a593Smuzhiyun 				  struct sk_buff_head *transmit,
633*4882a593Smuzhiyun 				  struct socket *sock)
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun 	struct sk_buff *skb;
636*4882a593Smuzhiyun 	int ret;
637*4882a593Smuzhiyun 
638*4882a593Smuzhiyun 	BT_DBG("session %p", session);
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun 	while ((skb = skb_dequeue(transmit))) {
641*4882a593Smuzhiyun 		ret = hidp_send_frame(sock, skb->data, skb->len);
642*4882a593Smuzhiyun 		if (ret == -EAGAIN) {
643*4882a593Smuzhiyun 			skb_queue_head(transmit, skb);
644*4882a593Smuzhiyun 			break;
645*4882a593Smuzhiyun 		} else if (ret < 0) {
646*4882a593Smuzhiyun 			hidp_session_terminate(session);
647*4882a593Smuzhiyun 			kfree_skb(skb);
648*4882a593Smuzhiyun 			break;
649*4882a593Smuzhiyun 		}
650*4882a593Smuzhiyun 
651*4882a593Smuzhiyun 		hidp_set_timer(session);
652*4882a593Smuzhiyun 		kfree_skb(skb);
653*4882a593Smuzhiyun 	}
654*4882a593Smuzhiyun }
655*4882a593Smuzhiyun 
hidp_setup_input(struct hidp_session * session,const struct hidp_connadd_req * req)656*4882a593Smuzhiyun static int hidp_setup_input(struct hidp_session *session,
657*4882a593Smuzhiyun 				const struct hidp_connadd_req *req)
658*4882a593Smuzhiyun {
659*4882a593Smuzhiyun 	struct input_dev *input;
660*4882a593Smuzhiyun 	int i;
661*4882a593Smuzhiyun 
662*4882a593Smuzhiyun 	input = input_allocate_device();
663*4882a593Smuzhiyun 	if (!input)
664*4882a593Smuzhiyun 		return -ENOMEM;
665*4882a593Smuzhiyun 
666*4882a593Smuzhiyun 	session->input = input;
667*4882a593Smuzhiyun 
668*4882a593Smuzhiyun 	input_set_drvdata(input, session);
669*4882a593Smuzhiyun 
670*4882a593Smuzhiyun 	input->name = "Bluetooth HID Boot Protocol Device";
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 	input->id.bustype = BUS_BLUETOOTH;
673*4882a593Smuzhiyun 	input->id.vendor  = req->vendor;
674*4882a593Smuzhiyun 	input->id.product = req->product;
675*4882a593Smuzhiyun 	input->id.version = req->version;
676*4882a593Smuzhiyun 
677*4882a593Smuzhiyun 	if (req->subclass & 0x40) {
678*4882a593Smuzhiyun 		set_bit(EV_KEY, input->evbit);
679*4882a593Smuzhiyun 		set_bit(EV_LED, input->evbit);
680*4882a593Smuzhiyun 		set_bit(EV_REP, input->evbit);
681*4882a593Smuzhiyun 
682*4882a593Smuzhiyun 		set_bit(LED_NUML,    input->ledbit);
683*4882a593Smuzhiyun 		set_bit(LED_CAPSL,   input->ledbit);
684*4882a593Smuzhiyun 		set_bit(LED_SCROLLL, input->ledbit);
685*4882a593Smuzhiyun 		set_bit(LED_COMPOSE, input->ledbit);
686*4882a593Smuzhiyun 		set_bit(LED_KANA,    input->ledbit);
687*4882a593Smuzhiyun 
688*4882a593Smuzhiyun 		for (i = 0; i < sizeof(hidp_keycode); i++)
689*4882a593Smuzhiyun 			set_bit(hidp_keycode[i], input->keybit);
690*4882a593Smuzhiyun 		clear_bit(0, input->keybit);
691*4882a593Smuzhiyun 	}
692*4882a593Smuzhiyun 
693*4882a593Smuzhiyun 	if (req->subclass & 0x80) {
694*4882a593Smuzhiyun 		input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REL);
695*4882a593Smuzhiyun 		input->keybit[BIT_WORD(BTN_MOUSE)] = BIT_MASK(BTN_LEFT) |
696*4882a593Smuzhiyun 			BIT_MASK(BTN_RIGHT) | BIT_MASK(BTN_MIDDLE);
697*4882a593Smuzhiyun 		input->relbit[0] = BIT_MASK(REL_X) | BIT_MASK(REL_Y);
698*4882a593Smuzhiyun 		input->keybit[BIT_WORD(BTN_MOUSE)] |= BIT_MASK(BTN_SIDE) |
699*4882a593Smuzhiyun 			BIT_MASK(BTN_EXTRA);
700*4882a593Smuzhiyun 		input->relbit[0] |= BIT_MASK(REL_WHEEL);
701*4882a593Smuzhiyun 	}
702*4882a593Smuzhiyun 
703*4882a593Smuzhiyun 	input->dev.parent = &session->conn->hcon->dev;
704*4882a593Smuzhiyun 
705*4882a593Smuzhiyun 	input->event = hidp_input_event;
706*4882a593Smuzhiyun 
707*4882a593Smuzhiyun 	return 0;
708*4882a593Smuzhiyun }
709*4882a593Smuzhiyun 
hidp_open(struct hid_device * hid)710*4882a593Smuzhiyun static int hidp_open(struct hid_device *hid)
711*4882a593Smuzhiyun {
712*4882a593Smuzhiyun 	return 0;
713*4882a593Smuzhiyun }
714*4882a593Smuzhiyun 
hidp_close(struct hid_device * hid)715*4882a593Smuzhiyun static void hidp_close(struct hid_device *hid)
716*4882a593Smuzhiyun {
717*4882a593Smuzhiyun }
718*4882a593Smuzhiyun 
hidp_parse(struct hid_device * hid)719*4882a593Smuzhiyun static int hidp_parse(struct hid_device *hid)
720*4882a593Smuzhiyun {
721*4882a593Smuzhiyun 	struct hidp_session *session = hid->driver_data;
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 	return hid_parse_report(session->hid, session->rd_data,
724*4882a593Smuzhiyun 			session->rd_size);
725*4882a593Smuzhiyun }
726*4882a593Smuzhiyun 
hidp_start(struct hid_device * hid)727*4882a593Smuzhiyun static int hidp_start(struct hid_device *hid)
728*4882a593Smuzhiyun {
729*4882a593Smuzhiyun 	return 0;
730*4882a593Smuzhiyun }
731*4882a593Smuzhiyun 
hidp_stop(struct hid_device * hid)732*4882a593Smuzhiyun static void hidp_stop(struct hid_device *hid)
733*4882a593Smuzhiyun {
734*4882a593Smuzhiyun 	struct hidp_session *session = hid->driver_data;
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 	skb_queue_purge(&session->ctrl_transmit);
737*4882a593Smuzhiyun 	skb_queue_purge(&session->intr_transmit);
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	hid->claimed = 0;
740*4882a593Smuzhiyun }
741*4882a593Smuzhiyun 
742*4882a593Smuzhiyun struct hid_ll_driver hidp_hid_driver = {
743*4882a593Smuzhiyun 	.parse = hidp_parse,
744*4882a593Smuzhiyun 	.start = hidp_start,
745*4882a593Smuzhiyun 	.stop = hidp_stop,
746*4882a593Smuzhiyun 	.open  = hidp_open,
747*4882a593Smuzhiyun 	.close = hidp_close,
748*4882a593Smuzhiyun 	.raw_request = hidp_raw_request,
749*4882a593Smuzhiyun 	.output_report = hidp_output_report,
750*4882a593Smuzhiyun };
751*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(hidp_hid_driver);
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun /* This function sets up the hid device. It does not add it
754*4882a593Smuzhiyun    to the HID system. That is done in hidp_add_connection(). */
hidp_setup_hid(struct hidp_session * session,const struct hidp_connadd_req * req)755*4882a593Smuzhiyun static int hidp_setup_hid(struct hidp_session *session,
756*4882a593Smuzhiyun 				const struct hidp_connadd_req *req)
757*4882a593Smuzhiyun {
758*4882a593Smuzhiyun 	struct hid_device *hid;
759*4882a593Smuzhiyun 	int err;
760*4882a593Smuzhiyun 
761*4882a593Smuzhiyun 	session->rd_data = memdup_user(req->rd_data, req->rd_size);
762*4882a593Smuzhiyun 	if (IS_ERR(session->rd_data))
763*4882a593Smuzhiyun 		return PTR_ERR(session->rd_data);
764*4882a593Smuzhiyun 
765*4882a593Smuzhiyun 	session->rd_size = req->rd_size;
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun 	hid = hid_allocate_device();
768*4882a593Smuzhiyun 	if (IS_ERR(hid)) {
769*4882a593Smuzhiyun 		err = PTR_ERR(hid);
770*4882a593Smuzhiyun 		goto fault;
771*4882a593Smuzhiyun 	}
772*4882a593Smuzhiyun 
773*4882a593Smuzhiyun 	session->hid = hid;
774*4882a593Smuzhiyun 
775*4882a593Smuzhiyun 	hid->driver_data = session;
776*4882a593Smuzhiyun 
777*4882a593Smuzhiyun 	hid->bus     = BUS_BLUETOOTH;
778*4882a593Smuzhiyun 	hid->vendor  = req->vendor;
779*4882a593Smuzhiyun 	hid->product = req->product;
780*4882a593Smuzhiyun 	hid->version = req->version;
781*4882a593Smuzhiyun 	hid->country = req->country;
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun 	strscpy(hid->name, req->name, sizeof(hid->name));
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun 	snprintf(hid->phys, sizeof(hid->phys), "%pMR",
786*4882a593Smuzhiyun 		 &l2cap_pi(session->ctrl_sock->sk)->chan->src);
787*4882a593Smuzhiyun 
788*4882a593Smuzhiyun 	/* NOTE: Some device modules depend on the dst address being stored in
789*4882a593Smuzhiyun 	 * uniq. Please be aware of this before making changes to this behavior.
790*4882a593Smuzhiyun 	 */
791*4882a593Smuzhiyun 	snprintf(hid->uniq, sizeof(hid->uniq), "%pMR",
792*4882a593Smuzhiyun 		 &l2cap_pi(session->ctrl_sock->sk)->chan->dst);
793*4882a593Smuzhiyun 
794*4882a593Smuzhiyun 	hid->dev.parent = &session->conn->hcon->dev;
795*4882a593Smuzhiyun 	hid->ll_driver = &hidp_hid_driver;
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun 	/* True if device is blacklisted in drivers/hid/hid-quirks.c */
798*4882a593Smuzhiyun 	if (hid_ignore(hid)) {
799*4882a593Smuzhiyun 		hid_destroy_device(session->hid);
800*4882a593Smuzhiyun 		session->hid = NULL;
801*4882a593Smuzhiyun 		return -ENODEV;
802*4882a593Smuzhiyun 	}
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun 	return 0;
805*4882a593Smuzhiyun 
806*4882a593Smuzhiyun fault:
807*4882a593Smuzhiyun 	kfree(session->rd_data);
808*4882a593Smuzhiyun 	session->rd_data = NULL;
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun 	return err;
811*4882a593Smuzhiyun }
812*4882a593Smuzhiyun 
813*4882a593Smuzhiyun /* initialize session devices */
hidp_session_dev_init(struct hidp_session * session,const struct hidp_connadd_req * req)814*4882a593Smuzhiyun static int hidp_session_dev_init(struct hidp_session *session,
815*4882a593Smuzhiyun 				 const struct hidp_connadd_req *req)
816*4882a593Smuzhiyun {
817*4882a593Smuzhiyun 	int ret;
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 	if (req->rd_size > 0) {
820*4882a593Smuzhiyun 		ret = hidp_setup_hid(session, req);
821*4882a593Smuzhiyun 		if (ret && ret != -ENODEV)
822*4882a593Smuzhiyun 			return ret;
823*4882a593Smuzhiyun 	}
824*4882a593Smuzhiyun 
825*4882a593Smuzhiyun 	if (!session->hid) {
826*4882a593Smuzhiyun 		ret = hidp_setup_input(session, req);
827*4882a593Smuzhiyun 		if (ret < 0)
828*4882a593Smuzhiyun 			return ret;
829*4882a593Smuzhiyun 	}
830*4882a593Smuzhiyun 
831*4882a593Smuzhiyun 	return 0;
832*4882a593Smuzhiyun }
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun /* destroy session devices */
hidp_session_dev_destroy(struct hidp_session * session)835*4882a593Smuzhiyun static void hidp_session_dev_destroy(struct hidp_session *session)
836*4882a593Smuzhiyun {
837*4882a593Smuzhiyun 	if (session->hid)
838*4882a593Smuzhiyun 		put_device(&session->hid->dev);
839*4882a593Smuzhiyun 	else if (session->input)
840*4882a593Smuzhiyun 		input_put_device(session->input);
841*4882a593Smuzhiyun 
842*4882a593Smuzhiyun 	kfree(session->rd_data);
843*4882a593Smuzhiyun 	session->rd_data = NULL;
844*4882a593Smuzhiyun }
845*4882a593Smuzhiyun 
846*4882a593Smuzhiyun /* add HID/input devices to their underlying bus systems */
hidp_session_dev_add(struct hidp_session * session)847*4882a593Smuzhiyun static int hidp_session_dev_add(struct hidp_session *session)
848*4882a593Smuzhiyun {
849*4882a593Smuzhiyun 	int ret;
850*4882a593Smuzhiyun 
851*4882a593Smuzhiyun 	/* Both HID and input systems drop a ref-count when unregistering the
852*4882a593Smuzhiyun 	 * device but they don't take a ref-count when registering them. Work
853*4882a593Smuzhiyun 	 * around this by explicitly taking a refcount during registration
854*4882a593Smuzhiyun 	 * which is dropped automatically by unregistering the devices. */
855*4882a593Smuzhiyun 
856*4882a593Smuzhiyun 	if (session->hid) {
857*4882a593Smuzhiyun 		ret = hid_add_device(session->hid);
858*4882a593Smuzhiyun 		if (ret)
859*4882a593Smuzhiyun 			return ret;
860*4882a593Smuzhiyun 		get_device(&session->hid->dev);
861*4882a593Smuzhiyun 	} else if (session->input) {
862*4882a593Smuzhiyun 		ret = input_register_device(session->input);
863*4882a593Smuzhiyun 		if (ret)
864*4882a593Smuzhiyun 			return ret;
865*4882a593Smuzhiyun 		input_get_device(session->input);
866*4882a593Smuzhiyun 	}
867*4882a593Smuzhiyun 
868*4882a593Smuzhiyun 	return 0;
869*4882a593Smuzhiyun }
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun /* remove HID/input devices from their bus systems */
hidp_session_dev_del(struct hidp_session * session)872*4882a593Smuzhiyun static void hidp_session_dev_del(struct hidp_session *session)
873*4882a593Smuzhiyun {
874*4882a593Smuzhiyun 	if (session->hid)
875*4882a593Smuzhiyun 		hid_destroy_device(session->hid);
876*4882a593Smuzhiyun 	else if (session->input)
877*4882a593Smuzhiyun 		input_unregister_device(session->input);
878*4882a593Smuzhiyun }
879*4882a593Smuzhiyun 
880*4882a593Smuzhiyun /*
881*4882a593Smuzhiyun  * Asynchronous device registration
882*4882a593Smuzhiyun  * HID device drivers might want to perform I/O during initialization to
883*4882a593Smuzhiyun  * detect device types. Therefore, call device registration in a separate
884*4882a593Smuzhiyun  * worker so the HIDP thread can schedule I/O operations.
885*4882a593Smuzhiyun  * Note that this must be called after the worker thread was initialized
886*4882a593Smuzhiyun  * successfully. This will then add the devices and increase session state
887*4882a593Smuzhiyun  * on success, otherwise it will terminate the session thread.
888*4882a593Smuzhiyun  */
hidp_session_dev_work(struct work_struct * work)889*4882a593Smuzhiyun static void hidp_session_dev_work(struct work_struct *work)
890*4882a593Smuzhiyun {
891*4882a593Smuzhiyun 	struct hidp_session *session = container_of(work,
892*4882a593Smuzhiyun 						    struct hidp_session,
893*4882a593Smuzhiyun 						    dev_init);
894*4882a593Smuzhiyun 	int ret;
895*4882a593Smuzhiyun 
896*4882a593Smuzhiyun 	ret = hidp_session_dev_add(session);
897*4882a593Smuzhiyun 	if (!ret)
898*4882a593Smuzhiyun 		atomic_inc(&session->state);
899*4882a593Smuzhiyun 	else
900*4882a593Smuzhiyun 		hidp_session_terminate(session);
901*4882a593Smuzhiyun }
902*4882a593Smuzhiyun 
903*4882a593Smuzhiyun /*
904*4882a593Smuzhiyun  * Create new session object
905*4882a593Smuzhiyun  * Allocate session object, initialize static fields, copy input data into the
906*4882a593Smuzhiyun  * object and take a reference to all sub-objects.
907*4882a593Smuzhiyun  * This returns 0 on success and puts a pointer to the new session object in
908*4882a593Smuzhiyun  * \out. Otherwise, an error code is returned.
909*4882a593Smuzhiyun  * The new session object has an initial ref-count of 1.
910*4882a593Smuzhiyun  */
hidp_session_new(struct hidp_session ** out,const bdaddr_t * bdaddr,struct socket * ctrl_sock,struct socket * intr_sock,const struct hidp_connadd_req * req,struct l2cap_conn * conn)911*4882a593Smuzhiyun static int hidp_session_new(struct hidp_session **out, const bdaddr_t *bdaddr,
912*4882a593Smuzhiyun 			    struct socket *ctrl_sock,
913*4882a593Smuzhiyun 			    struct socket *intr_sock,
914*4882a593Smuzhiyun 			    const struct hidp_connadd_req *req,
915*4882a593Smuzhiyun 			    struct l2cap_conn *conn)
916*4882a593Smuzhiyun {
917*4882a593Smuzhiyun 	struct hidp_session *session;
918*4882a593Smuzhiyun 	int ret;
919*4882a593Smuzhiyun 	struct bt_sock *ctrl, *intr;
920*4882a593Smuzhiyun 
921*4882a593Smuzhiyun 	ctrl = bt_sk(ctrl_sock->sk);
922*4882a593Smuzhiyun 	intr = bt_sk(intr_sock->sk);
923*4882a593Smuzhiyun 
924*4882a593Smuzhiyun 	session = kzalloc(sizeof(*session), GFP_KERNEL);
925*4882a593Smuzhiyun 	if (!session)
926*4882a593Smuzhiyun 		return -ENOMEM;
927*4882a593Smuzhiyun 
928*4882a593Smuzhiyun 	/* object and runtime management */
929*4882a593Smuzhiyun 	kref_init(&session->ref);
930*4882a593Smuzhiyun 	atomic_set(&session->state, HIDP_SESSION_IDLING);
931*4882a593Smuzhiyun 	init_waitqueue_head(&session->state_queue);
932*4882a593Smuzhiyun 	session->flags = req->flags & BIT(HIDP_BLUETOOTH_VENDOR_ID);
933*4882a593Smuzhiyun 
934*4882a593Smuzhiyun 	/* connection management */
935*4882a593Smuzhiyun 	bacpy(&session->bdaddr, bdaddr);
936*4882a593Smuzhiyun 	session->conn = l2cap_conn_get(conn);
937*4882a593Smuzhiyun 	session->user.probe = hidp_session_probe;
938*4882a593Smuzhiyun 	session->user.remove = hidp_session_remove;
939*4882a593Smuzhiyun 	INIT_LIST_HEAD(&session->user.list);
940*4882a593Smuzhiyun 	session->ctrl_sock = ctrl_sock;
941*4882a593Smuzhiyun 	session->intr_sock = intr_sock;
942*4882a593Smuzhiyun 	skb_queue_head_init(&session->ctrl_transmit);
943*4882a593Smuzhiyun 	skb_queue_head_init(&session->intr_transmit);
944*4882a593Smuzhiyun 	session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl)->chan->omtu,
945*4882a593Smuzhiyun 					l2cap_pi(ctrl)->chan->imtu);
946*4882a593Smuzhiyun 	session->intr_mtu = min_t(uint, l2cap_pi(intr)->chan->omtu,
947*4882a593Smuzhiyun 					l2cap_pi(intr)->chan->imtu);
948*4882a593Smuzhiyun 	session->idle_to = req->idle_to;
949*4882a593Smuzhiyun 
950*4882a593Smuzhiyun 	/* device management */
951*4882a593Smuzhiyun 	INIT_WORK(&session->dev_init, hidp_session_dev_work);
952*4882a593Smuzhiyun 	timer_setup(&session->timer, hidp_idle_timeout, 0);
953*4882a593Smuzhiyun 
954*4882a593Smuzhiyun 	/* session data */
955*4882a593Smuzhiyun 	mutex_init(&session->report_mutex);
956*4882a593Smuzhiyun 	init_waitqueue_head(&session->report_queue);
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun 	ret = hidp_session_dev_init(session, req);
959*4882a593Smuzhiyun 	if (ret)
960*4882a593Smuzhiyun 		goto err_free;
961*4882a593Smuzhiyun 
962*4882a593Smuzhiyun 	get_file(session->intr_sock->file);
963*4882a593Smuzhiyun 	get_file(session->ctrl_sock->file);
964*4882a593Smuzhiyun 	*out = session;
965*4882a593Smuzhiyun 	return 0;
966*4882a593Smuzhiyun 
967*4882a593Smuzhiyun err_free:
968*4882a593Smuzhiyun 	l2cap_conn_put(session->conn);
969*4882a593Smuzhiyun 	kfree(session);
970*4882a593Smuzhiyun 	return ret;
971*4882a593Smuzhiyun }
972*4882a593Smuzhiyun 
973*4882a593Smuzhiyun /* increase ref-count of the given session by one */
hidp_session_get(struct hidp_session * session)974*4882a593Smuzhiyun static void hidp_session_get(struct hidp_session *session)
975*4882a593Smuzhiyun {
976*4882a593Smuzhiyun 	kref_get(&session->ref);
977*4882a593Smuzhiyun }
978*4882a593Smuzhiyun 
979*4882a593Smuzhiyun /* release callback */
session_free(struct kref * ref)980*4882a593Smuzhiyun static void session_free(struct kref *ref)
981*4882a593Smuzhiyun {
982*4882a593Smuzhiyun 	struct hidp_session *session = container_of(ref, struct hidp_session,
983*4882a593Smuzhiyun 						    ref);
984*4882a593Smuzhiyun 
985*4882a593Smuzhiyun 	hidp_session_dev_destroy(session);
986*4882a593Smuzhiyun 	skb_queue_purge(&session->ctrl_transmit);
987*4882a593Smuzhiyun 	skb_queue_purge(&session->intr_transmit);
988*4882a593Smuzhiyun 	fput(session->intr_sock->file);
989*4882a593Smuzhiyun 	fput(session->ctrl_sock->file);
990*4882a593Smuzhiyun 	l2cap_conn_put(session->conn);
991*4882a593Smuzhiyun 	kfree(session);
992*4882a593Smuzhiyun }
993*4882a593Smuzhiyun 
994*4882a593Smuzhiyun /* decrease ref-count of the given session by one */
hidp_session_put(struct hidp_session * session)995*4882a593Smuzhiyun static void hidp_session_put(struct hidp_session *session)
996*4882a593Smuzhiyun {
997*4882a593Smuzhiyun 	kref_put(&session->ref, session_free);
998*4882a593Smuzhiyun }
999*4882a593Smuzhiyun 
1000*4882a593Smuzhiyun /*
1001*4882a593Smuzhiyun  * Search the list of active sessions for a session with target address
1002*4882a593Smuzhiyun  * \bdaddr. You must hold at least a read-lock on \hidp_session_sem. As long as
1003*4882a593Smuzhiyun  * you do not release this lock, the session objects cannot vanish and you can
1004*4882a593Smuzhiyun  * safely take a reference to the session yourself.
1005*4882a593Smuzhiyun  */
__hidp_session_find(const bdaddr_t * bdaddr)1006*4882a593Smuzhiyun static struct hidp_session *__hidp_session_find(const bdaddr_t *bdaddr)
1007*4882a593Smuzhiyun {
1008*4882a593Smuzhiyun 	struct hidp_session *session;
1009*4882a593Smuzhiyun 
1010*4882a593Smuzhiyun 	list_for_each_entry(session, &hidp_session_list, list) {
1011*4882a593Smuzhiyun 		if (!bacmp(bdaddr, &session->bdaddr))
1012*4882a593Smuzhiyun 			return session;
1013*4882a593Smuzhiyun 	}
1014*4882a593Smuzhiyun 
1015*4882a593Smuzhiyun 	return NULL;
1016*4882a593Smuzhiyun }
1017*4882a593Smuzhiyun 
1018*4882a593Smuzhiyun /*
1019*4882a593Smuzhiyun  * Same as __hidp_session_find() but no locks must be held. This also takes a
1020*4882a593Smuzhiyun  * reference of the returned session (if non-NULL) so you must drop this
1021*4882a593Smuzhiyun  * reference if you no longer use the object.
1022*4882a593Smuzhiyun  */
hidp_session_find(const bdaddr_t * bdaddr)1023*4882a593Smuzhiyun static struct hidp_session *hidp_session_find(const bdaddr_t *bdaddr)
1024*4882a593Smuzhiyun {
1025*4882a593Smuzhiyun 	struct hidp_session *session;
1026*4882a593Smuzhiyun 
1027*4882a593Smuzhiyun 	down_read(&hidp_session_sem);
1028*4882a593Smuzhiyun 
1029*4882a593Smuzhiyun 	session = __hidp_session_find(bdaddr);
1030*4882a593Smuzhiyun 	if (session)
1031*4882a593Smuzhiyun 		hidp_session_get(session);
1032*4882a593Smuzhiyun 
1033*4882a593Smuzhiyun 	up_read(&hidp_session_sem);
1034*4882a593Smuzhiyun 
1035*4882a593Smuzhiyun 	return session;
1036*4882a593Smuzhiyun }
1037*4882a593Smuzhiyun 
1038*4882a593Smuzhiyun /*
1039*4882a593Smuzhiyun  * Start session synchronously
1040*4882a593Smuzhiyun  * This starts a session thread and waits until initialization
1041*4882a593Smuzhiyun  * is done or returns an error if it couldn't be started.
1042*4882a593Smuzhiyun  * If this returns 0 the session thread is up and running. You must call
1043*4882a593Smuzhiyun  * hipd_session_stop_sync() before deleting any runtime resources.
1044*4882a593Smuzhiyun  */
hidp_session_start_sync(struct hidp_session * session)1045*4882a593Smuzhiyun static int hidp_session_start_sync(struct hidp_session *session)
1046*4882a593Smuzhiyun {
1047*4882a593Smuzhiyun 	unsigned int vendor, product;
1048*4882a593Smuzhiyun 
1049*4882a593Smuzhiyun 	if (session->hid) {
1050*4882a593Smuzhiyun 		vendor  = session->hid->vendor;
1051*4882a593Smuzhiyun 		product = session->hid->product;
1052*4882a593Smuzhiyun 	} else if (session->input) {
1053*4882a593Smuzhiyun 		vendor  = session->input->id.vendor;
1054*4882a593Smuzhiyun 		product = session->input->id.product;
1055*4882a593Smuzhiyun 	} else {
1056*4882a593Smuzhiyun 		vendor = 0x0000;
1057*4882a593Smuzhiyun 		product = 0x0000;
1058*4882a593Smuzhiyun 	}
1059*4882a593Smuzhiyun 
1060*4882a593Smuzhiyun 	session->task = kthread_run(hidp_session_thread, session,
1061*4882a593Smuzhiyun 				    "khidpd_%04x%04x", vendor, product);
1062*4882a593Smuzhiyun 	if (IS_ERR(session->task))
1063*4882a593Smuzhiyun 		return PTR_ERR(session->task);
1064*4882a593Smuzhiyun 
1065*4882a593Smuzhiyun 	while (atomic_read(&session->state) <= HIDP_SESSION_IDLING)
1066*4882a593Smuzhiyun 		wait_event(session->state_queue,
1067*4882a593Smuzhiyun 			   atomic_read(&session->state) > HIDP_SESSION_IDLING);
1068*4882a593Smuzhiyun 
1069*4882a593Smuzhiyun 	return 0;
1070*4882a593Smuzhiyun }
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun /*
1073*4882a593Smuzhiyun  * Terminate session thread
1074*4882a593Smuzhiyun  * Wake up session thread and notify it to stop. This is asynchronous and
1075*4882a593Smuzhiyun  * returns immediately. Call this whenever a runtime error occurs and you want
1076*4882a593Smuzhiyun  * the session to stop.
1077*4882a593Smuzhiyun  * Note: wake_up_interruptible() performs any necessary memory-barriers for us.
1078*4882a593Smuzhiyun  */
hidp_session_terminate(struct hidp_session * session)1079*4882a593Smuzhiyun static void hidp_session_terminate(struct hidp_session *session)
1080*4882a593Smuzhiyun {
1081*4882a593Smuzhiyun 	atomic_inc(&session->terminate);
1082*4882a593Smuzhiyun 	/*
1083*4882a593Smuzhiyun 	 * See the comment preceding the call to wait_woken()
1084*4882a593Smuzhiyun 	 * in hidp_session_run().
1085*4882a593Smuzhiyun 	 */
1086*4882a593Smuzhiyun 	wake_up_interruptible(&hidp_session_wq);
1087*4882a593Smuzhiyun }
1088*4882a593Smuzhiyun 
1089*4882a593Smuzhiyun /*
1090*4882a593Smuzhiyun  * Probe HIDP session
1091*4882a593Smuzhiyun  * This is called from the l2cap_conn core when our l2cap_user object is bound
1092*4882a593Smuzhiyun  * to the hci-connection. We get the session via the \user object and can now
1093*4882a593Smuzhiyun  * start the session thread, link it into the global session list and
1094*4882a593Smuzhiyun  * schedule HID/input device registration.
1095*4882a593Smuzhiyun  * The global session-list owns its own reference to the session object so you
1096*4882a593Smuzhiyun  * can drop your own reference after registering the l2cap_user object.
1097*4882a593Smuzhiyun  */
hidp_session_probe(struct l2cap_conn * conn,struct l2cap_user * user)1098*4882a593Smuzhiyun static int hidp_session_probe(struct l2cap_conn *conn,
1099*4882a593Smuzhiyun 			      struct l2cap_user *user)
1100*4882a593Smuzhiyun {
1101*4882a593Smuzhiyun 	struct hidp_session *session = container_of(user,
1102*4882a593Smuzhiyun 						    struct hidp_session,
1103*4882a593Smuzhiyun 						    user);
1104*4882a593Smuzhiyun 	struct hidp_session *s;
1105*4882a593Smuzhiyun 	int ret;
1106*4882a593Smuzhiyun 
1107*4882a593Smuzhiyun 	down_write(&hidp_session_sem);
1108*4882a593Smuzhiyun 
1109*4882a593Smuzhiyun 	/* check that no other session for this device exists */
1110*4882a593Smuzhiyun 	s = __hidp_session_find(&session->bdaddr);
1111*4882a593Smuzhiyun 	if (s) {
1112*4882a593Smuzhiyun 		ret = -EEXIST;
1113*4882a593Smuzhiyun 		goto out_unlock;
1114*4882a593Smuzhiyun 	}
1115*4882a593Smuzhiyun 
1116*4882a593Smuzhiyun 	if (session->input) {
1117*4882a593Smuzhiyun 		ret = hidp_session_dev_add(session);
1118*4882a593Smuzhiyun 		if (ret)
1119*4882a593Smuzhiyun 			goto out_unlock;
1120*4882a593Smuzhiyun 	}
1121*4882a593Smuzhiyun 
1122*4882a593Smuzhiyun 	ret = hidp_session_start_sync(session);
1123*4882a593Smuzhiyun 	if (ret)
1124*4882a593Smuzhiyun 		goto out_del;
1125*4882a593Smuzhiyun 
1126*4882a593Smuzhiyun 	/* HID device registration is async to allow I/O during probe */
1127*4882a593Smuzhiyun 	if (session->input)
1128*4882a593Smuzhiyun 		atomic_inc(&session->state);
1129*4882a593Smuzhiyun 	else
1130*4882a593Smuzhiyun 		schedule_work(&session->dev_init);
1131*4882a593Smuzhiyun 
1132*4882a593Smuzhiyun 	hidp_session_get(session);
1133*4882a593Smuzhiyun 	list_add(&session->list, &hidp_session_list);
1134*4882a593Smuzhiyun 	ret = 0;
1135*4882a593Smuzhiyun 	goto out_unlock;
1136*4882a593Smuzhiyun 
1137*4882a593Smuzhiyun out_del:
1138*4882a593Smuzhiyun 	if (session->input)
1139*4882a593Smuzhiyun 		hidp_session_dev_del(session);
1140*4882a593Smuzhiyun out_unlock:
1141*4882a593Smuzhiyun 	up_write(&hidp_session_sem);
1142*4882a593Smuzhiyun 	return ret;
1143*4882a593Smuzhiyun }
1144*4882a593Smuzhiyun 
1145*4882a593Smuzhiyun /*
1146*4882a593Smuzhiyun  * Remove HIDP session
1147*4882a593Smuzhiyun  * Called from the l2cap_conn core when either we explicitly unregistered
1148*4882a593Smuzhiyun  * the l2cap_user object or if the underlying connection is shut down.
1149*4882a593Smuzhiyun  * We signal the hidp-session thread to shut down, unregister the HID/input
1150*4882a593Smuzhiyun  * devices and unlink the session from the global list.
1151*4882a593Smuzhiyun  * This drops the reference to the session that is owned by the global
1152*4882a593Smuzhiyun  * session-list.
1153*4882a593Smuzhiyun  * Note: We _must_ not synchronosly wait for the session-thread to shut down.
1154*4882a593Smuzhiyun  * This is, because the session-thread might be waiting for an HCI lock that is
1155*4882a593Smuzhiyun  * held while we are called. Therefore, we only unregister the devices and
1156*4882a593Smuzhiyun  * notify the session-thread to terminate. The thread itself owns a reference
1157*4882a593Smuzhiyun  * to the session object so it can safely shut down.
1158*4882a593Smuzhiyun  */
hidp_session_remove(struct l2cap_conn * conn,struct l2cap_user * user)1159*4882a593Smuzhiyun static void hidp_session_remove(struct l2cap_conn *conn,
1160*4882a593Smuzhiyun 				struct l2cap_user *user)
1161*4882a593Smuzhiyun {
1162*4882a593Smuzhiyun 	struct hidp_session *session = container_of(user,
1163*4882a593Smuzhiyun 						    struct hidp_session,
1164*4882a593Smuzhiyun 						    user);
1165*4882a593Smuzhiyun 
1166*4882a593Smuzhiyun 	down_write(&hidp_session_sem);
1167*4882a593Smuzhiyun 
1168*4882a593Smuzhiyun 	hidp_session_terminate(session);
1169*4882a593Smuzhiyun 
1170*4882a593Smuzhiyun 	cancel_work_sync(&session->dev_init);
1171*4882a593Smuzhiyun 	if (session->input ||
1172*4882a593Smuzhiyun 	    atomic_read(&session->state) > HIDP_SESSION_PREPARING)
1173*4882a593Smuzhiyun 		hidp_session_dev_del(session);
1174*4882a593Smuzhiyun 
1175*4882a593Smuzhiyun 	list_del(&session->list);
1176*4882a593Smuzhiyun 
1177*4882a593Smuzhiyun 	up_write(&hidp_session_sem);
1178*4882a593Smuzhiyun 
1179*4882a593Smuzhiyun 	hidp_session_put(session);
1180*4882a593Smuzhiyun }
1181*4882a593Smuzhiyun 
1182*4882a593Smuzhiyun /*
1183*4882a593Smuzhiyun  * Session Worker
1184*4882a593Smuzhiyun  * This performs the actual main-loop of the HIDP worker. We first check
1185*4882a593Smuzhiyun  * whether the underlying connection is still alive, then parse all pending
1186*4882a593Smuzhiyun  * messages and finally send all outstanding messages.
1187*4882a593Smuzhiyun  */
hidp_session_run(struct hidp_session * session)1188*4882a593Smuzhiyun static void hidp_session_run(struct hidp_session *session)
1189*4882a593Smuzhiyun {
1190*4882a593Smuzhiyun 	struct sock *ctrl_sk = session->ctrl_sock->sk;
1191*4882a593Smuzhiyun 	struct sock *intr_sk = session->intr_sock->sk;
1192*4882a593Smuzhiyun 	struct sk_buff *skb;
1193*4882a593Smuzhiyun 	DEFINE_WAIT_FUNC(wait, woken_wake_function);
1194*4882a593Smuzhiyun 
1195*4882a593Smuzhiyun 	add_wait_queue(&hidp_session_wq, &wait);
1196*4882a593Smuzhiyun 	for (;;) {
1197*4882a593Smuzhiyun 		/*
1198*4882a593Smuzhiyun 		 * This thread can be woken up two ways:
1199*4882a593Smuzhiyun 		 *  - You call hidp_session_terminate() which sets the
1200*4882a593Smuzhiyun 		 *    session->terminate flag and wakes this thread up.
1201*4882a593Smuzhiyun 		 *  - Via modifying the socket state of ctrl/intr_sock. This
1202*4882a593Smuzhiyun 		 *    thread is woken up by ->sk_state_changed().
1203*4882a593Smuzhiyun 		 */
1204*4882a593Smuzhiyun 
1205*4882a593Smuzhiyun 		if (atomic_read(&session->terminate))
1206*4882a593Smuzhiyun 			break;
1207*4882a593Smuzhiyun 
1208*4882a593Smuzhiyun 		if (ctrl_sk->sk_state != BT_CONNECTED ||
1209*4882a593Smuzhiyun 		    intr_sk->sk_state != BT_CONNECTED)
1210*4882a593Smuzhiyun 			break;
1211*4882a593Smuzhiyun 
1212*4882a593Smuzhiyun 		/* parse incoming intr-skbs */
1213*4882a593Smuzhiyun 		while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
1214*4882a593Smuzhiyun 			skb_orphan(skb);
1215*4882a593Smuzhiyun 			if (!skb_linearize(skb))
1216*4882a593Smuzhiyun 				hidp_recv_intr_frame(session, skb);
1217*4882a593Smuzhiyun 			else
1218*4882a593Smuzhiyun 				kfree_skb(skb);
1219*4882a593Smuzhiyun 		}
1220*4882a593Smuzhiyun 
1221*4882a593Smuzhiyun 		/* send pending intr-skbs */
1222*4882a593Smuzhiyun 		hidp_process_transmit(session, &session->intr_transmit,
1223*4882a593Smuzhiyun 				      session->intr_sock);
1224*4882a593Smuzhiyun 
1225*4882a593Smuzhiyun 		/* parse incoming ctrl-skbs */
1226*4882a593Smuzhiyun 		while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
1227*4882a593Smuzhiyun 			skb_orphan(skb);
1228*4882a593Smuzhiyun 			if (!skb_linearize(skb))
1229*4882a593Smuzhiyun 				hidp_recv_ctrl_frame(session, skb);
1230*4882a593Smuzhiyun 			else
1231*4882a593Smuzhiyun 				kfree_skb(skb);
1232*4882a593Smuzhiyun 		}
1233*4882a593Smuzhiyun 
1234*4882a593Smuzhiyun 		/* send pending ctrl-skbs */
1235*4882a593Smuzhiyun 		hidp_process_transmit(session, &session->ctrl_transmit,
1236*4882a593Smuzhiyun 				      session->ctrl_sock);
1237*4882a593Smuzhiyun 
1238*4882a593Smuzhiyun 		/*
1239*4882a593Smuzhiyun 		 * wait_woken() performs the necessary memory barriers
1240*4882a593Smuzhiyun 		 * for us; see the header comment for this primitive.
1241*4882a593Smuzhiyun 		 */
1242*4882a593Smuzhiyun 		wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT);
1243*4882a593Smuzhiyun 	}
1244*4882a593Smuzhiyun 	remove_wait_queue(&hidp_session_wq, &wait);
1245*4882a593Smuzhiyun 
1246*4882a593Smuzhiyun 	atomic_inc(&session->terminate);
1247*4882a593Smuzhiyun }
1248*4882a593Smuzhiyun 
hidp_session_wake_function(wait_queue_entry_t * wait,unsigned int mode,int sync,void * key)1249*4882a593Smuzhiyun static int hidp_session_wake_function(wait_queue_entry_t *wait,
1250*4882a593Smuzhiyun 				      unsigned int mode,
1251*4882a593Smuzhiyun 				      int sync, void *key)
1252*4882a593Smuzhiyun {
1253*4882a593Smuzhiyun 	wake_up_interruptible(&hidp_session_wq);
1254*4882a593Smuzhiyun 	return false;
1255*4882a593Smuzhiyun }
1256*4882a593Smuzhiyun 
1257*4882a593Smuzhiyun /*
1258*4882a593Smuzhiyun  * HIDP session thread
1259*4882a593Smuzhiyun  * This thread runs the I/O for a single HIDP session. Startup is synchronous
1260*4882a593Smuzhiyun  * which allows us to take references to ourself here instead of doing that in
1261*4882a593Smuzhiyun  * the caller.
1262*4882a593Smuzhiyun  * When we are ready to run we notify the caller and call hidp_session_run().
1263*4882a593Smuzhiyun  */
hidp_session_thread(void * arg)1264*4882a593Smuzhiyun static int hidp_session_thread(void *arg)
1265*4882a593Smuzhiyun {
1266*4882a593Smuzhiyun 	struct hidp_session *session = arg;
1267*4882a593Smuzhiyun 	DEFINE_WAIT_FUNC(ctrl_wait, hidp_session_wake_function);
1268*4882a593Smuzhiyun 	DEFINE_WAIT_FUNC(intr_wait, hidp_session_wake_function);
1269*4882a593Smuzhiyun 
1270*4882a593Smuzhiyun 	BT_DBG("session %p", session);
1271*4882a593Smuzhiyun 
1272*4882a593Smuzhiyun 	/* initialize runtime environment */
1273*4882a593Smuzhiyun 	hidp_session_get(session);
1274*4882a593Smuzhiyun 	__module_get(THIS_MODULE);
1275*4882a593Smuzhiyun 	set_user_nice(current, -15);
1276*4882a593Smuzhiyun 	hidp_set_timer(session);
1277*4882a593Smuzhiyun 
1278*4882a593Smuzhiyun 	add_wait_queue(sk_sleep(session->ctrl_sock->sk), &ctrl_wait);
1279*4882a593Smuzhiyun 	add_wait_queue(sk_sleep(session->intr_sock->sk), &intr_wait);
1280*4882a593Smuzhiyun 	/* This memory barrier is paired with wq_has_sleeper(). See
1281*4882a593Smuzhiyun 	 * sock_poll_wait() for more information why this is needed. */
1282*4882a593Smuzhiyun 	smp_mb__before_atomic();
1283*4882a593Smuzhiyun 
1284*4882a593Smuzhiyun 	/* notify synchronous startup that we're ready */
1285*4882a593Smuzhiyun 	atomic_inc(&session->state);
1286*4882a593Smuzhiyun 	wake_up(&session->state_queue);
1287*4882a593Smuzhiyun 
1288*4882a593Smuzhiyun 	/* run session */
1289*4882a593Smuzhiyun 	hidp_session_run(session);
1290*4882a593Smuzhiyun 
1291*4882a593Smuzhiyun 	/* cleanup runtime environment */
1292*4882a593Smuzhiyun 	remove_wait_queue(sk_sleep(session->intr_sock->sk), &intr_wait);
1293*4882a593Smuzhiyun 	remove_wait_queue(sk_sleep(session->ctrl_sock->sk), &ctrl_wait);
1294*4882a593Smuzhiyun 	wake_up_interruptible(&session->report_queue);
1295*4882a593Smuzhiyun 	hidp_del_timer(session);
1296*4882a593Smuzhiyun 
1297*4882a593Smuzhiyun 	/*
1298*4882a593Smuzhiyun 	 * If we stopped ourself due to any internal signal, we should try to
1299*4882a593Smuzhiyun 	 * unregister our own session here to avoid having it linger until the
1300*4882a593Smuzhiyun 	 * parent l2cap_conn dies or user-space cleans it up.
1301*4882a593Smuzhiyun 	 * This does not deadlock as we don't do any synchronous shutdown.
1302*4882a593Smuzhiyun 	 * Instead, this call has the same semantics as if user-space tried to
1303*4882a593Smuzhiyun 	 * delete the session.
1304*4882a593Smuzhiyun 	 */
1305*4882a593Smuzhiyun 	l2cap_unregister_user(session->conn, &session->user);
1306*4882a593Smuzhiyun 	hidp_session_put(session);
1307*4882a593Smuzhiyun 
1308*4882a593Smuzhiyun 	module_put_and_exit(0);
1309*4882a593Smuzhiyun 	return 0;
1310*4882a593Smuzhiyun }
1311*4882a593Smuzhiyun 
hidp_verify_sockets(struct socket * ctrl_sock,struct socket * intr_sock)1312*4882a593Smuzhiyun static int hidp_verify_sockets(struct socket *ctrl_sock,
1313*4882a593Smuzhiyun 			       struct socket *intr_sock)
1314*4882a593Smuzhiyun {
1315*4882a593Smuzhiyun 	struct l2cap_chan *ctrl_chan, *intr_chan;
1316*4882a593Smuzhiyun 	struct bt_sock *ctrl, *intr;
1317*4882a593Smuzhiyun 	struct hidp_session *session;
1318*4882a593Smuzhiyun 
1319*4882a593Smuzhiyun 	if (!l2cap_is_socket(ctrl_sock) || !l2cap_is_socket(intr_sock))
1320*4882a593Smuzhiyun 		return -EINVAL;
1321*4882a593Smuzhiyun 
1322*4882a593Smuzhiyun 	ctrl_chan = l2cap_pi(ctrl_sock->sk)->chan;
1323*4882a593Smuzhiyun 	intr_chan = l2cap_pi(intr_sock->sk)->chan;
1324*4882a593Smuzhiyun 
1325*4882a593Smuzhiyun 	if (bacmp(&ctrl_chan->src, &intr_chan->src) ||
1326*4882a593Smuzhiyun 	    bacmp(&ctrl_chan->dst, &intr_chan->dst))
1327*4882a593Smuzhiyun 		return -ENOTUNIQ;
1328*4882a593Smuzhiyun 
1329*4882a593Smuzhiyun 	ctrl = bt_sk(ctrl_sock->sk);
1330*4882a593Smuzhiyun 	intr = bt_sk(intr_sock->sk);
1331*4882a593Smuzhiyun 
1332*4882a593Smuzhiyun 	if (ctrl->sk.sk_state != BT_CONNECTED ||
1333*4882a593Smuzhiyun 	    intr->sk.sk_state != BT_CONNECTED)
1334*4882a593Smuzhiyun 		return -EBADFD;
1335*4882a593Smuzhiyun 
1336*4882a593Smuzhiyun 	/* early session check, we check again during session registration */
1337*4882a593Smuzhiyun 	session = hidp_session_find(&ctrl_chan->dst);
1338*4882a593Smuzhiyun 	if (session) {
1339*4882a593Smuzhiyun 		hidp_session_put(session);
1340*4882a593Smuzhiyun 		return -EEXIST;
1341*4882a593Smuzhiyun 	}
1342*4882a593Smuzhiyun 
1343*4882a593Smuzhiyun 	return 0;
1344*4882a593Smuzhiyun }
1345*4882a593Smuzhiyun 
hidp_connection_add(const struct hidp_connadd_req * req,struct socket * ctrl_sock,struct socket * intr_sock)1346*4882a593Smuzhiyun int hidp_connection_add(const struct hidp_connadd_req *req,
1347*4882a593Smuzhiyun 			struct socket *ctrl_sock,
1348*4882a593Smuzhiyun 			struct socket *intr_sock)
1349*4882a593Smuzhiyun {
1350*4882a593Smuzhiyun 	u32 valid_flags = BIT(HIDP_VIRTUAL_CABLE_UNPLUG) |
1351*4882a593Smuzhiyun 			  BIT(HIDP_BOOT_PROTOCOL_MODE);
1352*4882a593Smuzhiyun 	struct hidp_session *session;
1353*4882a593Smuzhiyun 	struct l2cap_conn *conn;
1354*4882a593Smuzhiyun 	struct l2cap_chan *chan;
1355*4882a593Smuzhiyun 	int ret;
1356*4882a593Smuzhiyun 
1357*4882a593Smuzhiyun 	ret = hidp_verify_sockets(ctrl_sock, intr_sock);
1358*4882a593Smuzhiyun 	if (ret)
1359*4882a593Smuzhiyun 		return ret;
1360*4882a593Smuzhiyun 
1361*4882a593Smuzhiyun 	if (req->flags & ~valid_flags)
1362*4882a593Smuzhiyun 		return -EINVAL;
1363*4882a593Smuzhiyun 
1364*4882a593Smuzhiyun 	chan = l2cap_pi(ctrl_sock->sk)->chan;
1365*4882a593Smuzhiyun 	conn = NULL;
1366*4882a593Smuzhiyun 	l2cap_chan_lock(chan);
1367*4882a593Smuzhiyun 	if (chan->conn)
1368*4882a593Smuzhiyun 		conn = l2cap_conn_get(chan->conn);
1369*4882a593Smuzhiyun 	l2cap_chan_unlock(chan);
1370*4882a593Smuzhiyun 
1371*4882a593Smuzhiyun 	if (!conn)
1372*4882a593Smuzhiyun 		return -EBADFD;
1373*4882a593Smuzhiyun 
1374*4882a593Smuzhiyun 	ret = hidp_session_new(&session, &chan->dst, ctrl_sock,
1375*4882a593Smuzhiyun 			       intr_sock, req, conn);
1376*4882a593Smuzhiyun 	if (ret)
1377*4882a593Smuzhiyun 		goto out_conn;
1378*4882a593Smuzhiyun 
1379*4882a593Smuzhiyun 	ret = l2cap_register_user(conn, &session->user);
1380*4882a593Smuzhiyun 	if (ret)
1381*4882a593Smuzhiyun 		goto out_session;
1382*4882a593Smuzhiyun 
1383*4882a593Smuzhiyun 	ret = 0;
1384*4882a593Smuzhiyun 
1385*4882a593Smuzhiyun out_session:
1386*4882a593Smuzhiyun 	hidp_session_put(session);
1387*4882a593Smuzhiyun out_conn:
1388*4882a593Smuzhiyun 	l2cap_conn_put(conn);
1389*4882a593Smuzhiyun 	return ret;
1390*4882a593Smuzhiyun }
1391*4882a593Smuzhiyun 
hidp_connection_del(struct hidp_conndel_req * req)1392*4882a593Smuzhiyun int hidp_connection_del(struct hidp_conndel_req *req)
1393*4882a593Smuzhiyun {
1394*4882a593Smuzhiyun 	u32 valid_flags = BIT(HIDP_VIRTUAL_CABLE_UNPLUG);
1395*4882a593Smuzhiyun 	struct hidp_session *session;
1396*4882a593Smuzhiyun 
1397*4882a593Smuzhiyun 	if (req->flags & ~valid_flags)
1398*4882a593Smuzhiyun 		return -EINVAL;
1399*4882a593Smuzhiyun 
1400*4882a593Smuzhiyun 	session = hidp_session_find(&req->bdaddr);
1401*4882a593Smuzhiyun 	if (!session)
1402*4882a593Smuzhiyun 		return -ENOENT;
1403*4882a593Smuzhiyun 
1404*4882a593Smuzhiyun 	if (req->flags & BIT(HIDP_VIRTUAL_CABLE_UNPLUG))
1405*4882a593Smuzhiyun 		hidp_send_ctrl_message(session,
1406*4882a593Smuzhiyun 				       HIDP_TRANS_HID_CONTROL |
1407*4882a593Smuzhiyun 				         HIDP_CTRL_VIRTUAL_CABLE_UNPLUG,
1408*4882a593Smuzhiyun 				       NULL, 0);
1409*4882a593Smuzhiyun 	else
1410*4882a593Smuzhiyun 		l2cap_unregister_user(session->conn, &session->user);
1411*4882a593Smuzhiyun 
1412*4882a593Smuzhiyun 	hidp_session_put(session);
1413*4882a593Smuzhiyun 
1414*4882a593Smuzhiyun 	return 0;
1415*4882a593Smuzhiyun }
1416*4882a593Smuzhiyun 
hidp_get_connlist(struct hidp_connlist_req * req)1417*4882a593Smuzhiyun int hidp_get_connlist(struct hidp_connlist_req *req)
1418*4882a593Smuzhiyun {
1419*4882a593Smuzhiyun 	struct hidp_session *session;
1420*4882a593Smuzhiyun 	int err = 0, n = 0;
1421*4882a593Smuzhiyun 
1422*4882a593Smuzhiyun 	BT_DBG("");
1423*4882a593Smuzhiyun 
1424*4882a593Smuzhiyun 	down_read(&hidp_session_sem);
1425*4882a593Smuzhiyun 
1426*4882a593Smuzhiyun 	list_for_each_entry(session, &hidp_session_list, list) {
1427*4882a593Smuzhiyun 		struct hidp_conninfo ci;
1428*4882a593Smuzhiyun 
1429*4882a593Smuzhiyun 		hidp_copy_session(session, &ci);
1430*4882a593Smuzhiyun 
1431*4882a593Smuzhiyun 		if (copy_to_user(req->ci, &ci, sizeof(ci))) {
1432*4882a593Smuzhiyun 			err = -EFAULT;
1433*4882a593Smuzhiyun 			break;
1434*4882a593Smuzhiyun 		}
1435*4882a593Smuzhiyun 
1436*4882a593Smuzhiyun 		if (++n >= req->cnum)
1437*4882a593Smuzhiyun 			break;
1438*4882a593Smuzhiyun 
1439*4882a593Smuzhiyun 		req->ci++;
1440*4882a593Smuzhiyun 	}
1441*4882a593Smuzhiyun 	req->cnum = n;
1442*4882a593Smuzhiyun 
1443*4882a593Smuzhiyun 	up_read(&hidp_session_sem);
1444*4882a593Smuzhiyun 	return err;
1445*4882a593Smuzhiyun }
1446*4882a593Smuzhiyun 
hidp_get_conninfo(struct hidp_conninfo * ci)1447*4882a593Smuzhiyun int hidp_get_conninfo(struct hidp_conninfo *ci)
1448*4882a593Smuzhiyun {
1449*4882a593Smuzhiyun 	struct hidp_session *session;
1450*4882a593Smuzhiyun 
1451*4882a593Smuzhiyun 	session = hidp_session_find(&ci->bdaddr);
1452*4882a593Smuzhiyun 	if (session) {
1453*4882a593Smuzhiyun 		hidp_copy_session(session, ci);
1454*4882a593Smuzhiyun 		hidp_session_put(session);
1455*4882a593Smuzhiyun 	}
1456*4882a593Smuzhiyun 
1457*4882a593Smuzhiyun 	return session ? 0 : -ENOENT;
1458*4882a593Smuzhiyun }
1459*4882a593Smuzhiyun 
hidp_init(void)1460*4882a593Smuzhiyun static int __init hidp_init(void)
1461*4882a593Smuzhiyun {
1462*4882a593Smuzhiyun 	BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION);
1463*4882a593Smuzhiyun 
1464*4882a593Smuzhiyun 	return hidp_init_sockets();
1465*4882a593Smuzhiyun }
1466*4882a593Smuzhiyun 
hidp_exit(void)1467*4882a593Smuzhiyun static void __exit hidp_exit(void)
1468*4882a593Smuzhiyun {
1469*4882a593Smuzhiyun 	hidp_cleanup_sockets();
1470*4882a593Smuzhiyun }
1471*4882a593Smuzhiyun 
1472*4882a593Smuzhiyun module_init(hidp_init);
1473*4882a593Smuzhiyun module_exit(hidp_exit);
1474*4882a593Smuzhiyun 
1475*4882a593Smuzhiyun MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
1476*4882a593Smuzhiyun MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
1477*4882a593Smuzhiyun MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
1478*4882a593Smuzhiyun MODULE_VERSION(VERSION);
1479*4882a593Smuzhiyun MODULE_LICENSE("GPL");
1480*4882a593Smuzhiyun MODULE_ALIAS("bt-proto-6");
1481