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