aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/bluetooth/hidp/core.c555
-rw-r--r--net/bluetooth/hidp/hidp.h53
2 files changed, 583 insertions, 25 deletions
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index cef1021d5403..8d30a33b27d9 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -1,6 +1,7 @@
1/* 1/*
2 HIDP implementation for Linux Bluetooth stack (BlueZ). 2 HIDP implementation for Linux Bluetooth stack (BlueZ).
3 Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org> 3 Copyright (C) 2003-2004 Marcel Holtmann <marcel@holtmann.org>
4 Copyright (C) 2013 David Herrmann <dh.herrmann@gmail.com>
4 5
5 This program is free software; you can redistribute it and/or modify 6 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License version 2 as 7 it under the terms of the GNU General Public License version 2 as
@@ -20,6 +21,7 @@
20 SOFTWARE IS DISCLAIMED. 21 SOFTWARE IS DISCLAIMED.
21*/ 22*/
22 23
24#include <linux/kref.h>
23#include <linux/module.h> 25#include <linux/module.h>
24#include <linux/file.h> 26#include <linux/file.h>
25#include <linux/kthread.h> 27#include <linux/kthread.h>
@@ -59,6 +61,13 @@ static unsigned char hidp_keycode[256] = {
59 61
60static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }; 62static unsigned char hidp_mkeyspat[] = { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 };
61 63
64static int hidp_session_probe(struct l2cap_conn *conn,
65 struct l2cap_user *user);
66static void hidp_session_remove(struct l2cap_conn *conn,
67 struct l2cap_user *user);
68static int hidp_session_thread(void *arg);
69static void hidp_session_terminate(struct hidp_session *s);
70
62static inline void hidp_schedule(struct hidp_session *session) 71static inline void hidp_schedule(struct hidp_session *session)
63{ 72{
64 struct sock *ctrl_sk = session->ctrl_sock->sk; 73 struct sock *ctrl_sk = session->ctrl_sock->sk;
@@ -838,7 +847,7 @@ static int hidp_setup_input(struct hidp_session *session,
838 input->relbit[0] |= BIT_MASK(REL_WHEEL); 847 input->relbit[0] |= BIT_MASK(REL_WHEEL);
839 } 848 }
840 849
841 input->dev.parent = &session->conn->dev; 850 input->dev.parent = &session->hconn->dev;
842 851
843 input->event = hidp_input_event; 852 input->event = hidp_input_event;
844 853
@@ -942,7 +951,7 @@ static int hidp_setup_hid(struct hidp_session *session,
942 snprintf(hid->uniq, sizeof(hid->uniq), "%pMR", 951 snprintf(hid->uniq, sizeof(hid->uniq), "%pMR",
943 &bt_sk(session->ctrl_sock->sk)->dst); 952 &bt_sk(session->ctrl_sock->sk)->dst);
944 953
945 hid->dev.parent = &session->conn->dev; 954 hid->dev.parent = &session->hconn->dev;
946 hid->ll_driver = &hidp_hid_driver; 955 hid->ll_driver = &hidp_hid_driver;
947 956
948 hid->hid_get_raw_report = hidp_get_raw_report; 957 hid->hid_get_raw_report = hidp_get_raw_report;
@@ -964,6 +973,543 @@ fault:
964 return err; 973 return err;
965} 974}
966 975
976/* initialize session devices */
977static int hidp_session_dev_init(struct hidp_session *session,
978 struct hidp_connadd_req *req)
979{
980 int ret;
981
982 if (req->rd_size > 0) {
983 ret = hidp_setup_hid(session, req);
984 if (ret && ret != -ENODEV)
985 return ret;
986 }
987
988 if (!session->hid) {
989 ret = hidp_setup_input(session, req);
990 if (ret < 0)
991 return ret;
992 }
993
994 return 0;
995}
996
997/* destroy session devices */
998static void hidp_session_dev_destroy(struct hidp_session *session)
999{
1000 if (session->hid)
1001 put_device(&session->hid->dev);
1002 else if (session->input)
1003 input_put_device(session->input);
1004
1005 kfree(session->rd_data);
1006 session->rd_data = NULL;
1007}
1008
1009/* add HID/input devices to their underlying bus systems */
1010static int hidp_session_dev_add(struct hidp_session *session)
1011{
1012 int ret;
1013
1014 /* Both HID and input systems drop a ref-count when unregistering the
1015 * device but they don't take a ref-count when registering them. Work
1016 * around this by explicitly taking a refcount during registration
1017 * which is dropped automatically by unregistering the devices. */
1018
1019 if (session->hid) {
1020 ret = hid_add_device(session->hid);
1021 if (ret)
1022 return ret;
1023 get_device(&session->hid->dev);
1024 } else if (session->input) {
1025 ret = input_register_device(session->input);
1026 if (ret)
1027 return ret;
1028 input_get_device(session->input);
1029 }
1030
1031 return 0;
1032}
1033
1034/* remove HID/input devices from their bus systems */
1035static void hidp_session_dev_del(struct hidp_session *session)
1036{
1037 if (session->hid)
1038 hid_destroy_device(session->hid);
1039 else if (session->input)
1040 input_unregister_device(session->input);
1041}
1042
1043/*
1044 * Create new session object
1045 * Allocate session object, initialize static fields, copy input data into the
1046 * object and take a reference to all sub-objects.
1047 * This returns 0 on success and puts a pointer to the new session object in
1048 * \out. Otherwise, an error code is returned.
1049 * The new session object has an initial ref-count of 1.
1050 */
1051static int hidp_session_new(struct hidp_session **out, const bdaddr_t *bdaddr,
1052 struct socket *ctrl_sock,
1053 struct socket *intr_sock,
1054 struct hidp_connadd_req *req,
1055 struct l2cap_conn *conn)
1056{
1057 struct hidp_session *session;
1058 int ret;
1059 struct bt_sock *ctrl, *intr;
1060
1061 ctrl = bt_sk(ctrl_sock->sk);
1062 intr = bt_sk(intr_sock->sk);
1063
1064 session = kzalloc(sizeof(*session), GFP_KERNEL);
1065 if (!session)
1066 return -ENOMEM;
1067
1068 /* object and runtime management */
1069 kref_init(&session->ref);
1070 atomic_set(&session->state, HIDP_SESSION_IDLING);
1071 init_waitqueue_head(&session->state_queue);
1072 session->flags = req->flags & (1 << HIDP_BLUETOOTH_VENDOR_ID);
1073
1074 /* connection management */
1075 bacpy(&session->bdaddr, bdaddr);
1076 session->conn = conn;
1077 session->user.probe = hidp_session_probe;
1078 session->user.remove = hidp_session_remove;
1079 session->ctrl_sock = ctrl_sock;
1080 session->intr_sock = intr_sock;
1081 skb_queue_head_init(&session->ctrl_transmit);
1082 skb_queue_head_init(&session->intr_transmit);
1083 session->ctrl_mtu = min_t(uint, l2cap_pi(ctrl)->chan->omtu,
1084 l2cap_pi(ctrl)->chan->imtu);
1085 session->intr_mtu = min_t(uint, l2cap_pi(intr)->chan->omtu,
1086 l2cap_pi(intr)->chan->imtu);
1087 session->idle_to = req->idle_to;
1088
1089 /* device management */
1090 setup_timer(&session->timer, hidp_idle_timeout,
1091 (unsigned long)session);
1092
1093 /* session data */
1094 mutex_init(&session->report_mutex);
1095 init_waitqueue_head(&session->report_queue);
1096
1097 ret = hidp_session_dev_init(session, req);
1098 if (ret)
1099 goto err_free;
1100
1101 l2cap_conn_get(session->conn);
1102 get_file(session->intr_sock->file);
1103 get_file(session->ctrl_sock->file);
1104 *out = session;
1105 return 0;
1106
1107err_free:
1108 kfree(session);
1109 return ret;
1110}
1111
1112/* increase ref-count of the given session by one */
1113static void hidp_session_get(struct hidp_session *session)
1114{
1115 kref_get(&session->ref);
1116}
1117
1118/* release callback */
1119static void session_free(struct kref *ref)
1120{
1121 struct hidp_session *session = container_of(ref, struct hidp_session,
1122 ref);
1123
1124 hidp_session_dev_destroy(session);
1125 skb_queue_purge(&session->ctrl_transmit);
1126 skb_queue_purge(&session->intr_transmit);
1127 fput(session->intr_sock->file);
1128 fput(session->ctrl_sock->file);
1129 l2cap_conn_put(session->conn);
1130 kfree(session);
1131}
1132
1133/* decrease ref-count of the given session by one */
1134static void hidp_session_put(struct hidp_session *session)
1135{
1136 kref_put(&session->ref, session_free);
1137}
1138
1139/*
1140 * Search the list of active sessions for a session with target address
1141 * \bdaddr. You must hold at least a read-lock on \hidp_session_sem. As long as
1142 * you do not release this lock, the session objects cannot vanish and you can
1143 * safely take a reference to the session yourself.
1144 */
1145static struct hidp_session *__hidp_session_find(const bdaddr_t *bdaddr)
1146{
1147 struct hidp_session *session;
1148
1149 list_for_each_entry(session, &hidp_session_list, list) {
1150 if (!bacmp(bdaddr, &session->bdaddr))
1151 return session;
1152 }
1153
1154 return NULL;
1155}
1156
1157/*
1158 * Same as __hidp_session_find() but no locks must be held. This also takes a
1159 * reference of the returned session (if non-NULL) so you must drop this
1160 * reference if you no longer use the object.
1161 */
1162static struct hidp_session *hidp_session_find(const bdaddr_t *bdaddr)
1163{
1164 struct hidp_session *session;
1165
1166 down_read(&hidp_session_sem);
1167
1168 session = __hidp_session_find(bdaddr);
1169 if (session)
1170 hidp_session_get(session);
1171
1172 up_read(&hidp_session_sem);
1173
1174 return session;
1175}
1176
1177/*
1178 * Start session synchronously
1179 * This starts a session thread and waits until initialization
1180 * is done or returns an error if it couldn't be started.
1181 * If this returns 0 the session thread is up and running. You must call
1182 * hipd_session_stop_sync() before deleting any runtime resources.
1183 */
1184static int hidp_session_start_sync(struct hidp_session *session)
1185{
1186 unsigned int vendor, product;
1187
1188 if (session->hid) {
1189 vendor = session->hid->vendor;
1190 product = session->hid->product;
1191 } else if (session->input) {
1192 vendor = session->input->id.vendor;
1193 product = session->input->id.product;
1194 } else {
1195 vendor = 0x0000;
1196 product = 0x0000;
1197 }
1198
1199 session->task = kthread_run(hidp_session_thread, session,
1200 "khidpd_%04x%04x", vendor, product);
1201 if (IS_ERR(session->task))
1202 return PTR_ERR(session->task);
1203
1204 while (atomic_read(&session->state) <= HIDP_SESSION_IDLING)
1205 wait_event(session->state_queue,
1206 atomic_read(&session->state) > HIDP_SESSION_IDLING);
1207
1208 return 0;
1209}
1210
1211/*
1212 * Terminate session thread
1213 * Wake up session thread and notify it to stop. This is asynchronous and
1214 * returns immediately. Call this whenever a runtime error occurs and you want
1215 * the session to stop.
1216 * Note: wake_up_process() performs any necessary memory-barriers for us.
1217 */
1218static void hidp_session_terminate(struct hidp_session *session)
1219{
1220 atomic_inc(&session->terminate);
1221 wake_up_process(session->task);
1222}
1223
1224/*
1225 * Probe HIDP session
1226 * This is called from the l2cap_conn core when our l2cap_user object is bound
1227 * to the hci-connection. We get the session via the \user object and can now
1228 * start the session thread, register the HID/input devices and link it into
1229 * the global session list.
1230 * The global session-list owns its own reference to the session object so you
1231 * can drop your own reference after registering the l2cap_user object.
1232 */
1233static int hidp_session_probe(struct l2cap_conn *conn,
1234 struct l2cap_user *user)
1235{
1236 struct hidp_session *session = container_of(user,
1237 struct hidp_session,
1238 user);
1239 struct hidp_session *s;
1240 int ret;
1241
1242 down_write(&hidp_session_sem);
1243
1244 /* check that no other session for this device exists */
1245 s = __hidp_session_find(&session->bdaddr);
1246 if (s) {
1247 ret = -EEXIST;
1248 goto out_unlock;
1249 }
1250
1251 ret = hidp_session_start_sync(session);
1252 if (ret)
1253 goto out_unlock;
1254
1255 ret = hidp_session_dev_add(session);
1256 if (ret)
1257 goto out_stop;
1258
1259 hidp_session_get(session);
1260 list_add(&session->list, &hidp_session_list);
1261 ret = 0;
1262 goto out_unlock;
1263
1264out_stop:
1265 hidp_session_terminate(session);
1266out_unlock:
1267 up_write(&hidp_session_sem);
1268 return ret;
1269}
1270
1271/*
1272 * Remove HIDP session
1273 * Called from the l2cap_conn core when either we explicitly unregistered
1274 * the l2cap_user object or if the underlying connection is shut down.
1275 * We signal the hidp-session thread to shut down, unregister the HID/input
1276 * devices and unlink the session from the global list.
1277 * This drops the reference to the session that is owned by the global
1278 * session-list.
1279 * Note: We _must_ not synchronosly wait for the session-thread to shut down.
1280 * This is, because the session-thread might be waiting for an HCI lock that is
1281 * held while we are called. Therefore, we only unregister the devices and
1282 * notify the session-thread to terminate. The thread itself owns a reference
1283 * to the session object so it can safely shut down.
1284 */
1285static void hidp_session_remove(struct l2cap_conn *conn,
1286 struct l2cap_user *user)
1287{
1288 struct hidp_session *session = container_of(user,
1289 struct hidp_session,
1290 user);
1291
1292 down_write(&hidp_session_sem);
1293
1294 hidp_session_terminate(session);
1295 hidp_session_dev_del(session);
1296 list_del(&session->list);
1297
1298 up_write(&hidp_session_sem);
1299
1300 hidp_session_put(session);
1301}
1302
1303/*
1304 * Session Worker
1305 * This performs the actual main-loop of the HIDP worker. We first check
1306 * whether the underlying connection is still alive, then parse all pending
1307 * messages and finally send all outstanding messages.
1308 */
1309static void hidp_session_run(struct hidp_session *session)
1310{
1311 struct sock *ctrl_sk = session->ctrl_sock->sk;
1312 struct sock *intr_sk = session->intr_sock->sk;
1313 struct sk_buff *skb;
1314
1315 for (;;) {
1316 /*
1317 * This thread can be woken up two ways:
1318 * - You call hidp_session_terminate() which sets the
1319 * session->terminate flag and wakes this thread up.
1320 * - Via modifying the socket state of ctrl/intr_sock. This
1321 * thread is woken up by ->sk_state_changed().
1322 *
1323 * Note: set_current_state() performs any necessary
1324 * memory-barriers for us.
1325 */
1326 set_current_state(TASK_INTERRUPTIBLE);
1327
1328 if (atomic_read(&session->terminate))
1329 break;
1330
1331 if (ctrl_sk->sk_state != BT_CONNECTED ||
1332 intr_sk->sk_state != BT_CONNECTED)
1333 break;
1334
1335 /* parse incoming intr-skbs */
1336 while ((skb = skb_dequeue(&intr_sk->sk_receive_queue))) {
1337 skb_orphan(skb);
1338 if (!skb_linearize(skb))
1339 hidp_recv_intr_frame(session, skb);
1340 else
1341 kfree_skb(skb);
1342 }
1343
1344 /* send pending intr-skbs */
1345 hidp_process_intr_transmit(session);
1346
1347 /* parse incoming ctrl-skbs */
1348 while ((skb = skb_dequeue(&ctrl_sk->sk_receive_queue))) {
1349 skb_orphan(skb);
1350 if (!skb_linearize(skb))
1351 hidp_recv_ctrl_frame(session, skb);
1352 else
1353 kfree_skb(skb);
1354 }
1355
1356 /* send pending ctrl-skbs */
1357 hidp_process_ctrl_transmit(session);
1358
1359 schedule();
1360 }
1361
1362 atomic_inc(&session->terminate);
1363 set_current_state(TASK_RUNNING);
1364}
1365
1366/*
1367 * HIDP session thread
1368 * This thread runs the I/O for a single HIDP session. Startup is synchronous
1369 * which allows us to take references to ourself here instead of doing that in
1370 * the caller.
1371 * When we are ready to run we notify the caller and call hidp_session_run().
1372 */
1373static int hidp_session_thread(void *arg)
1374{
1375 struct hidp_session *session = arg;
1376 wait_queue_t ctrl_wait, intr_wait;
1377
1378 BT_DBG("session %p", session);
1379
1380 /* initialize runtime environment */
1381 hidp_session_get(session);
1382 __module_get(THIS_MODULE);
1383 set_user_nice(current, -15);
1384 hidp_set_timer(session);
1385
1386 init_waitqueue_entry(&ctrl_wait, current);
1387 init_waitqueue_entry(&intr_wait, current);
1388 add_wait_queue(sk_sleep(session->ctrl_sock->sk), &ctrl_wait);
1389 add_wait_queue(sk_sleep(session->intr_sock->sk), &intr_wait);
1390 /* This memory barrier is paired with wq_has_sleeper(). See
1391 * sock_poll_wait() for more information why this is needed. */
1392 smp_mb();
1393
1394 /* notify synchronous startup that we're ready */
1395 atomic_inc(&session->state);
1396 wake_up(&session->state_queue);
1397
1398 /* run session */
1399 hidp_session_run(session);
1400
1401 /* cleanup runtime environment */
1402 remove_wait_queue(sk_sleep(session->intr_sock->sk), &intr_wait);
1403 remove_wait_queue(sk_sleep(session->intr_sock->sk), &ctrl_wait);
1404 wake_up_interruptible(&session->report_queue);
1405 hidp_del_timer(session);
1406
1407 /*
1408 * If we stopped ourself due to any internal signal, we should try to
1409 * unregister our own session here to avoid having it linger until the
1410 * parent l2cap_conn dies or user-space cleans it up.
1411 * This does not deadlock as we don't do any synchronous shutdown.
1412 * Instead, this call has the same semantics as if user-space tried to
1413 * delete the session.
1414 */
1415 l2cap_unregister_user(session->conn, &session->user);
1416 hidp_session_put(session);
1417
1418 module_put_and_exit(0);
1419 return 0;
1420}
1421
1422static int hidp_verify_sockets(struct socket *ctrl_sock,
1423 struct socket *intr_sock)
1424{
1425 struct bt_sock *ctrl, *intr;
1426 struct hidp_session *session;
1427
1428 if (!l2cap_is_socket(ctrl_sock) || !l2cap_is_socket(intr_sock))
1429 return -EINVAL;
1430
1431 ctrl = bt_sk(ctrl_sock->sk);
1432 intr = bt_sk(intr_sock->sk);
1433
1434 if (bacmp(&ctrl->src, &intr->src) || bacmp(&ctrl->dst, &intr->dst))
1435 return -ENOTUNIQ;
1436 if (ctrl->sk.sk_state != BT_CONNECTED ||
1437 intr->sk.sk_state != BT_CONNECTED)
1438 return -EBADFD;
1439
1440 /* early session check, we check again during session registration */
1441 session = hidp_session_find(&ctrl->dst);
1442 if (session) {
1443 hidp_session_put(session);
1444 return -EEXIST;
1445 }
1446
1447 return 0;
1448}
1449
1450int hidp_connection_add(struct hidp_connadd_req *req,
1451 struct socket *ctrl_sock,
1452 struct socket *intr_sock)
1453{
1454 struct hidp_session *session;
1455 struct l2cap_conn *conn;
1456 struct l2cap_chan *chan = l2cap_pi(ctrl_sock->sk)->chan;
1457 int ret;
1458
1459 ret = hidp_verify_sockets(ctrl_sock, intr_sock);
1460 if (ret)
1461 return ret;
1462
1463 conn = NULL;
1464 l2cap_chan_lock(chan);
1465 if (chan->conn) {
1466 l2cap_conn_get(chan->conn);
1467 conn = chan->conn;
1468 }
1469 l2cap_chan_unlock(chan);
1470
1471 if (!conn)
1472 return -EBADFD;
1473
1474 ret = hidp_session_new(&session, &bt_sk(ctrl_sock->sk)->dst, ctrl_sock,
1475 intr_sock, req, conn);
1476 if (ret)
1477 goto out_conn;
1478
1479 ret = l2cap_register_user(conn, &session->user);
1480 if (ret)
1481 goto out_session;
1482
1483 ret = 0;
1484
1485out_session:
1486 hidp_session_put(session);
1487out_conn:
1488 l2cap_conn_put(conn);
1489 return ret;
1490}
1491
1492int hidp_connection_del(struct hidp_conndel_req *req)
1493{
1494 struct hidp_session *session;
1495
1496 session = hidp_session_find(&req->bdaddr);
1497 if (!session)
1498 return -ENOENT;
1499
1500 if (req->flags & (1 << HIDP_VIRTUAL_CABLE_UNPLUG))
1501 hidp_send_ctrl_message(session,
1502 HIDP_TRANS_HID_CONTROL |
1503 HIDP_CTRL_VIRTUAL_CABLE_UNPLUG,
1504 NULL, 0);
1505 else
1506 l2cap_unregister_user(session->conn, &session->user);
1507
1508 hidp_session_put(session);
1509
1510 return 0;
1511}
1512
967int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock) 1513int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock)
968{ 1514{
969 struct hidp_session *session, *s; 1515 struct hidp_session *session, *s;
@@ -1006,8 +1552,8 @@ int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock,
1006 session->ctrl_sock = ctrl_sock; 1552 session->ctrl_sock = ctrl_sock;
1007 session->intr_sock = intr_sock; 1553 session->intr_sock = intr_sock;
1008 1554
1009 session->conn = hidp_get_connection(session); 1555 session->hconn = hidp_get_connection(session);
1010 if (!session->conn) { 1556 if (!session->hconn) {
1011 err = -ENOTCONN; 1557 err = -ENOTCONN;
1012 goto failed; 1558 goto failed;
1013 } 1559 }
@@ -1208,6 +1754,7 @@ module_init(hidp_init);
1208module_exit(hidp_exit); 1754module_exit(hidp_exit);
1209 1755
1210MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>"); 1756MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
1757MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
1211MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION); 1758MODULE_DESCRIPTION("Bluetooth HIDP ver " VERSION);
1212MODULE_VERSION(VERSION); 1759MODULE_VERSION(VERSION);
1213MODULE_LICENSE("GPL"); 1760MODULE_LICENSE("GPL");
diff --git a/net/bluetooth/hidp/hidp.h b/net/bluetooth/hidp/hidp.h
index c84442061793..c4fb980c2434 100644
--- a/net/bluetooth/hidp/hidp.h
+++ b/net/bluetooth/hidp/hidp.h
@@ -24,7 +24,9 @@
24#define __HIDP_H 24#define __HIDP_H
25 25
26#include <linux/types.h> 26#include <linux/types.h>
27#include <linux/kref.h>
27#include <net/bluetooth/bluetooth.h> 28#include <net/bluetooth/bluetooth.h>
29#include <net/bluetooth/l2cap.h>
28 30
29/* HIDP header masks */ 31/* HIDP header masks */
30#define HIDP_HEADER_TRANS_MASK 0xf0 32#define HIDP_HEADER_TRANS_MASK 0xf0
@@ -119,42 +121,55 @@ struct hidp_connlist_req {
119 struct hidp_conninfo __user *ci; 121 struct hidp_conninfo __user *ci;
120}; 122};
121 123
124int hidp_connection_add(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock);
125int hidp_connection_del(struct hidp_conndel_req *req);
122int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock); 126int hidp_add_connection(struct hidp_connadd_req *req, struct socket *ctrl_sock, struct socket *intr_sock);
123int hidp_del_connection(struct hidp_conndel_req *req); 127int hidp_del_connection(struct hidp_conndel_req *req);
124int hidp_get_connlist(struct hidp_connlist_req *req); 128int hidp_get_connlist(struct hidp_connlist_req *req);
125int hidp_get_conninfo(struct hidp_conninfo *ci); 129int hidp_get_conninfo(struct hidp_conninfo *ci);
126 130
131enum hidp_session_state {
132 HIDP_SESSION_IDLING,
133 HIDP_SESSION_RUNNING,
134};
135
127/* HIDP session defines */ 136/* HIDP session defines */
128struct hidp_session { 137struct hidp_session {
129 struct list_head list; 138 struct list_head list;
139 struct kref ref;
130 140
131 struct hci_conn *conn; 141 /* runtime management */
142 atomic_t state;
143 wait_queue_head_t state_queue;
144 atomic_t terminate;
145 struct task_struct *task;
146 unsigned long flags;
132 147
148 /* connection management */
149 bdaddr_t bdaddr;
150 struct hci_conn *hconn;
151 struct l2cap_conn *conn;
152 struct l2cap_user user;
133 struct socket *ctrl_sock; 153 struct socket *ctrl_sock;
134 struct socket *intr_sock; 154 struct socket *intr_sock;
135 155 struct sk_buff_head ctrl_transmit;
136 bdaddr_t bdaddr; 156 struct sk_buff_head intr_transmit;
137
138 unsigned long flags;
139 unsigned long idle_to;
140
141 uint ctrl_mtu; 157 uint ctrl_mtu;
142 uint intr_mtu; 158 uint intr_mtu;
159 unsigned long idle_to;
143 160
144 atomic_t terminate; 161 /* device management */
145 struct task_struct *task;
146
147 unsigned char keys[8];
148 unsigned char leds;
149
150 struct input_dev *input; 162 struct input_dev *input;
151
152 struct hid_device *hid; 163 struct hid_device *hid;
153
154 struct timer_list timer; 164 struct timer_list timer;
155 165
156 struct sk_buff_head ctrl_transmit; 166 /* Report descriptor */
157 struct sk_buff_head intr_transmit; 167 __u8 *rd_data;
168 uint rd_size;
169
170 /* session data */
171 unsigned char keys[8];
172 unsigned char leds;
158 173
159 /* Used in hidp_get_raw_report() */ 174 /* Used in hidp_get_raw_report() */
160 int waiting_report_type; /* HIDP_DATA_RTYPE_* */ 175 int waiting_report_type; /* HIDP_DATA_RTYPE_* */
@@ -166,10 +181,6 @@ struct hidp_session {
166 /* Used in hidp_output_raw_report() */ 181 /* Used in hidp_output_raw_report() */
167 int output_report_success; /* boolean */ 182 int output_report_success; /* boolean */
168 183
169 /* Report descriptor */
170 __u8 *rd_data;
171 uint rd_size;
172
173 wait_queue_head_t startup_queue; 184 wait_queue_head_t startup_queue;
174 int waiting_for_startup; 185 int waiting_for_startup;
175}; 186};