aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/hidp/hidp.h
diff options
context:
space:
mode:
authorDavid Herrmann <dh.herrmann@gmail.com>2013-04-06 14:28:46 -0400
committerGustavo Padovan <gustavo.padovan@collabora.co.uk>2013-04-17 02:03:51 -0400
commitb4f34d8d9d26b2428fa7cf7c8f97690a297978e6 (patch)
tree9b513935dfb1b7b83a711462ff4bc9a6f3dbfce0 /net/bluetooth/hidp/hidp.h
parent2c8e1411e93391c5a78f55b09697a997474a4707 (diff)
Bluetooth: hidp: add new session-management helpers
This is a rewrite of the HIDP session management. It implements HIDP as an l2cap_user sub-module so we get proper notification when the underlying connection goes away. The helpers are not yet used but only added in this commit. The old session management is still used and will be removed in a following patch. The old session-management was flawed. Hotplugging is horribly broken and we have no way of getting notified when the underlying connection goes down. The whole idea of removing the HID/input sub-devices from within the session itself is broken and suffers from major dead-locks. We never can guarantee that the session can unregister itself as long as we use synchronous shutdowns. This can only work with asynchronous shutdowns. However, in this case we _must_ be able to unregister the session from the outside as otherwise the l2cap_conn object might be unlinked before we are. The new session-management is based on l2cap_user. There is only one way how to add a session and how to delete a session: "probe" and "remove" callbacks from l2cap_user. This guarantees that the session can be registered and unregistered at _any_ time without any synchronous shutdown. On the other hand, much work has been put into proper session-refcounting. We can unregister/unlink the session only if we can guarantee that it will stay alive. But for asynchronous shutdowns we never know when the last user goes away so we must use proper ref-counting. The old ->conn field has been renamed to ->hconn so we can reuse ->conn in the new session management. No other existing HIDP code is modified. Signed-off-by: David Herrmann <dh.herrmann@gmail.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Diffstat (limited to 'net/bluetooth/hidp/hidp.h')
-rw-r--r--net/bluetooth/hidp/hidp.h53
1 files changed, 32 insertions, 21 deletions
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};