xref: /openbmc/linux/include/net/bluetooth/hci_core.h (revision 34918cd7)
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