blob: 26233d4d371c2681c67a1168130671125441e1c1 [file] [log] [blame]
Ron Shaffer04fafe42010-05-28 11:53:45 -04001/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002 BlueZ - Bluetooth protocol stack for Linux
Ron Shaffer2d0a0342010-05-28 11:53:46 -04003 Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Linus Torvalds1da177e2005-04-16 15:20:36 -07004
5 Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License version 2 as
9 published by the Free Software Foundation;
10
11 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
12 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS.
14 IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY
Ron Shaffer04fafe42010-05-28 11:53:45 -040015 CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES
16 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19
Ron Shaffer04fafe42010-05-28 11:53:45 -040020 ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS,
21 COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS
Linus Torvalds1da177e2005-04-16 15:20:36 -070022 SOFTWARE IS DISCLAIMED.
23*/
24
25#ifndef __HCI_CORE_H
26#define __HCI_CORE_H
27
Linus Torvalds1da177e2005-04-16 15:20:36 -070028#include <net/bluetooth/hci.h>
29
30/* HCI upper protocols */
31#define HCI_PROTO_L2CAP 0
32#define HCI_PROTO_SCO 1
33
Linus Torvalds1da177e2005-04-16 15:20:36 -070034/* HCI Core structures */
Linus Torvalds1da177e2005-04-16 15:20:36 -070035struct inquiry_data {
36 bdaddr_t bdaddr;
37 __u8 pscan_rep_mode;
38 __u8 pscan_period_mode;
39 __u8 pscan_mode;
40 __u8 dev_class[3];
Marcel Holtmann1ebb9252005-11-08 09:57:21 -080041 __le16 clock_offset;
Linus Torvalds1da177e2005-04-16 15:20:36 -070042 __s8 rssi;
Marcel Holtmann41a96212008-07-14 20:13:48 +020043 __u8 ssp_mode;
Linus Torvalds1da177e2005-04-16 15:20:36 -070044};
45
46struct inquiry_entry {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +020047 struct inquiry_entry *next;
Linus Torvalds1da177e2005-04-16 15:20:36 -070048 __u32 timestamp;
49 struct inquiry_data data;
50};
51
52struct inquiry_cache {
Andrei Emeltchenko70f230202010-12-01 16:58:25 +020053 spinlock_t lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -070054 __u32 timestamp;
Andrei Emeltchenko70f230202010-12-01 16:58:25 +020055 struct inquiry_entry *list;
Linus Torvalds1da177e2005-04-16 15:20:36 -070056};
57
58struct hci_conn_hash {
59 struct list_head list;
60 spinlock_t lock;
61 unsigned int acl_num;
62 unsigned int sco_num;
Ville Tervofcd89c02011-02-10 22:38:47 -030063 unsigned int le_num;
Linus Torvalds1da177e2005-04-16 15:20:36 -070064};
65
Johan Hedbergf0358562010-05-18 13:20:32 +020066struct bdaddr_list {
67 struct list_head list;
68 bdaddr_t bdaddr;
69};
Johan Hedberg2aeb9a12011-01-04 12:08:51 +020070
71struct bt_uuid {
72 struct list_head list;
73 u8 uuid[16];
Johan Hedberg1aff6f02011-01-13 21:56:52 +020074 u8 svc_hint;
Johan Hedberg2aeb9a12011-01-04 12:08:51 +020075};
76
Johan Hedberg55ed8ca12011-01-17 14:41:05 +020077struct link_key {
78 struct list_head list;
79 bdaddr_t bdaddr;
80 u8 type;
81 u8 val[16];
82 u8 pin_len;
83};
84
Szymon Janc2763eda2011-03-22 13:12:22 +010085struct oob_data {
86 struct list_head list;
87 bdaddr_t bdaddr;
88 u8 hash[16];
89 u8 randomizer[16];
90};
91
Andre Guedes76c86862011-05-26 16:23:50 -030092struct adv_entry {
93 struct list_head list;
94 bdaddr_t bdaddr;
95 u8 bdaddr_type;
96};
97
Suraj Sumangalacd4c5392010-07-14 13:02:16 +053098#define NUM_REASSEMBLY 4
Linus Torvalds1da177e2005-04-16 15:20:36 -070099struct hci_dev {
100 struct list_head list;
101 spinlock_t lock;
102 atomic_t refcnt;
103
104 char name[8];
105 unsigned long flags;
106 __u16 id;
Marcel Holtmannc13854c2010-02-08 15:27:07 +0100107 __u8 bus;
Marcel Holtmann943da252010-02-13 02:28:41 +0100108 __u8 dev_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109 bdaddr_t bdaddr;
Johan Hedberg1f6c6372011-03-16 14:29:35 +0200110 __u8 dev_name[HCI_MAX_NAME_LENGTH];
Johan Hedberg80a1e1d2011-03-28 14:07:23 +0300111 __u8 eir[HCI_MAX_EIR_LENGTH];
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200112 __u8 dev_class[3];
Johan Hedberg1aff6f02011-01-13 21:56:52 +0200113 __u8 major_class;
114 __u8 minor_class;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700115 __u8 features[8];
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200116 __u8 commands[64];
Marcel Holtmann333140b2008-07-14 20:13:48 +0200117 __u8 ssp_mode;
Marcel Holtmann1143e5a2006-09-23 09:57:20 +0200118 __u8 hci_ver;
119 __u16 hci_rev;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200120 __u8 lmp_ver;
Marcel Holtmann1143e5a2006-09-23 09:57:20 +0200121 __u16 manufacturer;
Johan Hedbergd5859e22011-01-25 01:19:58 +0200122 __le16 lmp_subver;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123 __u16 voice_setting;
Johan Hedberg17fa4b92011-01-25 13:28:33 +0200124 __u8 io_capability;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125
126 __u16 pkt_type;
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200127 __u16 esco_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128 __u16 link_policy;
129 __u16 link_mode;
130
Marcel Holtmann04837f62006-07-03 10:02:33 +0200131 __u32 idle_timeout;
132 __u16 sniff_min_interval;
133 __u16 sniff_max_interval;
134
Johan Hedberg9f616562011-04-28 11:28:54 -0700135 unsigned int auto_accept_delay;
136
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137 unsigned long quirks;
138
139 atomic_t cmd_cnt;
140 unsigned int acl_cnt;
141 unsigned int sco_cnt;
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300142 unsigned int le_cnt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143
144 unsigned int acl_mtu;
145 unsigned int sco_mtu;
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300146 unsigned int le_mtu;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700147 unsigned int acl_pkts;
148 unsigned int sco_pkts;
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300149 unsigned int le_pkts;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700150
Linus Torvalds1da177e2005-04-16 15:20:36 -0700151 unsigned long acl_last_tx;
152 unsigned long sco_last_tx;
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300153 unsigned long le_last_tx;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154
Marcel Holtmannf48fd9c2010-03-20 15:20:04 +0100155 struct workqueue_struct *workqueue;
156
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200157 struct work_struct power_on;
158 struct work_struct power_off;
159 struct timer_list off_timer;
160
Ville Tervo6bd32322011-02-16 16:32:41 +0200161 struct timer_list cmd_timer;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700162 struct tasklet_struct cmd_task;
163 struct tasklet_struct rx_task;
164 struct tasklet_struct tx_task;
165
166 struct sk_buff_head rx_q;
167 struct sk_buff_head raw_q;
168 struct sk_buff_head cmd_q;
169
170 struct sk_buff *sent_cmd;
Suraj Sumangalacd4c5392010-07-14 13:02:16 +0530171 struct sk_buff *reassembly[NUM_REASSEMBLY];
Linus Torvalds1da177e2005-04-16 15:20:36 -0700172
Thomas Gleixnera6a67ef2009-07-26 08:18:19 +0000173 struct mutex req_lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700174 wait_queue_head_t req_wait_q;
175 __u32 req_status;
176 __u32 req_result;
Johan Hedberga5040ef2011-01-10 13:28:59 +0200177
178 __u16 init_last_cmd;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700179
Vinicius Costa Gomes3a0259b2011-06-09 18:50:43 -0300180 struct crypto_blkcipher *tfm;
181
Linus Torvalds1da177e2005-04-16 15:20:36 -0700182 struct inquiry_cache inq_cache;
183 struct hci_conn_hash conn_hash;
David Millerea4bd8b2010-07-30 21:54:49 -0700184 struct list_head blacklist;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700185
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200186 struct list_head uuids;
187
Johan Hedberg55ed8ca12011-01-17 14:41:05 +0200188 struct list_head link_keys;
189
Szymon Janc2763eda2011-03-22 13:12:22 +0100190 struct list_head remote_oob_data;
191
Andre Guedes76c86862011-05-26 16:23:50 -0300192 struct list_head adv_entries;
Andre Guedes35815082011-05-26 16:23:53 -0300193 struct timer_list adv_timer;
Andre Guedes76c86862011-05-26 16:23:50 -0300194
Linus Torvalds1da177e2005-04-16 15:20:36 -0700195 struct hci_dev_stats stat;
196
197 struct sk_buff_head driver_init;
198
199 void *driver_data;
200 void *core_data;
201
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200202 atomic_t promisc;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203
Marcel Holtmannca325f62010-02-08 16:22:31 +0100204 struct dentry *debugfs;
205
Marcel Holtmanna91f2e32006-07-03 10:02:41 +0200206 struct device *parent;
207 struct device dev;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208
Marcel Holtmann611b30f2009-06-08 14:41:38 +0200209 struct rfkill *rfkill;
210
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200211 struct module *owner;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212
213 int (*open)(struct hci_dev *hdev);
214 int (*close)(struct hci_dev *hdev);
215 int (*flush)(struct hci_dev *hdev);
216 int (*send)(struct sk_buff *skb);
217 void (*destruct)(struct hci_dev *hdev);
218 void (*notify)(struct hci_dev *hdev, unsigned int evt);
219 int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);
220};
221
222struct hci_conn {
223 struct list_head list;
224
Szymon Jancadc42662011-02-17 16:42:00 +0100225 atomic_t refcnt;
226 spinlock_t lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700227
Szymon Jancadc42662011-02-17 16:42:00 +0100228 bdaddr_t dst;
Waldemar Rymarkiewicz5a9d0a32011-06-07 11:18:06 +0200229 __u8 dst_type;
Szymon Jancadc42662011-02-17 16:42:00 +0100230 __u16 handle;
231 __u16 state;
232 __u8 mode;
233 __u8 type;
234 __u8 out;
235 __u8 attempt;
236 __u8 dev_class[3];
237 __u8 features[8];
238 __u8 ssp_mode;
239 __u16 interval;
240 __u16 pkt_type;
241 __u16 link_policy;
242 __u32 link_mode;
Waldemar Rymarkiewicz13d39312011-04-28 12:07:55 +0200243 __u8 key_type;
Szymon Jancadc42662011-02-17 16:42:00 +0100244 __u8 auth_type;
245 __u8 sec_level;
246 __u8 pending_sec_level;
247 __u8 pin_length;
248 __u8 io_capability;
249 __u8 power_save;
250 __u16 disc_timeout;
251 unsigned long pend;
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300252 __u8 ltk[16];
Marcel Holtmann04837f62006-07-03 10:02:33 +0200253
Johan Hedberg03b555e2011-01-04 15:40:05 +0200254 __u8 remote_cap;
255 __u8 remote_oob;
256 __u8 remote_auth;
257
Szymon Jancadc42662011-02-17 16:42:00 +0100258 unsigned int sent;
Marcel Holtmann04837f62006-07-03 10:02:33 +0200259
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260 struct sk_buff_head data_q;
261
Marcel Holtmann04837f62006-07-03 10:02:33 +0200262 struct timer_list disc_timer;
263 struct timer_list idle_timer;
Johan Hedberg9f616562011-04-28 11:28:54 -0700264 struct timer_list auto_accept_timer;
Marcel Holtmann04837f62006-07-03 10:02:33 +0200265
Roger Quadrosf3784d82009-04-23 14:50:54 +0300266 struct work_struct work_add;
267 struct work_struct work_del;
Marcel Holtmannb219e3a2006-07-06 12:38:46 +0200268
269 struct device dev;
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700270 atomic_t devref;
Marcel Holtmannb219e3a2006-07-06 12:38:46 +0200271
Linus Torvalds1da177e2005-04-16 15:20:36 -0700272 struct hci_dev *hdev;
273 void *l2cap_data;
274 void *sco_data;
275 void *priv;
276
277 struct hci_conn *link;
Johan Hedberge9a416b2011-02-19 12:05:56 -0300278
279 void (*connect_cfm_cb) (struct hci_conn *conn, u8 status);
280 void (*security_cfm_cb) (struct hci_conn *conn, u8 status);
281 void (*disconn_cfm_cb) (struct hci_conn *conn, u8 reason);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700282};
283
284extern struct hci_proto *hci_proto[];
285extern struct list_head hci_dev_list;
286extern struct list_head hci_cb_list;
287extern rwlock_t hci_dev_list_lock;
288extern rwlock_t hci_cb_list_lock;
289
290/* ----- Inquiry cache ----- */
Andrei Emeltchenko70f230202010-12-01 16:58:25 +0200291#define INQUIRY_CACHE_AGE_MAX (HZ*30) /* 30 seconds */
292#define INQUIRY_ENTRY_AGE_MAX (HZ*60) /* 60 seconds */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700293
294#define inquiry_cache_lock(c) spin_lock(&c->lock)
295#define inquiry_cache_unlock(c) spin_unlock(&c->lock)
296#define inquiry_cache_lock_bh(c) spin_lock_bh(&c->lock)
297#define inquiry_cache_unlock_bh(c) spin_unlock_bh(&c->lock)
298
299static inline void inquiry_cache_init(struct hci_dev *hdev)
300{
301 struct inquiry_cache *c = &hdev->inq_cache;
302 spin_lock_init(&c->lock);
303 c->list = NULL;
304}
305
306static inline int inquiry_cache_empty(struct hci_dev *hdev)
307{
308 struct inquiry_cache *c = &hdev->inq_cache;
Eric Dumazeta02cec22010-09-22 20:43:57 +0000309 return c->list == NULL;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700310}
311
312static inline long inquiry_cache_age(struct hci_dev *hdev)
313{
314 struct inquiry_cache *c = &hdev->inq_cache;
315 return jiffies - c->timestamp;
316}
317
318static inline long inquiry_entry_age(struct inquiry_entry *e)
319{
320 return jiffies - e->timestamp;
321}
322
Waldemar Rymarkiewicz5a9d0a32011-06-07 11:18:06 +0200323struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev,
324 bdaddr_t *bdaddr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700325void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data);
326
327/* ----- HCI Connections ----- */
328enum {
329 HCI_CONN_AUTH_PEND,
Waldemar Rymarkiewicz19f8def2011-05-31 15:49:25 +0200330 HCI_CONN_REAUTH_PEND,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700331 HCI_CONN_ENCRYPT_PEND,
Marcel Holtmann04837f62006-07-03 10:02:33 +0200332 HCI_CONN_RSWITCH_PEND,
333 HCI_CONN_MODE_CHANGE_PEND,
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400334 HCI_CONN_SCO_SETUP_PEND,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700335};
336
337static inline void hci_conn_hash_init(struct hci_dev *hdev)
338{
339 struct hci_conn_hash *h = &hdev->conn_hash;
340 INIT_LIST_HEAD(&h->list);
341 spin_lock_init(&h->lock);
342 h->acl_num = 0;
343 h->sco_num = 0;
344}
345
346static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)
347{
348 struct hci_conn_hash *h = &hdev->conn_hash;
349 list_add(&c->list, &h->list);
Ville Tervofcd89c02011-02-10 22:38:47 -0300350 switch (c->type) {
351 case ACL_LINK:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700352 h->acl_num++;
Ville Tervofcd89c02011-02-10 22:38:47 -0300353 break;
354 case LE_LINK:
355 h->le_num++;
356 break;
357 case SCO_LINK:
358 case ESCO_LINK:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359 h->sco_num++;
Ville Tervofcd89c02011-02-10 22:38:47 -0300360 break;
361 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700362}
363
364static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)
365{
366 struct hci_conn_hash *h = &hdev->conn_hash;
367 list_del(&c->list);
Ville Tervofcd89c02011-02-10 22:38:47 -0300368 switch (c->type) {
369 case ACL_LINK:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700370 h->acl_num--;
Ville Tervofcd89c02011-02-10 22:38:47 -0300371 break;
372 case LE_LINK:
373 h->le_num--;
374 break;
375 case SCO_LINK:
376 case ESCO_LINK:
Linus Torvalds1da177e2005-04-16 15:20:36 -0700377 h->sco_num--;
Ville Tervofcd89c02011-02-10 22:38:47 -0300378 break;
379 }
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380}
381
382static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev,
Szymon Jancadc42662011-02-17 16:42:00 +0100383 __u16 handle)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700384{
385 struct hci_conn_hash *h = &hdev->conn_hash;
386 struct list_head *p;
387 struct hci_conn *c;
388
389 list_for_each(p, &h->list) {
390 c = list_entry(p, struct hci_conn, list);
391 if (c->handle == handle)
392 return c;
393 }
394 return NULL;
395}
396
397static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev,
Szymon Jancadc42662011-02-17 16:42:00 +0100398 __u8 type, bdaddr_t *ba)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700399{
400 struct hci_conn_hash *h = &hdev->conn_hash;
401 struct list_head *p;
402 struct hci_conn *c;
403
404 list_for_each(p, &h->list) {
405 c = list_entry(p, struct hci_conn, list);
406 if (c->type == type && !bacmp(&c->dst, ba))
407 return c;
408 }
409 return NULL;
410}
411
Marcel Holtmann4c67bc72006-10-15 17:30:56 +0200412static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev,
Szymon Jancadc42662011-02-17 16:42:00 +0100413 __u8 type, __u16 state)
Marcel Holtmann4c67bc72006-10-15 17:30:56 +0200414{
415 struct hci_conn_hash *h = &hdev->conn_hash;
416 struct list_head *p;
417 struct hci_conn *c;
418
419 list_for_each(p, &h->list) {
420 c = list_entry(p, struct hci_conn, list);
421 if (c->type == type && c->state == state)
422 return c;
423 }
424 return NULL;
425}
426
427void hci_acl_connect(struct hci_conn *conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428void hci_acl_disconn(struct hci_conn *conn, __u8 reason);
429void hci_add_sco(struct hci_conn *conn, __u16 handle);
Marcel Holtmannb6a0dc82007-10-20 14:55:10 +0200430void hci_setup_sync(struct hci_conn *conn, __u16 handle);
Marcel Holtmanne73439d2010-07-26 10:06:00 -0400431void hci_sco_setup(struct hci_conn *conn, __u8 status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432
433struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200434int hci_conn_del(struct hci_conn *conn);
435void hci_conn_hash_flush(struct hci_dev *hdev);
436void hci_conn_check_pending(struct hci_dev *hdev);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437
Waldemar Rymarkiewicz5a9d0a32011-06-07 11:18:06 +0200438struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,
439 __u8 sec_level, __u8 auth_type);
Marcel Holtmanne7c29cb2008-09-09 07:19:20 +0200440int hci_conn_check_link_mode(struct hci_conn *conn);
Waldemar Rymarkiewiczb3b1b062011-05-06 09:42:31 +0200441int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level);
Marcel Holtmann0684e5f2009-02-09 02:48:38 +0100442int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443int hci_conn_change_link_key(struct hci_conn *conn);
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100444int hci_conn_switch_role(struct hci_conn *conn, __u8 role);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445
Jaikumar Ganesh14b12d02011-05-23 18:06:04 -0700446void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200447void hci_conn_enter_sniff_mode(struct hci_conn *conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448
Marcel Holtmann9eba32b2009-08-22 14:19:26 -0700449void hci_conn_hold_device(struct hci_conn *conn);
450void hci_conn_put_device(struct hci_conn *conn);
451
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452static inline void hci_conn_hold(struct hci_conn *conn)
453{
454 atomic_inc(&conn->refcnt);
Marcel Holtmann04837f62006-07-03 10:02:33 +0200455 del_timer(&conn->disc_timer);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456}
457
458static inline void hci_conn_put(struct hci_conn *conn)
459{
460 if (atomic_dec_and_test(&conn->refcnt)) {
Marcel Holtmann04837f62006-07-03 10:02:33 +0200461 unsigned long timeo;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 if (conn->type == ACL_LINK) {
Marcel Holtmann04837f62006-07-03 10:02:33 +0200463 del_timer(&conn->idle_timer);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200464 if (conn->state == BT_CONNECTED) {
Marcel Holtmann052b30b2009-04-26 20:01:22 +0200465 timeo = msecs_to_jiffies(conn->disc_timeout);
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200466 if (!conn->out)
Marcel Holtmann052b30b2009-04-26 20:01:22 +0200467 timeo *= 2;
Waldemar Rymarkiewicz5a9d0a32011-06-07 11:18:06 +0200468 } else {
Marcel Holtmann6ac59342006-09-26 09:43:48 +0200469 timeo = msecs_to_jiffies(10);
Waldemar Rymarkiewicz5a9d0a32011-06-07 11:18:06 +0200470 }
471 } else {
Marcel Holtmann04837f62006-07-03 10:02:33 +0200472 timeo = msecs_to_jiffies(10);
Waldemar Rymarkiewicz5a9d0a32011-06-07 11:18:06 +0200473 }
Marcel Holtmann04837f62006-07-03 10:02:33 +0200474 mod_timer(&conn->disc_timer, jiffies + timeo);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700475 }
476}
477
Linus Torvalds1da177e2005-04-16 15:20:36 -0700478/* ----- HCI Devices ----- */
479static inline void __hci_dev_put(struct hci_dev *d)
480{
481 if (atomic_dec_and_test(&d->refcnt))
482 d->destruct(d);
483}
484
485static inline void hci_dev_put(struct hci_dev *d)
Ron Shaffer04fafe42010-05-28 11:53:45 -0400486{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700487 __hci_dev_put(d);
488 module_put(d->owner);
489}
490
491static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d)
492{
493 atomic_inc(&d->refcnt);
494 return d;
495}
496
497static inline struct hci_dev *hci_dev_hold(struct hci_dev *d)
498{
499 if (try_module_get(d->owner))
500 return __hci_dev_hold(d);
501 return NULL;
502}
503
504#define hci_dev_lock(d) spin_lock(&d->lock)
505#define hci_dev_unlock(d) spin_unlock(&d->lock)
506#define hci_dev_lock_bh(d) spin_lock_bh(&d->lock)
507#define hci_dev_unlock_bh(d) spin_unlock_bh(&d->lock)
508
509struct hci_dev *hci_dev_get(int index);
510struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst);
511
512struct hci_dev *hci_alloc_dev(void);
513void hci_free_dev(struct hci_dev *hdev);
514int hci_register_dev(struct hci_dev *hdev);
515int hci_unregister_dev(struct hci_dev *hdev);
516int hci_suspend_dev(struct hci_dev *hdev);
517int hci_resume_dev(struct hci_dev *hdev);
518int hci_dev_open(__u16 dev);
519int hci_dev_close(__u16 dev);
520int hci_dev_reset(__u16 dev);
521int hci_dev_reset_stat(__u16 dev);
522int hci_dev_cmd(unsigned int cmd, void __user *arg);
523int hci_get_dev_list(void __user *arg);
524int hci_get_dev_info(void __user *arg);
525int hci_get_conn_list(void __user *arg);
526int hci_get_conn_info(struct hci_dev *hdev, void __user *arg);
Marcel Holtmann40be4922008-07-14 20:13:50 +0200527int hci_get_auth_info(struct hci_dev *hdev, void __user *arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528int hci_inquiry(void __user *arg);
529
Johan Hedbergf0358562010-05-18 13:20:32 +0200530struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr);
531int hci_blacklist_clear(struct hci_dev *hdev);
Antti Julkub2a66aa2011-06-15 12:01:14 +0300532int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr);
533int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr);
Johan Hedbergf0358562010-05-18 13:20:32 +0200534
Johan Hedberg2aeb9a12011-01-04 12:08:51 +0200535int hci_uuids_clear(struct hci_dev *hdev);
536
Johan Hedberg55ed8ca12011-01-17 14:41:05 +0200537int hci_link_keys_clear(struct hci_dev *hdev);
538struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
Johan Hedbergd25e28a2011-04-28 11:28:59 -0700539int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key,
540 bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len);
Johan Hedberg55ed8ca12011-01-17 14:41:05 +0200541int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr);
542
Szymon Janc2763eda2011-03-22 13:12:22 +0100543int hci_remote_oob_data_clear(struct hci_dev *hdev);
544struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev,
545 bdaddr_t *bdaddr);
546int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
547 u8 *randomizer);
548int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr);
549
Andre Guedes35815082011-05-26 16:23:53 -0300550#define ADV_CLEAR_TIMEOUT (3*60*HZ) /* Three minutes */
Andre Guedes76c86862011-05-26 16:23:50 -0300551int hci_adv_entries_clear(struct hci_dev *hdev);
552struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr);
553int hci_add_adv_entry(struct hci_dev *hdev,
554 struct hci_ev_le_advertising_info *ev);
555
Johan Hedbergab81cbf2010-12-15 13:53:18 +0200556void hci_del_off_timer(struct hci_dev *hdev);
557
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);
559
Marcel Holtmann76bca882009-11-18 00:40:39 +0100560int hci_recv_frame(struct sk_buff *skb);
Marcel Holtmannef222012007-07-11 06:42:04 +0200561int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count);
Suraj Sumangala99811512010-07-14 13:02:19 +0530562int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count);
Marcel Holtmannef222012007-07-11 06:42:04 +0200563
Linus Torvalds1da177e2005-04-16 15:20:36 -0700564int hci_register_sysfs(struct hci_dev *hdev);
565void hci_unregister_sysfs(struct hci_dev *hdev);
Marcel Holtmanna67e8992009-05-02 18:24:06 -0700566void hci_conn_init_sysfs(struct hci_conn *conn);
Marcel Holtmannb219e3a2006-07-06 12:38:46 +0200567void hci_conn_add_sysfs(struct hci_conn *conn);
568void hci_conn_del_sysfs(struct hci_conn *conn);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700569
Marcel Holtmanna91f2e32006-07-03 10:02:41 +0200570#define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->parent = (pdev))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571
572/* ----- LMP capabilities ----- */
Marcel Holtmann04837f62006-07-03 10:02:33 +0200573#define lmp_rswitch_capable(dev) ((dev)->features[0] & LMP_RSWITCH)
574#define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT)
575#define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF)
576#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR)
Marcel Holtmann5b7f9902007-07-11 09:51:55 +0200577#define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO)
Marcel Holtmann769be972008-07-14 20:13:49 +0200578#define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR)
Andrei Emeltchenkoe7021122011-01-03 11:14:36 +0200579#define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH)
Ville Tervo6ed58ec2011-02-10 22:38:48 -0300580#define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581
582/* ----- HCI protocols ----- */
583struct hci_proto {
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100584 char *name;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 unsigned int id;
586 unsigned long flags;
587
588 void *priv;
589
Waldemar Rymarkiewicz5a9d0a32011-06-07 11:18:06 +0200590 int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr,
591 __u8 type);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 int (*connect_cfm) (struct hci_conn *conn, __u8 status);
Marcel Holtmann2950f212009-02-12 14:02:50 +0100593 int (*disconn_ind) (struct hci_conn *conn);
594 int (*disconn_cfm) (struct hci_conn *conn, __u8 reason);
Waldemar Rymarkiewicz5a9d0a32011-06-07 11:18:06 +0200595 int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb,
596 __u16 flags);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb);
Waldemar Rymarkiewicz5a9d0a32011-06-07 11:18:06 +0200598 int (*security_cfm) (struct hci_conn *conn, __u8 status,
599 __u8 encrypt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600};
601
Waldemar Rymarkiewicz5a9d0a32011-06-07 11:18:06 +0200602static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,
603 __u8 type)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604{
605 register struct hci_proto *hp;
606 int mask = 0;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100607
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 hp = hci_proto[HCI_PROTO_L2CAP];
609 if (hp && hp->connect_ind)
610 mask |= hp->connect_ind(hdev, bdaddr, type);
611
612 hp = hci_proto[HCI_PROTO_SCO];
613 if (hp && hp->connect_ind)
614 mask |= hp->connect_ind(hdev, bdaddr, type);
615
616 return mask;
617}
618
619static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status)
620{
621 register struct hci_proto *hp;
622
623 hp = hci_proto[HCI_PROTO_L2CAP];
624 if (hp && hp->connect_cfm)
625 hp->connect_cfm(conn, status);
626
627 hp = hci_proto[HCI_PROTO_SCO];
628 if (hp && hp->connect_cfm)
629 hp->connect_cfm(conn, status);
Johan Hedberge9a416b2011-02-19 12:05:56 -0300630
631 if (conn->connect_cfm_cb)
632 conn->connect_cfm_cb(conn, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633}
634
Marcel Holtmann2950f212009-02-12 14:02:50 +0100635static inline int hci_proto_disconn_ind(struct hci_conn *conn)
636{
637 register struct hci_proto *hp;
638 int reason = 0x13;
639
640 hp = hci_proto[HCI_PROTO_L2CAP];
641 if (hp && hp->disconn_ind)
642 reason = hp->disconn_ind(conn);
643
644 hp = hci_proto[HCI_PROTO_SCO];
645 if (hp && hp->disconn_ind)
646 reason = hp->disconn_ind(conn);
647
648 return reason;
649}
650
651static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652{
653 register struct hci_proto *hp;
654
655 hp = hci_proto[HCI_PROTO_L2CAP];
Marcel Holtmann2950f212009-02-12 14:02:50 +0100656 if (hp && hp->disconn_cfm)
657 hp->disconn_cfm(conn, reason);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658
659 hp = hci_proto[HCI_PROTO_SCO];
Marcel Holtmann2950f212009-02-12 14:02:50 +0100660 if (hp && hp->disconn_cfm)
661 hp->disconn_cfm(conn, reason);
Johan Hedberge9a416b2011-02-19 12:05:56 -0300662
663 if (conn->disconn_cfm_cb)
664 conn->disconn_cfm_cb(conn, reason);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665}
666
667static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status)
668{
669 register struct hci_proto *hp;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100670 __u8 encrypt;
671
672 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
673 return;
674
675 encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676
677 hp = hci_proto[HCI_PROTO_L2CAP];
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100678 if (hp && hp->security_cfm)
679 hp->security_cfm(conn, status, encrypt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700680
681 hp = hci_proto[HCI_PROTO_SCO];
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100682 if (hp && hp->security_cfm)
683 hp->security_cfm(conn, status, encrypt);
Johan Hedberge9a416b2011-02-19 12:05:56 -0300684
685 if (conn->security_cfm_cb)
686 conn->security_cfm_cb(conn, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687}
688
Waldemar Rymarkiewicz5a9d0a32011-06-07 11:18:06 +0200689static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status,
690 __u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700691{
692 register struct hci_proto *hp;
693
694 hp = hci_proto[HCI_PROTO_L2CAP];
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100695 if (hp && hp->security_cfm)
696 hp->security_cfm(conn, status, encrypt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697
698 hp = hci_proto[HCI_PROTO_SCO];
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100699 if (hp && hp->security_cfm)
700 hp->security_cfm(conn, status, encrypt);
Johan Hedberge9a416b2011-02-19 12:05:56 -0300701
702 if (conn->security_cfm_cb)
703 conn->security_cfm_cb(conn, status);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700704}
705
706int hci_register_proto(struct hci_proto *hproto);
707int hci_unregister_proto(struct hci_proto *hproto);
708
709/* ----- HCI callbacks ----- */
710struct hci_cb {
711 struct list_head list;
712
713 char *name;
714
Waldemar Rymarkiewicz5a9d0a32011-06-07 11:18:06 +0200715 void (*security_cfm) (struct hci_conn *conn, __u8 status,
716 __u8 encrypt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717 void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
718 void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
719};
720
721static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
722{
723 struct list_head *p;
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100724 __u8 encrypt;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700725
726 hci_proto_auth_cfm(conn, status);
727
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100728 if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend))
729 return;
730
731 encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;
732
Linus Torvalds1da177e2005-04-16 15:20:36 -0700733 read_lock_bh(&hci_cb_list_lock);
734 list_for_each(p, &hci_cb_list) {
735 struct hci_cb *cb = list_entry(p, struct hci_cb, list);
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100736 if (cb->security_cfm)
737 cb->security_cfm(conn, status, encrypt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700738 }
739 read_unlock_bh(&hci_cb_list_lock);
740}
741
Waldemar Rymarkiewicz5a9d0a32011-06-07 11:18:06 +0200742static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,
743 __u8 encrypt)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744{
745 struct list_head *p;
746
Marcel Holtmann435fef22009-02-09 03:55:28 +0100747 if (conn->sec_level == BT_SECURITY_SDP)
748 conn->sec_level = BT_SECURITY_LOW;
749
Vinicius Costa Gomes88167ae2011-06-09 18:50:51 -0300750 if (conn->pending_sec_level > conn->sec_level)
751 conn->sec_level = conn->pending_sec_level;
752
Marcel Holtmann9719f8a2008-07-14 20:13:45 +0200753 hci_proto_encrypt_cfm(conn, status, encrypt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700754
755 read_lock_bh(&hci_cb_list_lock);
756 list_for_each(p, &hci_cb_list) {
757 struct hci_cb *cb = list_entry(p, struct hci_cb, list);
Marcel Holtmann8c1b2352009-01-15 21:58:04 +0100758 if (cb->security_cfm)
759 cb->security_cfm(conn, status, encrypt);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700760 }
761 read_unlock_bh(&hci_cb_list_lock);
762}
763
764static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
765{
766 struct list_head *p;
767
768 read_lock_bh(&hci_cb_list_lock);
769 list_for_each(p, &hci_cb_list) {
770 struct hci_cb *cb = list_entry(p, struct hci_cb, list);
771 if (cb->key_change_cfm)
772 cb->key_change_cfm(conn, status);
773 }
774 read_unlock_bh(&hci_cb_list_lock);
775}
776
Waldemar Rymarkiewicz5a9d0a32011-06-07 11:18:06 +0200777static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
778 __u8 role)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779{
780 struct list_head *p;
781
782 read_lock_bh(&hci_cb_list_lock);
783 list_for_each(p, &hci_cb_list) {
784 struct hci_cb *cb = list_entry(p, struct hci_cb, list);
785 if (cb->role_switch_cfm)
786 cb->role_switch_cfm(conn, status, role);
787 }
788 read_unlock_bh(&hci_cb_list_lock);
789}
790
791int hci_register_cb(struct hci_cb *hcb);
792int hci_unregister_cb(struct hci_cb *hcb);
793
794int hci_register_notifier(struct notifier_block *nb);
795int hci_unregister_notifier(struct notifier_block *nb);
796
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200797int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
Gustavo F. Padovan9a9c6a32010-05-01 16:15:43 -0300798void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags);
Gustavo F. Padovan0d861d82010-05-01 16:15:35 -0300799void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700800
Marcel Holtmanna9de9242007-10-20 13:33:56 +0200801void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700802
803void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data);
804
805/* ----- HCI Sockets ----- */
Johan Hedbergeec8d2b2010-12-16 10:17:38 +0200806void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb,
807 struct sock *skip_sk);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700808
Johan Hedberg03811012010-12-08 00:21:06 +0200809/* Management interface */
810int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len);
Johan Hedbergc71e97b2010-12-13 21:07:07 +0200811int mgmt_index_added(u16 index);
812int mgmt_index_removed(u16 index);
Johan Hedberg5add6af2010-12-16 10:00:37 +0200813int mgmt_powered(u16 index, u8 powered);
Johan Hedberg73f22f62010-12-29 16:00:25 +0200814int mgmt_discoverable(u16 index, u8 discoverable);
Johan Hedberg9fbcbb42010-12-30 00:18:33 +0200815int mgmt_connectable(u16 index, u8 connectable);
Johan Hedberg4df378a2011-04-28 11:29:03 -0700816int mgmt_new_key(u16 index, struct link_key *key, u8 persistent);
Johan Hedbergf7520542011-01-20 12:34:39 +0200817int mgmt_connected(u16 index, bdaddr_t *bdaddr);
818int mgmt_disconnected(u16 index, bdaddr_t *bdaddr);
Johan Hedberg8962ee72011-01-20 12:40:27 +0200819int mgmt_disconnect_failed(u16 index);
Johan Hedberg17d5c042011-01-22 06:09:08 +0200820int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status);
Waldemar Rymarkiewicza770bb52011-04-28 12:07:59 +0200821int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure);
Johan Hedberg980e1a52011-01-22 06:10:07 +0200822int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
823int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
Johan Hedberg55bc1a32011-04-28 11:28:56 -0700824int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value,
825 u8 confirm_hint);
Johan Hedberga5c29682011-02-19 12:05:57 -0300826int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status);
827int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr,
828 u8 status);
Johan Hedberg2a611692011-02-19 12:06:00 -0300829int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status);
Johan Hedbergb312b1612011-03-16 14:29:37 +0200830int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status);
Szymon Jancc35938b2011-03-22 13:12:21 +0100831int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer,
832 u8 status);
Johan Hedberge17acd42011-03-30 23:57:16 +0300833int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi,
834 u8 *eir);
Johan Hedberga88a9652011-03-30 13:18:12 +0300835int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name);
Johan Hedberg314b2382011-04-27 10:29:57 -0400836int mgmt_discovering(u16 index, u8 discovering);
Johan Hedberg03811012010-12-08 00:21:06 +0200837
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838/* HCI info for socket */
839#define hci_pi(sk) ((struct hci_pinfo *) sk)
840
841struct hci_pinfo {
842 struct bt_sock bt;
843 struct hci_dev *hdev;
844 struct hci_filter filter;
845 __u32 cmsg_mask;
Johan Hedbergc02178d2010-12-08 00:21:05 +0200846 unsigned short channel;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700847};
848
849/* HCI security filter */
850#define HCI_SFLT_MAX_OGF 5
851
852struct hci_sec_filter {
853 __u32 type_mask;
854 __u32 event_mask[2];
855 __u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4];
856};
857
858/* ----- HCI requests ----- */
859#define HCI_REQ_DONE 0
860#define HCI_REQ_PEND 1
861#define HCI_REQ_CANCELED 2
862
Thomas Gleixnera6a67ef2009-07-26 08:18:19 +0000863#define hci_req_lock(d) mutex_lock(&d->req_lock)
864#define hci_req_unlock(d) mutex_unlock(&d->req_lock)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700865
Johan Hedberg23bb5762010-12-21 23:01:27 +0200866void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700867
Claudio Takahasi2ce603e2011-02-16 20:44:53 -0200868void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
869 u16 latency, u16 to_multiplier);
Vinicius Costa Gomesa7a595f2011-06-09 18:50:47 -0300870void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
871 __u8 ltk[16]);
872void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]);
873void hci_le_ltk_neg_reply(struct hci_conn *conn);
874
Linus Torvalds1da177e2005-04-16 15:20:36 -0700875#endif /* __HCI_CORE_H */