diff options
Diffstat (limited to 'include/net/bluetooth')
| -rw-r--r-- | include/net/bluetooth/a2mp.h | 24 | ||||
| -rw-r--r-- | include/net/bluetooth/amp.h | 54 | ||||
| -rw-r--r-- | include/net/bluetooth/bluetooth.h | 1 | ||||
| -rw-r--r-- | include/net/bluetooth/hci.h | 69 | ||||
| -rw-r--r-- | include/net/bluetooth/hci_core.h | 123 | ||||
| -rw-r--r-- | include/net/bluetooth/l2cap.h | 50 | 
6 files changed, 287 insertions, 34 deletions
| diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h index 6a76e0a0705e..42f21766c538 100644 --- a/include/net/bluetooth/a2mp.h +++ b/include/net/bluetooth/a2mp.h @@ -19,13 +19,25 @@  #define A2MP_FEAT_EXT	0x8000 +enum amp_mgr_state { +	READ_LOC_AMP_INFO, +	READ_LOC_AMP_ASSOC, +	READ_LOC_AMP_ASSOC_FINAL, +}; +  struct amp_mgr { +	struct list_head	list;  	struct l2cap_conn	*l2cap_conn;  	struct l2cap_chan	*a2mp_chan; +	struct l2cap_chan	*bredr_chan;  	struct kref		kref;  	__u8			ident;  	__u8			handle; +	enum amp_mgr_state	state;  	unsigned long		flags; + +	struct list_head	amp_ctrls; +	struct mutex		amp_ctrls_lock;  };  struct a2mp_cmd { @@ -118,9 +130,19 @@ struct a2mp_physlink_rsp {  #define A2MP_STATUS_PHYS_LINK_EXISTS		0x05  #define A2MP_STATUS_SECURITY_VIOLATION		0x06 -void amp_mgr_get(struct amp_mgr *mgr); +extern struct list_head amp_mgr_list; +extern struct mutex amp_mgr_list_lock; + +struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr);  int amp_mgr_put(struct amp_mgr *mgr); +u8 __next_ident(struct amp_mgr *mgr);  struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,  				       struct sk_buff *skb); +struct amp_mgr *amp_mgr_lookup_by_state(u8 state); +void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data); +void a2mp_discover_amp(struct l2cap_chan *chan); +void a2mp_send_getinfo_rsp(struct hci_dev *hdev); +void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status); +void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status);  #endif /* __A2MP_H */ diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h new file mode 100644 index 000000000000..7ea3db77ba89 --- /dev/null +++ b/include/net/bluetooth/amp.h @@ -0,0 +1,54 @@ +/* +   Copyright (c) 2011,2012 Intel Corp. + +   This program is free software; you can redistribute it and/or modify +   it under the terms of the GNU General Public License version 2 and +   only version 2 as published by the Free Software Foundation. + +   This program is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. +*/ + +#ifndef __AMP_H +#define __AMP_H + +struct amp_ctrl { +	struct list_head	list; +	struct kref		kref; +	__u8			id; +	__u16			assoc_len_so_far; +	__u16			assoc_rem_len; +	__u16			assoc_len; +	__u8			*assoc; +}; + +int amp_ctrl_put(struct amp_ctrl *ctrl); +void amp_ctrl_get(struct amp_ctrl *ctrl); +struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id); +struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id); +void amp_ctrl_list_flush(struct amp_mgr *mgr); + +struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, +			     u8 remote_id, bool out); + +int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type); + +void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr); +void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle); +void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr); +void amp_read_loc_assoc_final_data(struct hci_dev *hdev, +				   struct hci_conn *hcon); +void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, +			struct hci_conn *hcon); +void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, +			struct hci_conn *hcon); +void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle); +void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle); +void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon); +void amp_create_logical_link(struct l2cap_chan *chan); +void amp_disconnect_logical_link(struct hci_chan *hchan); +void amp_destroy_logical_link(struct hci_chan *hchan, u8 reason); + +#endif /* __AMP_H */ diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index ede036977ae8..2554b3f5222a 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -180,7 +180,6 @@ static inline void bacpy(bdaddr_t *dst, bdaddr_t *src)  }  void baswap(bdaddr_t *dst, bdaddr_t *src); -char *batostr(bdaddr_t *ba);  /* Common socket structures and functions */ diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 76b2b6bdcf36..45eee08157bb 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -33,6 +33,8 @@  #define HCI_LINK_KEY_SIZE	16  #define HCI_AMP_LINK_KEY_SIZE	(2 * HCI_LINK_KEY_SIZE) +#define HCI_MAX_AMP_ASSOC_SIZE	672 +  /* HCI dev events */  #define HCI_DEV_REG			1  #define HCI_DEV_UNREG			2 @@ -113,6 +115,7 @@ enum {  	HCI_SSP_ENABLED,  	HCI_HS_ENABLED,  	HCI_LE_ENABLED, +	HCI_LE_PERIPHERAL,  	HCI_CONNECTABLE,  	HCI_DISCOVERABLE,  	HCI_LINK_SECURITY, @@ -151,7 +154,7 @@ enum {  #define HCI_DISCONN_TIMEOUT	msecs_to_jiffies(2000)	/* 2 seconds */  #define HCI_PAIRING_TIMEOUT	msecs_to_jiffies(60000)	/* 60 seconds */  #define HCI_INIT_TIMEOUT	msecs_to_jiffies(10000)	/* 10 seconds */ -#define HCI_CMD_TIMEOUT		msecs_to_jiffies(1000)	/* 1 second */ +#define HCI_CMD_TIMEOUT		msecs_to_jiffies(2000)	/* 2 seconds */  #define HCI_ACL_TX_TIMEOUT	msecs_to_jiffies(45000)	/* 45 seconds */  #define HCI_AUTO_OFF_TIMEOUT	msecs_to_jiffies(2000)	/* 2 seconds */ @@ -196,6 +199,7 @@ enum {  #define ACL_START_NO_FLUSH	0x00  #define ACL_CONT		0x01  #define ACL_START		0x02 +#define ACL_COMPLETE		0x03  #define ACL_ACTIVE_BCAST	0x04  #define ACL_PICO_BCAST		0x08 @@ -205,6 +209,7 @@ enum {  #define ESCO_LINK	0x02  /* Low Energy links do not have defined link type. Use invented one */  #define LE_LINK		0x80 +#define AMP_LINK	0x81  /* LMP features */  #define LMP_3SLOT	0x01 @@ -314,6 +319,9 @@ enum {  #define HCI_FLOW_CTL_MODE_PACKET_BASED	0x00  #define HCI_FLOW_CTL_MODE_BLOCK_BASED	0x01 +/* The core spec defines 127 as the "not available" value */ +#define HCI_TX_POWER_INVALID	127 +  /* Extended Inquiry Response field types */  #define EIR_FLAGS		0x01 /* flags */  #define EIR_UUID16_SOME		0x02 /* 16-bit UUID, more available */ @@ -330,6 +338,13 @@ enum {  #define EIR_SSP_RAND_R		0x0F /* Simple Pairing Randomizer R */  #define EIR_DEVICE_ID		0x10 /* device ID */ +/* Low Energy Advertising Flags */ +#define LE_AD_LIMITED		0x01 /* Limited Discoverable */ +#define LE_AD_GENERAL		0x02 /* General Discoverable */ +#define LE_AD_NO_BREDR		0x04 /* BR/EDR not supported */ +#define LE_AD_SIM_LE_BREDR_CTRL	0x08 /* Simultaneous LE & BR/EDR Controller */ +#define LE_AD_SIM_LE_BREDR_HOST	0x10 /* Simultaneous LE & BR/EDR Host */ +  /* -----  HCI Commands ---- */  #define HCI_OP_NOP			0x0000 @@ -556,12 +571,46 @@ struct hci_cp_accept_phy_link {  	__u8     key[HCI_AMP_LINK_KEY_SIZE];  } __packed; -#define HCI_OP_DISCONN_PHY_LINK	0x0437 +#define HCI_OP_DISCONN_PHY_LINK		0x0437  struct hci_cp_disconn_phy_link {  	__u8     phy_handle;  	__u8     reason;  } __packed; +struct ext_flow_spec { +	__u8       id; +	__u8       stype; +	__le16     msdu; +	__le32     sdu_itime; +	__le32     acc_lat; +	__le32     flush_to; +} __packed; + +#define HCI_OP_CREATE_LOGICAL_LINK	0x0438 +#define HCI_OP_ACCEPT_LOGICAL_LINK	0x0439 +struct hci_cp_create_accept_logical_link { +	__u8                  phy_handle; +	struct ext_flow_spec  tx_flow_spec; +	struct ext_flow_spec  rx_flow_spec; +} __packed; + +#define HCI_OP_DISCONN_LOGICAL_LINK	0x043a +struct hci_cp_disconn_logical_link { +	__le16   log_handle; +} __packed; + +#define HCI_OP_LOGICAL_LINK_CANCEL	0x043b +struct hci_cp_logical_link_cancel { +	__u8     phy_handle; +	__u8     flow_spec_id; +} __packed; + +struct hci_rp_logical_link_cancel { +	__u8     status; +	__u8     phy_handle; +	__u8     flow_spec_id; +} __packed; +  #define HCI_OP_SNIFF_MODE		0x0803  struct hci_cp_sniff_mode {  	__le16   handle; @@ -894,6 +943,22 @@ struct hci_rp_le_read_buffer_size {  	__u8     le_max_pkt;  } __packed; +#define HCI_OP_LE_READ_ADV_TX_POWER	0x2007 +struct hci_rp_le_read_adv_tx_power { +	__u8	status; +	__s8	tx_power; +} __packed; + +#define HCI_MAX_AD_LENGTH		31 + +#define HCI_OP_LE_SET_ADV_DATA		0x2008 +struct hci_cp_le_set_adv_data { +	__u8	length; +	__u8	data[HCI_MAX_AD_LENGTH]; +} __packed; + +#define HCI_OP_LE_SET_ADV_ENABLE	0x200a +  #define HCI_OP_LE_SET_SCAN_PARAM	0x200b  struct hci_cp_le_set_scan_param {  	__u8    type; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index e7d454609881..014a2eaa5389 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -73,6 +73,7 @@ struct discovery_state {  struct hci_conn_hash {  	struct list_head list;  	unsigned int     acl_num; +	unsigned int     amp_num;  	unsigned int     sco_num;  	unsigned int     le_num;  }; @@ -124,6 +125,14 @@ struct le_scan_params {  #define HCI_MAX_SHORT_NAME_LENGTH	10 +struct amp_assoc { +	__u16	len; +	__u16	offset; +	__u16	rem_len; +	__u16	len_so_far; +	__u8	data[HCI_MAX_AMP_ASSOC_SIZE]; +}; +  #define NUM_REASSEMBLY 4  struct hci_dev {  	struct list_head list; @@ -177,6 +186,8 @@ struct hci_dev {  	__u32		amp_max_flush_to;  	__u32		amp_be_flush_to; +	struct amp_assoc	loc_assoc; +  	__u8		flow_ctl_mode;  	unsigned int	auto_accept_delay; @@ -252,8 +263,6 @@ struct hci_dev {  	struct sk_buff_head	driver_init; -	void			*core_data; -  	atomic_t		promisc;  	struct dentry		*debugfs; @@ -269,6 +278,10 @@ struct hci_dev {  	struct work_struct	le_scan;  	struct le_scan_params	le_scan_params; +	__s8			adv_tx_power; +	__u8			adv_data[HCI_MAX_AD_LENGTH]; +	__u8			adv_data_len; +  	int (*open)(struct hci_dev *hdev);  	int (*close)(struct hci_dev *hdev);  	int (*flush)(struct hci_dev *hdev); @@ -277,6 +290,8 @@ struct hci_dev {  	int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg);  }; +#define HCI_PHY_HANDLE(handle)	(handle & 0xff) +  struct hci_conn {  	struct list_head list; @@ -310,6 +325,7 @@ struct hci_conn {  	__u8		remote_cap;  	__u8		remote_auth; +	__u8		remote_id;  	bool		flush_key;  	unsigned int	sent; @@ -339,10 +355,11 @@ struct hci_conn {  struct hci_chan {  	struct list_head list; - +	__u16 handle;  	struct hci_conn *conn;  	struct sk_buff_head data_q;  	unsigned int	sent; +	__u8		state;  };  extern struct list_head hci_dev_list; @@ -359,7 +376,7 @@ extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt);  extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb,  			      u16 flags); -extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); +extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags);  extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status);  extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason);  extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb); @@ -438,6 +455,9 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c)  	case ACL_LINK:  		h->acl_num++;  		break; +	case AMP_LINK: +		h->amp_num++; +		break;  	case LE_LINK:  		h->le_num++;  		break; @@ -459,6 +479,9 @@ static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c)  	case ACL_LINK:  		h->acl_num--;  		break; +	case AMP_LINK: +		h->amp_num--; +		break;  	case LE_LINK:  		h->le_num--;  		break; @@ -475,6 +498,8 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type)  	switch (type) {  	case ACL_LINK:  		return h->acl_num; +	case AMP_LINK: +		return h->amp_num;  	case LE_LINK:  		return h->le_num;  	case SCO_LINK: @@ -552,10 +577,12 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst);  int hci_conn_del(struct hci_conn *conn);  void hci_conn_hash_flush(struct hci_dev *hdev);  void hci_conn_check_pending(struct hci_dev *hdev); +void hci_conn_accept(struct hci_conn *conn, int mask);  struct hci_chan *hci_chan_create(struct hci_conn *conn);  void hci_chan_del(struct hci_chan *chan);  void hci_chan_list_flush(struct hci_conn *conn); +struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle);  struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst,  			     __u8 dst_type, __u8 sec_level, __u8 auth_type); @@ -584,7 +611,10 @@ static inline void hci_conn_put(struct hci_conn *conn)  	if (atomic_dec_and_test(&conn->refcnt)) {  		unsigned long timeo; -		if (conn->type == ACL_LINK || conn->type == LE_LINK) { + +		switch (conn->type) { +		case ACL_LINK: +		case LE_LINK:  			del_timer(&conn->idle_timer);  			if (conn->state == BT_CONNECTED) {  				timeo = conn->disc_timeout; @@ -593,12 +623,20 @@ static inline void hci_conn_put(struct hci_conn *conn)  			} else {  				timeo = msecs_to_jiffies(10);  			} -		} else { +			break; + +		case AMP_LINK: +			timeo = conn->disc_timeout; +			break; + +		default:  			timeo = msecs_to_jiffies(10); +			break;  		} +  		cancel_delayed_work(&conn->disc_work);  		queue_delayed_work(conn->hdev->workqueue, -					&conn->disc_work, timeo); +				   &conn->disc_work, timeo);  	}  } @@ -650,7 +688,7 @@ static inline uint8_t __hci_num_ctrl(void)  }  struct hci_dev *hci_dev_get(int index); -struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst); +struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src);  struct hci_dev *hci_alloc_dev(void);  void hci_free_dev(struct hci_dev *hdev); @@ -699,6 +737,8 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,  								u8 *randomizer);  int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); +int hci_update_ad(struct hci_dev *hdev); +  void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb);  int hci_recv_frame(struct sk_buff *skb); @@ -715,22 +755,51 @@ void hci_conn_del_sysfs(struct hci_conn *conn);  #define SET_HCIDEV_DEV(hdev, pdev) ((hdev)->dev.parent = (pdev))  /* ----- LMP capabilities ----- */ -#define lmp_rswitch_capable(dev)   ((dev)->features[0] & LMP_RSWITCH)  #define lmp_encrypt_capable(dev)   ((dev)->features[0] & LMP_ENCRYPT) +#define lmp_rswitch_capable(dev)   ((dev)->features[0] & LMP_RSWITCH) +#define lmp_hold_capable(dev)      ((dev)->features[0] & LMP_HOLD)  #define lmp_sniff_capable(dev)     ((dev)->features[0] & LMP_SNIFF) -#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR) +#define lmp_park_capable(dev)      ((dev)->features[1] & LMP_PARK) +#define lmp_inq_rssi_capable(dev)  ((dev)->features[3] & LMP_RSSI_INQ)  #define lmp_esco_capable(dev)      ((dev)->features[3] & LMP_ESCO) +#define lmp_bredr_capable(dev)     (!((dev)->features[4] & LMP_NO_BREDR)) +#define lmp_le_capable(dev)        ((dev)->features[4] & LMP_LE) +#define lmp_sniffsubr_capable(dev) ((dev)->features[5] & LMP_SNIFF_SUBR) +#define lmp_pause_enc_capable(dev) ((dev)->features[5] & LMP_PAUSE_ENC) +#define lmp_ext_inq_capable(dev)   ((dev)->features[6] & LMP_EXT_INQ) +#define lmp_le_br_capable(dev)     !!((dev)->features[6] & LMP_SIMUL_LE_BR)  #define lmp_ssp_capable(dev)       ((dev)->features[6] & LMP_SIMPLE_PAIR)  #define lmp_no_flush_capable(dev)  ((dev)->features[6] & LMP_NO_FLUSH) -#define lmp_le_capable(dev)        ((dev)->features[4] & LMP_LE) -#define lmp_bredr_capable(dev)     (!((dev)->features[4] & LMP_NO_BREDR)) +#define lmp_lsto_capable(dev)      ((dev)->features[7] & LMP_LSTO) +#define lmp_inq_tx_pwr_capable(dev) ((dev)->features[7] & LMP_INQ_TX_PWR) +#define lmp_ext_feat_capable(dev)  ((dev)->features[7] & LMP_EXTFEATURES)  /* ----- Extended LMP capabilities ----- */ -#define lmp_host_le_capable(dev)   ((dev)->host_features[0] & LMP_HOST_LE) +#define lmp_host_ssp_capable(dev)  ((dev)->host_features[0] & LMP_HOST_SSP) +#define lmp_host_le_capable(dev)   !!((dev)->host_features[0] & LMP_HOST_LE) +#define lmp_host_le_br_capable(dev) !!((dev)->host_features[0] & LMP_HOST_LE_BREDR) + +/* returns true if at least one AMP active */ +static inline bool hci_amp_capable(void) +{ +	struct hci_dev *hdev; +	bool ret = false; + +	read_lock(&hci_dev_list_lock); +	list_for_each_entry(hdev, &hci_dev_list, list) +		if (hdev->amp_type == HCI_AMP && +		    test_bit(HCI_UP, &hdev->flags)) +			ret = true; +	read_unlock(&hci_dev_list_lock); + +	return ret; +}  /* ----- HCI protocols ----- */ +#define HCI_PROTO_DEFER             0x01 +  static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, -								__u8 type) +					__u8 type, __u8 *flags)  {  	switch (type) {  	case ACL_LINK: @@ -738,7 +807,7 @@ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr,  	case SCO_LINK:  	case ESCO_LINK: -		return sco_connect_ind(hdev, bdaddr); +		return sco_connect_ind(hdev, bdaddr, flags);  	default:  		BT_ERR("unknown link type %d", type); @@ -789,6 +858,10 @@ static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason)  		sco_disconn_cfm(conn, reason);  		break; +	/* L2CAP would be handled for BREDR chan */ +	case AMP_LINK: +		break; +  	default:  		BT_ERR("unknown link type %d", conn->type);  		break; @@ -841,7 +914,7 @@ struct hci_cb {  static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)  { -	struct list_head *p; +	struct hci_cb *cb;  	__u8 encrypt;  	hci_proto_auth_cfm(conn, status); @@ -852,8 +925,7 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)  	encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00;  	read_lock(&hci_cb_list_lock); -	list_for_each(p, &hci_cb_list) { -		struct hci_cb *cb = list_entry(p, struct hci_cb, list); +	list_for_each_entry(cb, &hci_cb_list, list) {  		if (cb->security_cfm)  			cb->security_cfm(conn, status, encrypt);  	} @@ -863,7 +935,7 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)  static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,  								__u8 encrypt)  { -	struct list_head *p; +	struct hci_cb *cb;  	if (conn->sec_level == BT_SECURITY_SDP)  		conn->sec_level = BT_SECURITY_LOW; @@ -874,8 +946,7 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,  	hci_proto_encrypt_cfm(conn, status, encrypt);  	read_lock(&hci_cb_list_lock); -	list_for_each(p, &hci_cb_list) { -		struct hci_cb *cb = list_entry(p, struct hci_cb, list); +	list_for_each_entry(cb, &hci_cb_list, list) {  		if (cb->security_cfm)  			cb->security_cfm(conn, status, encrypt);  	} @@ -884,11 +955,10 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status,  static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)  { -	struct list_head *p; +	struct hci_cb *cb;  	read_lock(&hci_cb_list_lock); -	list_for_each(p, &hci_cb_list) { -		struct hci_cb *cb = list_entry(p, struct hci_cb, list); +	list_for_each_entry(cb, &hci_cb_list, list) {  		if (cb->key_change_cfm)  			cb->key_change_cfm(conn, status);  	} @@ -898,11 +968,10 @@ static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)  static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,  								__u8 role)  { -	struct list_head *p; +	struct hci_cb *cb;  	read_lock(&hci_cb_list_lock); -	list_for_each(p, &hci_cb_list) { -		struct hci_cb *cb = list_entry(p, struct hci_cb, list); +	list_for_each_entry(cb, &hci_cb_list, list) {  		if (cb->role_switch_cfm)  			cb->role_switch_cfm(conn, status, role);  	} diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 7ed8e356425a..7588ef44ebaf 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -32,13 +32,14 @@  /* L2CAP defaults */  #define L2CAP_DEFAULT_MTU		672  #define L2CAP_DEFAULT_MIN_MTU		48 -#define L2CAP_DEFAULT_FLUSH_TO		0xffff +#define L2CAP_DEFAULT_FLUSH_TO		0xFFFF +#define L2CAP_EFS_DEFAULT_FLUSH_TO	0xFFFFFFFF  #define L2CAP_DEFAULT_TX_WINDOW		63  #define L2CAP_DEFAULT_EXT_WINDOW	0x3FFF  #define L2CAP_DEFAULT_MAX_TX		3  #define L2CAP_DEFAULT_RETRANS_TO	2000    /* 2 seconds */  #define L2CAP_DEFAULT_MONITOR_TO	12000   /* 12 seconds */ -#define L2CAP_DEFAULT_MAX_PDU_SIZE	1009    /* Sized for 3-DH5 packet */ +#define L2CAP_DEFAULT_MAX_PDU_SIZE	1492    /* Sized for AMP packet */  #define L2CAP_DEFAULT_ACK_TO		200  #define L2CAP_DEFAULT_MAX_SDU_SIZE	0xFFFF  #define L2CAP_DEFAULT_SDU_ITIME		0xFFFFFFFF @@ -51,6 +52,8 @@  #define L2CAP_ENC_TIMEOUT		msecs_to_jiffies(5000)  #define L2CAP_CONN_TIMEOUT		msecs_to_jiffies(40000)  #define L2CAP_INFO_TIMEOUT		msecs_to_jiffies(4000) +#define L2CAP_MOVE_TIMEOUT		msecs_to_jiffies(4000) +#define L2CAP_MOVE_ERTX_TIMEOUT		msecs_to_jiffies(60000)  #define L2CAP_A2MP_DEFAULT_MTU		670 @@ -433,6 +436,8 @@ struct l2cap_chan {  	struct sock *sk;  	struct l2cap_conn	*conn; +	struct hci_conn		*hs_hcon; +	struct hci_chan		*hs_hchan;  	struct kref	kref;  	__u8		state; @@ -476,6 +481,12 @@ struct l2cap_chan {  	unsigned long	conn_state;  	unsigned long	flags; +	__u8		remote_amp_id; +	__u8		local_amp_id; +	__u8		move_id; +	__u8		move_state; +	__u8		move_role; +  	__u16		next_tx_seq;  	__u16		expected_ack_seq;  	__u16		expected_tx_seq; @@ -538,6 +549,7 @@ struct l2cap_ops {  	void			(*state_change) (struct l2cap_chan *chan,  						 int state);  	void			(*ready) (struct l2cap_chan *chan); +	void			(*defer) (struct l2cap_chan *chan);  	struct sk_buff		*(*alloc_skb) (struct l2cap_chan *chan,  					       unsigned long len, int nb);  }; @@ -599,7 +611,7 @@ enum {  	CONF_MTU_DONE,  	CONF_MODE_DONE,  	CONF_CONNECT_PEND, -	CONF_NO_FCS_RECV, +	CONF_RECV_NO_FCS,  	CONF_STATE2_DEVICE,  	CONF_EWS_RECV,  	CONF_LOC_CONF_PEND, @@ -640,6 +652,9 @@ enum {  enum {  	L2CAP_RX_STATE_RECV,  	L2CAP_RX_STATE_SREJ_SENT, +	L2CAP_RX_STATE_MOVE, +	L2CAP_RX_STATE_WAIT_P, +	L2CAP_RX_STATE_WAIT_F,  };  enum { @@ -670,6 +685,25 @@ enum {  	L2CAP_EV_RECV_FRAME,  }; +enum { +	L2CAP_MOVE_ROLE_NONE, +	L2CAP_MOVE_ROLE_INITIATOR, +	L2CAP_MOVE_ROLE_RESPONDER, +}; + +enum { +	L2CAP_MOVE_STABLE, +	L2CAP_MOVE_WAIT_REQ, +	L2CAP_MOVE_WAIT_RSP, +	L2CAP_MOVE_WAIT_RSP_SUCCESS, +	L2CAP_MOVE_WAIT_CONFIRM, +	L2CAP_MOVE_WAIT_CONFIRM_RSP, +	L2CAP_MOVE_WAIT_LOGICAL_COMP, +	L2CAP_MOVE_WAIT_LOGICAL_CFM, +	L2CAP_MOVE_WAIT_LOCAL_BUSY, +	L2CAP_MOVE_WAIT_PREPARE, +}; +  void l2cap_chan_hold(struct l2cap_chan *c);  void l2cap_chan_put(struct l2cap_chan *c); @@ -745,6 +779,10 @@ static inline void l2cap_chan_no_ready(struct l2cap_chan *chan)  {  } +static inline void l2cap_chan_no_defer(struct l2cap_chan *chan) +{ +} +  extern bool disable_ertm;  int l2cap_init_sockets(void); @@ -767,6 +805,12 @@ int l2cap_chan_check_security(struct l2cap_chan *chan);  void l2cap_chan_set_defaults(struct l2cap_chan *chan);  int l2cap_ertm_init(struct l2cap_chan *chan);  void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan); +void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan);  void l2cap_chan_del(struct l2cap_chan *chan, int err); +void l2cap_send_conn_req(struct l2cap_chan *chan); +void l2cap_move_start(struct l2cap_chan *chan); +void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, +		       u8 status); +void __l2cap_physical_cfm(struct l2cap_chan *chan, int result);  #endif /* __L2CAP_H */ |