11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds BlueZ - Bluetooth protocol stack for Linux 32d0a0346SRon Shaffer Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved. 41da177e4SLinus Torvalds 51da177e4SLinus Torvalds Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com> 61da177e4SLinus Torvalds 71da177e4SLinus Torvalds This program is free software; you can redistribute it and/or modify 81da177e4SLinus Torvalds it under the terms of the GNU General Public License version 2 as 91da177e4SLinus Torvalds published by the Free Software Foundation; 101da177e4SLinus Torvalds 111da177e4SLinus Torvalds THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 121da177e4SLinus Torvalds OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 131da177e4SLinus Torvalds FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. 141da177e4SLinus Torvalds IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY 151da177e4SLinus Torvalds CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES 161da177e4SLinus Torvalds WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 171da177e4SLinus Torvalds ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 181da177e4SLinus Torvalds OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 191da177e4SLinus Torvalds 201da177e4SLinus Torvalds ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, 211da177e4SLinus Torvalds COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS 221da177e4SLinus Torvalds SOFTWARE IS DISCLAIMED. 231da177e4SLinus Torvalds */ 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds #ifndef __HCI_CORE_H 261da177e4SLinus Torvalds #define __HCI_CORE_H 271da177e4SLinus Torvalds 281da177e4SLinus Torvalds #include <net/bluetooth/hci.h> 291da177e4SLinus Torvalds 301da177e4SLinus Torvalds /* HCI upper protocols */ 311da177e4SLinus Torvalds #define HCI_PROTO_L2CAP 0 321da177e4SLinus Torvalds #define HCI_PROTO_SCO 1 331da177e4SLinus Torvalds 341da177e4SLinus Torvalds /* HCI Core structures */ 351da177e4SLinus Torvalds struct inquiry_data { 361da177e4SLinus Torvalds bdaddr_t bdaddr; 371da177e4SLinus Torvalds __u8 pscan_rep_mode; 381da177e4SLinus Torvalds __u8 pscan_period_mode; 391da177e4SLinus Torvalds __u8 pscan_mode; 401da177e4SLinus Torvalds __u8 dev_class[3]; 411ebb9252SMarcel Holtmann __le16 clock_offset; 421da177e4SLinus Torvalds __s8 rssi; 4341a96212SMarcel Holtmann __u8 ssp_mode; 441da177e4SLinus Torvalds }; 451da177e4SLinus Torvalds 461da177e4SLinus Torvalds struct inquiry_entry { 471da177e4SLinus Torvalds struct inquiry_entry *next; 481da177e4SLinus Torvalds __u32 timestamp; 491da177e4SLinus Torvalds struct inquiry_data data; 501da177e4SLinus Torvalds }; 511da177e4SLinus Torvalds 521da177e4SLinus Torvalds struct inquiry_cache { 531da177e4SLinus Torvalds spinlock_t lock; 541da177e4SLinus Torvalds __u32 timestamp; 551da177e4SLinus Torvalds struct inquiry_entry *list; 561da177e4SLinus Torvalds }; 571da177e4SLinus Torvalds 581da177e4SLinus Torvalds struct hci_conn_hash { 591da177e4SLinus Torvalds struct list_head list; 601da177e4SLinus Torvalds spinlock_t lock; 611da177e4SLinus Torvalds unsigned int acl_num; 621da177e4SLinus Torvalds unsigned int sco_num; 63fcd89c09SVille Tervo unsigned int le_num; 641da177e4SLinus Torvalds }; 651da177e4SLinus Torvalds 66f0358568SJohan Hedberg struct bdaddr_list { 67f0358568SJohan Hedberg struct list_head list; 68f0358568SJohan Hedberg bdaddr_t bdaddr; 69f0358568SJohan Hedberg }; 702aeb9a1aSJohan Hedberg 712aeb9a1aSJohan Hedberg struct bt_uuid { 722aeb9a1aSJohan Hedberg struct list_head list; 732aeb9a1aSJohan Hedberg u8 uuid[16]; 741aff6f09SJohan Hedberg u8 svc_hint; 752aeb9a1aSJohan Hedberg }; 762aeb9a1aSJohan Hedberg 7734918cd7SVinicius Costa Gomes struct key_master_id { 7834918cd7SVinicius Costa Gomes __le16 ediv; 7934918cd7SVinicius Costa Gomes u8 rand[8]; 8034918cd7SVinicius Costa Gomes } __packed; 8134918cd7SVinicius Costa Gomes 8234918cd7SVinicius Costa Gomes struct link_key_data { 8334918cd7SVinicius Costa Gomes bdaddr_t bdaddr; 8434918cd7SVinicius Costa Gomes u8 type; 8534918cd7SVinicius Costa Gomes u8 val[16]; 8634918cd7SVinicius Costa Gomes u8 pin_len; 8734918cd7SVinicius Costa Gomes u8 dlen; 8834918cd7SVinicius Costa Gomes u8 data[0]; 8934918cd7SVinicius Costa Gomes } __packed; 9034918cd7SVinicius Costa Gomes 9155ed8ca1SJohan Hedberg struct link_key { 9255ed8ca1SJohan Hedberg struct list_head list; 9355ed8ca1SJohan Hedberg bdaddr_t bdaddr; 9455ed8ca1SJohan Hedberg u8 type; 9555ed8ca1SJohan Hedberg u8 val[16]; 9655ed8ca1SJohan Hedberg u8 pin_len; 9734918cd7SVinicius Costa Gomes u8 dlen; 9834918cd7SVinicius Costa Gomes u8 data[0]; 9955ed8ca1SJohan Hedberg }; 10055ed8ca1SJohan Hedberg 1012763eda6SSzymon Janc struct oob_data { 1022763eda6SSzymon Janc struct list_head list; 1032763eda6SSzymon Janc bdaddr_t bdaddr; 1042763eda6SSzymon Janc u8 hash[16]; 1052763eda6SSzymon Janc u8 randomizer[16]; 1062763eda6SSzymon Janc }; 1072763eda6SSzymon Janc 10876c8686fSAndre Guedes struct adv_entry { 10976c8686fSAndre Guedes struct list_head list; 11076c8686fSAndre Guedes bdaddr_t bdaddr; 11176c8686fSAndre Guedes u8 bdaddr_type; 11276c8686fSAndre Guedes }; 11376c8686fSAndre Guedes 114cd4c5391SSuraj Sumangala #define NUM_REASSEMBLY 4 1151da177e4SLinus Torvalds struct hci_dev { 1161da177e4SLinus Torvalds struct list_head list; 1171da177e4SLinus Torvalds spinlock_t lock; 1181da177e4SLinus Torvalds atomic_t refcnt; 1191da177e4SLinus Torvalds 1201da177e4SLinus Torvalds char name[8]; 1211da177e4SLinus Torvalds unsigned long flags; 1221da177e4SLinus Torvalds __u16 id; 123c13854ceSMarcel Holtmann __u8 bus; 124943da25dSMarcel Holtmann __u8 dev_type; 1251da177e4SLinus Torvalds bdaddr_t bdaddr; 1261f6c6378SJohan Hedberg __u8 dev_name[HCI_MAX_NAME_LENGTH]; 12780a1e1dbSJohan Hedberg __u8 eir[HCI_MAX_EIR_LENGTH]; 128a9de9248SMarcel Holtmann __u8 dev_class[3]; 1291aff6f09SJohan Hedberg __u8 major_class; 1301aff6f09SJohan Hedberg __u8 minor_class; 1311da177e4SLinus Torvalds __u8 features[8]; 132971e3a4bSAndre Guedes __u8 extfeatures[8]; 133a9de9248SMarcel Holtmann __u8 commands[64]; 134333140b5SMarcel Holtmann __u8 ssp_mode; 1351143e5a6SMarcel Holtmann __u8 hci_ver; 1361143e5a6SMarcel Holtmann __u16 hci_rev; 137d5859e22SJohan Hedberg __u8 lmp_ver; 1381143e5a6SMarcel Holtmann __u16 manufacturer; 139d5859e22SJohan Hedberg __le16 lmp_subver; 1401da177e4SLinus Torvalds __u16 voice_setting; 14117fa4b9dSJohan Hedberg __u8 io_capability; 1421da177e4SLinus Torvalds 1431da177e4SLinus Torvalds __u16 pkt_type; 1445b7f9909SMarcel Holtmann __u16 esco_type; 1451da177e4SLinus Torvalds __u16 link_policy; 1461da177e4SLinus Torvalds __u16 link_mode; 1471da177e4SLinus Torvalds 14804837f64SMarcel Holtmann __u32 idle_timeout; 14904837f64SMarcel Holtmann __u16 sniff_min_interval; 15004837f64SMarcel Holtmann __u16 sniff_max_interval; 15104837f64SMarcel Holtmann 1529f61656aSJohan Hedberg unsigned int auto_accept_delay; 1539f61656aSJohan Hedberg 1541da177e4SLinus Torvalds unsigned long quirks; 1551da177e4SLinus Torvalds 1561da177e4SLinus Torvalds atomic_t cmd_cnt; 1571da177e4SLinus Torvalds unsigned int acl_cnt; 1581da177e4SLinus Torvalds unsigned int sco_cnt; 1596ed58ec5SVille Tervo unsigned int le_cnt; 1601da177e4SLinus Torvalds 1611da177e4SLinus Torvalds unsigned int acl_mtu; 1621da177e4SLinus Torvalds unsigned int sco_mtu; 1636ed58ec5SVille Tervo unsigned int le_mtu; 1641da177e4SLinus Torvalds unsigned int acl_pkts; 1651da177e4SLinus Torvalds unsigned int sco_pkts; 1666ed58ec5SVille Tervo unsigned int le_pkts; 1671da177e4SLinus Torvalds 1681da177e4SLinus Torvalds unsigned long acl_last_tx; 1691da177e4SLinus Torvalds unsigned long sco_last_tx; 1706ed58ec5SVille Tervo unsigned long le_last_tx; 1711da177e4SLinus Torvalds 172f48fd9c8SMarcel Holtmann struct workqueue_struct *workqueue; 173f48fd9c8SMarcel Holtmann 174ab81cbf9SJohan Hedberg struct work_struct power_on; 175ab81cbf9SJohan Hedberg struct work_struct power_off; 176ab81cbf9SJohan Hedberg struct timer_list off_timer; 177ab81cbf9SJohan Hedberg 1786bd32326SVille Tervo struct timer_list cmd_timer; 1791da177e4SLinus Torvalds struct tasklet_struct cmd_task; 1801da177e4SLinus Torvalds struct tasklet_struct rx_task; 1811da177e4SLinus Torvalds struct tasklet_struct tx_task; 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds struct sk_buff_head rx_q; 1841da177e4SLinus Torvalds struct sk_buff_head raw_q; 1851da177e4SLinus Torvalds struct sk_buff_head cmd_q; 1861da177e4SLinus Torvalds 1871da177e4SLinus Torvalds struct sk_buff *sent_cmd; 188cd4c5391SSuraj Sumangala struct sk_buff *reassembly[NUM_REASSEMBLY]; 1891da177e4SLinus Torvalds 190a6a67efdSThomas Gleixner struct mutex req_lock; 1911da177e4SLinus Torvalds wait_queue_head_t req_wait_q; 1921da177e4SLinus Torvalds __u32 req_status; 1931da177e4SLinus Torvalds __u32 req_result; 194a5040efaSJohan Hedberg 195a5040efaSJohan Hedberg __u16 init_last_cmd; 1961da177e4SLinus Torvalds 1973a0259bbSVinicius Costa Gomes struct crypto_blkcipher *tfm; 1983a0259bbSVinicius Costa Gomes 1991da177e4SLinus Torvalds struct inquiry_cache inq_cache; 2001da177e4SLinus Torvalds struct hci_conn_hash conn_hash; 201ea4bd8baSDavid Miller struct list_head blacklist; 2021da177e4SLinus Torvalds 2032aeb9a1aSJohan Hedberg struct list_head uuids; 2042aeb9a1aSJohan Hedberg 20555ed8ca1SJohan Hedberg struct list_head link_keys; 20655ed8ca1SJohan Hedberg 2072763eda6SSzymon Janc struct list_head remote_oob_data; 2082763eda6SSzymon Janc 20976c8686fSAndre Guedes struct list_head adv_entries; 21035815085SAndre Guedes struct timer_list adv_timer; 21176c8686fSAndre Guedes 2121da177e4SLinus Torvalds struct hci_dev_stats stat; 2131da177e4SLinus Torvalds 2141da177e4SLinus Torvalds struct sk_buff_head driver_init; 2151da177e4SLinus Torvalds 2161da177e4SLinus Torvalds void *driver_data; 2171da177e4SLinus Torvalds void *core_data; 2181da177e4SLinus Torvalds 2191da177e4SLinus Torvalds atomic_t promisc; 2201da177e4SLinus Torvalds 221ca325f69SMarcel Holtmann struct dentry *debugfs; 222ca325f69SMarcel Holtmann 223a91f2e39SMarcel Holtmann struct device *parent; 224a91f2e39SMarcel Holtmann struct device dev; 2251da177e4SLinus Torvalds 226611b30f7SMarcel Holtmann struct rfkill *rfkill; 227611b30f7SMarcel Holtmann 2281da177e4SLinus Torvalds struct module *owner; 2291da177e4SLinus Torvalds 2301da177e4SLinus Torvalds int (*open)(struct hci_dev *hdev); 2311da177e4SLinus Torvalds int (*close)(struct hci_dev *hdev); 2321da177e4SLinus Torvalds int (*flush)(struct hci_dev *hdev); 2331da177e4SLinus Torvalds int (*send)(struct sk_buff *skb); 2341da177e4SLinus Torvalds void (*destruct)(struct hci_dev *hdev); 2351da177e4SLinus Torvalds void (*notify)(struct hci_dev *hdev, unsigned int evt); 2361da177e4SLinus Torvalds int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg); 2371da177e4SLinus Torvalds }; 2381da177e4SLinus Torvalds 2391da177e4SLinus Torvalds struct hci_conn { 2401da177e4SLinus Torvalds struct list_head list; 2411da177e4SLinus Torvalds 2421da177e4SLinus Torvalds atomic_t refcnt; 2431da177e4SLinus Torvalds 2441da177e4SLinus Torvalds bdaddr_t dst; 24529b7988aSAndre Guedes __u8 dst_type; 2461da177e4SLinus Torvalds __u16 handle; 2471da177e4SLinus Torvalds __u16 state; 24804837f64SMarcel Holtmann __u8 mode; 2491da177e4SLinus Torvalds __u8 type; 2501da177e4SLinus Torvalds __u8 out; 2514c67bc74SMarcel Holtmann __u8 attempt; 2521da177e4SLinus Torvalds __u8 dev_class[3]; 25304837f64SMarcel Holtmann __u8 features[8]; 25441a96212SMarcel Holtmann __u8 ssp_mode; 25504837f64SMarcel Holtmann __u16 interval; 256a8746417SMarcel Holtmann __u16 pkt_type; 25704837f64SMarcel Holtmann __u16 link_policy; 2581da177e4SLinus Torvalds __u32 link_mode; 25913d39315SWaldemar Rymarkiewicz __u8 key_type; 26040be492fSMarcel Holtmann __u8 auth_type; 2618c1b2355SMarcel Holtmann __u8 sec_level; 262765c2a96SJohan Hedberg __u8 pending_sec_level; 263980e1a53SJohan Hedberg __u8 pin_length; 26417fa4b9dSJohan Hedberg __u8 io_capability; 26504837f64SMarcel Holtmann __u8 power_save; 266052b30b0SMarcel Holtmann __u16 disc_timeout; 2671da177e4SLinus Torvalds unsigned long pend; 268a7a595f6SVinicius Costa Gomes __u8 ltk[16]; 2691da177e4SLinus Torvalds 27003b555e1SJohan Hedberg __u8 remote_cap; 27103b555e1SJohan Hedberg __u8 remote_oob; 27203b555e1SJohan Hedberg __u8 remote_auth; 27303b555e1SJohan Hedberg 2741da177e4SLinus Torvalds unsigned int sent; 2751da177e4SLinus Torvalds 2761da177e4SLinus Torvalds struct sk_buff_head data_q; 2771da177e4SLinus Torvalds 27804837f64SMarcel Holtmann struct timer_list disc_timer; 27904837f64SMarcel Holtmann struct timer_list idle_timer; 2809f61656aSJohan Hedberg struct timer_list auto_accept_timer; 2811da177e4SLinus Torvalds 282f3784d83SRoger Quadros struct work_struct work_add; 283f3784d83SRoger Quadros struct work_struct work_del; 284b219e3acSMarcel Holtmann 285b219e3acSMarcel Holtmann struct device dev; 2869eba32b8SMarcel Holtmann atomic_t devref; 287b219e3acSMarcel Holtmann 2881da177e4SLinus Torvalds struct hci_dev *hdev; 2891da177e4SLinus Torvalds void *l2cap_data; 2901da177e4SLinus Torvalds void *sco_data; 2911da177e4SLinus Torvalds 2921da177e4SLinus Torvalds struct hci_conn *link; 293e9a416b5SJohan Hedberg 294e9a416b5SJohan Hedberg void (*connect_cfm_cb) (struct hci_conn *conn, u8 status); 295e9a416b5SJohan Hedberg void (*security_cfm_cb) (struct hci_conn *conn, u8 status); 296e9a416b5SJohan Hedberg void (*disconn_cfm_cb) (struct hci_conn *conn, u8 reason); 2971da177e4SLinus Torvalds }; 2981da177e4SLinus Torvalds 2991da177e4SLinus Torvalds extern struct hci_proto *hci_proto[]; 3001da177e4SLinus Torvalds extern struct list_head hci_dev_list; 3011da177e4SLinus Torvalds extern struct list_head hci_cb_list; 3021da177e4SLinus Torvalds extern rwlock_t hci_dev_list_lock; 3031da177e4SLinus Torvalds extern rwlock_t hci_cb_list_lock; 3041da177e4SLinus Torvalds 3051da177e4SLinus Torvalds /* ----- Inquiry cache ----- */ 30670f23020SAndrei Emeltchenko #define INQUIRY_CACHE_AGE_MAX (HZ*30) /* 30 seconds */ 30770f23020SAndrei Emeltchenko #define INQUIRY_ENTRY_AGE_MAX (HZ*60) /* 60 seconds */ 3081da177e4SLinus Torvalds 3091da177e4SLinus Torvalds #define inquiry_cache_lock(c) spin_lock(&c->lock) 3101da177e4SLinus Torvalds #define inquiry_cache_unlock(c) spin_unlock(&c->lock) 3111da177e4SLinus Torvalds #define inquiry_cache_lock_bh(c) spin_lock_bh(&c->lock) 3121da177e4SLinus Torvalds #define inquiry_cache_unlock_bh(c) spin_unlock_bh(&c->lock) 3131da177e4SLinus Torvalds 3141da177e4SLinus Torvalds static inline void inquiry_cache_init(struct hci_dev *hdev) 3151da177e4SLinus Torvalds { 3161da177e4SLinus Torvalds struct inquiry_cache *c = &hdev->inq_cache; 3171da177e4SLinus Torvalds spin_lock_init(&c->lock); 3181da177e4SLinus Torvalds c->list = NULL; 3191da177e4SLinus Torvalds } 3201da177e4SLinus Torvalds 3211da177e4SLinus Torvalds static inline int inquiry_cache_empty(struct hci_dev *hdev) 3221da177e4SLinus Torvalds { 3231da177e4SLinus Torvalds struct inquiry_cache *c = &hdev->inq_cache; 324a02cec21SEric Dumazet return c->list == NULL; 3251da177e4SLinus Torvalds } 3261da177e4SLinus Torvalds 3271da177e4SLinus Torvalds static inline long inquiry_cache_age(struct hci_dev *hdev) 3281da177e4SLinus Torvalds { 3291da177e4SLinus Torvalds struct inquiry_cache *c = &hdev->inq_cache; 3301da177e4SLinus Torvalds return jiffies - c->timestamp; 3311da177e4SLinus Torvalds } 3321da177e4SLinus Torvalds 3331da177e4SLinus Torvalds static inline long inquiry_entry_age(struct inquiry_entry *e) 3341da177e4SLinus Torvalds { 3351da177e4SLinus Torvalds return jiffies - e->timestamp; 3361da177e4SLinus Torvalds } 3371da177e4SLinus Torvalds 3385a9d0a3fSWaldemar Rymarkiewicz struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, 3395a9d0a3fSWaldemar Rymarkiewicz bdaddr_t *bdaddr); 3401da177e4SLinus Torvalds void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data); 3411da177e4SLinus Torvalds 3421da177e4SLinus Torvalds /* ----- HCI Connections ----- */ 3431da177e4SLinus Torvalds enum { 3441da177e4SLinus Torvalds HCI_CONN_AUTH_PEND, 34519f8def0SWaldemar Rymarkiewicz HCI_CONN_REAUTH_PEND, 3461da177e4SLinus Torvalds HCI_CONN_ENCRYPT_PEND, 34704837f64SMarcel Holtmann HCI_CONN_RSWITCH_PEND, 34804837f64SMarcel Holtmann HCI_CONN_MODE_CHANGE_PEND, 349e73439d8SMarcel Holtmann HCI_CONN_SCO_SETUP_PEND, 3501da177e4SLinus Torvalds }; 3511da177e4SLinus Torvalds 3521da177e4SLinus Torvalds static inline void hci_conn_hash_init(struct hci_dev *hdev) 3531da177e4SLinus Torvalds { 3541da177e4SLinus Torvalds struct hci_conn_hash *h = &hdev->conn_hash; 3551da177e4SLinus Torvalds INIT_LIST_HEAD(&h->list); 3561da177e4SLinus Torvalds spin_lock_init(&h->lock); 3571da177e4SLinus Torvalds h->acl_num = 0; 3581da177e4SLinus Torvalds h->sco_num = 0; 3591da177e4SLinus Torvalds } 3601da177e4SLinus Torvalds 3611da177e4SLinus Torvalds static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) 3621da177e4SLinus Torvalds { 3631da177e4SLinus Torvalds struct hci_conn_hash *h = &hdev->conn_hash; 3641da177e4SLinus Torvalds list_add(&c->list, &h->list); 365fcd89c09SVille Tervo switch (c->type) { 366fcd89c09SVille Tervo case ACL_LINK: 3671da177e4SLinus Torvalds h->acl_num++; 368fcd89c09SVille Tervo break; 369fcd89c09SVille Tervo case LE_LINK: 370fcd89c09SVille Tervo h->le_num++; 371fcd89c09SVille Tervo break; 372fcd89c09SVille Tervo case SCO_LINK: 373fcd89c09SVille Tervo case ESCO_LINK: 3741da177e4SLinus Torvalds h->sco_num++; 375fcd89c09SVille Tervo break; 376fcd89c09SVille Tervo } 3771da177e4SLinus Torvalds } 3781da177e4SLinus Torvalds 3791da177e4SLinus Torvalds static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) 3801da177e4SLinus Torvalds { 3811da177e4SLinus Torvalds struct hci_conn_hash *h = &hdev->conn_hash; 3821da177e4SLinus Torvalds list_del(&c->list); 383fcd89c09SVille Tervo switch (c->type) { 384fcd89c09SVille Tervo case ACL_LINK: 3851da177e4SLinus Torvalds h->acl_num--; 386fcd89c09SVille Tervo break; 387fcd89c09SVille Tervo case LE_LINK: 388fcd89c09SVille Tervo h->le_num--; 389fcd89c09SVille Tervo break; 390fcd89c09SVille Tervo case SCO_LINK: 391fcd89c09SVille Tervo case ESCO_LINK: 3921da177e4SLinus Torvalds h->sco_num--; 393fcd89c09SVille Tervo break; 394fcd89c09SVille Tervo } 3951da177e4SLinus Torvalds } 3961da177e4SLinus Torvalds 3971da177e4SLinus Torvalds static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev, 3981da177e4SLinus Torvalds __u16 handle) 3991da177e4SLinus Torvalds { 4001da177e4SLinus Torvalds struct hci_conn_hash *h = &hdev->conn_hash; 4011da177e4SLinus Torvalds struct list_head *p; 4021da177e4SLinus Torvalds struct hci_conn *c; 4031da177e4SLinus Torvalds 4041da177e4SLinus Torvalds list_for_each(p, &h->list) { 4051da177e4SLinus Torvalds c = list_entry(p, struct hci_conn, list); 4061da177e4SLinus Torvalds if (c->handle == handle) 4071da177e4SLinus Torvalds return c; 4081da177e4SLinus Torvalds } 4091da177e4SLinus Torvalds return NULL; 4101da177e4SLinus Torvalds } 4111da177e4SLinus Torvalds 4121da177e4SLinus Torvalds static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev, 4131da177e4SLinus Torvalds __u8 type, bdaddr_t *ba) 4141da177e4SLinus Torvalds { 4151da177e4SLinus Torvalds struct hci_conn_hash *h = &hdev->conn_hash; 4161da177e4SLinus Torvalds struct list_head *p; 4171da177e4SLinus Torvalds struct hci_conn *c; 4181da177e4SLinus Torvalds 4191da177e4SLinus Torvalds list_for_each(p, &h->list) { 4201da177e4SLinus Torvalds c = list_entry(p, struct hci_conn, list); 4211da177e4SLinus Torvalds if (c->type == type && !bacmp(&c->dst, ba)) 4221da177e4SLinus Torvalds return c; 4231da177e4SLinus Torvalds } 4241da177e4SLinus Torvalds return NULL; 4251da177e4SLinus Torvalds } 4261da177e4SLinus Torvalds 4274c67bc74SMarcel Holtmann static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev, 4284c67bc74SMarcel Holtmann __u8 type, __u16 state) 4294c67bc74SMarcel Holtmann { 4304c67bc74SMarcel Holtmann struct hci_conn_hash *h = &hdev->conn_hash; 4314c67bc74SMarcel Holtmann struct list_head *p; 4324c67bc74SMarcel Holtmann struct hci_conn *c; 4334c67bc74SMarcel Holtmann 4344c67bc74SMarcel Holtmann list_for_each(p, &h->list) { 4354c67bc74SMarcel Holtmann c = list_entry(p, struct hci_conn, list); 4364c67bc74SMarcel Holtmann if (c->type == type && c->state == state) 4374c67bc74SMarcel Holtmann return c; 4384c67bc74SMarcel Holtmann } 4394c67bc74SMarcel Holtmann return NULL; 4404c67bc74SMarcel Holtmann } 4414c67bc74SMarcel Holtmann 4424c67bc74SMarcel Holtmann void hci_acl_connect(struct hci_conn *conn); 4431da177e4SLinus Torvalds void hci_acl_disconn(struct hci_conn *conn, __u8 reason); 4441da177e4SLinus Torvalds void hci_add_sco(struct hci_conn *conn, __u16 handle); 445b6a0dc82SMarcel Holtmann void hci_setup_sync(struct hci_conn *conn, __u16 handle); 446e73439d8SMarcel Holtmann void hci_sco_setup(struct hci_conn *conn, __u8 status); 4471da177e4SLinus Torvalds 4481da177e4SLinus Torvalds struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst); 4491da177e4SLinus Torvalds int hci_conn_del(struct hci_conn *conn); 4501da177e4SLinus Torvalds void hci_conn_hash_flush(struct hci_dev *hdev); 451a9de9248SMarcel Holtmann void hci_conn_check_pending(struct hci_dev *hdev); 4521da177e4SLinus Torvalds 4535a9d0a3fSWaldemar Rymarkiewicz struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, 4545a9d0a3fSWaldemar Rymarkiewicz __u8 sec_level, __u8 auth_type); 455e7c29cb1SMarcel Holtmann int hci_conn_check_link_mode(struct hci_conn *conn); 456b3b1b061SWaldemar Rymarkiewicz int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level); 4570684e5f9SMarcel Holtmann int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type); 4581da177e4SLinus Torvalds int hci_conn_change_link_key(struct hci_conn *conn); 4598c1b2355SMarcel Holtmann int hci_conn_switch_role(struct hci_conn *conn, __u8 role); 4601da177e4SLinus Torvalds 46114b12d0bSJaikumar Ganesh void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active); 46204837f64SMarcel Holtmann void hci_conn_enter_sniff_mode(struct hci_conn *conn); 4631da177e4SLinus Torvalds 4649eba32b8SMarcel Holtmann void hci_conn_hold_device(struct hci_conn *conn); 4659eba32b8SMarcel Holtmann void hci_conn_put_device(struct hci_conn *conn); 4669eba32b8SMarcel Holtmann 4671da177e4SLinus Torvalds static inline void hci_conn_hold(struct hci_conn *conn) 4681da177e4SLinus Torvalds { 4691da177e4SLinus Torvalds atomic_inc(&conn->refcnt); 47004837f64SMarcel Holtmann del_timer(&conn->disc_timer); 4711da177e4SLinus Torvalds } 4721da177e4SLinus Torvalds 4731da177e4SLinus Torvalds static inline void hci_conn_put(struct hci_conn *conn) 4741da177e4SLinus Torvalds { 4751da177e4SLinus Torvalds if (atomic_dec_and_test(&conn->refcnt)) { 47604837f64SMarcel Holtmann unsigned long timeo; 4771da177e4SLinus Torvalds if (conn->type == ACL_LINK) { 4786ac59344SMarcel Holtmann del_timer(&conn->idle_timer); 4796ac59344SMarcel Holtmann if (conn->state == BT_CONNECTED) { 480052b30b0SMarcel Holtmann timeo = msecs_to_jiffies(conn->disc_timeout); 48104837f64SMarcel Holtmann if (!conn->out) 482052b30b0SMarcel Holtmann timeo *= 2; 4835a9d0a3fSWaldemar Rymarkiewicz } else { 4846ac59344SMarcel Holtmann timeo = msecs_to_jiffies(10); 4855a9d0a3fSWaldemar Rymarkiewicz } 4865a9d0a3fSWaldemar Rymarkiewicz } else { 48704837f64SMarcel Holtmann timeo = msecs_to_jiffies(10); 4885a9d0a3fSWaldemar Rymarkiewicz } 48904837f64SMarcel Holtmann mod_timer(&conn->disc_timer, jiffies + timeo); 4901da177e4SLinus Torvalds } 4911da177e4SLinus Torvalds } 4921da177e4SLinus Torvalds 4931da177e4SLinus Torvalds /* ----- HCI Devices ----- */ 4941da177e4SLinus Torvalds static inline void __hci_dev_put(struct hci_dev *d) 4951da177e4SLinus Torvalds { 4961da177e4SLinus Torvalds if (atomic_dec_and_test(&d->refcnt)) 4971da177e4SLinus Torvalds d->destruct(d); 4981da177e4SLinus Torvalds } 4991da177e4SLinus Torvalds 5001da177e4SLinus Torvalds static inline void hci_dev_put(struct hci_dev *d) 5011da177e4SLinus Torvalds { 5021da177e4SLinus Torvalds __hci_dev_put(d); 5031da177e4SLinus Torvalds module_put(d->owner); 5041da177e4SLinus Torvalds } 5051da177e4SLinus Torvalds 5061da177e4SLinus Torvalds static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d) 5071da177e4SLinus Torvalds { 5081da177e4SLinus Torvalds atomic_inc(&d->refcnt); 5091da177e4SLinus Torvalds return d; 5101da177e4SLinus Torvalds } 5111da177e4SLinus Torvalds 5121da177e4SLinus Torvalds static inline struct hci_dev *hci_dev_hold(struct hci_dev *d) 5131da177e4SLinus Torvalds { 5141da177e4SLinus Torvalds if (try_module_get(d->owner)) 5151da177e4SLinus Torvalds return __hci_dev_hold(d); 5161da177e4SLinus Torvalds return NULL; 5171da177e4SLinus Torvalds } 5181da177e4SLinus Torvalds 5191da177e4SLinus Torvalds #define hci_dev_lock(d) spin_lock(&d->lock) 5201da177e4SLinus Torvalds #define hci_dev_unlock(d) spin_unlock(&d->lock) 5211da177e4SLinus Torvalds #define hci_dev_lock_bh(d) spin_lock_bh(&d->lock) 5221da177e4SLinus Torvalds #define hci_dev_unlock_bh(d) spin_unlock_bh(&d->lock) 5231da177e4SLinus Torvalds 5241da177e4SLinus Torvalds struct hci_dev *hci_dev_get(int index); 5251da177e4SLinus Torvalds struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst); 5261da177e4SLinus Torvalds 5271da177e4SLinus Torvalds struct hci_dev *hci_alloc_dev(void); 5281da177e4SLinus Torvalds void hci_free_dev(struct hci_dev *hdev); 5291da177e4SLinus Torvalds int hci_register_dev(struct hci_dev *hdev); 5301da177e4SLinus Torvalds int hci_unregister_dev(struct hci_dev *hdev); 5311da177e4SLinus Torvalds int hci_suspend_dev(struct hci_dev *hdev); 5321da177e4SLinus Torvalds int hci_resume_dev(struct hci_dev *hdev); 5331da177e4SLinus Torvalds int hci_dev_open(__u16 dev); 5341da177e4SLinus Torvalds int hci_dev_close(__u16 dev); 5351da177e4SLinus Torvalds int hci_dev_reset(__u16 dev); 5361da177e4SLinus Torvalds int hci_dev_reset_stat(__u16 dev); 5371da177e4SLinus Torvalds int hci_dev_cmd(unsigned int cmd, void __user *arg); 5381da177e4SLinus Torvalds int hci_get_dev_list(void __user *arg); 5391da177e4SLinus Torvalds int hci_get_dev_info(void __user *arg); 5401da177e4SLinus Torvalds int hci_get_conn_list(void __user *arg); 5411da177e4SLinus Torvalds int hci_get_conn_info(struct hci_dev *hdev, void __user *arg); 54240be492fSMarcel Holtmann int hci_get_auth_info(struct hci_dev *hdev, void __user *arg); 5431da177e4SLinus Torvalds int hci_inquiry(void __user *arg); 5441da177e4SLinus Torvalds 545f0358568SJohan Hedberg struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr); 546f0358568SJohan Hedberg int hci_blacklist_clear(struct hci_dev *hdev); 547b2a66aadSAntti Julku int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr); 548b2a66aadSAntti Julku int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr); 549f0358568SJohan Hedberg 5502aeb9a1aSJohan Hedberg int hci_uuids_clear(struct hci_dev *hdev); 5512aeb9a1aSJohan Hedberg 55255ed8ca1SJohan Hedberg int hci_link_keys_clear(struct hci_dev *hdev); 55355ed8ca1SJohan Hedberg struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); 554d25e28abSJohan Hedberg int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, 555d25e28abSJohan Hedberg bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len); 55655ed8ca1SJohan Hedberg int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); 55755ed8ca1SJohan Hedberg 5582763eda6SSzymon Janc int hci_remote_oob_data_clear(struct hci_dev *hdev); 5592763eda6SSzymon Janc struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev, 5602763eda6SSzymon Janc bdaddr_t *bdaddr); 5612763eda6SSzymon Janc int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, 5622763eda6SSzymon Janc u8 *randomizer); 5632763eda6SSzymon Janc int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); 5642763eda6SSzymon Janc 56535815085SAndre Guedes #define ADV_CLEAR_TIMEOUT (3*60*HZ) /* Three minutes */ 56676c8686fSAndre Guedes int hci_adv_entries_clear(struct hci_dev *hdev); 56776c8686fSAndre Guedes struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr); 56876c8686fSAndre Guedes int hci_add_adv_entry(struct hci_dev *hdev, 56976c8686fSAndre Guedes struct hci_ev_le_advertising_info *ev); 57076c8686fSAndre Guedes 571ab81cbf9SJohan Hedberg void hci_del_off_timer(struct hci_dev *hdev); 572ab81cbf9SJohan Hedberg 5731da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); 5741da177e4SLinus Torvalds 57576bca880SMarcel Holtmann int hci_recv_frame(struct sk_buff *skb); 576ef222013SMarcel Holtmann int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count); 57799811510SSuraj Sumangala int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count); 578ef222013SMarcel Holtmann 5791da177e4SLinus Torvalds int hci_register_sysfs(struct hci_dev *hdev); 5801da177e4SLinus Torvalds void hci_unregister_sysfs(struct hci_dev *hdev); 581a67e899cSMarcel Holtmann void hci_conn_init_sysfs(struct hci_conn *conn); 582b219e3acSMarcel Holtmann void hci_conn_add_sysfs(struct hci_conn *conn); 583b219e3acSMarcel Holtmann void hci_conn_del_sysfs(struct hci_conn *conn); 5841da177e4SLinus Torvalds 585a91f2e39SMarcel Holtmann #define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->parent = (pdev)) 5861da177e4SLinus Torvalds 5871da177e4SLinus Torvalds /* ----- LMP capabilities ----- */ 58804837f64SMarcel Holtmann #define lmp_rswitch_capable(dev) ((dev)->features[0] & LMP_RSWITCH) 58904837f64SMarcel Holtmann #define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT) 59004837f64SMarcel Holtmann #define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF) 59104837f64SMarcel Holtmann #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR) 5925b7f9909SMarcel Holtmann #define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO) 593769be974SMarcel Holtmann #define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR) 594e702112fSAndrei Emeltchenko #define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH) 5956ed58ec5SVille Tervo #define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE) 5961da177e4SLinus Torvalds 597eead27daSAndre Guedes /* ----- Extended LMP capabilities ----- */ 598eead27daSAndre Guedes #define lmp_host_le_capable(dev) ((dev)->extfeatures[0] & LMP_HOST_LE) 599eead27daSAndre Guedes 6001da177e4SLinus Torvalds /* ----- HCI protocols ----- */ 6011da177e4SLinus Torvalds struct hci_proto { 6021da177e4SLinus Torvalds char *name; 6031da177e4SLinus Torvalds unsigned int id; 6041da177e4SLinus Torvalds unsigned long flags; 6051da177e4SLinus Torvalds 6061da177e4SLinus Torvalds void *priv; 6071da177e4SLinus Torvalds 6085a9d0a3fSWaldemar Rymarkiewicz int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr, 6095a9d0a3fSWaldemar Rymarkiewicz __u8 type); 6101da177e4SLinus Torvalds int (*connect_cfm) (struct hci_conn *conn, __u8 status); 6112950f21aSMarcel Holtmann int (*disconn_ind) (struct hci_conn *conn); 6122950f21aSMarcel Holtmann int (*disconn_cfm) (struct hci_conn *conn, __u8 reason); 6135a9d0a3fSWaldemar Rymarkiewicz int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, 6145a9d0a3fSWaldemar Rymarkiewicz __u16 flags); 6151da177e4SLinus Torvalds int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb); 6165a9d0a3fSWaldemar Rymarkiewicz int (*security_cfm) (struct hci_conn *conn, __u8 status, 6175a9d0a3fSWaldemar Rymarkiewicz __u8 encrypt); 6181da177e4SLinus Torvalds }; 6191da177e4SLinus Torvalds 6205a9d0a3fSWaldemar Rymarkiewicz static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, 6215a9d0a3fSWaldemar Rymarkiewicz __u8 type) 6221da177e4SLinus Torvalds { 6231da177e4SLinus Torvalds register struct hci_proto *hp; 6241da177e4SLinus Torvalds int mask = 0; 6251da177e4SLinus Torvalds 6261da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_L2CAP]; 6271da177e4SLinus Torvalds if (hp && hp->connect_ind) 6281da177e4SLinus Torvalds mask |= hp->connect_ind(hdev, bdaddr, type); 6291da177e4SLinus Torvalds 6301da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_SCO]; 6311da177e4SLinus Torvalds if (hp && hp->connect_ind) 6321da177e4SLinus Torvalds mask |= hp->connect_ind(hdev, bdaddr, type); 6331da177e4SLinus Torvalds 6341da177e4SLinus Torvalds return mask; 6351da177e4SLinus Torvalds } 6361da177e4SLinus Torvalds 6371da177e4SLinus Torvalds static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status) 6381da177e4SLinus Torvalds { 6391da177e4SLinus Torvalds register struct hci_proto *hp; 6401da177e4SLinus Torvalds 6411da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_L2CAP]; 6421da177e4SLinus Torvalds if (hp && hp->connect_cfm) 6431da177e4SLinus Torvalds hp->connect_cfm(conn, status); 6441da177e4SLinus Torvalds 6451da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_SCO]; 6461da177e4SLinus Torvalds if (hp && hp->connect_cfm) 6471da177e4SLinus Torvalds hp->connect_cfm(conn, status); 648e9a416b5SJohan Hedberg 649e9a416b5SJohan Hedberg if (conn->connect_cfm_cb) 650e9a416b5SJohan Hedberg conn->connect_cfm_cb(conn, status); 6511da177e4SLinus Torvalds } 6521da177e4SLinus Torvalds 6532950f21aSMarcel Holtmann static inline int hci_proto_disconn_ind(struct hci_conn *conn) 6542950f21aSMarcel Holtmann { 6552950f21aSMarcel Holtmann register struct hci_proto *hp; 6562950f21aSMarcel Holtmann int reason = 0x13; 6572950f21aSMarcel Holtmann 6582950f21aSMarcel Holtmann hp = hci_proto[HCI_PROTO_L2CAP]; 6592950f21aSMarcel Holtmann if (hp && hp->disconn_ind) 6602950f21aSMarcel Holtmann reason = hp->disconn_ind(conn); 6612950f21aSMarcel Holtmann 6622950f21aSMarcel Holtmann hp = hci_proto[HCI_PROTO_SCO]; 6632950f21aSMarcel Holtmann if (hp && hp->disconn_ind) 6642950f21aSMarcel Holtmann reason = hp->disconn_ind(conn); 6652950f21aSMarcel Holtmann 6662950f21aSMarcel Holtmann return reason; 6672950f21aSMarcel Holtmann } 6682950f21aSMarcel Holtmann 6692950f21aSMarcel Holtmann static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason) 6701da177e4SLinus Torvalds { 6711da177e4SLinus Torvalds register struct hci_proto *hp; 6721da177e4SLinus Torvalds 6731da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_L2CAP]; 6742950f21aSMarcel Holtmann if (hp && hp->disconn_cfm) 6752950f21aSMarcel Holtmann hp->disconn_cfm(conn, reason); 6761da177e4SLinus Torvalds 6771da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_SCO]; 6782950f21aSMarcel Holtmann if (hp && hp->disconn_cfm) 6792950f21aSMarcel Holtmann hp->disconn_cfm(conn, reason); 680e9a416b5SJohan Hedberg 681e9a416b5SJohan Hedberg if (conn->disconn_cfm_cb) 682e9a416b5SJohan Hedberg conn->disconn_cfm_cb(conn, reason); 6831da177e4SLinus Torvalds } 6841da177e4SLinus Torvalds 6851da177e4SLinus Torvalds static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status) 6861da177e4SLinus Torvalds { 6871da177e4SLinus Torvalds register struct hci_proto *hp; 6888c1b2355SMarcel Holtmann __u8 encrypt; 6898c1b2355SMarcel Holtmann 6908c1b2355SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) 6918c1b2355SMarcel Holtmann return; 6928c1b2355SMarcel Holtmann 6938c1b2355SMarcel Holtmann encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00; 6941da177e4SLinus Torvalds 6951da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_L2CAP]; 6968c1b2355SMarcel Holtmann if (hp && hp->security_cfm) 6978c1b2355SMarcel Holtmann hp->security_cfm(conn, status, encrypt); 6981da177e4SLinus Torvalds 6991da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_SCO]; 7008c1b2355SMarcel Holtmann if (hp && hp->security_cfm) 7018c1b2355SMarcel Holtmann hp->security_cfm(conn, status, encrypt); 702e9a416b5SJohan Hedberg 703e9a416b5SJohan Hedberg if (conn->security_cfm_cb) 704e9a416b5SJohan Hedberg conn->security_cfm_cb(conn, status); 7051da177e4SLinus Torvalds } 7061da177e4SLinus Torvalds 7075a9d0a3fSWaldemar Rymarkiewicz static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, 7085a9d0a3fSWaldemar Rymarkiewicz __u8 encrypt) 7091da177e4SLinus Torvalds { 7101da177e4SLinus Torvalds register struct hci_proto *hp; 7111da177e4SLinus Torvalds 7121da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_L2CAP]; 7138c1b2355SMarcel Holtmann if (hp && hp->security_cfm) 7148c1b2355SMarcel Holtmann hp->security_cfm(conn, status, encrypt); 7151da177e4SLinus Torvalds 7161da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_SCO]; 7178c1b2355SMarcel Holtmann if (hp && hp->security_cfm) 7188c1b2355SMarcel Holtmann hp->security_cfm(conn, status, encrypt); 719e9a416b5SJohan Hedberg 720e9a416b5SJohan Hedberg if (conn->security_cfm_cb) 721e9a416b5SJohan Hedberg conn->security_cfm_cb(conn, status); 7221da177e4SLinus Torvalds } 7231da177e4SLinus Torvalds 7241da177e4SLinus Torvalds int hci_register_proto(struct hci_proto *hproto); 7251da177e4SLinus Torvalds int hci_unregister_proto(struct hci_proto *hproto); 7261da177e4SLinus Torvalds 7271da177e4SLinus Torvalds /* ----- HCI callbacks ----- */ 7281da177e4SLinus Torvalds struct hci_cb { 7291da177e4SLinus Torvalds struct list_head list; 7301da177e4SLinus Torvalds 7311da177e4SLinus Torvalds char *name; 7321da177e4SLinus Torvalds 7335a9d0a3fSWaldemar Rymarkiewicz void (*security_cfm) (struct hci_conn *conn, __u8 status, 7345a9d0a3fSWaldemar Rymarkiewicz __u8 encrypt); 7351da177e4SLinus Torvalds void (*key_change_cfm) (struct hci_conn *conn, __u8 status); 7361da177e4SLinus Torvalds void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role); 7371da177e4SLinus Torvalds }; 7381da177e4SLinus Torvalds 7391da177e4SLinus Torvalds static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) 7401da177e4SLinus Torvalds { 7411da177e4SLinus Torvalds struct list_head *p; 7428c1b2355SMarcel Holtmann __u8 encrypt; 7431da177e4SLinus Torvalds 7441da177e4SLinus Torvalds hci_proto_auth_cfm(conn, status); 7451da177e4SLinus Torvalds 7468c1b2355SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) 7478c1b2355SMarcel Holtmann return; 7488c1b2355SMarcel Holtmann 7498c1b2355SMarcel Holtmann encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00; 7508c1b2355SMarcel Holtmann 7511da177e4SLinus Torvalds read_lock_bh(&hci_cb_list_lock); 7521da177e4SLinus Torvalds list_for_each(p, &hci_cb_list) { 7531da177e4SLinus Torvalds struct hci_cb *cb = list_entry(p, struct hci_cb, list); 7548c1b2355SMarcel Holtmann if (cb->security_cfm) 7558c1b2355SMarcel Holtmann cb->security_cfm(conn, status, encrypt); 7561da177e4SLinus Torvalds } 7571da177e4SLinus Torvalds read_unlock_bh(&hci_cb_list_lock); 7581da177e4SLinus Torvalds } 7591da177e4SLinus Torvalds 7605a9d0a3fSWaldemar Rymarkiewicz static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, 7615a9d0a3fSWaldemar Rymarkiewicz __u8 encrypt) 7621da177e4SLinus Torvalds { 7631da177e4SLinus Torvalds struct list_head *p; 7641da177e4SLinus Torvalds 765435fef20SMarcel Holtmann if (conn->sec_level == BT_SECURITY_SDP) 766435fef20SMarcel Holtmann conn->sec_level = BT_SECURITY_LOW; 767435fef20SMarcel Holtmann 76888167aedSVinicius Costa Gomes if (conn->pending_sec_level > conn->sec_level) 76988167aedSVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 77088167aedSVinicius Costa Gomes 7719719f8afSMarcel Holtmann hci_proto_encrypt_cfm(conn, status, encrypt); 7721da177e4SLinus Torvalds 7731da177e4SLinus Torvalds read_lock_bh(&hci_cb_list_lock); 7741da177e4SLinus Torvalds list_for_each(p, &hci_cb_list) { 7751da177e4SLinus Torvalds struct hci_cb *cb = list_entry(p, struct hci_cb, list); 7768c1b2355SMarcel Holtmann if (cb->security_cfm) 7778c1b2355SMarcel Holtmann cb->security_cfm(conn, status, encrypt); 7781da177e4SLinus Torvalds } 7791da177e4SLinus Torvalds read_unlock_bh(&hci_cb_list_lock); 7801da177e4SLinus Torvalds } 7811da177e4SLinus Torvalds 7821da177e4SLinus Torvalds static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status) 7831da177e4SLinus Torvalds { 7841da177e4SLinus Torvalds struct list_head *p; 7851da177e4SLinus Torvalds 7861da177e4SLinus Torvalds read_lock_bh(&hci_cb_list_lock); 7871da177e4SLinus Torvalds list_for_each(p, &hci_cb_list) { 7881da177e4SLinus Torvalds struct hci_cb *cb = list_entry(p, struct hci_cb, list); 7891da177e4SLinus Torvalds if (cb->key_change_cfm) 7901da177e4SLinus Torvalds cb->key_change_cfm(conn, status); 7911da177e4SLinus Torvalds } 7921da177e4SLinus Torvalds read_unlock_bh(&hci_cb_list_lock); 7931da177e4SLinus Torvalds } 7941da177e4SLinus Torvalds 7955a9d0a3fSWaldemar Rymarkiewicz static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, 7965a9d0a3fSWaldemar Rymarkiewicz __u8 role) 7971da177e4SLinus Torvalds { 7981da177e4SLinus Torvalds struct list_head *p; 7991da177e4SLinus Torvalds 8001da177e4SLinus Torvalds read_lock_bh(&hci_cb_list_lock); 8011da177e4SLinus Torvalds list_for_each(p, &hci_cb_list) { 8021da177e4SLinus Torvalds struct hci_cb *cb = list_entry(p, struct hci_cb, list); 8031da177e4SLinus Torvalds if (cb->role_switch_cfm) 8041da177e4SLinus Torvalds cb->role_switch_cfm(conn, status, role); 8051da177e4SLinus Torvalds } 8061da177e4SLinus Torvalds read_unlock_bh(&hci_cb_list_lock); 8071da177e4SLinus Torvalds } 8081da177e4SLinus Torvalds 8091da177e4SLinus Torvalds int hci_register_cb(struct hci_cb *hcb); 8101da177e4SLinus Torvalds int hci_unregister_cb(struct hci_cb *hcb); 8111da177e4SLinus Torvalds 8121da177e4SLinus Torvalds int hci_register_notifier(struct notifier_block *nb); 8131da177e4SLinus Torvalds int hci_unregister_notifier(struct notifier_block *nb); 8141da177e4SLinus Torvalds 815a9de9248SMarcel Holtmann int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param); 8169a9c6a34SGustavo F. Padovan void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags); 8170d861d8bSGustavo F. Padovan void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); 8181da177e4SLinus Torvalds 819a9de9248SMarcel Holtmann void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode); 8201da177e4SLinus Torvalds 8211da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data); 8221da177e4SLinus Torvalds 8231da177e4SLinus Torvalds /* ----- HCI Sockets ----- */ 824eec8d2bcSJohan Hedberg void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb, 825eec8d2bcSJohan Hedberg struct sock *skip_sk); 8261da177e4SLinus Torvalds 8270381101fSJohan Hedberg /* Management interface */ 8280381101fSJohan Hedberg int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); 829c71e97bfSJohan Hedberg int mgmt_index_added(u16 index); 830c71e97bfSJohan Hedberg int mgmt_index_removed(u16 index); 8315add6af8SJohan Hedberg int mgmt_powered(u16 index, u8 powered); 83273f22f62SJohan Hedberg int mgmt_discoverable(u16 index, u8 discoverable); 8339fbcbb45SJohan Hedberg int mgmt_connectable(u16 index, u8 connectable); 8344df378a1SJohan Hedberg int mgmt_new_key(u16 index, struct link_key *key, u8 persistent); 835f7520543SJohan Hedberg int mgmt_connected(u16 index, bdaddr_t *bdaddr); 836f7520543SJohan Hedberg int mgmt_disconnected(u16 index, bdaddr_t *bdaddr); 8378962ee74SJohan Hedberg int mgmt_disconnect_failed(u16 index); 83817d5c04cSJohan Hedberg int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status); 839a770bb5aSWaldemar Rymarkiewicz int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure); 840980e1a53SJohan Hedberg int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); 841980e1a53SJohan Hedberg int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); 84255bc1a37SJohan Hedberg int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value, 84355bc1a37SJohan Hedberg u8 confirm_hint); 844a5c29683SJohan Hedberg int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); 845a5c29683SJohan Hedberg int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, 846a5c29683SJohan Hedberg u8 status); 8472a611692SJohan Hedberg int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status); 848b312b161SJohan Hedberg int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status); 849c35938b2SSzymon Janc int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, 850c35938b2SSzymon Janc u8 status); 851e17acd40SJohan Hedberg int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, 852e17acd40SJohan Hedberg u8 *eir); 853a88a9652SJohan Hedberg int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name); 854314b2381SJohan Hedberg int mgmt_discovering(u16 index, u8 discovering); 8550381101fSJohan Hedberg 8561da177e4SLinus Torvalds /* HCI info for socket */ 8571da177e4SLinus Torvalds #define hci_pi(sk) ((struct hci_pinfo *) sk) 8581da177e4SLinus Torvalds 8591da177e4SLinus Torvalds struct hci_pinfo { 8601da177e4SLinus Torvalds struct bt_sock bt; 8611da177e4SLinus Torvalds struct hci_dev *hdev; 8621da177e4SLinus Torvalds struct hci_filter filter; 8631da177e4SLinus Torvalds __u32 cmsg_mask; 864c02178d2SJohan Hedberg unsigned short channel; 8651da177e4SLinus Torvalds }; 8661da177e4SLinus Torvalds 8671da177e4SLinus Torvalds /* HCI security filter */ 8681da177e4SLinus Torvalds #define HCI_SFLT_MAX_OGF 5 8691da177e4SLinus Torvalds 8701da177e4SLinus Torvalds struct hci_sec_filter { 8711da177e4SLinus Torvalds __u32 type_mask; 8721da177e4SLinus Torvalds __u32 event_mask[2]; 8731da177e4SLinus Torvalds __u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4]; 8741da177e4SLinus Torvalds }; 8751da177e4SLinus Torvalds 8761da177e4SLinus Torvalds /* ----- HCI requests ----- */ 8771da177e4SLinus Torvalds #define HCI_REQ_DONE 0 8781da177e4SLinus Torvalds #define HCI_REQ_PEND 1 8791da177e4SLinus Torvalds #define HCI_REQ_CANCELED 2 8801da177e4SLinus Torvalds 881a6a67efdSThomas Gleixner #define hci_req_lock(d) mutex_lock(&d->req_lock) 882a6a67efdSThomas Gleixner #define hci_req_unlock(d) mutex_unlock(&d->req_lock) 8831da177e4SLinus Torvalds 88423bb5763SJohan Hedberg void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result); 8851da177e4SLinus Torvalds 8862ce603ebSClaudio Takahasi void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, 8872ce603ebSClaudio Takahasi u16 latency, u16 to_multiplier); 888a7a595f6SVinicius Costa Gomes void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], 889a7a595f6SVinicius Costa Gomes __u8 ltk[16]); 890a7a595f6SVinicius Costa Gomes void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]); 891a7a595f6SVinicius Costa Gomes void hci_le_ltk_neg_reply(struct hci_conn *conn); 892a7a595f6SVinicius Costa Gomes 8931da177e4SLinus Torvalds #endif /* __HCI_CORE_H */ 894