core.c revision 7b19ffc40b0247fcfe083644fdb621fdb3c05ef6
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 16469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 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 252448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg#include <linux/types.h> 26469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes 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> 334a332a385a86e31bfe181d969a8cb5579798fe03Alina Friedrichsen#include <linux/socket.h> 34469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#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 42469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <net/bluetooth/bluetooth.h> 43469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <net/bluetooth/hci_core.h> 44469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include <net/bluetooth/l2cap.h> 45469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 46469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#include "hidp.h" 47469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 48469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#ifndef CONFIG_BT_HIDP_DEBUG 49469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#undef BT_DBG 50469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#define BT_DBG(D...) 51469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#endif 52469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 53469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg#define VERSION "1.1" 54469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 55469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic DECLARE_RWSEM(hidp_session_sem); 56469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic LIST_HEAD(hidp_session_list); 57469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 58469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic unsigned char hidp_keycode[256] = { 59469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 0, 0, 0, 0, 30, 48, 46, 32, 18, 33, 34, 35, 23, 36, 37, 38, 60fffd0934b9390f34bec45762192b7edd3b12b4b5Johannes Berg 50, 49, 24, 25, 16, 19, 31, 20, 22, 47, 17, 45, 21, 44, 2, 3, 61469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 4, 5, 6, 7, 8, 9, 10, 11, 28, 1, 14, 15, 57, 12, 13, 26, 62469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 27, 43, 43, 39, 40, 41, 51, 52, 53, 58, 59, 60, 61, 62, 63, 64, 63af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 65, 66, 67, 68, 87, 88, 99, 70,119,110,102,104,111,107,109,106, 64af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 105,108,103, 69, 98, 55, 74, 78, 96, 79, 80, 81, 75, 76, 77, 71, 65af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 72, 73, 82, 83, 86,127,116,117,183,184,185,186,187,188,189,190, 66b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg 191,192,193,194,134,138,130,132,128,129,131,137,133,135,136,113, 67af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 115,114, 0, 0, 0,121, 0, 89, 93,124, 92, 94, 95, 0, 0, 0, 68469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 122,123, 90, 91, 85, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 69469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 0, 0, 0, 0, 0, 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, 71b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 72469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 73469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 29, 42, 56,125, 97, 54,100,126,164,166,165,163,161,115,114,113, 74469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 150,158,159,128,136,177,178,176,142,152,173,140 75469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg}; 76f446d10f214091408b7300f15c9adf60569edf28Johannes Berg 7757c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Bergstatic unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; 78b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg 792448798133d747ad339e57099e32a1d1e68aca1cJohannes Bergstatic struct hidp_session *__hidp_get_session(bdaddr_t *bdaddr) 802448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg{ 812448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg struct hidp_session *session; 82469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct list_head *p; 83af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 84af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg BT_DBG(""); 85af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 86af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg list_for_each(p, &hidp_session_list) { 87af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg session = list_entry(p, struct hidp_session, list); 88af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg if (!bacmp(bdaddr, &session->bdaddr)) 89af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg return session; 90469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 91af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg return NULL; 92af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg} 93469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 94469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic void __hidp_link_session(struct hidp_session *session) 95469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 96af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg __module_get(THIS_MODULE); 97469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg list_add(&session->list, &hidp_session_list); 98af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg} 99af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 100af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Bergstatic void __hidp_unlink_session(struct hidp_session *session) 10157c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg{ 102af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg list_del(&session->list); 103469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg module_put(THIS_MODULE); 104b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg} 105b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg 106b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Bergstatic void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci) 107b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg{ 108b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg bacpy(&ci->bdaddr, &session->bdaddr); 109b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg 110b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg ci->flags = session->flags; 111b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg ci->state = session->state; 112b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg 113b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg ci->vendor = 0x0000; 114469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg ci->product = 0x0000; 115af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg ci->version = 0x0000; 116469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg memset(ci->name, 0, 128); 117469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 118469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (session->input) { 119469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg ci->vendor = session->input->id.vendor; 12047846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg ci->product = session->input->id.product; 121469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg ci->version = session->input->id.version; 12257c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg if (session->input->name) 123707c1b4e68a2811ff2c9e75750a98a3310789a2dSujith strncpy(ci->name, session->input->name, 128); 124469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg else 125469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg strncpy(ci->name, "HID Boot Device", 128); 126469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 127469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 128469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 129469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic int hidp_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) 130469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 131b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg struct hidp_session *session = dev->private; 132469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct sk_buff *skb; 133469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg unsigned char newleds; 134469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 135469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg BT_DBG("input %p type %d code %d value %d", dev, type, code, value); 136469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 137469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (type != EV_LED) 138469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg return -1; 139469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 140469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg newleds = (!!test_bit(LED_KANA, dev->led) << 3) | 141469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg (!!test_bit(LED_COMPOSE, dev->led) << 3) | 142469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg (!!test_bit(LED_SCROLLL, dev->led) << 2) | 143af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg (!!test_bit(LED_CAPSL, dev->led) << 1) | 144469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg (!!test_bit(LED_NUML, dev->led)); 145469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 146469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (session->leds == newleds) 147469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg return 0; 148469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 149469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session->leds = newleds; 150469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 151469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (!(skb = alloc_skb(3, GFP_ATOMIC))) { 152469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg BT_ERR("Can't allocate memory for new frame"); 153b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg return -ENOMEM; 154b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg } 155469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 156469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg *skb_put(skb, 1) = HIDP_TRANS_DATA | HIDP_DATA_RTYPE_OUPUT; 157469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg *skb_put(skb, 1) = 0x01; 158469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg *skb_put(skb, 1) = newleds; 159469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 160469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg skb_queue_tail(&session->intr_transmit, skb); 161af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 162af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg hidp_schedule(session); 163af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 164af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg return 0; 165af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg} 166469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 1672d0ddec5b2b859f06116f631fc0ffe94fbceb556Johannes Bergstatic void hidp_input_report(struct hidp_session *session, struct sk_buff *skb) 1682d0ddec5b2b859f06116f631fc0ffe94fbceb556Johannes Berg{ 1692d0ddec5b2b859f06116f631fc0ffe94fbceb556Johannes Berg struct input_dev *dev = session->input; 1702d0ddec5b2b859f06116f631fc0ffe94fbceb556Johannes Berg unsigned char *keys = session->keys; 1712d0ddec5b2b859f06116f631fc0ffe94fbceb556Johannes Berg unsigned char *udata = skb->data + 1; 1722d0ddec5b2b859f06116f631fc0ffe94fbceb556Johannes Berg signed char *sdata = skb->data + 1; 1732d0ddec5b2b859f06116f631fc0ffe94fbceb556Johannes Berg int i, size = skb->len - 1; 174469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 175b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg switch (skb->data[0]) { 176469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case 0x01: /* Keyboard report */ 177469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg for (i = 0; i < 8; i++) 178af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1); 179af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 180469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg /* If all the key codes have been set to 0x01, it means 181f446d10f214091408b7300f15c9adf60569edf28Johannes Berg * too many keys were pressed at the same time. */ 182f446d10f214091408b7300f15c9adf60569edf28Johannes Berg if (!memcmp(udata + 2, hidp_mkeyspat, 6)) 183f446d10f214091408b7300f15c9adf60569edf28Johannes Berg break; 184af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 185469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg for (i = 2; i < 8; i++) { 186469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (keys[i] > 3 && memscan(udata + 2, keys[i], 6) == udata + 8) { 187af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg if (hidp_keycode[keys[i]]) 188af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg input_report_key(dev, hidp_keycode[keys[i]], 0); 189469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg else 1900c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg BT_ERR("Unknown key (scancode %#x) released.", keys[i]); 1910c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg } 192b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg 193b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg if (udata[i] > 3 && memscan(keys + 2, udata[i], 6) == keys + 8) { 194b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg if (hidp_keycode[udata[i]]) 1950c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg input_report_key(dev, hidp_keycode[udata[i]], 1); 19657c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg else 19757c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg BT_ERR("Unknown key (scancode %#x) pressed.", udata[i]); 19857c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg } 19957c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg } 2000c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg 201b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg memcpy(keys, udata, 8); 202b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg break; 203b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg 204b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg case 0x02: /* Mouse report */ 205b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg input_report_key(dev, BTN_LEFT, sdata[0] & 0x01); 206b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg input_report_key(dev, BTN_RIGHT, sdata[0] & 0x02); 207b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04); 208b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg input_report_key(dev, BTN_SIDE, sdata[0] & 0x08); 209b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg input_report_key(dev, BTN_EXTRA, sdata[0] & 0x10); 210b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg 211b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg input_report_rel(dev, REL_X, sdata[1]); 212b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg input_report_rel(dev, REL_Y, sdata[2]); 213b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg 214b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg if (size > 3) 215b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg input_report_rel(dev, REL_WHEEL, sdata[3]); 216b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg break; 2170c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg } 21857c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg 2190c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg input_sync(dev); 220b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg} 2210c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg 2220c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Bergstatic void hidp_idle_timeout(unsigned long arg) 223469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 224469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct hidp_session *session = (struct hidp_session *) arg; 225469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 226469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg atomic_inc(&session->terminate); 227469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_schedule(session); 228469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 229469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 230469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline void hidp_set_timer(struct hidp_session *session) 231469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 232469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (session->idle_to > 0) 233469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg mod_timer(&session->timer, jiffies + HZ * session->idle_to); 2340c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg} 235469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 236469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline void hidp_del_timer(struct hidp_session *session) 237469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 238469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (session->idle_to > 0) 239469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg del_timer(&session->timer); 240469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 241469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 242469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic int __hidp_send_ctrl_message(struct hidp_session *session, 243469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg unsigned char hdr, unsigned char *data, int size) 244469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 245469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct sk_buff *skb; 246469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 247469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg BT_DBG("session %p data %p size %d", session, data, size); 248469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 249469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (!(skb = alloc_skb(size + 1, GFP_ATOMIC))) { 250469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg BT_ERR("Can't allocate memory for new frame"); 251469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg return -ENOMEM; 252469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 253469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 254469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg *skb_put(skb, 1) = hdr; 255469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (data && size > 0) 256469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg memcpy(skb_put(skb, size), data, size); 257469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 258abe60632f311d515b082b450504ee24006023951Johannes Berg skb_queue_tail(&session->ctrl_transmit, skb); 259469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 260469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg return 0; 261469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 262469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 263469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic int inline hidp_send_ctrl_message(struct hidp_session *session, 264469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg unsigned char hdr, unsigned char *data, int size) 265469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 266469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg int err; 267469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 268469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg err = __hidp_send_ctrl_message(session, hdr, data, size); 269469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 270469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_schedule(session); 271469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 27247846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg return err; 273469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 274469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 275469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline void hidp_process_handshake(struct hidp_session *session, unsigned char param) 276469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 277469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg BT_DBG("session %p param 0x%02x", session, param); 278469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 279469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg switch (param) { 280469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_HSHK_SUCCESSFUL: 281469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg /* FIXME: Call into SET_ GET_ handlers here */ 282469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg break; 283469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 284469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_HSHK_NOT_READY: 285469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_HSHK_ERR_INVALID_REPORT_ID: 286469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_HSHK_ERR_UNSUPPORTED_REQUEST: 287469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_HSHK_ERR_INVALID_PARAMETER: 288469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg /* FIXME: Call into SET_ GET_ handlers here */ 2890c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg break; 2900c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg 291469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_HSHK_ERR_UNKNOWN: 2920c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg break; 293469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 294469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_HSHK_ERR_FATAL: 295469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg /* Device requests a reboot, as this is the only way this error 296469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg * can be recovered. */ 297469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg __hidp_send_ctrl_message(session, 298469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg HIDP_TRANS_HID_CONTROL | HIDP_CTRL_SOFT_RESET, NULL, 0); 299469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg break; 300469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 301af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg default: 302469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg __hidp_send_ctrl_message(session, 303469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0); 304469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg break; 3050c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg } 306469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 307469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 308469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline void hidp_process_hid_control(struct hidp_session *session, unsigned char param) 3090c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg{ 310469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg BT_DBG("session %p param 0x%02x", session, param); 311469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 312469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg switch (param) { 313469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_CTRL_NOP: 314469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg break; 315469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 316469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_CTRL_VIRTUAL_CABLE_UNPLUG: 317469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg /* Flush the transmit queues */ 31834e8f08231388f9e16c6f1e2461f53afaf7f1e5eAlina Friedrichsen skb_queue_purge(&session->ctrl_transmit); 3190c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg skb_queue_purge(&session->intr_transmit); 32034e8f08231388f9e16c6f1e2461f53afaf7f1e5eAlina Friedrichsen 32134e8f08231388f9e16c6f1e2461f53afaf7f1e5eAlina Friedrichsen /* Kill session thread */ 322469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg atomic_inc(&session->terminate); 323469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg break; 324469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 325469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_CTRL_HARD_RESET: 326469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_CTRL_SOFT_RESET: 327469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_CTRL_SUSPEND: 328469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_CTRL_EXIT_SUSPEND: 329469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg /* FIXME: We have to parse these and return no error */ 330469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg break; 331469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 332469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg default: 333469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg __hidp_send_ctrl_message(session, 334469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0); 335469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg break; 336469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 337469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 338469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 339469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline void hidp_process_data(struct hidp_session *session, struct sk_buff *skb, unsigned char param) 340469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 341469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg BT_DBG("session %p skb %p len %d param 0x%02x", session, skb, skb->len, param); 342469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 343469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg switch (param) { 344469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_DATA_RTYPE_INPUT: 345469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_set_timer(session); 3462448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg 3472448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg if (session->input) 3482448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg hidp_input_report(session, skb); 3492448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg break; 3502448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg 3512448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg case HIDP_DATA_RTYPE_OTHER: 3522448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg case HIDP_DATA_RTYPE_OUPUT: 353469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_DATA_RTYPE_FEATURE: 354469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg break; 355469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 356469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg default: 357469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg __hidp_send_ctrl_message(session, 358469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_INVALID_PARAMETER, NULL, 0); 359469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 360469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 361469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 362469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic inline void hidp_recv_ctrl_frame(struct hidp_session *session, struct sk_buff *skb) 363469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 3644a332a385a86e31bfe181d969a8cb5579798fe03Alina Friedrichsen unsigned char hdr, type, param; 3654a332a385a86e31bfe181d969a8cb5579798fe03Alina Friedrichsen 3664a332a385a86e31bfe181d969a8cb5579798fe03Alina Friedrichsen BT_DBG("session %p skb %p len %d", session, skb, skb->len); 3674a332a385a86e31bfe181d969a8cb5579798fe03Alina Friedrichsen 368469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hdr = skb->data[0]; 369469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg skb_pull(skb, 1); 370469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 371469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg type = hdr & HIDP_HEADER_TRANS_MASK; 37247846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg param = hdr & HIDP_HEADER_PARAM_MASK; 373469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 374469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg switch (type) { 375469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_TRANS_HANDSHAKE: 376469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_process_handshake(session, param); 377469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg break; 378469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 379469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_TRANS_HID_CONTROL: 380469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_process_hid_control(session, param); 381469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg break; 382469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 383469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg case HIDP_TRANS_DATA: 384469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_process_data(session, skb, param); 385469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg break; 386469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 387469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg default: 388469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg __hidp_send_ctrl_message(session, 389469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg HIDP_TRANS_HANDSHAKE | HIDP_HSHK_ERR_UNSUPPORTED_REQUEST, NULL, 0); 3902e10d330f8d5f039fa1e00baf59435ab0f11c722Felix Fietkau break; 391469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 392469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 393469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg kfree_skb(skb); 394469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 395af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 396af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Bergstatic inline void hidp_recv_intr_frame(struct hidp_session *session, struct sk_buff *skb) 397af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg{ 398af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg unsigned char hdr; 399469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 400af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg BT_DBG("session %p skb %p len %d", session, skb, skb->len); 401af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 40247846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg hdr = skb->data[0]; 403469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg skb_pull(skb, 1); 404469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 405469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (hdr == (HIDP_TRANS_DATA | HIDP_DATA_RTYPE_INPUT)) { 4062e10d330f8d5f039fa1e00baf59435ab0f11c722Felix Fietkau hidp_set_timer(session); 4072e10d330f8d5f039fa1e00baf59435ab0f11c722Felix Fietkau if (session->input) 4082e10d330f8d5f039fa1e00baf59435ab0f11c722Felix Fietkau hidp_input_report(session, skb); 409469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } else { 410469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg BT_DBG("Unsupported protocol header 0x%02x", hdr); 411469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 412469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 413469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg kfree_skb(skb); 41447846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg} 415469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 416469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic int hidp_send_frame(struct socket *sock, unsigned char *data, int len) 417469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 418469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct kvec iv = { data, len }; 419469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct msghdr msg; 420469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 421469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg BT_DBG("sock %p data %p len %d", sock, data, len); 422469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 423469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (!len) 424469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg return 0; 425469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 426469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg memset(&msg, 0, sizeof(msg)); 427469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 428469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg return kernel_sendmsg(sock, &msg, &iv, 1, len); 429469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 430469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 431469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic void hidp_process_transmit(struct hidp_session *session) 432469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 433469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct sk_buff *skb; 434469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 435469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg BT_DBG("session %p", session); 436469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 437469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg while ((skb = skb_dequeue(&session->ctrl_transmit))) { 438469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (hidp_send_frame(session->ctrl_sock, skb->data, skb->len) < 0) { 439469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg skb_queue_head(&session->ctrl_transmit, skb); 440469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg break; 441469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 442469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 443469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_set_timer(session); 444469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg kfree_skb(skb); 445469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 446469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 447469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg while ((skb = skb_dequeue(&session->intr_transmit))) { 448469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (hidp_send_frame(session->intr_sock, skb->data, skb->len) < 0) { 449469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg skb_queue_head(&session->intr_transmit, skb); 450469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg break; 451469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 452469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 453469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_set_timer(session); 454469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg kfree_skb(skb); 455469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 456469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 457ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault 458ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillaultstatic int hidp_session(void *arg) 459ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault{ 460469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct hidp_session *session = arg; 461469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct sock *ctrl_sk = session->ctrl_sock->sk; 462469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct sock *intr_sk = session->intr_sock->sk; 463469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct sk_buff *skb; 464469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg int vendor = 0x0000, product = 0x0000; 465af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg wait_queue_t ctrl_wait, intr_wait; 466af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 467469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg BT_DBG("session %p", session); 468469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 469af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg if (session->input) { 470450aae3d7b60a970f266349a837dfb30a539198bSujith vendor = session->input->id.vendor; 471450aae3d7b60a970f266349a837dfb30a539198bSujith product = session->input->id.product; 472450aae3d7b60a970f266349a837dfb30a539198bSujith } 473450aae3d7b60a970f266349a837dfb30a539198bSujith 474469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg daemonize("khidpd_%04x%04x", vendor, product); 475469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg set_user_nice(current, -15); 476469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg current->flags |= PF_NOFREEZE; 477af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 478469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg init_waitqueue_entry(&ctrl_wait, current); 479469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg init_waitqueue_entry(&intr_wait, current); 480469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg add_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait); 48147846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg add_wait_queue(intr_sk->sk_sleep, &intr_wait); 482469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg while (!atomic_read(&session->terminate)) { 483f3b85252f081581a8f257545ed748062dce7798bJohannes Berg set_current_state(TASK_INTERRUPTIBLE); 484469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 485469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (ctrl_sk->sk_state != BT_CONNECTED || intr_sk->sk_state != BT_CONNECTED) 486af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg break; 487469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 488469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) { 489469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg skb_orphan(skb); 490469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_recv_ctrl_frame(session, skb); 491469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 492469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 493469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) { 494469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg skb_orphan(skb); 495af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg hidp_recv_intr_frame(session, skb); 496469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 497469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 498469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_process_transmit(session); 499469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 500469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg schedule(); 501469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 502469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg set_current_state(TASK_RUNNING); 50347846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg remove_wait_queue(intr_sk->sk_sleep, &intr_wait); 504469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg remove_wait_queue(ctrl_sk->sk_sleep, &ctrl_wait); 505469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 506469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg down_write(&hidp_session_sem); 507469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 508469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_del_timer(session); 50947846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg 510469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg fput(session->intr_sock->file); 511af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 512469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg wait_event_timeout(*(ctrl_sk->sk_sleep), 513469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg (ctrl_sk->sk_state == BT_CLOSED), msecs_to_jiffies(500)); 514469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 515fffd0934b9390f34bec45762192b7edd3b12b4b5Johannes Berg fput(session->ctrl_sock->file); 516469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 517469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg __hidp_unlink_session(session); 518469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 519469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (session->input) { 52057c4d7b4c4986037be51476b8e3025d5ba18d8b8Johannes Berg input_unregister_device(session->input); 521b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg session->input = NULL; 522b59066a291ca7c12a1e5b58f3ada5ab6e32cb6bdJohannes Berg } 523469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 524469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg up_write(&hidp_session_sem); 525ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault 526ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault kfree(session); 527ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault return 0; 528ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault} 529af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 530469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic struct device *hidp_get_device(struct hidp_session *session) 531469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 532469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src; 5330c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst; 534af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg struct hci_dev *hdev; 535469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct hci_conn *conn; 536469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 537e0d61887c2ee19bb63f6a8c0e2c149184e879501Johannes Berg hdev = hci_get_route(dst, src); 538469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (!hdev) 539469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg return NULL; 540469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 541469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); 54247846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg 543469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hci_dev_put(hdev); 544469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 545469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg return conn ? &conn->dev : NULL; 546af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg} 547469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 548e0d61887c2ee19bb63f6a8c0e2c149184e879501Johannes Bergstatic inline void hidp_setup_input(struct hidp_session *session, struct hidp_connadd_req *req) 549fffd0934b9390f34bec45762192b7edd3b12b4b5Johannes Berg{ 550e0d61887c2ee19bb63f6a8c0e2c149184e879501Johannes Berg struct input_dev *input = session->input; 551af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg int i; 552af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 553af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg input->private = session; 554af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 555af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg input->name = "Bluetooth HID Boot Protocol Device"; 556469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 5570c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg input->id.bustype = BUS_BLUETOOTH; 5580c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg input->id.vendor = req->vendor; 5590c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg input->id.product = req->product; 5600c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg input->id.version = req->version; 5610c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg 5620c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg if (req->subclass & 0x40) { 5630c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg set_bit(EV_KEY, input->evbit); 564469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg set_bit(EV_LED, input->evbit); 5650c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg set_bit(EV_REP, input->evbit); 566469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 567469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg set_bit(LED_NUML, input->ledbit); 5680c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg set_bit(LED_CAPSL, input->ledbit); 569469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg set_bit(LED_SCROLLL, input->ledbit); 570469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg set_bit(LED_COMPOSE, input->ledbit); 571469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg set_bit(LED_KANA, input->ledbit); 572469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 5730c1ad2cac1cb54db38fd4cc1822965071ee83f6eJohannes Berg for (i = 0; i < sizeof(hidp_keycode); i++) 574469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg set_bit(hidp_keycode[i], input->keybit); 575af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg clear_bit(0, input->keybit); 576469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 577af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 578d419b9f0fa69e79ccba3e5e79a58a52ae0c2ed6aReinette Chatre if (req->subclass & 0x80) { 579469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg input->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); 580469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg input->keybit[LONG(BTN_MOUSE)] = BIT(BTN_LEFT) | BIT(BTN_RIGHT) | BIT(BTN_MIDDLE); 581469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg input->relbit[0] = BIT(REL_X) | BIT(REL_Y); 582469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg input->keybit[LONG(BTN_MOUSE)] |= BIT(BTN_SIDE) | BIT(BTN_EXTRA); 583469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg input->relbit[0] |= BIT(REL_WHEEL); 584469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 585ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault 586469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg input->cdev.dev = hidp_get_device(session); 587469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 58847846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg input->event = hidp_input_event; 589469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 590f3b85252f081581a8f257545ed748062dce7798bJohannes Berg input_register_device(input); 591f3b85252f081581a8f257545ed748062dce7798bJohannes Berg} 592ce9058aedd75f14785400dcc49a2bc352ca38871Benoit Papillault 593469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergint hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock) 594469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 595469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct hidp_session *session, *s; 596469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg int err; 597af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 598af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg BT_DBG(""); 599af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 600af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg if (bacmp(&bt_sk(ctrl_sock->sk)->src, &bt_sk(intr_sock->sk)->src) || 601469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg bacmp(&bt_sk(ctrl_sock->sk)->dst, &bt_sk(intr_sock->sk)->dst)) 60247846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg return -ENOTUNIQ; 603469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 604469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session = kzalloc(sizeof(struct hidp_session), GFP_KERNEL); 605469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (!session) 606469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg return -ENOMEM; 607469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 608469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session->input = input_allocate_device(); 609469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (!session->input) { 610af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg kfree(session); 611af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg return -ENOMEM; 612469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 613469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 614469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg down_write(&hidp_session_sem); 615469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 616469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg s = __hidp_get_session(&bt_sk(ctrl_sock->sk)->dst); 617469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (s && s->state == BT_CONNECTED) { 618469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg err = -EEXIST; 619469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg goto failed; 620469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 621469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 622469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg bacpy(&session->bdaddr, &bt_sk(ctrl_sock->sk)->dst); 623469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 624469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl_sock->sk)->omtu, l2cap_pi(ctrl_sock->sk)->imtu); 625469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session->intr_mtu = min_t(uint, l2cap_pi(intr_sock->sk)->omtu, l2cap_pi(intr_sock->sk)->imtu); 626469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 627af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg BT_DBG("ctrl mtu %d intr mtu %d", session->ctrl_mtu, session->intr_mtu); 628469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 629469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session->ctrl_sock = ctrl_sock; 6302448798133d747ad339e57099e32a1d1e68aca1cJohannes Berg session->intr_sock = intr_sock; 631469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session->state = BT_CONNECTED; 632469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 633469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg init_timer(&session->timer); 634469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 63547846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg session->timer.function = hidp_idle_timeout; 636469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session->timer.data = (unsigned long) session; 637469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 638469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg skb_queue_head_init(&session->ctrl_transmit); 639469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg skb_queue_head_init(&session->intr_transmit); 640469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 641469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID); 642469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session->idle_to = req->idle_to; 643469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 644469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (session->input) 645469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_setup_input(session, req); 646469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 647469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg __hidp_link_session(session); 648469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 649469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_set_timer(session); 650469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 651469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg err = kernel_thread(hidp_session, session, CLONE_KERNEL); 652469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (err < 0) 65347846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg goto unlink; 654469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 655469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (session->input) { 656469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_send_ctrl_message(session, 657469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg HIDP_TRANS_SET_PROTOCOL | HIDP_PROTO_BOOT, NULL, 0); 658469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session->flags |= (1 << HIDP_BOOT_PROTOCOL_MODE); 659af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg 660469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session->leds = 0xff; 661469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_input_event(session->input, EV_LED, 0, 0); 662469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 663469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 664469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg up_write(&hidp_session_sem); 665af8cdcd828ad751fae8e6cbfe94eef9f2f23b14bJohannes Berg return 0; 666469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 667469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergunlink: 668469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_del_timer(session); 669469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 670469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg __hidp_unlink_session(session); 671469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 672469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (session->input) { 67347846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg input_unregister_device(session->input); 674469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session->input = NULL; /* don't try to free it here */ 67562ae67be31c2346b6d74653a148ddbd1b9a94424Johannes Berg } 67662ae67be31c2346b6d74653a148ddbd1b9a94424Johannes Berg 677469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergfailed: 678469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg up_write(&hidp_session_sem); 679469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 680469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg kfree(session->input); 681469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg kfree(session); 682469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg return err; 683469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 684469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 685469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergint hidp_del_connection(struct hidp_conndel_req *req) 686469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 68747846c9b0c10808d9337d2e7d09361f3e0a0a71aJohannes Berg struct hidp_session *session; 688469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg int err = 0; 689469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 690469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg BT_DBG(""); 691469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 692469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg down_read(&hidp_session_sem); 693469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 694469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session = __hidp_get_session(&req->bdaddr); 695469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (session) { 696469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG)) { 697469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_send_ctrl_message(session, 698469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG, NULL, 0); 699469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } else { 700469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg /* Flush the transmit queues */ 701469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg skb_queue_purge(&session->ctrl_transmit); 702469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg skb_queue_purge(&session->intr_transmit); 703469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 704469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg /* Kill session thread */ 705469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg atomic_inc(&session->terminate); 706469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_schedule(session); 707469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 708469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } else 709469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg err = -ENOENT; 710469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 711469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg up_read(&hidp_session_sem); 712469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg return err; 713469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 714469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 715469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergint hidp_get_connlist(struct hidp_connlist_req *req) 716469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 717469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct list_head *p; 718469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg int err = 0, n = 0; 719469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 720469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg BT_DBG(""); 721469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 722469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg down_read(&hidp_session_sem); 723469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 724469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg list_for_each(p, &hidp_session_list) { 725f1d58c2521eb160178b2151d6326d8dc5d7c8560Johannes Berg struct hidp_session *session; 726469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct hidp_conninfo ci; 727469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 728469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session = list_entry(p, struct hidp_session, list); 729469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 730469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg __hidp_copy_session(session, &ci); 731469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 732469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (copy_to_user(req->ci, &ci, sizeof(ci))) { 733469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg err = -EFAULT; 734469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg break; 735469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 736469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 737469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (++n >= req->cnum) 738469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg break; 739469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 740469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg req->ci++; 741469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg } 742469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg req->cnum = n; 743469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 744469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg up_read(&hidp_session_sem); 745469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg return err; 746469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 747469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 748469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergint hidp_get_conninfo(struct hidp_conninfo *ci) 749469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 750469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg struct hidp_session *session; 751469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg int err = 0; 752469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 753469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg down_read(&hidp_session_sem); 754469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 755469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg session = __hidp_get_session(&ci->bdaddr); 756469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg if (session) 7575bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg __hidp_copy_session(session, ci); 7585bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg else 7595bb644a0fd25a5e083ecbfaa92a211db99aa6ef7Johannes Berg err = -ENOENT; 7609607e6b66a0d25ca63b70d54a4283fa13d8f7c9dJohannes Berg 761469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg up_read(&hidp_session_sem); 762469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg return err; 763fbe9c429f195111bbf7f1630efa19aee295fd8e7Helmut Schaa} 764469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 765469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic int __init hidp_init(void) 766469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 767469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg l2cap_load(); 768469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 769469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg BT_INFO("HIDP (Human Interface Emulation) ver %s", VERSION); 770469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 771469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg return hidp_init_sockets(); 772469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 773469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 774469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergstatic void __exit hidp_exit(void) 775469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg{ 776469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg hidp_cleanup_sockets(); 777469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg} 778469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 779469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergmodule_init(hidp_init); 780469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Bergmodule_exit(hidp_exit); 781469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg 782469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes BergMODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); 783469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes BergMODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION); 784469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes BergMODULE_VERSION(VERSION); 785469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes BergMODULE_LICENSE("GPL"); 786469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes BergMODULE_ALIAS("bt-proto-6"); 787469002983fc90c2ff0959e2b03335c0fe2e4d5a9Johannes Berg