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 28a6b7a407SAlexey Dobriyan #include <linux/interrupt.h> 291da177e4SLinus Torvalds #include <net/bluetooth/hci.h> 301da177e4SLinus Torvalds 311da177e4SLinus Torvalds /* HCI upper protocols */ 321da177e4SLinus Torvalds #define HCI_PROTO_L2CAP 0 331da177e4SLinus Torvalds #define HCI_PROTO_SCO 1 341da177e4SLinus Torvalds 355e59b791SLuiz Augusto von Dentz /* HCI priority */ 365e59b791SLuiz Augusto von Dentz #define HCI_PRIO_MAX 7 375e59b791SLuiz Augusto von Dentz 381da177e4SLinus Torvalds /* HCI Core structures */ 391da177e4SLinus Torvalds struct inquiry_data { 401da177e4SLinus Torvalds bdaddr_t bdaddr; 411da177e4SLinus Torvalds __u8 pscan_rep_mode; 421da177e4SLinus Torvalds __u8 pscan_period_mode; 431da177e4SLinus Torvalds __u8 pscan_mode; 441da177e4SLinus Torvalds __u8 dev_class[3]; 451ebb9252SMarcel Holtmann __le16 clock_offset; 461da177e4SLinus Torvalds __s8 rssi; 4741a96212SMarcel Holtmann __u8 ssp_mode; 481da177e4SLinus Torvalds }; 491da177e4SLinus Torvalds 501da177e4SLinus Torvalds struct inquiry_entry { 511da177e4SLinus Torvalds struct inquiry_entry *next; 521da177e4SLinus Torvalds __u32 timestamp; 531da177e4SLinus Torvalds struct inquiry_data data; 541da177e4SLinus Torvalds }; 551da177e4SLinus Torvalds 561da177e4SLinus Torvalds struct inquiry_cache { 571da177e4SLinus Torvalds spinlock_t lock; 581da177e4SLinus Torvalds __u32 timestamp; 591da177e4SLinus Torvalds struct inquiry_entry *list; 601da177e4SLinus Torvalds }; 611da177e4SLinus Torvalds 621da177e4SLinus Torvalds struct hci_conn_hash { 631da177e4SLinus Torvalds struct list_head list; 641da177e4SLinus Torvalds spinlock_t lock; 651da177e4SLinus Torvalds unsigned int acl_num; 661da177e4SLinus Torvalds unsigned int sco_num; 67fcd89c09SVille Tervo unsigned int le_num; 681da177e4SLinus Torvalds }; 691da177e4SLinus Torvalds 7073d80debSLuiz Augusto von Dentz struct hci_chan_hash { 7173d80debSLuiz Augusto von Dentz struct list_head list; 7273d80debSLuiz Augusto von Dentz spinlock_t lock; 7373d80debSLuiz Augusto von Dentz unsigned int num; 7473d80debSLuiz Augusto von Dentz }; 7573d80debSLuiz Augusto von Dentz 76f0358568SJohan Hedberg struct bdaddr_list { 77f0358568SJohan Hedberg struct list_head list; 78f0358568SJohan Hedberg bdaddr_t bdaddr; 79f0358568SJohan Hedberg }; 802aeb9a1aSJohan Hedberg 812aeb9a1aSJohan Hedberg struct bt_uuid { 822aeb9a1aSJohan Hedberg struct list_head list; 832aeb9a1aSJohan Hedberg u8 uuid[16]; 841aff6f09SJohan Hedberg u8 svc_hint; 852aeb9a1aSJohan Hedberg }; 862aeb9a1aSJohan Hedberg 8734918cd7SVinicius Costa Gomes struct key_master_id { 8834918cd7SVinicius Costa Gomes __le16 ediv; 8934918cd7SVinicius Costa Gomes u8 rand[8]; 9034918cd7SVinicius Costa Gomes } __packed; 9134918cd7SVinicius Costa Gomes 9234918cd7SVinicius Costa Gomes struct link_key_data { 9334918cd7SVinicius Costa Gomes bdaddr_t bdaddr; 9434918cd7SVinicius Costa Gomes u8 type; 9534918cd7SVinicius Costa Gomes u8 val[16]; 9634918cd7SVinicius Costa Gomes u8 pin_len; 9734918cd7SVinicius Costa Gomes u8 dlen; 9834918cd7SVinicius Costa Gomes u8 data[0]; 9934918cd7SVinicius Costa Gomes } __packed; 10034918cd7SVinicius Costa Gomes 10155ed8ca1SJohan Hedberg struct link_key { 10255ed8ca1SJohan Hedberg struct list_head list; 10355ed8ca1SJohan Hedberg bdaddr_t bdaddr; 10455ed8ca1SJohan Hedberg u8 type; 10555ed8ca1SJohan Hedberg u8 val[16]; 10655ed8ca1SJohan Hedberg u8 pin_len; 10734918cd7SVinicius Costa Gomes u8 dlen; 10834918cd7SVinicius Costa Gomes u8 data[0]; 10955ed8ca1SJohan Hedberg }; 11055ed8ca1SJohan Hedberg 1112763eda6SSzymon Janc struct oob_data { 1122763eda6SSzymon Janc struct list_head list; 1132763eda6SSzymon Janc bdaddr_t bdaddr; 1142763eda6SSzymon Janc u8 hash[16]; 1152763eda6SSzymon Janc u8 randomizer[16]; 1162763eda6SSzymon Janc }; 1172763eda6SSzymon Janc 11876c8686fSAndre Guedes struct adv_entry { 11976c8686fSAndre Guedes struct list_head list; 12076c8686fSAndre Guedes bdaddr_t bdaddr; 12176c8686fSAndre Guedes u8 bdaddr_type; 12276c8686fSAndre Guedes }; 12376c8686fSAndre Guedes 124cd4c5391SSuraj Sumangala #define NUM_REASSEMBLY 4 1251da177e4SLinus Torvalds struct hci_dev { 1261da177e4SLinus Torvalds struct list_head list; 1271da177e4SLinus Torvalds spinlock_t lock; 1281da177e4SLinus Torvalds atomic_t refcnt; 1291da177e4SLinus Torvalds 1301da177e4SLinus Torvalds char name[8]; 1311da177e4SLinus Torvalds unsigned long flags; 1321da177e4SLinus Torvalds __u16 id; 133c13854ceSMarcel Holtmann __u8 bus; 134943da25dSMarcel Holtmann __u8 dev_type; 1351da177e4SLinus Torvalds bdaddr_t bdaddr; 1361f6c6378SJohan Hedberg __u8 dev_name[HCI_MAX_NAME_LENGTH]; 13780a1e1dbSJohan Hedberg __u8 eir[HCI_MAX_EIR_LENGTH]; 138a9de9248SMarcel Holtmann __u8 dev_class[3]; 1391aff6f09SJohan Hedberg __u8 major_class; 1401aff6f09SJohan Hedberg __u8 minor_class; 1411da177e4SLinus Torvalds __u8 features[8]; 142971e3a4bSAndre Guedes __u8 extfeatures[8]; 143a9de9248SMarcel Holtmann __u8 commands[64]; 144333140b5SMarcel Holtmann __u8 ssp_mode; 1451143e5a6SMarcel Holtmann __u8 hci_ver; 1461143e5a6SMarcel Holtmann __u16 hci_rev; 147d5859e22SJohan Hedberg __u8 lmp_ver; 1481143e5a6SMarcel Holtmann __u16 manufacturer; 149d5859e22SJohan Hedberg __le16 lmp_subver; 1501da177e4SLinus Torvalds __u16 voice_setting; 15117fa4b9dSJohan Hedberg __u8 io_capability; 1521da177e4SLinus Torvalds 1531da177e4SLinus Torvalds __u16 pkt_type; 1545b7f9909SMarcel Holtmann __u16 esco_type; 1551da177e4SLinus Torvalds __u16 link_policy; 1561da177e4SLinus Torvalds __u16 link_mode; 1571da177e4SLinus Torvalds 15804837f64SMarcel Holtmann __u32 idle_timeout; 15904837f64SMarcel Holtmann __u16 sniff_min_interval; 16004837f64SMarcel Holtmann __u16 sniff_max_interval; 16104837f64SMarcel Holtmann 162928abaa7SAndrei Emeltchenko __u8 amp_status; 163928abaa7SAndrei Emeltchenko __u32 amp_total_bw; 164928abaa7SAndrei Emeltchenko __u32 amp_max_bw; 165928abaa7SAndrei Emeltchenko __u32 amp_min_latency; 166928abaa7SAndrei Emeltchenko __u32 amp_max_pdu; 167928abaa7SAndrei Emeltchenko __u8 amp_type; 168928abaa7SAndrei Emeltchenko __u16 amp_pal_cap; 169928abaa7SAndrei Emeltchenko __u16 amp_assoc_size; 170928abaa7SAndrei Emeltchenko __u32 amp_max_flush_to; 171928abaa7SAndrei Emeltchenko __u32 amp_be_flush_to; 172928abaa7SAndrei Emeltchenko 1739f61656aSJohan Hedberg unsigned int auto_accept_delay; 1749f61656aSJohan Hedberg 1751da177e4SLinus Torvalds unsigned long quirks; 1761da177e4SLinus Torvalds 1771da177e4SLinus Torvalds atomic_t cmd_cnt; 1781da177e4SLinus Torvalds unsigned int acl_cnt; 1791da177e4SLinus Torvalds unsigned int sco_cnt; 1806ed58ec5SVille Tervo unsigned int le_cnt; 1811da177e4SLinus Torvalds 1821da177e4SLinus Torvalds unsigned int acl_mtu; 1831da177e4SLinus Torvalds unsigned int sco_mtu; 1846ed58ec5SVille Tervo unsigned int le_mtu; 1851da177e4SLinus Torvalds unsigned int acl_pkts; 1861da177e4SLinus Torvalds unsigned int sco_pkts; 1876ed58ec5SVille Tervo unsigned int le_pkts; 1881da177e4SLinus Torvalds 1891da177e4SLinus Torvalds unsigned long acl_last_tx; 1901da177e4SLinus Torvalds unsigned long sco_last_tx; 1916ed58ec5SVille Tervo unsigned long le_last_tx; 1921da177e4SLinus Torvalds 193f48fd9c8SMarcel Holtmann struct workqueue_struct *workqueue; 194f48fd9c8SMarcel Holtmann 195ab81cbf9SJohan Hedberg struct work_struct power_on; 196ab81cbf9SJohan Hedberg struct work_struct power_off; 197ab81cbf9SJohan Hedberg struct timer_list off_timer; 198ab81cbf9SJohan Hedberg 1996bd32326SVille Tervo struct timer_list cmd_timer; 2001da177e4SLinus Torvalds struct tasklet_struct cmd_task; 2011da177e4SLinus Torvalds struct tasklet_struct rx_task; 2021da177e4SLinus Torvalds struct tasklet_struct tx_task; 2031da177e4SLinus Torvalds 2041da177e4SLinus Torvalds struct sk_buff_head rx_q; 2051da177e4SLinus Torvalds struct sk_buff_head raw_q; 2061da177e4SLinus Torvalds struct sk_buff_head cmd_q; 2071da177e4SLinus Torvalds 2081da177e4SLinus Torvalds struct sk_buff *sent_cmd; 209cd4c5391SSuraj Sumangala struct sk_buff *reassembly[NUM_REASSEMBLY]; 2101da177e4SLinus Torvalds 211a6a67efdSThomas Gleixner struct mutex req_lock; 2121da177e4SLinus Torvalds wait_queue_head_t req_wait_q; 2131da177e4SLinus Torvalds __u32 req_status; 2141da177e4SLinus Torvalds __u32 req_result; 215a5040efaSJohan Hedberg 216a5040efaSJohan Hedberg __u16 init_last_cmd; 2171da177e4SLinus Torvalds 2181da177e4SLinus Torvalds struct inquiry_cache inq_cache; 2191da177e4SLinus Torvalds struct hci_conn_hash conn_hash; 220ea4bd8baSDavid Miller struct list_head blacklist; 2211da177e4SLinus Torvalds 2222aeb9a1aSJohan Hedberg struct list_head uuids; 2232aeb9a1aSJohan Hedberg 22455ed8ca1SJohan Hedberg struct list_head link_keys; 22555ed8ca1SJohan Hedberg 2262763eda6SSzymon Janc struct list_head remote_oob_data; 2272763eda6SSzymon Janc 22876c8686fSAndre Guedes struct list_head adv_entries; 22935815085SAndre Guedes struct timer_list adv_timer; 23076c8686fSAndre Guedes 2311da177e4SLinus Torvalds struct hci_dev_stats stat; 2321da177e4SLinus Torvalds 2331da177e4SLinus Torvalds struct sk_buff_head driver_init; 2341da177e4SLinus Torvalds 2351da177e4SLinus Torvalds void *driver_data; 2361da177e4SLinus Torvalds void *core_data; 2371da177e4SLinus Torvalds 2381da177e4SLinus Torvalds atomic_t promisc; 2391da177e4SLinus Torvalds 240ca325f69SMarcel Holtmann struct dentry *debugfs; 241ca325f69SMarcel Holtmann 242a91f2e39SMarcel Holtmann struct device *parent; 243a91f2e39SMarcel Holtmann struct device dev; 2441da177e4SLinus Torvalds 245611b30f7SMarcel Holtmann struct rfkill *rfkill; 246611b30f7SMarcel Holtmann 2471da177e4SLinus Torvalds struct module *owner; 2481da177e4SLinus Torvalds 2491da177e4SLinus Torvalds int (*open)(struct hci_dev *hdev); 2501da177e4SLinus Torvalds int (*close)(struct hci_dev *hdev); 2511da177e4SLinus Torvalds int (*flush)(struct hci_dev *hdev); 2521da177e4SLinus Torvalds int (*send)(struct sk_buff *skb); 2531da177e4SLinus Torvalds void (*destruct)(struct hci_dev *hdev); 2541da177e4SLinus Torvalds void (*notify)(struct hci_dev *hdev, unsigned int evt); 2551da177e4SLinus Torvalds int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg); 2561da177e4SLinus Torvalds }; 2571da177e4SLinus Torvalds 2581da177e4SLinus Torvalds struct hci_conn { 2591da177e4SLinus Torvalds struct list_head list; 2601da177e4SLinus Torvalds 2611da177e4SLinus Torvalds atomic_t refcnt; 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds bdaddr_t dst; 26429b7988aSAndre Guedes __u8 dst_type; 2651da177e4SLinus Torvalds __u16 handle; 2661da177e4SLinus Torvalds __u16 state; 26704837f64SMarcel Holtmann __u8 mode; 2681da177e4SLinus Torvalds __u8 type; 2691da177e4SLinus Torvalds __u8 out; 2704c67bc74SMarcel Holtmann __u8 attempt; 2711da177e4SLinus Torvalds __u8 dev_class[3]; 27204837f64SMarcel Holtmann __u8 features[8]; 27341a96212SMarcel Holtmann __u8 ssp_mode; 27404837f64SMarcel Holtmann __u16 interval; 275a8746417SMarcel Holtmann __u16 pkt_type; 27604837f64SMarcel Holtmann __u16 link_policy; 2771da177e4SLinus Torvalds __u32 link_mode; 27813d39315SWaldemar Rymarkiewicz __u8 key_type; 27940be492fSMarcel Holtmann __u8 auth_type; 2808c1b2355SMarcel Holtmann __u8 sec_level; 281765c2a96SJohan Hedberg __u8 pending_sec_level; 282980e1a53SJohan Hedberg __u8 pin_length; 283726b4ffcSVinicius Costa Gomes __u8 enc_key_size; 28417fa4b9dSJohan Hedberg __u8 io_capability; 28504837f64SMarcel Holtmann __u8 power_save; 286052b30b0SMarcel Holtmann __u16 disc_timeout; 2871da177e4SLinus Torvalds unsigned long pend; 2881da177e4SLinus Torvalds 28903b555e1SJohan Hedberg __u8 remote_cap; 29003b555e1SJohan Hedberg __u8 remote_oob; 29103b555e1SJohan Hedberg __u8 remote_auth; 29203b555e1SJohan Hedberg 2931da177e4SLinus Torvalds unsigned int sent; 2941da177e4SLinus Torvalds 2951da177e4SLinus Torvalds struct sk_buff_head data_q; 29673d80debSLuiz Augusto von Dentz struct hci_chan_hash chan_hash; 2971da177e4SLinus Torvalds 29804837f64SMarcel Holtmann struct timer_list disc_timer; 29904837f64SMarcel Holtmann struct timer_list idle_timer; 3009f61656aSJohan Hedberg struct timer_list auto_accept_timer; 3011da177e4SLinus Torvalds 302f3784d83SRoger Quadros struct work_struct work_add; 303f3784d83SRoger Quadros struct work_struct work_del; 304b219e3acSMarcel Holtmann 305b219e3acSMarcel Holtmann struct device dev; 3069eba32b8SMarcel Holtmann atomic_t devref; 307b219e3acSMarcel Holtmann 3081da177e4SLinus Torvalds struct hci_dev *hdev; 3091da177e4SLinus Torvalds void *l2cap_data; 3101da177e4SLinus Torvalds void *sco_data; 3111da177e4SLinus Torvalds 3121da177e4SLinus Torvalds struct hci_conn *link; 313e9a416b5SJohan Hedberg 314e9a416b5SJohan Hedberg void (*connect_cfm_cb) (struct hci_conn *conn, u8 status); 315e9a416b5SJohan Hedberg void (*security_cfm_cb) (struct hci_conn *conn, u8 status); 316e9a416b5SJohan Hedberg void (*disconn_cfm_cb) (struct hci_conn *conn, u8 reason); 3171da177e4SLinus Torvalds }; 3181da177e4SLinus Torvalds 31973d80debSLuiz Augusto von Dentz struct hci_chan { 32073d80debSLuiz Augusto von Dentz struct list_head list; 32173d80debSLuiz Augusto von Dentz 32273d80debSLuiz Augusto von Dentz struct hci_conn *conn; 32373d80debSLuiz Augusto von Dentz struct sk_buff_head data_q; 32473d80debSLuiz Augusto von Dentz unsigned int sent; 32573d80debSLuiz Augusto von Dentz }; 32673d80debSLuiz Augusto von Dentz 3271da177e4SLinus Torvalds extern struct hci_proto *hci_proto[]; 3281da177e4SLinus Torvalds extern struct list_head hci_dev_list; 3291da177e4SLinus Torvalds extern struct list_head hci_cb_list; 3301da177e4SLinus Torvalds extern rwlock_t hci_dev_list_lock; 3311da177e4SLinus Torvalds extern rwlock_t hci_cb_list_lock; 3321da177e4SLinus Torvalds 3331da177e4SLinus Torvalds /* ----- Inquiry cache ----- */ 33470f23020SAndrei Emeltchenko #define INQUIRY_CACHE_AGE_MAX (HZ*30) /* 30 seconds */ 33570f23020SAndrei Emeltchenko #define INQUIRY_ENTRY_AGE_MAX (HZ*60) /* 60 seconds */ 3361da177e4SLinus Torvalds 3371da177e4SLinus Torvalds #define inquiry_cache_lock(c) spin_lock(&c->lock) 3381da177e4SLinus Torvalds #define inquiry_cache_unlock(c) spin_unlock(&c->lock) 3391da177e4SLinus Torvalds #define inquiry_cache_lock_bh(c) spin_lock_bh(&c->lock) 3401da177e4SLinus Torvalds #define inquiry_cache_unlock_bh(c) spin_unlock_bh(&c->lock) 3411da177e4SLinus Torvalds 3421da177e4SLinus Torvalds static inline void inquiry_cache_init(struct hci_dev *hdev) 3431da177e4SLinus Torvalds { 3441da177e4SLinus Torvalds struct inquiry_cache *c = &hdev->inq_cache; 3451da177e4SLinus Torvalds spin_lock_init(&c->lock); 3461da177e4SLinus Torvalds c->list = NULL; 3471da177e4SLinus Torvalds } 3481da177e4SLinus Torvalds 3491da177e4SLinus Torvalds static inline int inquiry_cache_empty(struct hci_dev *hdev) 3501da177e4SLinus Torvalds { 3511da177e4SLinus Torvalds struct inquiry_cache *c = &hdev->inq_cache; 352a02cec21SEric Dumazet return c->list == NULL; 3531da177e4SLinus Torvalds } 3541da177e4SLinus Torvalds 3551da177e4SLinus Torvalds static inline long inquiry_cache_age(struct hci_dev *hdev) 3561da177e4SLinus Torvalds { 3571da177e4SLinus Torvalds struct inquiry_cache *c = &hdev->inq_cache; 3581da177e4SLinus Torvalds return jiffies - c->timestamp; 3591da177e4SLinus Torvalds } 3601da177e4SLinus Torvalds 3611da177e4SLinus Torvalds static inline long inquiry_entry_age(struct inquiry_entry *e) 3621da177e4SLinus Torvalds { 3631da177e4SLinus Torvalds return jiffies - e->timestamp; 3641da177e4SLinus Torvalds } 3651da177e4SLinus Torvalds 3665a9d0a3fSWaldemar Rymarkiewicz struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, 3675a9d0a3fSWaldemar Rymarkiewicz bdaddr_t *bdaddr); 3681da177e4SLinus Torvalds void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data); 3691da177e4SLinus Torvalds 3701da177e4SLinus Torvalds /* ----- HCI Connections ----- */ 3711da177e4SLinus Torvalds enum { 3721da177e4SLinus Torvalds HCI_CONN_AUTH_PEND, 37319f8def0SWaldemar Rymarkiewicz HCI_CONN_REAUTH_PEND, 3741da177e4SLinus Torvalds HCI_CONN_ENCRYPT_PEND, 37504837f64SMarcel Holtmann HCI_CONN_RSWITCH_PEND, 37604837f64SMarcel Holtmann HCI_CONN_MODE_CHANGE_PEND, 377e73439d8SMarcel Holtmann HCI_CONN_SCO_SETUP_PEND, 378d26a2345SVinicius Costa Gomes HCI_CONN_LE_SMP_PEND, 3791da177e4SLinus Torvalds }; 3801da177e4SLinus Torvalds 3811da177e4SLinus Torvalds static inline void hci_conn_hash_init(struct hci_dev *hdev) 3821da177e4SLinus Torvalds { 3831da177e4SLinus Torvalds struct hci_conn_hash *h = &hdev->conn_hash; 3841da177e4SLinus Torvalds INIT_LIST_HEAD(&h->list); 3851da177e4SLinus Torvalds spin_lock_init(&h->lock); 3861da177e4SLinus Torvalds h->acl_num = 0; 3871da177e4SLinus Torvalds h->sco_num = 0; 3881da177e4SLinus Torvalds } 3891da177e4SLinus Torvalds 3901da177e4SLinus Torvalds static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) 3911da177e4SLinus Torvalds { 3921da177e4SLinus Torvalds struct hci_conn_hash *h = &hdev->conn_hash; 3931da177e4SLinus Torvalds list_add(&c->list, &h->list); 394fcd89c09SVille Tervo switch (c->type) { 395fcd89c09SVille Tervo case ACL_LINK: 3961da177e4SLinus Torvalds h->acl_num++; 397fcd89c09SVille Tervo break; 398fcd89c09SVille Tervo case LE_LINK: 399fcd89c09SVille Tervo h->le_num++; 400fcd89c09SVille Tervo break; 401fcd89c09SVille Tervo case SCO_LINK: 402fcd89c09SVille Tervo case ESCO_LINK: 4031da177e4SLinus Torvalds h->sco_num++; 404fcd89c09SVille Tervo break; 405fcd89c09SVille Tervo } 4061da177e4SLinus Torvalds } 4071da177e4SLinus Torvalds 4081da177e4SLinus Torvalds static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) 4091da177e4SLinus Torvalds { 4101da177e4SLinus Torvalds struct hci_conn_hash *h = &hdev->conn_hash; 4111da177e4SLinus Torvalds list_del(&c->list); 412fcd89c09SVille Tervo switch (c->type) { 413fcd89c09SVille Tervo case ACL_LINK: 4141da177e4SLinus Torvalds h->acl_num--; 415fcd89c09SVille Tervo break; 416fcd89c09SVille Tervo case LE_LINK: 417fcd89c09SVille Tervo h->le_num--; 418fcd89c09SVille Tervo break; 419fcd89c09SVille Tervo case SCO_LINK: 420fcd89c09SVille Tervo case ESCO_LINK: 4211da177e4SLinus Torvalds h->sco_num--; 422fcd89c09SVille Tervo break; 423fcd89c09SVille Tervo } 4241da177e4SLinus Torvalds } 4251da177e4SLinus Torvalds 42652087a79SLuiz Augusto von Dentz static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type) 42752087a79SLuiz Augusto von Dentz { 42852087a79SLuiz Augusto von Dentz struct hci_conn_hash *h = &hdev->conn_hash; 42952087a79SLuiz Augusto von Dentz switch (type) { 43052087a79SLuiz Augusto von Dentz case ACL_LINK: 43152087a79SLuiz Augusto von Dentz return h->acl_num; 43252087a79SLuiz Augusto von Dentz case LE_LINK: 43352087a79SLuiz Augusto von Dentz return h->le_num; 43452087a79SLuiz Augusto von Dentz case SCO_LINK: 43552087a79SLuiz Augusto von Dentz case ESCO_LINK: 43652087a79SLuiz Augusto von Dentz return h->sco_num; 43752087a79SLuiz Augusto von Dentz default: 43852087a79SLuiz Augusto von Dentz return 0; 43952087a79SLuiz Augusto von Dentz } 44052087a79SLuiz Augusto von Dentz } 44152087a79SLuiz Augusto von Dentz 4421da177e4SLinus Torvalds static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev, 4431da177e4SLinus Torvalds __u16 handle) 4441da177e4SLinus Torvalds { 4451da177e4SLinus Torvalds struct hci_conn_hash *h = &hdev->conn_hash; 4461da177e4SLinus Torvalds struct list_head *p; 4471da177e4SLinus Torvalds struct hci_conn *c; 4481da177e4SLinus Torvalds 4491da177e4SLinus Torvalds list_for_each(p, &h->list) { 4501da177e4SLinus Torvalds c = list_entry(p, struct hci_conn, list); 4511da177e4SLinus Torvalds if (c->handle == handle) 4521da177e4SLinus Torvalds return c; 4531da177e4SLinus Torvalds } 4541da177e4SLinus Torvalds return NULL; 4551da177e4SLinus Torvalds } 4561da177e4SLinus Torvalds 4571da177e4SLinus Torvalds static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev, 4581da177e4SLinus Torvalds __u8 type, bdaddr_t *ba) 4591da177e4SLinus Torvalds { 4601da177e4SLinus Torvalds struct hci_conn_hash *h = &hdev->conn_hash; 4611da177e4SLinus Torvalds struct list_head *p; 4621da177e4SLinus Torvalds struct hci_conn *c; 4631da177e4SLinus Torvalds 4641da177e4SLinus Torvalds list_for_each(p, &h->list) { 4651da177e4SLinus Torvalds c = list_entry(p, struct hci_conn, list); 4661da177e4SLinus Torvalds if (c->type == type && !bacmp(&c->dst, ba)) 4671da177e4SLinus Torvalds return c; 4681da177e4SLinus Torvalds } 4691da177e4SLinus Torvalds return NULL; 4701da177e4SLinus Torvalds } 4711da177e4SLinus Torvalds 4724c67bc74SMarcel Holtmann static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev, 4734c67bc74SMarcel Holtmann __u8 type, __u16 state) 4744c67bc74SMarcel Holtmann { 4754c67bc74SMarcel Holtmann struct hci_conn_hash *h = &hdev->conn_hash; 4764c67bc74SMarcel Holtmann struct list_head *p; 4774c67bc74SMarcel Holtmann struct hci_conn *c; 4784c67bc74SMarcel Holtmann 4794c67bc74SMarcel Holtmann list_for_each(p, &h->list) { 4804c67bc74SMarcel Holtmann c = list_entry(p, struct hci_conn, list); 4814c67bc74SMarcel Holtmann if (c->type == type && c->state == state) 4824c67bc74SMarcel Holtmann return c; 4834c67bc74SMarcel Holtmann } 4844c67bc74SMarcel Holtmann return NULL; 4854c67bc74SMarcel Holtmann } 4864c67bc74SMarcel Holtmann 48773d80debSLuiz Augusto von Dentz static inline void hci_chan_hash_init(struct hci_conn *c) 48873d80debSLuiz Augusto von Dentz { 48973d80debSLuiz Augusto von Dentz struct hci_chan_hash *h = &c->chan_hash; 49073d80debSLuiz Augusto von Dentz INIT_LIST_HEAD(&h->list); 49173d80debSLuiz Augusto von Dentz spin_lock_init(&h->lock); 49273d80debSLuiz Augusto von Dentz h->num = 0; 49373d80debSLuiz Augusto von Dentz } 49473d80debSLuiz Augusto von Dentz 49573d80debSLuiz Augusto von Dentz static inline void hci_chan_hash_add(struct hci_conn *c, struct hci_chan *chan) 49673d80debSLuiz Augusto von Dentz { 49773d80debSLuiz Augusto von Dentz struct hci_chan_hash *h = &c->chan_hash; 49873d80debSLuiz Augusto von Dentz list_add(&chan->list, &h->list); 49973d80debSLuiz Augusto von Dentz h->num++; 50073d80debSLuiz Augusto von Dentz } 50173d80debSLuiz Augusto von Dentz 50273d80debSLuiz Augusto von Dentz static inline void hci_chan_hash_del(struct hci_conn *c, struct hci_chan *chan) 50373d80debSLuiz Augusto von Dentz { 50473d80debSLuiz Augusto von Dentz struct hci_chan_hash *h = &c->chan_hash; 50573d80debSLuiz Augusto von Dentz list_del(&chan->list); 50673d80debSLuiz Augusto von Dentz h->num--; 50773d80debSLuiz Augusto von Dentz } 50873d80debSLuiz Augusto von Dentz 5094c67bc74SMarcel Holtmann void hci_acl_connect(struct hci_conn *conn); 5101da177e4SLinus Torvalds void hci_acl_disconn(struct hci_conn *conn, __u8 reason); 5111da177e4SLinus Torvalds void hci_add_sco(struct hci_conn *conn, __u16 handle); 512b6a0dc82SMarcel Holtmann void hci_setup_sync(struct hci_conn *conn, __u16 handle); 513e73439d8SMarcel Holtmann void hci_sco_setup(struct hci_conn *conn, __u8 status); 5141da177e4SLinus Torvalds 5151da177e4SLinus Torvalds struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst); 5161da177e4SLinus Torvalds int hci_conn_del(struct hci_conn *conn); 5171da177e4SLinus Torvalds void hci_conn_hash_flush(struct hci_dev *hdev); 518a9de9248SMarcel Holtmann void hci_conn_check_pending(struct hci_dev *hdev); 5191da177e4SLinus Torvalds 52073d80debSLuiz Augusto von Dentz struct hci_chan *hci_chan_create(struct hci_conn *conn); 52173d80debSLuiz Augusto von Dentz int hci_chan_del(struct hci_chan *chan); 52273d80debSLuiz Augusto von Dentz void hci_chan_hash_flush(struct hci_conn *conn); 52373d80debSLuiz Augusto von Dentz 5245a9d0a3fSWaldemar Rymarkiewicz struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, 5255a9d0a3fSWaldemar Rymarkiewicz __u8 sec_level, __u8 auth_type); 526e7c29cb1SMarcel Holtmann int hci_conn_check_link_mode(struct hci_conn *conn); 527b3b1b061SWaldemar Rymarkiewicz int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level); 5280684e5f9SMarcel Holtmann int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type); 5291da177e4SLinus Torvalds int hci_conn_change_link_key(struct hci_conn *conn); 5308c1b2355SMarcel Holtmann int hci_conn_switch_role(struct hci_conn *conn, __u8 role); 5311da177e4SLinus Torvalds 53214b12d0bSJaikumar Ganesh void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active); 53304837f64SMarcel Holtmann void hci_conn_enter_sniff_mode(struct hci_conn *conn); 5341da177e4SLinus Torvalds 5359eba32b8SMarcel Holtmann void hci_conn_hold_device(struct hci_conn *conn); 5369eba32b8SMarcel Holtmann void hci_conn_put_device(struct hci_conn *conn); 5379eba32b8SMarcel Holtmann 5381da177e4SLinus Torvalds static inline void hci_conn_hold(struct hci_conn *conn) 5391da177e4SLinus Torvalds { 5401da177e4SLinus Torvalds atomic_inc(&conn->refcnt); 54104837f64SMarcel Holtmann del_timer(&conn->disc_timer); 5421da177e4SLinus Torvalds } 5431da177e4SLinus Torvalds 5441da177e4SLinus Torvalds static inline void hci_conn_put(struct hci_conn *conn) 5451da177e4SLinus Torvalds { 5461da177e4SLinus Torvalds if (atomic_dec_and_test(&conn->refcnt)) { 54704837f64SMarcel Holtmann unsigned long timeo; 548454d48ffSVinicius Costa Gomes if (conn->type == ACL_LINK || conn->type == LE_LINK) { 5496ac59344SMarcel Holtmann del_timer(&conn->idle_timer); 5506ac59344SMarcel Holtmann if (conn->state == BT_CONNECTED) { 551052b30b0SMarcel Holtmann timeo = msecs_to_jiffies(conn->disc_timeout); 55204837f64SMarcel Holtmann if (!conn->out) 553052b30b0SMarcel Holtmann timeo *= 2; 5545a9d0a3fSWaldemar Rymarkiewicz } else { 5556ac59344SMarcel Holtmann timeo = msecs_to_jiffies(10); 5565a9d0a3fSWaldemar Rymarkiewicz } 5575a9d0a3fSWaldemar Rymarkiewicz } else { 55804837f64SMarcel Holtmann timeo = msecs_to_jiffies(10); 5595a9d0a3fSWaldemar Rymarkiewicz } 56004837f64SMarcel Holtmann mod_timer(&conn->disc_timer, jiffies + timeo); 5611da177e4SLinus Torvalds } 5621da177e4SLinus Torvalds } 5631da177e4SLinus Torvalds 5641da177e4SLinus Torvalds /* ----- HCI Devices ----- */ 5651da177e4SLinus Torvalds static inline void __hci_dev_put(struct hci_dev *d) 5661da177e4SLinus Torvalds { 5671da177e4SLinus Torvalds if (atomic_dec_and_test(&d->refcnt)) 5681da177e4SLinus Torvalds d->destruct(d); 5691da177e4SLinus Torvalds } 5701da177e4SLinus Torvalds 5711da177e4SLinus Torvalds static inline void hci_dev_put(struct hci_dev *d) 5721da177e4SLinus Torvalds { 5731da177e4SLinus Torvalds __hci_dev_put(d); 5741da177e4SLinus Torvalds module_put(d->owner); 5751da177e4SLinus Torvalds } 5761da177e4SLinus Torvalds 5771da177e4SLinus Torvalds static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d) 5781da177e4SLinus Torvalds { 5791da177e4SLinus Torvalds atomic_inc(&d->refcnt); 5801da177e4SLinus Torvalds return d; 5811da177e4SLinus Torvalds } 5821da177e4SLinus Torvalds 5831da177e4SLinus Torvalds static inline struct hci_dev *hci_dev_hold(struct hci_dev *d) 5841da177e4SLinus Torvalds { 5851da177e4SLinus Torvalds if (try_module_get(d->owner)) 5861da177e4SLinus Torvalds return __hci_dev_hold(d); 5871da177e4SLinus Torvalds return NULL; 5881da177e4SLinus Torvalds } 5891da177e4SLinus Torvalds 5901da177e4SLinus Torvalds #define hci_dev_lock(d) spin_lock(&d->lock) 5911da177e4SLinus Torvalds #define hci_dev_unlock(d) spin_unlock(&d->lock) 5921da177e4SLinus Torvalds #define hci_dev_lock_bh(d) spin_lock_bh(&d->lock) 5931da177e4SLinus Torvalds #define hci_dev_unlock_bh(d) spin_unlock_bh(&d->lock) 5941da177e4SLinus Torvalds 5951da177e4SLinus Torvalds struct hci_dev *hci_dev_get(int index); 5961da177e4SLinus Torvalds struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst); 5971da177e4SLinus Torvalds 5981da177e4SLinus Torvalds struct hci_dev *hci_alloc_dev(void); 5991da177e4SLinus Torvalds void hci_free_dev(struct hci_dev *hdev); 6001da177e4SLinus Torvalds int hci_register_dev(struct hci_dev *hdev); 60159735631SDavid Herrmann void hci_unregister_dev(struct hci_dev *hdev); 6021da177e4SLinus Torvalds int hci_suspend_dev(struct hci_dev *hdev); 6031da177e4SLinus Torvalds int hci_resume_dev(struct hci_dev *hdev); 6041da177e4SLinus Torvalds int hci_dev_open(__u16 dev); 6051da177e4SLinus Torvalds int hci_dev_close(__u16 dev); 6061da177e4SLinus Torvalds int hci_dev_reset(__u16 dev); 6071da177e4SLinus Torvalds int hci_dev_reset_stat(__u16 dev); 6081da177e4SLinus Torvalds int hci_dev_cmd(unsigned int cmd, void __user *arg); 6091da177e4SLinus Torvalds int hci_get_dev_list(void __user *arg); 6101da177e4SLinus Torvalds int hci_get_dev_info(void __user *arg); 6111da177e4SLinus Torvalds int hci_get_conn_list(void __user *arg); 6121da177e4SLinus Torvalds int hci_get_conn_info(struct hci_dev *hdev, void __user *arg); 61340be492fSMarcel Holtmann int hci_get_auth_info(struct hci_dev *hdev, void __user *arg); 6141da177e4SLinus Torvalds int hci_inquiry(void __user *arg); 6151da177e4SLinus Torvalds 616f0358568SJohan Hedberg struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr); 617f0358568SJohan Hedberg int hci_blacklist_clear(struct hci_dev *hdev); 618b2a66aadSAntti Julku int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr); 619b2a66aadSAntti Julku int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr); 620f0358568SJohan Hedberg 6212aeb9a1aSJohan Hedberg int hci_uuids_clear(struct hci_dev *hdev); 6222aeb9a1aSJohan Hedberg 62355ed8ca1SJohan Hedberg int hci_link_keys_clear(struct hci_dev *hdev); 62455ed8ca1SJohan Hedberg struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); 625d25e28abSJohan Hedberg int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, 626d25e28abSJohan Hedberg bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len); 62775d262c2SVinicius Costa Gomes struct link_key *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]); 62875d262c2SVinicius Costa Gomes struct link_key *hci_find_link_key_type(struct hci_dev *hdev, 62975d262c2SVinicius Costa Gomes bdaddr_t *bdaddr, u8 type); 63075d262c2SVinicius Costa Gomes int hci_add_ltk(struct hci_dev *hdev, int new_key, bdaddr_t *bdaddr, 631726b4ffcSVinicius Costa Gomes u8 key_size, __le16 ediv, u8 rand[8], u8 ltk[16]); 63255ed8ca1SJohan Hedberg int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); 63355ed8ca1SJohan Hedberg 6342763eda6SSzymon Janc int hci_remote_oob_data_clear(struct hci_dev *hdev); 6352763eda6SSzymon Janc struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev, 6362763eda6SSzymon Janc bdaddr_t *bdaddr); 6372763eda6SSzymon Janc int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, 6382763eda6SSzymon Janc u8 *randomizer); 6392763eda6SSzymon Janc int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); 6402763eda6SSzymon Janc 64135815085SAndre Guedes #define ADV_CLEAR_TIMEOUT (3*60*HZ) /* Three minutes */ 64276c8686fSAndre Guedes int hci_adv_entries_clear(struct hci_dev *hdev); 64376c8686fSAndre Guedes struct adv_entry *hci_find_adv_entry(struct hci_dev *hdev, bdaddr_t *bdaddr); 64476c8686fSAndre Guedes int hci_add_adv_entry(struct hci_dev *hdev, 64576c8686fSAndre Guedes struct hci_ev_le_advertising_info *ev); 64676c8686fSAndre Guedes 647ab81cbf9SJohan Hedberg void hci_del_off_timer(struct hci_dev *hdev); 648ab81cbf9SJohan Hedberg 6491da177e4SLinus Torvalds void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); 6501da177e4SLinus Torvalds 65176bca880SMarcel Holtmann int hci_recv_frame(struct sk_buff *skb); 652ef222013SMarcel Holtmann int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count); 65399811510SSuraj Sumangala int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count); 654ef222013SMarcel Holtmann 6550ac7e700SDavid Herrmann void hci_init_sysfs(struct hci_dev *hdev); 656ce242970SDavid Herrmann int hci_add_sysfs(struct hci_dev *hdev); 657ce242970SDavid Herrmann void hci_del_sysfs(struct hci_dev *hdev); 658a67e899cSMarcel Holtmann void hci_conn_init_sysfs(struct hci_conn *conn); 659b219e3acSMarcel Holtmann void hci_conn_add_sysfs(struct hci_conn *conn); 660b219e3acSMarcel Holtmann void hci_conn_del_sysfs(struct hci_conn *conn); 6611da177e4SLinus Torvalds 662a91f2e39SMarcel Holtmann #define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->parent = (pdev)) 6631da177e4SLinus Torvalds 6641da177e4SLinus Torvalds /* ----- LMP capabilities ----- */ 66504837f64SMarcel Holtmann #define lmp_rswitch_capable(dev) ((dev)->features[0] & LMP_RSWITCH) 66604837f64SMarcel Holtmann #define lmp_encrypt_capable(dev) ((dev)->features[0] & LMP_ENCRYPT) 66704837f64SMarcel Holtmann #define lmp_sniff_capable(dev) ((dev)->features[0] & LMP_SNIFF) 66804837f64SMarcel Holtmann #define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR) 6695b7f9909SMarcel Holtmann #define lmp_esco_capable(dev) ((dev)->features[3] & LMP_ESCO) 670769be974SMarcel Holtmann #define lmp_ssp_capable(dev) ((dev)->features[6] & LMP_SIMPLE_PAIR) 671e702112fSAndrei Emeltchenko #define lmp_no_flush_capable(dev) ((dev)->features[6] & LMP_NO_FLUSH) 6726ed58ec5SVille Tervo #define lmp_le_capable(dev) ((dev)->features[4] & LMP_LE) 6731da177e4SLinus Torvalds 674eead27daSAndre Guedes /* ----- Extended LMP capabilities ----- */ 675eead27daSAndre Guedes #define lmp_host_le_capable(dev) ((dev)->extfeatures[0] & LMP_HOST_LE) 676eead27daSAndre Guedes 6771da177e4SLinus Torvalds /* ----- HCI protocols ----- */ 6781da177e4SLinus Torvalds struct hci_proto { 6791da177e4SLinus Torvalds char *name; 6801da177e4SLinus Torvalds unsigned int id; 6811da177e4SLinus Torvalds unsigned long flags; 6821da177e4SLinus Torvalds 6831da177e4SLinus Torvalds void *priv; 6841da177e4SLinus Torvalds 6855a9d0a3fSWaldemar Rymarkiewicz int (*connect_ind) (struct hci_dev *hdev, bdaddr_t *bdaddr, 6865a9d0a3fSWaldemar Rymarkiewicz __u8 type); 6871da177e4SLinus Torvalds int (*connect_cfm) (struct hci_conn *conn, __u8 status); 6882950f21aSMarcel Holtmann int (*disconn_ind) (struct hci_conn *conn); 6892950f21aSMarcel Holtmann int (*disconn_cfm) (struct hci_conn *conn, __u8 reason); 6905a9d0a3fSWaldemar Rymarkiewicz int (*recv_acldata) (struct hci_conn *conn, struct sk_buff *skb, 6915a9d0a3fSWaldemar Rymarkiewicz __u16 flags); 6921da177e4SLinus Torvalds int (*recv_scodata) (struct hci_conn *conn, struct sk_buff *skb); 6935a9d0a3fSWaldemar Rymarkiewicz int (*security_cfm) (struct hci_conn *conn, __u8 status, 6945a9d0a3fSWaldemar Rymarkiewicz __u8 encrypt); 6951da177e4SLinus Torvalds }; 6961da177e4SLinus Torvalds 6975a9d0a3fSWaldemar Rymarkiewicz static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, 6985a9d0a3fSWaldemar Rymarkiewicz __u8 type) 6991da177e4SLinus Torvalds { 7001da177e4SLinus Torvalds register struct hci_proto *hp; 7011da177e4SLinus Torvalds int mask = 0; 7021da177e4SLinus Torvalds 7031da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_L2CAP]; 7041da177e4SLinus Torvalds if (hp && hp->connect_ind) 7051da177e4SLinus Torvalds mask |= hp->connect_ind(hdev, bdaddr, type); 7061da177e4SLinus Torvalds 7071da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_SCO]; 7081da177e4SLinus Torvalds if (hp && hp->connect_ind) 7091da177e4SLinus Torvalds mask |= hp->connect_ind(hdev, bdaddr, type); 7101da177e4SLinus Torvalds 7111da177e4SLinus Torvalds return mask; 7121da177e4SLinus Torvalds } 7131da177e4SLinus Torvalds 7141da177e4SLinus Torvalds static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status) 7151da177e4SLinus Torvalds { 7161da177e4SLinus Torvalds register struct hci_proto *hp; 7171da177e4SLinus Torvalds 7181da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_L2CAP]; 7191da177e4SLinus Torvalds if (hp && hp->connect_cfm) 7201da177e4SLinus Torvalds hp->connect_cfm(conn, status); 7211da177e4SLinus Torvalds 7221da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_SCO]; 7231da177e4SLinus Torvalds if (hp && hp->connect_cfm) 7241da177e4SLinus Torvalds hp->connect_cfm(conn, status); 725e9a416b5SJohan Hedberg 726e9a416b5SJohan Hedberg if (conn->connect_cfm_cb) 727e9a416b5SJohan Hedberg conn->connect_cfm_cb(conn, status); 7281da177e4SLinus Torvalds } 7291da177e4SLinus Torvalds 7302950f21aSMarcel Holtmann static inline int hci_proto_disconn_ind(struct hci_conn *conn) 7312950f21aSMarcel Holtmann { 7322950f21aSMarcel Holtmann register struct hci_proto *hp; 7339f5a0d7bSAndrei Emeltchenko int reason = HCI_ERROR_REMOTE_USER_TERM; 7342950f21aSMarcel Holtmann 7352950f21aSMarcel Holtmann hp = hci_proto[HCI_PROTO_L2CAP]; 7362950f21aSMarcel Holtmann if (hp && hp->disconn_ind) 7372950f21aSMarcel Holtmann reason = hp->disconn_ind(conn); 7382950f21aSMarcel Holtmann 7392950f21aSMarcel Holtmann hp = hci_proto[HCI_PROTO_SCO]; 7402950f21aSMarcel Holtmann if (hp && hp->disconn_ind) 7412950f21aSMarcel Holtmann reason = hp->disconn_ind(conn); 7422950f21aSMarcel Holtmann 7432950f21aSMarcel Holtmann return reason; 7442950f21aSMarcel Holtmann } 7452950f21aSMarcel Holtmann 7462950f21aSMarcel Holtmann static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason) 7471da177e4SLinus Torvalds { 7481da177e4SLinus Torvalds register struct hci_proto *hp; 7491da177e4SLinus Torvalds 7501da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_L2CAP]; 7512950f21aSMarcel Holtmann if (hp && hp->disconn_cfm) 7522950f21aSMarcel Holtmann hp->disconn_cfm(conn, reason); 7531da177e4SLinus Torvalds 7541da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_SCO]; 7552950f21aSMarcel Holtmann if (hp && hp->disconn_cfm) 7562950f21aSMarcel Holtmann hp->disconn_cfm(conn, reason); 757e9a416b5SJohan Hedberg 758e9a416b5SJohan Hedberg if (conn->disconn_cfm_cb) 759e9a416b5SJohan Hedberg conn->disconn_cfm_cb(conn, reason); 7601da177e4SLinus Torvalds } 7611da177e4SLinus Torvalds 7621da177e4SLinus Torvalds static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status) 7631da177e4SLinus Torvalds { 7641da177e4SLinus Torvalds register struct hci_proto *hp; 7658c1b2355SMarcel Holtmann __u8 encrypt; 7668c1b2355SMarcel Holtmann 7678c1b2355SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) 7688c1b2355SMarcel Holtmann return; 7698c1b2355SMarcel Holtmann 7708c1b2355SMarcel Holtmann encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00; 7711da177e4SLinus Torvalds 7721da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_L2CAP]; 7738c1b2355SMarcel Holtmann if (hp && hp->security_cfm) 7748c1b2355SMarcel Holtmann hp->security_cfm(conn, status, encrypt); 7751da177e4SLinus Torvalds 7761da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_SCO]; 7778c1b2355SMarcel Holtmann if (hp && hp->security_cfm) 7788c1b2355SMarcel Holtmann hp->security_cfm(conn, status, encrypt); 779e9a416b5SJohan Hedberg 780e9a416b5SJohan Hedberg if (conn->security_cfm_cb) 781e9a416b5SJohan Hedberg conn->security_cfm_cb(conn, status); 7821da177e4SLinus Torvalds } 7831da177e4SLinus Torvalds 7845a9d0a3fSWaldemar Rymarkiewicz static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, 7855a9d0a3fSWaldemar Rymarkiewicz __u8 encrypt) 7861da177e4SLinus Torvalds { 7871da177e4SLinus Torvalds register struct hci_proto *hp; 7881da177e4SLinus Torvalds 7891da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_L2CAP]; 7908c1b2355SMarcel Holtmann if (hp && hp->security_cfm) 7918c1b2355SMarcel Holtmann hp->security_cfm(conn, status, encrypt); 7921da177e4SLinus Torvalds 7931da177e4SLinus Torvalds hp = hci_proto[HCI_PROTO_SCO]; 7948c1b2355SMarcel Holtmann if (hp && hp->security_cfm) 7958c1b2355SMarcel Holtmann hp->security_cfm(conn, status, encrypt); 796e9a416b5SJohan Hedberg 797e9a416b5SJohan Hedberg if (conn->security_cfm_cb) 798e9a416b5SJohan Hedberg conn->security_cfm_cb(conn, status); 7991da177e4SLinus Torvalds } 8001da177e4SLinus Torvalds 8011da177e4SLinus Torvalds int hci_register_proto(struct hci_proto *hproto); 8021da177e4SLinus Torvalds int hci_unregister_proto(struct hci_proto *hproto); 8031da177e4SLinus Torvalds 8041da177e4SLinus Torvalds /* ----- HCI callbacks ----- */ 8051da177e4SLinus Torvalds struct hci_cb { 8061da177e4SLinus Torvalds struct list_head list; 8071da177e4SLinus Torvalds 8081da177e4SLinus Torvalds char *name; 8091da177e4SLinus Torvalds 8105a9d0a3fSWaldemar Rymarkiewicz void (*security_cfm) (struct hci_conn *conn, __u8 status, 8115a9d0a3fSWaldemar Rymarkiewicz __u8 encrypt); 8121da177e4SLinus Torvalds void (*key_change_cfm) (struct hci_conn *conn, __u8 status); 8131da177e4SLinus Torvalds void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role); 8141da177e4SLinus Torvalds }; 8151da177e4SLinus Torvalds 8161da177e4SLinus Torvalds static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) 8171da177e4SLinus Torvalds { 8181da177e4SLinus Torvalds struct list_head *p; 8198c1b2355SMarcel Holtmann __u8 encrypt; 8201da177e4SLinus Torvalds 8211da177e4SLinus Torvalds hci_proto_auth_cfm(conn, status); 8221da177e4SLinus Torvalds 8238c1b2355SMarcel Holtmann if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) 8248c1b2355SMarcel Holtmann return; 8258c1b2355SMarcel Holtmann 8268c1b2355SMarcel Holtmann encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00; 8278c1b2355SMarcel Holtmann 8281da177e4SLinus Torvalds read_lock_bh(&hci_cb_list_lock); 8291da177e4SLinus Torvalds list_for_each(p, &hci_cb_list) { 8301da177e4SLinus Torvalds struct hci_cb *cb = list_entry(p, struct hci_cb, list); 8318c1b2355SMarcel Holtmann if (cb->security_cfm) 8328c1b2355SMarcel Holtmann cb->security_cfm(conn, status, encrypt); 8331da177e4SLinus Torvalds } 8341da177e4SLinus Torvalds read_unlock_bh(&hci_cb_list_lock); 8351da177e4SLinus Torvalds } 8361da177e4SLinus Torvalds 8375a9d0a3fSWaldemar Rymarkiewicz static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, 8385a9d0a3fSWaldemar Rymarkiewicz __u8 encrypt) 8391da177e4SLinus Torvalds { 8401da177e4SLinus Torvalds struct list_head *p; 8411da177e4SLinus Torvalds 842435fef20SMarcel Holtmann if (conn->sec_level == BT_SECURITY_SDP) 843435fef20SMarcel Holtmann conn->sec_level = BT_SECURITY_LOW; 844435fef20SMarcel Holtmann 84588167aedSVinicius Costa Gomes if (conn->pending_sec_level > conn->sec_level) 84688167aedSVinicius Costa Gomes conn->sec_level = conn->pending_sec_level; 84788167aedSVinicius Costa Gomes 8489719f8afSMarcel Holtmann hci_proto_encrypt_cfm(conn, status, encrypt); 8491da177e4SLinus Torvalds 8501da177e4SLinus Torvalds read_lock_bh(&hci_cb_list_lock); 8511da177e4SLinus Torvalds list_for_each(p, &hci_cb_list) { 8521da177e4SLinus Torvalds struct hci_cb *cb = list_entry(p, struct hci_cb, list); 8538c1b2355SMarcel Holtmann if (cb->security_cfm) 8548c1b2355SMarcel Holtmann cb->security_cfm(conn, status, encrypt); 8551da177e4SLinus Torvalds } 8561da177e4SLinus Torvalds read_unlock_bh(&hci_cb_list_lock); 8571da177e4SLinus Torvalds } 8581da177e4SLinus Torvalds 8591da177e4SLinus Torvalds static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status) 8601da177e4SLinus Torvalds { 8611da177e4SLinus Torvalds struct list_head *p; 8621da177e4SLinus Torvalds 8631da177e4SLinus Torvalds read_lock_bh(&hci_cb_list_lock); 8641da177e4SLinus Torvalds list_for_each(p, &hci_cb_list) { 8651da177e4SLinus Torvalds struct hci_cb *cb = list_entry(p, struct hci_cb, list); 8661da177e4SLinus Torvalds if (cb->key_change_cfm) 8671da177e4SLinus Torvalds cb->key_change_cfm(conn, status); 8681da177e4SLinus Torvalds } 8691da177e4SLinus Torvalds read_unlock_bh(&hci_cb_list_lock); 8701da177e4SLinus Torvalds } 8711da177e4SLinus Torvalds 8725a9d0a3fSWaldemar Rymarkiewicz static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, 8735a9d0a3fSWaldemar Rymarkiewicz __u8 role) 8741da177e4SLinus Torvalds { 8751da177e4SLinus Torvalds struct list_head *p; 8761da177e4SLinus Torvalds 8771da177e4SLinus Torvalds read_lock_bh(&hci_cb_list_lock); 8781da177e4SLinus Torvalds list_for_each(p, &hci_cb_list) { 8791da177e4SLinus Torvalds struct hci_cb *cb = list_entry(p, struct hci_cb, list); 8801da177e4SLinus Torvalds if (cb->role_switch_cfm) 8811da177e4SLinus Torvalds cb->role_switch_cfm(conn, status, role); 8821da177e4SLinus Torvalds } 8831da177e4SLinus Torvalds read_unlock_bh(&hci_cb_list_lock); 8841da177e4SLinus Torvalds } 8851da177e4SLinus Torvalds 8861da177e4SLinus Torvalds int hci_register_cb(struct hci_cb *hcb); 8871da177e4SLinus Torvalds int hci_unregister_cb(struct hci_cb *hcb); 8881da177e4SLinus Torvalds 8891da177e4SLinus Torvalds int hci_register_notifier(struct notifier_block *nb); 8901da177e4SLinus Torvalds int hci_unregister_notifier(struct notifier_block *nb); 8911da177e4SLinus Torvalds 892a9de9248SMarcel Holtmann int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param); 89373d80debSLuiz Augusto von Dentz void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags); 8940d861d8bSGustavo F. Padovan void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb); 8951da177e4SLinus Torvalds 896a9de9248SMarcel Holtmann void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode); 8971da177e4SLinus Torvalds 8981da177e4SLinus Torvalds void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data); 8991da177e4SLinus Torvalds 9001da177e4SLinus Torvalds /* ----- HCI Sockets ----- */ 901eec8d2bcSJohan Hedberg void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb, 902eec8d2bcSJohan Hedberg struct sock *skip_sk); 9031da177e4SLinus Torvalds 9040381101fSJohan Hedberg /* Management interface */ 9050381101fSJohan Hedberg int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); 906c71e97bfSJohan Hedberg int mgmt_index_added(u16 index); 907c71e97bfSJohan Hedberg int mgmt_index_removed(u16 index); 9085add6af8SJohan Hedberg int mgmt_powered(u16 index, u8 powered); 90973f22f62SJohan Hedberg int mgmt_discoverable(u16 index, u8 discoverable); 9109fbcbb45SJohan Hedberg int mgmt_connectable(u16 index, u8 connectable); 9114df378a1SJohan Hedberg int mgmt_new_key(u16 index, struct link_key *key, u8 persistent); 912cfafccf7SVinicius Costa Gomes int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 link_type); 913f7520543SJohan Hedberg int mgmt_disconnected(u16 index, bdaddr_t *bdaddr); 9148962ee74SJohan Hedberg int mgmt_disconnect_failed(u16 index); 91517d5c04cSJohan Hedberg int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status); 916a770bb5aSWaldemar Rymarkiewicz int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr, u8 secure); 917980e1a53SJohan Hedberg int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); 918980e1a53SJohan Hedberg int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); 91955bc1a37SJohan Hedberg int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value, 92055bc1a37SJohan Hedberg u8 confirm_hint); 921a5c29683SJohan Hedberg int mgmt_user_confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status); 922a5c29683SJohan Hedberg int mgmt_user_confirm_neg_reply_complete(u16 index, bdaddr_t *bdaddr, 923a5c29683SJohan Hedberg u8 status); 9242a611692SJohan Hedberg int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status); 925b312b161SJohan Hedberg int mgmt_set_local_name_complete(u16 index, u8 *name, u8 status); 926c35938b2SSzymon Janc int mgmt_read_local_oob_data_reply_complete(u16 index, u8 *hash, u8 *randomizer, 927c35938b2SSzymon Janc u8 status); 928e17acd40SJohan Hedberg int mgmt_device_found(u16 index, bdaddr_t *bdaddr, u8 *dev_class, s8 rssi, 929e17acd40SJohan Hedberg u8 *eir); 930a88a9652SJohan Hedberg int mgmt_remote_name(u16 index, bdaddr_t *bdaddr, u8 *name); 931164a6e78SJohan Hedberg int mgmt_inquiry_failed(u16 index, u8 status); 932314b2381SJohan Hedberg int mgmt_discovering(u16 index, u8 discovering); 9335e762444SAntti Julku int mgmt_device_blocked(u16 index, bdaddr_t *bdaddr); 9345e762444SAntti Julku int mgmt_device_unblocked(u16 index, bdaddr_t *bdaddr); 9350381101fSJohan Hedberg 9361da177e4SLinus Torvalds /* HCI info for socket */ 9371da177e4SLinus Torvalds #define hci_pi(sk) ((struct hci_pinfo *) sk) 9381da177e4SLinus Torvalds 9391da177e4SLinus Torvalds struct hci_pinfo { 9401da177e4SLinus Torvalds struct bt_sock bt; 9411da177e4SLinus Torvalds struct hci_dev *hdev; 9421da177e4SLinus Torvalds struct hci_filter filter; 9431da177e4SLinus Torvalds __u32 cmsg_mask; 944c02178d2SJohan Hedberg unsigned short channel; 9451da177e4SLinus Torvalds }; 9461da177e4SLinus Torvalds 9471da177e4SLinus Torvalds /* HCI security filter */ 9481da177e4SLinus Torvalds #define HCI_SFLT_MAX_OGF 5 9491da177e4SLinus Torvalds 9501da177e4SLinus Torvalds struct hci_sec_filter { 9511da177e4SLinus Torvalds __u32 type_mask; 9521da177e4SLinus Torvalds __u32 event_mask[2]; 9531da177e4SLinus Torvalds __u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4]; 9541da177e4SLinus Torvalds }; 9551da177e4SLinus Torvalds 9561da177e4SLinus Torvalds /* ----- HCI requests ----- */ 9571da177e4SLinus Torvalds #define HCI_REQ_DONE 0 9581da177e4SLinus Torvalds #define HCI_REQ_PEND 1 9591da177e4SLinus Torvalds #define HCI_REQ_CANCELED 2 9601da177e4SLinus Torvalds 961a6a67efdSThomas Gleixner #define hci_req_lock(d) mutex_lock(&d->req_lock) 962a6a67efdSThomas Gleixner #define hci_req_unlock(d) mutex_unlock(&d->req_lock) 9631da177e4SLinus Torvalds 96423bb5763SJohan Hedberg void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result); 9651da177e4SLinus Torvalds 9662ce603ebSClaudio Takahasi void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, 9672ce603ebSClaudio Takahasi u16 latency, u16 to_multiplier); 968a7a595f6SVinicius Costa Gomes void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], 969a7a595f6SVinicius Costa Gomes __u8 ltk[16]); 970a7a595f6SVinicius Costa Gomes void hci_le_ltk_reply(struct hci_conn *conn, u8 ltk[16]); 971a7a595f6SVinicius Costa Gomes void hci_le_ltk_neg_reply(struct hci_conn *conn); 972a7a595f6SVinicius Costa Gomes 9732519a1fcSAndre Guedes int hci_do_inquiry(struct hci_dev *hdev, u8 length); 9742519a1fcSAndre Guedes 9751da177e4SLinus Torvalds #endif /* __HCI_CORE_H */ 976