Commit 33b44342 authored by John W. Linville's avatar John W. Linville

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
parents b476d3f1 d78a32a8
...@@ -282,6 +282,7 @@ struct bt_skb_cb { ...@@ -282,6 +282,7 @@ struct bt_skb_cb {
__u8 incoming; __u8 incoming;
__u16 expect; __u16 expect;
__u8 force_active; __u8 force_active;
struct l2cap_chan *chan;
struct l2cap_ctrl control; struct l2cap_ctrl control;
struct hci_req_ctrl req; struct hci_req_ctrl req;
bdaddr_t bdaddr; bdaddr_t bdaddr;
......
...@@ -115,6 +115,7 @@ enum { ...@@ -115,6 +115,7 @@ enum {
HCI_PAIRABLE, HCI_PAIRABLE,
HCI_SERVICE_CACHE, HCI_SERVICE_CACHE,
HCI_DEBUG_KEYS, HCI_DEBUG_KEYS,
HCI_DUT_MODE,
HCI_UNREGISTER, HCI_UNREGISTER,
HCI_USER_CHANNEL, HCI_USER_CHANNEL,
...@@ -125,6 +126,7 @@ enum { ...@@ -125,6 +126,7 @@ enum {
HCI_ADVERTISING, HCI_ADVERTISING,
HCI_CONNECTABLE, HCI_CONNECTABLE,
HCI_DISCOVERABLE, HCI_DISCOVERABLE,
HCI_LIMITED_DISCOVERABLE,
HCI_LINK_SECURITY, HCI_LINK_SECURITY,
HCI_PERIODIC_INQ, HCI_PERIODIC_INQ,
HCI_FAST_CONNECTABLE, HCI_FAST_CONNECTABLE,
...@@ -823,6 +825,12 @@ struct hci_rp_read_num_supported_iac { ...@@ -823,6 +825,12 @@ struct hci_rp_read_num_supported_iac {
#define HCI_OP_READ_CURRENT_IAC_LAP 0x0c39 #define HCI_OP_READ_CURRENT_IAC_LAP 0x0c39
#define HCI_OP_WRITE_CURRENT_IAC_LAP 0x0c3a
struct hci_cp_write_current_iac_lap {
__u8 num_iac;
__u8 iac_lap[6];
} __packed;
#define HCI_OP_WRITE_INQUIRY_MODE 0x0c45 #define HCI_OP_WRITE_INQUIRY_MODE 0x0c45
#define HCI_MAX_EIR_LENGTH 240 #define HCI_MAX_EIR_LENGTH 240
...@@ -1036,6 +1044,10 @@ struct hci_rp_write_remote_amp_assoc { ...@@ -1036,6 +1044,10 @@ struct hci_rp_write_remote_amp_assoc {
__u8 phy_handle; __u8 phy_handle;
} __packed; } __packed;
#define HCI_OP_ENABLE_DUT_MODE 0x1803
#define HCI_OP_WRITE_SSP_DEBUG_MODE 0x1804
#define HCI_OP_LE_SET_EVENT_MASK 0x2001 #define HCI_OP_LE_SET_EVENT_MASK 0x2001
struct hci_cp_le_set_event_mask { struct hci_cp_le_set_event_mask {
__u8 mask[8]; __u8 mask[8];
...@@ -1056,11 +1068,6 @@ struct hci_rp_le_read_local_features { ...@@ -1056,11 +1068,6 @@ struct hci_rp_le_read_local_features {
#define HCI_OP_LE_SET_RANDOM_ADDR 0x2005 #define HCI_OP_LE_SET_RANDOM_ADDR 0x2005
#define LE_ADV_IND 0x00
#define LE_ADV_DIRECT_IND 0x01
#define LE_ADV_SCAN_IND 0x02
#define LE_ADV_NONCONN_IND 0x03
#define HCI_OP_LE_SET_ADV_PARAM 0x2006 #define HCI_OP_LE_SET_ADV_PARAM 0x2006
struct hci_cp_le_set_adv_param { struct hci_cp_le_set_adv_param {
__le16 min_interval; __le16 min_interval;
...@@ -1087,6 +1094,12 @@ struct hci_cp_le_set_adv_data { ...@@ -1087,6 +1094,12 @@ struct hci_cp_le_set_adv_data {
__u8 data[HCI_MAX_AD_LENGTH]; __u8 data[HCI_MAX_AD_LENGTH];
} __packed; } __packed;
#define HCI_OP_LE_SET_SCAN_RSP_DATA 0x2009
struct hci_cp_le_set_scan_rsp_data {
__u8 length;
__u8 data[HCI_MAX_AD_LENGTH];
} __packed;
#define HCI_OP_LE_SET_ADV_ENABLE 0x200a #define HCI_OP_LE_SET_ADV_ENABLE 0x200a
#define LE_SCAN_PASSIVE 0x00 #define LE_SCAN_PASSIVE 0x00
...@@ -1567,11 +1580,11 @@ struct hci_ev_le_ltk_req { ...@@ -1567,11 +1580,11 @@ struct hci_ev_le_ltk_req {
} __packed; } __packed;
/* Advertising report event types */ /* Advertising report event types */
#define ADV_IND 0x00 #define LE_ADV_IND 0x00
#define ADV_DIRECT_IND 0x01 #define LE_ADV_DIRECT_IND 0x01
#define ADV_SCAN_IND 0x02 #define LE_ADV_SCAN_IND 0x02
#define ADV_NONCONN_IND 0x03 #define LE_ADV_NONCONN_IND 0x03
#define ADV_SCAN_RSP 0x04 #define LE_ADV_SCAN_RSP 0x04
#define ADDR_LE_DEV_PUBLIC 0x00 #define ADDR_LE_DEV_PUBLIC 0x00
#define ADDR_LE_DEV_RANDOM 0x01 #define ADDR_LE_DEV_RANDOM 0x01
...@@ -1779,6 +1792,4 @@ struct hci_inquiry_req { ...@@ -1779,6 +1792,4 @@ struct hci_inquiry_req {
}; };
#define IREQ_CACHE_FLUSH 0x0001 #define IREQ_CACHE_FLUSH 0x0001
extern bool enable_hs;
#endif /* __HCI_H */ #endif /* __HCI_H */
...@@ -81,6 +81,7 @@ struct hci_conn_hash { ...@@ -81,6 +81,7 @@ struct hci_conn_hash {
struct bdaddr_list { struct bdaddr_list {
struct list_head list; struct list_head list;
bdaddr_t bdaddr; bdaddr_t bdaddr;
u8 bdaddr_type;
}; };
struct bt_uuid { struct bt_uuid {
...@@ -141,6 +142,7 @@ struct hci_dev { ...@@ -141,6 +142,7 @@ struct hci_dev {
__u8 dev_type; __u8 dev_type;
bdaddr_t bdaddr; bdaddr_t bdaddr;
bdaddr_t static_addr; bdaddr_t static_addr;
__u8 own_addr_type;
__u8 dev_name[HCI_MAX_NAME_LENGTH]; __u8 dev_name[HCI_MAX_NAME_LENGTH];
__u8 short_name[HCI_MAX_SHORT_NAME_LENGTH]; __u8 short_name[HCI_MAX_SHORT_NAME_LENGTH];
__u8 eir[HCI_MAX_EIR_LENGTH]; __u8 eir[HCI_MAX_EIR_LENGTH];
...@@ -167,6 +169,9 @@ struct hci_dev { ...@@ -167,6 +169,9 @@ struct hci_dev {
__u8 page_scan_type; __u8 page_scan_type;
__u16 le_scan_interval; __u16 le_scan_interval;
__u16 le_scan_window; __u16 le_scan_window;
__u16 le_conn_min_interval;
__u16 le_conn_max_interval;
__u8 ssp_debug_mode;
__u16 devid_source; __u16 devid_source;
__u16 devid_vendor; __u16 devid_vendor;
...@@ -283,6 +288,8 @@ struct hci_dev { ...@@ -283,6 +288,8 @@ struct hci_dev {
__s8 adv_tx_power; __s8 adv_tx_power;
__u8 adv_data[HCI_MAX_AD_LENGTH]; __u8 adv_data[HCI_MAX_AD_LENGTH];
__u8 adv_data_len; __u8 adv_data_len;
__u8 scan_rsp_data[HCI_MAX_AD_LENGTH];
__u8 scan_rsp_data_len;
int (*open)(struct hci_dev *hdev); int (*open)(struct hci_dev *hdev);
int (*close)(struct hci_dev *hdev); int (*close)(struct hci_dev *hdev);
...@@ -311,7 +318,6 @@ struct hci_conn { ...@@ -311,7 +318,6 @@ struct hci_conn {
__u8 attempt; __u8 attempt;
__u8 dev_class[3]; __u8 dev_class[3];
__u8 features[HCI_MAX_PAGES][8]; __u8 features[HCI_MAX_PAGES][8];
__u16 interval;
__u16 pkt_type; __u16 pkt_type;
__u16 link_policy; __u16 link_policy;
__u32 link_mode; __u32 link_mode;
...@@ -339,8 +345,8 @@ struct hci_conn { ...@@ -339,8 +345,8 @@ struct hci_conn {
struct list_head chan_list; struct list_head chan_list;
struct delayed_work disc_work; struct delayed_work disc_work;
struct timer_list idle_timer; struct delayed_work auto_accept_work;
struct timer_list auto_accept_timer; struct delayed_work idle_work;
struct device dev; struct device dev;
...@@ -649,7 +655,7 @@ static inline void hci_conn_drop(struct hci_conn *conn) ...@@ -649,7 +655,7 @@ static inline void hci_conn_drop(struct hci_conn *conn)
switch (conn->type) { switch (conn->type) {
case ACL_LINK: case ACL_LINK:
case LE_LINK: case LE_LINK:
del_timer(&conn->idle_timer); cancel_delayed_work(&conn->idle_work);
if (conn->state == BT_CONNECTED) { if (conn->state == BT_CONNECTED) {
timeo = conn->disc_timeout; timeo = conn->disc_timeout;
if (!conn->out) if (!conn->out)
...@@ -730,7 +736,7 @@ int hci_get_auth_info(struct hci_dev *hdev, void __user *arg); ...@@ -730,7 +736,7 @@ int hci_get_auth_info(struct hci_dev *hdev, void __user *arg);
int hci_inquiry(void __user *arg); int hci_inquiry(void __user *arg);
struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
bdaddr_t *bdaddr); bdaddr_t *bdaddr, u8 type);
int hci_blacklist_clear(struct hci_dev *hdev); int hci_blacklist_clear(struct hci_dev *hdev);
int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
...@@ -765,8 +771,6 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count); ...@@ -765,8 +771,6 @@ int hci_recv_fragment(struct hci_dev *hdev, int type, void *data, int count);
int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count); int hci_recv_stream_fragment(struct hci_dev *hdev, void *data, int count);
void hci_init_sysfs(struct hci_dev *hdev); void hci_init_sysfs(struct hci_dev *hdev);
int hci_add_sysfs(struct hci_dev *hdev);
void hci_del_sysfs(struct hci_dev *hdev);
void hci_conn_init_sysfs(struct hci_conn *conn); void hci_conn_init_sysfs(struct hci_conn *conn);
void hci_conn_add_sysfs(struct hci_conn *conn); void hci_conn_add_sysfs(struct hci_conn *conn);
void hci_conn_del_sysfs(struct hci_conn *conn); void hci_conn_del_sysfs(struct hci_conn *conn);
...@@ -1009,34 +1013,6 @@ static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type) ...@@ -1009,34 +1013,6 @@ static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type)
return false; return false;
} }
static inline size_t eir_get_length(u8 *eir, size_t eir_len)
{
size_t parsed = 0;
while (parsed < eir_len) {
u8 field_len = eir[0];
if (field_len == 0)
return parsed;
parsed += field_len + 1;
eir += field_len + 1;
}
return eir_len;
}
static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
u8 data_len)
{
eir[eir_len++] = sizeof(type) + data_len;
eir[eir_len++] = type;
memcpy(&eir[eir_len], data, data_len);
eir_len += data_len;
return eir_len;
}
int hci_register_cb(struct hci_cb *hcb); int hci_register_cb(struct hci_cb *hcb);
int hci_unregister_cb(struct hci_cb *hcb); int hci_unregister_cb(struct hci_cb *hcb);
...@@ -1100,11 +1076,12 @@ void mgmt_index_added(struct hci_dev *hdev); ...@@ -1100,11 +1076,12 @@ void mgmt_index_added(struct hci_dev *hdev);
void mgmt_index_removed(struct hci_dev *hdev); void mgmt_index_removed(struct hci_dev *hdev);
void mgmt_set_powered_failed(struct hci_dev *hdev, int err); void mgmt_set_powered_failed(struct hci_dev *hdev, int err);
int mgmt_powered(struct hci_dev *hdev, u8 powered); int mgmt_powered(struct hci_dev *hdev, u8 powered);
int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); void mgmt_discoverable_timeout(struct hci_dev *hdev);
int mgmt_connectable(struct hci_dev *hdev, u8 connectable); void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable);
int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); void mgmt_connectable(struct hci_dev *hdev, u8 connectable);
int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status);
bool persistent); void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
bool persistent);
void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u32 flags, u8 *name, u8 name_len, u8 addr_type, u32 flags, u8 *name, u8 name_len,
u8 *dev_class); u8 *dev_class);
...@@ -1114,11 +1091,11 @@ void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, ...@@ -1114,11 +1091,11 @@ void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u8 status); u8 link_type, u8 addr_type, u8 status);
void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 status); u8 addr_type, u8 status);
int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure); void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure);
int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 status); u8 status);
int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 status); u8 status);
int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, __le32 value, u8 link_type, u8 addr_type, __le32 value,
u8 confirm_hint); u8 confirm_hint);
...@@ -1135,15 +1112,15 @@ int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, ...@@ -1135,15 +1112,15 @@ int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr, int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u32 passkey, u8 link_type, u8 addr_type, u32 passkey,
u8 entered); u8 entered);
int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 status); u8 addr_type, u8 status);
int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status); void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status);
int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status); void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status);
int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
u8 status); u8 status);
int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status); void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status);
int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, void mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
u8 *randomizer, u8 status); u8 *randomizer, u8 status);
void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name,
u8 ssp, u8 *eir, u16 eir_len); u8 ssp, u8 *eir, u16 eir_len);
...@@ -1152,7 +1129,7 @@ void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, ...@@ -1152,7 +1129,7 @@ void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
void mgmt_discovering(struct hci_dev *hdev, u8 discovering); void mgmt_discovering(struct hci_dev *hdev, u8 discovering);
int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent); void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent);
void mgmt_reenable_advertising(struct hci_dev *hdev); void mgmt_reenable_advertising(struct hci_dev *hdev);
/* HCI info for socket */ /* HCI info for socket */
...@@ -1183,8 +1160,6 @@ struct hci_sec_filter { ...@@ -1183,8 +1160,6 @@ struct hci_sec_filter {
#define hci_req_lock(d) mutex_lock(&d->req_lock) #define hci_req_lock(d) mutex_lock(&d->req_lock)
#define hci_req_unlock(d) mutex_unlock(&d->req_lock) #define hci_req_unlock(d) mutex_unlock(&d->req_lock)
void hci_update_ad(struct hci_request *req);
void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max,
u16 latency, u16 to_multiplier); u16 latency, u16 to_multiplier);
void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8],
......
...@@ -435,8 +435,6 @@ struct l2cap_seq_list { ...@@ -435,8 +435,6 @@ struct l2cap_seq_list {
#define L2CAP_SEQ_LIST_TAIL 0x8000 #define L2CAP_SEQ_LIST_TAIL 0x8000
struct l2cap_chan { struct l2cap_chan {
struct sock *sk;
struct l2cap_conn *conn; struct l2cap_conn *conn;
struct hci_conn *hs_hcon; struct hci_conn *hs_hcon;
struct hci_chan *hs_hchan; struct hci_chan *hs_hchan;
...@@ -551,10 +549,12 @@ struct l2cap_ops { ...@@ -551,10 +549,12 @@ struct l2cap_ops {
void (*teardown) (struct l2cap_chan *chan, int err); void (*teardown) (struct l2cap_chan *chan, int err);
void (*close) (struct l2cap_chan *chan); void (*close) (struct l2cap_chan *chan);
void (*state_change) (struct l2cap_chan *chan, void (*state_change) (struct l2cap_chan *chan,
int state); int state, int err);
void (*ready) (struct l2cap_chan *chan); void (*ready) (struct l2cap_chan *chan);
void (*defer) (struct l2cap_chan *chan); void (*defer) (struct l2cap_chan *chan);
void (*resume) (struct l2cap_chan *chan); void (*resume) (struct l2cap_chan *chan);
void (*set_shutdown) (struct l2cap_chan *chan);
long (*get_sndtimeo) (struct l2cap_chan *chan);
struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan,
unsigned long len, int nb); unsigned long len, int nb);
}; };
...@@ -795,6 +795,19 @@ static inline void l2cap_chan_no_defer(struct l2cap_chan *chan) ...@@ -795,6 +795,19 @@ static inline void l2cap_chan_no_defer(struct l2cap_chan *chan)
{ {
} }
static inline void l2cap_chan_no_resume(struct l2cap_chan *chan)
{
}
static inline void l2cap_chan_no_set_shutdown(struct l2cap_chan *chan)
{
}
static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan)
{
return 0;
}
extern bool disable_ertm; extern bool disable_ertm;
int l2cap_init_sockets(void); int l2cap_init_sockets(void);
...@@ -802,7 +815,6 @@ void l2cap_cleanup_sockets(void); ...@@ -802,7 +815,6 @@ void l2cap_cleanup_sockets(void);
bool l2cap_is_socket(struct socket *sock); bool l2cap_is_socket(struct socket *sock);
void __l2cap_connect_rsp_defer(struct l2cap_chan *chan); void __l2cap_connect_rsp_defer(struct l2cap_chan *chan);
int __l2cap_wait_ack(struct sock *sk);
int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm); int l2cap_add_psm(struct l2cap_chan *chan, bdaddr_t *src, __le16 psm);
int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid);
......
...@@ -672,7 +672,8 @@ static void a2mp_chan_close_cb(struct l2cap_chan *chan) ...@@ -672,7 +672,8 @@ static void a2mp_chan_close_cb(struct l2cap_chan *chan)
l2cap_chan_put(chan); l2cap_chan_put(chan);
} }
static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state) static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state,
int err)
{ {
struct amp_mgr *mgr = chan->data; struct amp_mgr *mgr = chan->data;
...@@ -709,6 +710,9 @@ static struct l2cap_ops a2mp_chan_ops = { ...@@ -709,6 +710,9 @@ static struct l2cap_ops a2mp_chan_ops = {
.teardown = l2cap_chan_no_teardown, .teardown = l2cap_chan_no_teardown,
.ready = l2cap_chan_no_ready, .ready = l2cap_chan_no_ready,
.defer = l2cap_chan_no_defer, .defer = l2cap_chan_no_defer,
.resume = l2cap_chan_no_resume,
.set_shutdown = l2cap_chan_no_set_shutdown,
.get_sndtimeo = l2cap_chan_no_get_sndtimeo,
}; };
static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked)
...@@ -832,6 +836,9 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, ...@@ -832,6 +836,9 @@ struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn,
{ {
struct amp_mgr *mgr; struct amp_mgr *mgr;
if (conn->hcon->type != ACL_LINK)
return NULL;
mgr = amp_mgr_create(conn, false); mgr = amp_mgr_create(conn, false);
if (!mgr) { if (!mgr) {
BT_ERR("Could not create AMP manager"); BT_ERR("Could not create AMP manager");
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
/* Bluetooth address family and sockets. */ /* Bluetooth address family and sockets. */
#include <linux/module.h> #include <linux/module.h>
#include <linux/debugfs.h>
#include <asm/ioctls.h> #include <asm/ioctls.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
...@@ -708,12 +709,17 @@ static struct net_proto_family bt_sock_family_ops = { ...@@ -708,12 +709,17 @@ static struct net_proto_family bt_sock_family_ops = {
.create = bt_sock_create, .create = bt_sock_create,
}; };
struct dentry *bt_debugfs;
EXPORT_SYMBOL_GPL(bt_debugfs);
static int __init bt_init(void) static int __init bt_init(void)
{ {
int err; int err;
BT_INFO("Core ver %s", VERSION); BT_INFO("Core ver %s", VERSION);
bt_debugfs = debugfs_create_dir("bluetooth", NULL);
err = bt_sysfs_init(); err = bt_sysfs_init();
if (err < 0) if (err < 0)
return err; return err;
...@@ -754,7 +760,6 @@ static int __init bt_init(void) ...@@ -754,7 +760,6 @@ static int __init bt_init(void)
static void __exit bt_exit(void) static void __exit bt_exit(void)
{ {
sco_exit(); sco_exit();
l2cap_exit(); l2cap_exit();
...@@ -764,6 +769,8 @@ static void __exit bt_exit(void) ...@@ -764,6 +769,8 @@ static void __exit bt_exit(void)
sock_unregister(PF_BLUETOOTH); sock_unregister(PF_BLUETOOTH);
bt_sysfs_cleanup(); bt_sysfs_cleanup();
debugfs_remove_recursive(bt_debugfs);
} }
subsys_initcall(bt_init); subsys_initcall(bt_init);
......
...@@ -317,8 +317,10 @@ static void hci_conn_timeout(struct work_struct *work) ...@@ -317,8 +317,10 @@ static void hci_conn_timeout(struct work_struct *work)
} }
/* Enter sniff mode */ /* Enter sniff mode */
static void hci_conn_enter_sniff_mode(struct hci_conn *conn) static void hci_conn_idle(struct work_struct *work)
{ {
struct hci_conn *conn = container_of(work, struct hci_conn,
idle_work.work);
struct hci_dev *hdev = conn->hdev; struct hci_dev *hdev = conn->hdev;
BT_DBG("hcon %p mode %d", conn, conn->mode); BT_DBG("hcon %p mode %d", conn, conn->mode);
...@@ -352,21 +354,12 @@ static void hci_conn_enter_sniff_mode(struct hci_conn *conn) ...@@ -352,21 +354,12 @@ static void hci_conn_enter_sniff_mode(struct hci_conn *conn)
} }
} }
static void hci_conn_idle(unsigned long arg) static void hci_conn_auto_accept(struct work_struct *work)
{
struct hci_conn *conn = (void *) arg;
BT_DBG("hcon %p mode %d", conn, conn->mode);
hci_conn_enter_sniff_mode(conn);
}
static void hci_conn_auto_accept(unsigned long arg)
{ {
struct hci_conn *conn = (void *) arg; struct hci_conn *conn = container_of(work, struct hci_conn,
struct hci_dev *hdev = conn->hdev; auto_accept_work.work);
hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst), hci_send_cmd(conn->hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst),
&conn->dst); &conn->dst);
} }
...@@ -415,9 +408,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) ...@@ -415,9 +408,8 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst)
INIT_LIST_HEAD(&conn->chan_list); INIT_LIST_HEAD(&conn->chan_list);
INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout);
setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn); INIT_DELAYED_WORK(&conn->auto_accept_work, hci_conn_auto_accept);
setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept, INIT_DELAYED_WORK(&conn->idle_work, hci_conn_idle);
(unsigned long) conn);
atomic_set(&conn->refcnt, 0); atomic_set(&conn->refcnt, 0);
...@@ -438,11 +430,9 @@ int hci_conn_del(struct hci_conn *conn) ...@@ -438,11 +430,9 @@ int hci_conn_del(struct hci_conn *conn)
BT_DBG("%s hcon %p handle %d", hdev->name, conn, conn->handle); BT_DBG("%s hcon %p handle %d", hdev->name, conn, conn->handle);
del_timer(&conn->idle_timer);
cancel_delayed_work_sync(&conn->disc_work); cancel_delayed_work_sync(&conn->disc_work);
cancel_delayed_work_sync(&conn->auto_accept_work);
del_timer(&conn->auto_accept_timer); cancel_delayed_work_sync(&conn->idle_work);
if (conn->type == ACL_LINK) { if (conn->type == ACL_LINK) {
struct hci_conn *sco = conn->link; struct hci_conn *sco = conn->link;
...@@ -568,11 +558,12 @@ static int hci_create_le_conn(struct hci_conn *conn) ...@@ -568,11 +558,12 @@ static int hci_create_le_conn(struct hci_conn *conn)
bacpy(&cp.peer_addr, &conn->dst); bacpy(&cp.peer_addr, &conn->dst);
cp.peer_addr_type = conn->dst_type; cp.peer_addr_type = conn->dst_type;
cp.own_address_type = conn->src_type; cp.own_address_type = conn->src_type;
cp.conn_interval_min = __constant_cpu_to_le16(0x0028); cp.conn_interval_min = cpu_to_le16(hdev->le_conn_min_interval);
cp.conn_interval_max = __constant_cpu_to_le16(0x0038); cp.conn_interval_max = cpu_to_le16(hdev->le_conn_max_interval);
cp.supervision_timeout = __constant_cpu_to_le16(0x002a); cp.supervision_timeout = __constant_cpu_to_le16(0x002a);
cp.min_ce_len = __constant_cpu_to_le16(0x0000); cp.min_ce_len = __constant_cpu_to_le16(0x0000);
cp.max_ce_len = __constant_cpu_to_le16(0x0000); cp.max_ce_len = __constant_cpu_to_le16(0x0000);
hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp);
err = hci_req_run(&req, create_le_conn_complete); err = hci_req_run(&req, create_le_conn_complete);
...@@ -625,12 +616,7 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, ...@@ -625,12 +616,7 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst,
else else
conn->dst_type = ADDR_LE_DEV_RANDOM; conn->dst_type = ADDR_LE_DEV_RANDOM;
if (bacmp(&conn->src, BDADDR_ANY)) { conn->src_type = hdev->own_addr_type;
conn->src_type = ADDR_LE_DEV_PUBLIC;
} else {
bacpy(&conn->src, &hdev->static_addr);
conn->src_type = ADDR_LE_DEV_RANDOM;
}
conn->state = BT_CONNECT; conn->state = BT_CONNECT;
conn->out = true; conn->out = true;
...@@ -922,8 +908,8 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active) ...@@ -922,8 +908,8 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active)
timer: timer:
if (hdev->idle_timeout > 0) if (hdev->idle_timeout > 0)
mod_timer(&conn->idle_timer, queue_delayed_work(hdev->workqueue, &conn->idle_work,
jiffies + msecs_to_jiffies(hdev->idle_timeout)); msecs_to_jiffies(hdev->idle_timeout));
} }
/* Drop all connection on the device */ /* Drop all connection on the device */
......
...@@ -27,8 +27,9 @@ ...@@ -27,8 +27,9 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/idr.h> #include <linux/idr.h>
#include <linux/rfkill.h> #include <linux/rfkill.h>
#include <linux/debugfs.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
...@@ -55,6 +56,586 @@ static void hci_notify(struct hci_dev *hdev, int event) ...@@ -55,6 +56,586 @@ static void hci_notify(struct hci_dev *hdev, int event)
hci_sock_dev_event(hdev, event); hci_sock_dev_event(hdev, event);
} }
/* ---- HCI debugfs entries ---- */
static ssize_t dut_mode_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct hci_dev *hdev = file->private_data;
char buf[3];
buf[0] = test_bit(HCI_DUT_MODE, &hdev->dev_flags) ? 'Y': 'N';
buf[1] = '\n';
buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
}
static ssize_t dut_mode_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct hci_dev *hdev = file->private_data;
struct sk_buff *skb;
char buf[32];
size_t buf_size = min(count, (sizeof(buf)-1));
bool enable;
int err;
if (!test_bit(HCI_UP, &hdev->flags))
return -ENETDOWN;
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
buf[buf_size] = '\0';
if (strtobool(buf, &enable))
return -EINVAL;
if (enable == test_bit(HCI_DUT_MODE, &hdev->dev_flags))
return -EALREADY;
hci_req_lock(hdev);
if (enable)
skb = __hci_cmd_sync(hdev, HCI_OP_ENABLE_DUT_MODE, 0, NULL,
HCI_CMD_TIMEOUT);
else
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL,
HCI_CMD_TIMEOUT);
hci_req_unlock(hdev);
if (IS_ERR(skb))
return PTR_ERR(skb);
err = -bt_to_errno(skb->data[0]);
kfree_skb(skb);
if (err < 0)
return err;
change_bit(HCI_DUT_MODE, &hdev->dev_flags);
return count;
}
static const struct file_operations dut_mode_fops = {
.open = simple_open,
.read = dut_mode_read,
.write = dut_mode_write,
.llseek = default_llseek,
};
static int features_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
u8 p;
hci_dev_lock(hdev);
for (p = 0; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) {
seq_printf(f, "%2u: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x "
"0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n", p,
hdev->features[p][0], hdev->features[p][1],
hdev->features[p][2], hdev->features[p][3],
hdev->features[p][4], hdev->features[p][5],
hdev->features[p][6], hdev->features[p][7]);
}
if (lmp_le_capable(hdev))
seq_printf(f, "LE: 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x "
"0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x\n",
hdev->le_features[0], hdev->le_features[1],
hdev->le_features[2], hdev->le_features[3],
hdev->le_features[4], hdev->le_features[5],
hdev->le_features[6], hdev->le_features[7]);
hci_dev_unlock(hdev);
return 0;
}
static int features_open(struct inode *inode, struct file *file)
{
return single_open(file, features_show, inode->i_private);
}
static const struct file_operations features_fops = {
.open = features_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int blacklist_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
struct bdaddr_list *b;
hci_dev_lock(hdev);
list_for_each_entry(b, &hdev->blacklist, list)
seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type);
hci_dev_unlock(hdev);
return 0;
}
static int blacklist_open(struct inode *inode, struct file *file)
{
return single_open(file, blacklist_show, inode->i_private);
}
static const struct file_operations blacklist_fops = {
.open = blacklist_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int uuids_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
struct bt_uuid *uuid;
hci_dev_lock(hdev);
list_for_each_entry(uuid, &hdev->uuids, list) {
u8 i, val[16];
/* The Bluetooth UUID values are stored in big endian,
* but with reversed byte order. So convert them into
* the right order for the %pUb modifier.
*/
for (i = 0; i < 16; i++)
val[i] = uuid->uuid[15 - i];
seq_printf(f, "%pUb\n", val);
}
hci_dev_unlock(hdev);
return 0;
}
static int uuids_open(struct inode *inode, struct file *file)
{
return single_open(file, uuids_show, inode->i_private);
}
static const struct file_operations uuids_fops = {
.open = uuids_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int inquiry_cache_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *e;
hci_dev_lock(hdev);
list_for_each_entry(e, &cache->all, all) {
struct inquiry_data *data = &e->data;
seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
&data->bdaddr,
data->pscan_rep_mode, data->pscan_period_mode,
data->pscan_mode, data->dev_class[2],
data->dev_class[1], data->dev_class[0],
__le16_to_cpu(data->clock_offset),
data->rssi, data->ssp_mode, e->timestamp);
}
hci_dev_unlock(hdev);
return 0;
}
static int inquiry_cache_open(struct inode *inode, struct file *file)
{
return single_open(file, inquiry_cache_show, inode->i_private);
}
static const struct file_operations inquiry_cache_fops = {
.open = inquiry_cache_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int link_keys_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
struct list_head *p, *n;
hci_dev_lock(hdev);
list_for_each_safe(p, n, &hdev->link_keys) {
struct link_key *key = list_entry(p, struct link_key, list);
seq_printf(f, "%pMR %u %*phN %u\n", &key->bdaddr, key->type,
HCI_LINK_KEY_SIZE, key->val, key->pin_len);
}
hci_dev_unlock(hdev);
return 0;
}
static int link_keys_open(struct inode *inode, struct file *file)
{
return single_open(file, link_keys_show, inode->i_private);
}
static const struct file_operations link_keys_fops = {
.open = link_keys_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static ssize_t use_debug_keys_read(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
struct hci_dev *hdev = file->private_data;
char buf[3];
buf[0] = test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) ? 'Y': 'N';
buf[1] = '\n';
buf[2] = '\0';
return simple_read_from_buffer(user_buf, count, ppos, buf, 2);
}
static const struct file_operations use_debug_keys_fops = {
.open = simple_open,
.read = use_debug_keys_read,
.llseek = default_llseek,
};
static int dev_class_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
hci_dev_lock(hdev);
seq_printf(f, "0x%.2x%.2x%.2x\n", hdev->dev_class[2],
hdev->dev_class[1], hdev->dev_class[0]);
hci_dev_unlock(hdev);
return 0;
}
static int dev_class_open(struct inode *inode, struct file *file)
{
return single_open(file, dev_class_show, inode->i_private);
}
static const struct file_operations dev_class_fops = {
.open = dev_class_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int voice_setting_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->voice_setting;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(voice_setting_fops, voice_setting_get,
NULL, "0x%4.4llx\n");
static int auto_accept_delay_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
hdev->auto_accept_delay = val;
hci_dev_unlock(hdev);
return 0;
}
static int auto_accept_delay_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->auto_accept_delay;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get,
auto_accept_delay_set, "%llu\n");
static int ssp_debug_mode_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
struct sk_buff *skb;
__u8 mode;
int err;
if (val != 0 && val != 1)
return -EINVAL;
if (!test_bit(HCI_UP, &hdev->flags))
return -ENETDOWN;
hci_req_lock(hdev);
mode = val;
skb = __hci_cmd_sync(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE, sizeof(mode),
&mode, HCI_CMD_TIMEOUT);
hci_req_unlock(hdev);
if (IS_ERR(skb))
return PTR_ERR(skb);
err = -bt_to_errno(skb->data[0]);
kfree_skb(skb);
if (err < 0)
return err;
hci_dev_lock(hdev);
hdev->ssp_debug_mode = val;
hci_dev_unlock(hdev);
return 0;
}
static int ssp_debug_mode_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->ssp_debug_mode;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(ssp_debug_mode_fops, ssp_debug_mode_get,
ssp_debug_mode_set, "%llu\n");
static int idle_timeout_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
if (val != 0 && (val < 500 || val > 3600000))
return -EINVAL;
hci_dev_lock(hdev);
hdev->idle_timeout = val;
hci_dev_unlock(hdev);
return 0;
}
static int idle_timeout_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->idle_timeout;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(idle_timeout_fops, idle_timeout_get,
idle_timeout_set, "%llu\n");
static int sniff_min_interval_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
if (val == 0 || val % 2 || val > hdev->sniff_max_interval)
return -EINVAL;
hci_dev_lock(hdev);
hdev->sniff_min_interval = val;
hci_dev_unlock(hdev);
return 0;
}
static int sniff_min_interval_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->sniff_min_interval;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(sniff_min_interval_fops, sniff_min_interval_get,
sniff_min_interval_set, "%llu\n");
static int sniff_max_interval_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
if (val == 0 || val % 2 || val < hdev->sniff_min_interval)
return -EINVAL;
hci_dev_lock(hdev);
hdev->sniff_max_interval = val;
hci_dev_unlock(hdev);
return 0;
}
static int sniff_max_interval_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->sniff_max_interval;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(sniff_max_interval_fops, sniff_max_interval_get,
sniff_max_interval_set, "%llu\n");
static int static_address_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
hci_dev_lock(hdev);
seq_printf(f, "%pMR\n", &hdev->static_addr);
hci_dev_unlock(hdev);
return 0;
}
static int static_address_open(struct inode *inode, struct file *file)
{
return single_open(file, static_address_show, inode->i_private);
}
static const struct file_operations static_address_fops = {
.open = static_address_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int own_address_type_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
if (val != 0 && val != 1)
return -EINVAL;
hci_dev_lock(hdev);
hdev->own_addr_type = val;
hci_dev_unlock(hdev);
return 0;
}
static int own_address_type_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->own_addr_type;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(own_address_type_fops, own_address_type_get,
own_address_type_set, "%llu\n");
static int long_term_keys_show(struct seq_file *f, void *ptr)
{
struct hci_dev *hdev = f->private;
struct list_head *p, *n;
hci_dev_lock(hdev);
list_for_each_safe(p, n, &hdev->link_keys) {
struct smp_ltk *ltk = list_entry(p, struct smp_ltk, list);
seq_printf(f, "%pMR (type %u) %u %u %u %.4x %*phN %*phN\\n",
&ltk->bdaddr, ltk->bdaddr_type, ltk->authenticated,
ltk->type, ltk->enc_size, __le16_to_cpu(ltk->ediv),
8, ltk->rand, 16, ltk->val);
}
hci_dev_unlock(hdev);
return 0;
}
static int long_term_keys_open(struct inode *inode, struct file *file)
{
return single_open(file, long_term_keys_show, inode->i_private);
}
static const struct file_operations long_term_keys_fops = {
.open = long_term_keys_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int conn_min_interval_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
if (val < 0x0006 || val > 0x0c80 || val > hdev->le_conn_max_interval)
return -EINVAL;
hci_dev_lock(hdev);
hdev->le_conn_min_interval = val;
hci_dev_unlock(hdev);
return 0;
}
static int conn_min_interval_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->le_conn_min_interval;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(conn_min_interval_fops, conn_min_interval_get,
conn_min_interval_set, "%llu\n");
static int conn_max_interval_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
if (val < 0x0006 || val > 0x0c80 || val < hdev->le_conn_min_interval)
return -EINVAL;
hci_dev_lock(hdev);
hdev->le_conn_max_interval = val;
hci_dev_unlock(hdev);
return 0;
}
static int conn_max_interval_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->le_conn_max_interval;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get,
conn_max_interval_set, "%llu\n");
/* ---- HCI requests ---- */ /* ---- HCI requests ---- */
static void hci_req_sync_complete(struct hci_dev *hdev, u8 result) static void hci_req_sync_complete(struct hci_dev *hdev, u8 result)
...@@ -556,6 +1137,14 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt) ...@@ -556,6 +1137,14 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt)
hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL);
if (lmp_ssp_capable(hdev)) { if (lmp_ssp_capable(hdev)) {
/* When SSP is available, then the host features page
* should also be available as well. However some
* controllers list the max_page as 0 as long as SSP
* has not been enabled. To achieve proper debugging
* output, force the minimum max_page to 1 at least.
*/
hdev->max_page = 0x01;
if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
u8 mode = 0x01; u8 mode = 0x01;
hci_req_add(req, HCI_OP_WRITE_SSP_MODE, hci_req_add(req, HCI_OP_WRITE_SSP_MODE,
...@@ -686,8 +1275,17 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) ...@@ -686,8 +1275,17 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt)
hci_setup_link_policy(req); hci_setup_link_policy(req);
if (lmp_le_capable(hdev)) { if (lmp_le_capable(hdev)) {
/* If the controller has a public BD_ADDR, then by
* default use that one. If this is a LE only
* controller without one, default to the random
* address.
*/
if (bacmp(&hdev->bdaddr, BDADDR_ANY))
hdev->own_addr_type = ADDR_LE_DEV_PUBLIC;
else
hdev->own_addr_type = ADDR_LE_DEV_RANDOM;
hci_set_le_support(req); hci_set_le_support(req);
hci_update_ad(req);
} }
/* Read features beyond page 1 if available */ /* Read features beyond page 1 if available */
...@@ -721,6 +1319,14 @@ static int __hci_init(struct hci_dev *hdev) ...@@ -721,6 +1319,14 @@ static int __hci_init(struct hci_dev *hdev)
if (err < 0) if (err < 0)
return err; return err;
/* The Device Under Test (DUT) mode is special and available for
* all controller types. So just create it early on.
*/
if (test_bit(HCI_SETUP, &hdev->dev_flags)) {
debugfs_create_file("dut_mode", 0644, hdev->debugfs, hdev,
&dut_mode_fops);
}
/* HCI_BREDR covers both single-mode LE, BR/EDR and dual-mode /* HCI_BREDR covers both single-mode LE, BR/EDR and dual-mode
* BR/EDR/LE type controllers. AMP controllers only need the * BR/EDR/LE type controllers. AMP controllers only need the
* first stage init. * first stage init.
...@@ -736,7 +1342,71 @@ static int __hci_init(struct hci_dev *hdev) ...@@ -736,7 +1342,71 @@ static int __hci_init(struct hci_dev *hdev)
if (err < 0) if (err < 0)
return err; return err;
return __hci_req_sync(hdev, hci_init4_req, 0, HCI_INIT_TIMEOUT); err = __hci_req_sync(hdev, hci_init4_req, 0, HCI_INIT_TIMEOUT);
if (err < 0)
return err;
/* Only create debugfs entries during the initial setup
* phase and not every time the controller gets powered on.
*/
if (!test_bit(HCI_SETUP, &hdev->dev_flags))
return 0;
debugfs_create_file("features", 0444, hdev->debugfs, hdev,
&features_fops);
debugfs_create_u16("manufacturer", 0444, hdev->debugfs,
&hdev->manufacturer);
debugfs_create_u8("hci_version", 0444, hdev->debugfs, &hdev->hci_ver);
debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev);
debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev,
&blacklist_fops);
debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
if (lmp_bredr_capable(hdev)) {
debugfs_create_file("inquiry_cache", 0444, hdev->debugfs,
hdev, &inquiry_cache_fops);
debugfs_create_file("link_keys", 0400, hdev->debugfs,
hdev, &link_keys_fops);
debugfs_create_file("use_debug_keys", 0444, hdev->debugfs,
hdev, &use_debug_keys_fops);
debugfs_create_file("dev_class", 0444, hdev->debugfs,
hdev, &dev_class_fops);
debugfs_create_file("voice_setting", 0444, hdev->debugfs,
hdev, &voice_setting_fops);
}
if (lmp_ssp_capable(hdev)) {
debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs,
hdev, &auto_accept_delay_fops);
debugfs_create_file("ssp_debug_mode", 0644, hdev->debugfs,
hdev, &ssp_debug_mode_fops);
}
if (lmp_sniff_capable(hdev)) {
debugfs_create_file("idle_timeout", 0644, hdev->debugfs,
hdev, &idle_timeout_fops);
debugfs_create_file("sniff_min_interval", 0644, hdev->debugfs,
hdev, &sniff_min_interval_fops);
debugfs_create_file("sniff_max_interval", 0644, hdev->debugfs,
hdev, &sniff_max_interval_fops);
}
if (lmp_le_capable(hdev)) {
debugfs_create_u8("white_list_size", 0444, hdev->debugfs,
&hdev->le_white_list_size);
debugfs_create_file("static_address", 0444, hdev->debugfs,
hdev, &static_address_fops);
debugfs_create_file("own_address_type", 0644, hdev->debugfs,
hdev, &own_address_type_fops);
debugfs_create_file("long_term_keys", 0400, hdev->debugfs,
hdev, &long_term_keys_fops);
debugfs_create_file("conn_min_interval", 0644, hdev->debugfs,
hdev, &conn_min_interval_fops);
debugfs_create_file("conn_max_interval", 0644, hdev->debugfs,
hdev, &conn_max_interval_fops);
}
return 0;
} }
static void hci_scan_req(struct hci_request *req, unsigned long opt) static void hci_scan_req(struct hci_request *req, unsigned long opt)
...@@ -1127,89 +1797,6 @@ int hci_inquiry(void __user *arg) ...@@ -1127,89 +1797,6 @@ int hci_inquiry(void __user *arg)
return err; return err;
} }
static u8 create_ad(struct hci_dev *hdev, u8 *ptr)
{
u8 ad_len = 0, flags = 0;
size_t name_len;
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
flags |= LE_AD_GENERAL;
if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
if (lmp_le_br_capable(hdev))
flags |= LE_AD_SIM_LE_BREDR_CTRL;
if (lmp_host_le_br_capable(hdev))
flags |= LE_AD_SIM_LE_BREDR_HOST;
} else {
flags |= LE_AD_NO_BREDR;
}
if (flags) {
BT_DBG("adv flags 0x%02x", flags);
ptr[0] = 2;
ptr[1] = EIR_FLAGS;
ptr[2] = flags;
ad_len += 3;
ptr += 3;
}
if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
ptr[0] = 2;
ptr[1] = EIR_TX_POWER;
ptr[2] = (u8) hdev->adv_tx_power;
ad_len += 3;
ptr += 3;
}
name_len = strlen(hdev->dev_name);
if (name_len > 0) {
size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
if (name_len > max_len) {
name_len = max_len;
ptr[1] = EIR_NAME_SHORT;
} else
ptr[1] = EIR_NAME_COMPLETE;
ptr[0] = name_len + 1;
memcpy(ptr + 2, hdev->dev_name, name_len);
ad_len += (name_len + 2);
ptr += (name_len + 2);
}
return ad_len;
}
void hci_update_ad(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
struct hci_cp_le_set_adv_data cp;
u8 len;
if (!lmp_le_capable(hdev))
return;
memset(&cp, 0, sizeof(cp));
len = create_ad(hdev, cp.data);
if (hdev->adv_data_len == len &&
memcmp(cp.data, hdev->adv_data, len) == 0)
return;
memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
hdev->adv_data_len = len;
cp.length = len;
hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
}
static int hci_dev_do_open(struct hci_dev *hdev) static int hci_dev_do_open(struct hci_dev *hdev)
{ {
int ret = 0; int ret = 0;
...@@ -1367,6 +1954,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) ...@@ -1367,6 +1954,7 @@ static int hci_dev_do_close(struct hci_dev *hdev)
cancel_delayed_work(&hdev->discov_off); cancel_delayed_work(&hdev->discov_off);
hdev->discov_timeout = 0; hdev->discov_timeout = 0;
clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
} }
if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) if (test_and_clear_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
...@@ -1789,19 +2377,12 @@ static void hci_power_off(struct work_struct *work) ...@@ -1789,19 +2377,12 @@ static void hci_power_off(struct work_struct *work)
static void hci_discov_off(struct work_struct *work) static void hci_discov_off(struct work_struct *work)
{ {
struct hci_dev *hdev; struct hci_dev *hdev;
u8 scan = SCAN_PAGE;
hdev = container_of(work, struct hci_dev, discov_off.work); hdev = container_of(work, struct hci_dev, discov_off.work);
BT_DBG("%s", hdev->name); BT_DBG("%s", hdev->name);
hci_dev_lock(hdev); mgmt_discoverable_timeout(hdev);
hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
hdev->discov_timeout = 0;
hci_dev_unlock(hdev);
} }
int hci_uuids_clear(struct hci_dev *hdev) int hci_uuids_clear(struct hci_dev *hdev)
...@@ -2124,13 +2705,15 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, ...@@ -2124,13 +2705,15 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash,
return 0; return 0;
} }
struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr) struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev,
bdaddr_t *bdaddr, u8 type)
{ {
struct bdaddr_list *b; struct bdaddr_list *b;
list_for_each_entry(b, &hdev->blacklist, list) list_for_each_entry(b, &hdev->blacklist, list) {
if (bacmp(bdaddr, &b->bdaddr) == 0) if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type)
return b; return b;
}
return NULL; return NULL;
} }
...@@ -2140,9 +2723,7 @@ int hci_blacklist_clear(struct hci_dev *hdev) ...@@ -2140,9 +2723,7 @@ int hci_blacklist_clear(struct hci_dev *hdev)
struct list_head *p, *n; struct list_head *p, *n;
list_for_each_safe(p, n, &hdev->blacklist) { list_for_each_safe(p, n, &hdev->blacklist) {
struct bdaddr_list *b; struct bdaddr_list *b = list_entry(p, struct bdaddr_list, list);
b = list_entry(p, struct bdaddr_list, list);
list_del(p); list_del(p);
kfree(b); kfree(b);
...@@ -2155,10 +2736,10 @@ int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) ...@@ -2155,10 +2736,10 @@ int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
{ {
struct bdaddr_list *entry; struct bdaddr_list *entry;
if (bacmp(bdaddr, BDADDR_ANY) == 0) if (!bacmp(bdaddr, BDADDR_ANY))
return -EBADF; return -EBADF;
if (hci_blacklist_lookup(hdev, bdaddr)) if (hci_blacklist_lookup(hdev, bdaddr, type))
return -EEXIST; return -EEXIST;
entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL); entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL);
...@@ -2166,6 +2747,7 @@ int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) ...@@ -2166,6 +2747,7 @@ int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
return -ENOMEM; return -ENOMEM;
bacpy(&entry->bdaddr, bdaddr); bacpy(&entry->bdaddr, bdaddr);
entry->bdaddr_type = type;
list_add(&entry->list, &hdev->blacklist); list_add(&entry->list, &hdev->blacklist);
...@@ -2176,10 +2758,10 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) ...@@ -2176,10 +2758,10 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type)
{ {
struct bdaddr_list *entry; struct bdaddr_list *entry;
if (bacmp(bdaddr, BDADDR_ANY) == 0) if (!bacmp(bdaddr, BDADDR_ANY))
return hci_blacklist_clear(hdev); return hci_blacklist_clear(hdev);
entry = hci_blacklist_lookup(hdev, bdaddr); entry = hci_blacklist_lookup(hdev, bdaddr, type);
if (!entry) if (!entry)
return -ENOENT; return -ENOENT;
...@@ -2287,6 +2869,8 @@ struct hci_dev *hci_alloc_dev(void) ...@@ -2287,6 +2869,8 @@ struct hci_dev *hci_alloc_dev(void)
hdev->le_scan_interval = 0x0060; hdev->le_scan_interval = 0x0060;
hdev->le_scan_window = 0x0030; hdev->le_scan_window = 0x0030;
hdev->le_conn_min_interval = 0x0028;
hdev->le_conn_max_interval = 0x0038;
mutex_init(&hdev->lock); mutex_init(&hdev->lock);
mutex_init(&hdev->req_lock); mutex_init(&hdev->req_lock);
...@@ -2376,7 +2960,12 @@ int hci_register_dev(struct hci_dev *hdev) ...@@ -2376,7 +2960,12 @@ int hci_register_dev(struct hci_dev *hdev)
goto err; goto err;
} }
error = hci_add_sysfs(hdev); if (!IS_ERR_OR_NULL(bt_debugfs))
hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs);
dev_set_name(&hdev->dev, "%s", hdev->name);
error = device_add(&hdev->dev);
if (error < 0) if (error < 0)
goto err_wqueue; goto err_wqueue;
...@@ -2464,7 +3053,9 @@ void hci_unregister_dev(struct hci_dev *hdev) ...@@ -2464,7 +3053,9 @@ void hci_unregister_dev(struct hci_dev *hdev)
rfkill_destroy(hdev->rfkill); rfkill_destroy(hdev->rfkill);
} }
hci_del_sysfs(hdev); device_del(&hdev->dev);
debugfs_remove_recursive(hdev->debugfs);
destroy_workqueue(hdev->workqueue); destroy_workqueue(hdev->workqueue);
destroy_workqueue(hdev->req_workqueue); destroy_workqueue(hdev->req_workqueue);
......
...@@ -195,6 +195,11 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -195,6 +195,11 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb)
memset(hdev->adv_data, 0, sizeof(hdev->adv_data)); memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
hdev->adv_data_len = 0; hdev->adv_data_len = 0;
memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data));
hdev->scan_rsp_data_len = 0;
hdev->ssp_debug_mode = 0;
} }
static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb)
...@@ -310,11 +315,6 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -310,11 +315,6 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb)
set_bit(HCI_ISCAN, &hdev->flags); set_bit(HCI_ISCAN, &hdev->flags);
if (!old_iscan) if (!old_iscan)
mgmt_discoverable(hdev, 1); mgmt_discoverable(hdev, 1);
if (hdev->discov_timeout > 0) {
int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
queue_delayed_work(hdev->workqueue, &hdev->discov_off,
to);
}
} else if (old_iscan) } else if (old_iscan)
mgmt_discoverable(hdev, 0); mgmt_discoverable(hdev, 0);
...@@ -470,14 +470,13 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -470,14 +470,13 @@ static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb)
if (rp->status) if (rp->status)
return; return;
hdev->hci_ver = rp->hci_ver; if (test_bit(HCI_SETUP, &hdev->dev_flags)) {
hdev->hci_rev = __le16_to_cpu(rp->hci_rev); hdev->hci_ver = rp->hci_ver;
hdev->lmp_ver = rp->lmp_ver; hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
hdev->manufacturer = __le16_to_cpu(rp->manufacturer); hdev->lmp_ver = rp->lmp_ver;
hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver); hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
BT_DBG("%s manufacturer 0x%4.4x hci ver %d:%d", hdev->name, }
hdev->manufacturer, hdev->hci_ver, hdev->hci_rev);
} }
static void hci_cc_read_local_commands(struct hci_dev *hdev, static void hci_cc_read_local_commands(struct hci_dev *hdev,
...@@ -557,7 +556,8 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, ...@@ -557,7 +556,8 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev,
if (rp->status) if (rp->status)
return; return;
hdev->max_page = rp->max_page; if (hdev->max_page < rp->max_page)
hdev->max_page = rp->max_page;
if (rp->page < HCI_MAX_PAGES) if (rp->page < HCI_MAX_PAGES)
memcpy(hdev->features[rp->page], rp->features, 8); memcpy(hdev->features[rp->page], rp->features, 8);
...@@ -939,14 +939,6 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -939,14 +939,6 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb)
clear_bit(HCI_ADVERTISING, &hdev->dev_flags); clear_bit(HCI_ADVERTISING, &hdev->dev_flags);
} }
if (*sent && !test_bit(HCI_INIT, &hdev->flags)) {
struct hci_request req;
hci_req_init(&req, hdev);
hci_update_ad(&req);
hci_req_run(&req, NULL);
}
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
} }
...@@ -1702,7 +1694,7 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -1702,7 +1694,7 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb)
&flags); &flags);
if ((mask & HCI_LM_ACCEPT) && if ((mask & HCI_LM_ACCEPT) &&
!hci_blacklist_lookup(hdev, &ev->bdaddr)) { !hci_blacklist_lookup(hdev, &ev->bdaddr, BDADDR_BREDR)) {
/* Connection accepted */ /* Connection accepted */
struct inquiry_entry *ie; struct inquiry_entry *ie;
struct hci_conn *conn; struct hci_conn *conn;
...@@ -2559,7 +2551,6 @@ static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb) ...@@ -2559,7 +2551,6 @@ static void hci_mode_change_evt(struct hci_dev *hdev, struct sk_buff *skb)
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (conn) { if (conn) {
conn->mode = ev->mode; conn->mode = ev->mode;
conn->interval = __le16_to_cpu(ev->interval);
if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
&conn->flags)) { &conn->flags)) {
...@@ -2941,6 +2932,23 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, ...@@ -2941,6 +2932,23 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev,
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
} }
static inline size_t eir_get_length(u8 *eir, size_t eir_len)
{
size_t parsed = 0;
while (parsed < eir_len) {
u8 field_len = eir[0];
if (field_len == 0)
return parsed;
parsed += field_len + 1;
eir += field_len + 1;
}
return eir_len;
}
static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, static void hci_extended_inquiry_result_evt(struct hci_dev *hdev,
struct sk_buff *skb) struct sk_buff *skb)
{ {
...@@ -3181,7 +3189,8 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev, ...@@ -3181,7 +3189,8 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev,
if (hdev->auto_accept_delay > 0) { if (hdev->auto_accept_delay > 0) {
int delay = msecs_to_jiffies(hdev->auto_accept_delay); int delay = msecs_to_jiffies(hdev->auto_accept_delay);
mod_timer(&conn->auto_accept_timer, jiffies + delay); queue_delayed_work(conn->hdev->workqueue,
&conn->auto_accept_work, delay);
goto unlock; goto unlock;
} }
......
...@@ -481,7 +481,7 @@ static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg) ...@@ -481,7 +481,7 @@ static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg)
hci_dev_lock(hdev); hci_dev_lock(hdev);
err = hci_blacklist_add(hdev, &bdaddr, 0); err = hci_blacklist_add(hdev, &bdaddr, BDADDR_BREDR);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
...@@ -498,7 +498,7 @@ static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg) ...@@ -498,7 +498,7 @@ static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg)
hci_dev_lock(hdev); hci_dev_lock(hdev);
err = hci_blacklist_del(hdev, &bdaddr, 0); err = hci_blacklist_del(hdev, &bdaddr, BDADDR_BREDR);
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
......
/* Bluetooth HCI driver model support. */ /* Bluetooth HCI driver model support. */
#include <linux/debugfs.h>
#include <linux/module.h> #include <linux/module.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h> #include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h> #include <net/bluetooth/hci_core.h>
static struct class *bt_class; static struct class *bt_class;
struct dentry *bt_debugfs;
EXPORT_SYMBOL_GPL(bt_debugfs);
static inline char *link_typetostr(int type) static inline char *link_typetostr(int type)
{ {
switch (type) { switch (type) {
...@@ -42,29 +37,15 @@ static ssize_t show_link_address(struct device *dev, ...@@ -42,29 +37,15 @@ static ssize_t show_link_address(struct device *dev,
return sprintf(buf, "%pMR\n", &conn->dst); return sprintf(buf, "%pMR\n", &conn->dst);
} }
static ssize_t show_link_features(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hci_conn *conn = to_hci_conn(dev);
return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
conn->features[0][0], conn->features[0][1],
conn->features[0][2], conn->features[0][3],
conn->features[0][4], conn->features[0][5],
conn->features[0][6], conn->features[0][7]);
}
#define LINK_ATTR(_name, _mode, _show, _store) \ #define LINK_ATTR(_name, _mode, _show, _store) \
struct device_attribute link_attr_##_name = __ATTR(_name, _mode, _show, _store) struct device_attribute link_attr_##_name = __ATTR(_name, _mode, _show, _store)
static LINK_ATTR(type, S_IRUGO, show_link_type, NULL); static LINK_ATTR(type, S_IRUGO, show_link_type, NULL);
static LINK_ATTR(address, S_IRUGO, show_link_address, NULL); static LINK_ATTR(address, S_IRUGO, show_link_address, NULL);
static LINK_ATTR(features, S_IRUGO, show_link_features, NULL);
static struct attribute *bt_link_attrs[] = { static struct attribute *bt_link_attrs[] = {
&link_attr_type.attr, &link_attr_type.attr,
&link_attr_address.attr, &link_attr_address.attr,
&link_attr_features.attr,
NULL NULL
}; };
...@@ -150,28 +131,6 @@ void hci_conn_del_sysfs(struct hci_conn *conn) ...@@ -150,28 +131,6 @@ void hci_conn_del_sysfs(struct hci_conn *conn)
hci_dev_put(hdev); hci_dev_put(hdev);
} }
static inline char *host_bustostr(int bus)
{
switch (bus) {
case HCI_VIRTUAL:
return "VIRTUAL";
case HCI_USB:
return "USB";
case HCI_PCCARD:
return "PCCARD";
case HCI_UART:
return "UART";
case HCI_RS232:
return "RS232";
case HCI_PCI:
return "PCI";
case HCI_SDIO:
return "SDIO";
default:
return "UNKNOWN";
}
}
static inline char *host_typetostr(int type) static inline char *host_typetostr(int type)
{ {
switch (type) { switch (type) {
...@@ -184,13 +143,6 @@ static inline char *host_typetostr(int type) ...@@ -184,13 +143,6 @@ static inline char *host_typetostr(int type)
} }
} }
static ssize_t show_bus(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%s\n", host_bustostr(hdev->bus));
}
static ssize_t show_type(struct device *dev, static ssize_t show_type(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
...@@ -212,14 +164,6 @@ static ssize_t show_name(struct device *dev, ...@@ -212,14 +164,6 @@ static ssize_t show_name(struct device *dev,
return sprintf(buf, "%s\n", name); return sprintf(buf, "%s\n", name);
} }
static ssize_t show_class(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "0x%.2x%.2x%.2x\n", hdev->dev_class[2],
hdev->dev_class[1], hdev->dev_class[0]);
}
static ssize_t show_address(struct device *dev, static ssize_t show_address(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
...@@ -227,150 +171,14 @@ static ssize_t show_address(struct device *dev, ...@@ -227,150 +171,14 @@ static ssize_t show_address(struct device *dev,
return sprintf(buf, "%pMR\n", &hdev->bdaddr); return sprintf(buf, "%pMR\n", &hdev->bdaddr);
} }
static ssize_t show_features(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "0x%02x%02x%02x%02x%02x%02x%02x%02x\n",
hdev->features[0][0], hdev->features[0][1],
hdev->features[0][2], hdev->features[0][3],
hdev->features[0][4], hdev->features[0][5],
hdev->features[0][6], hdev->features[0][7]);
}
static ssize_t show_manufacturer(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%d\n", hdev->manufacturer);
}
static ssize_t show_hci_version(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%d\n", hdev->hci_ver);
}
static ssize_t show_hci_revision(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%d\n", hdev->hci_rev);
}
static ssize_t show_idle_timeout(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%d\n", hdev->idle_timeout);
}
static ssize_t store_idle_timeout(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct hci_dev *hdev = to_hci_dev(dev);
unsigned int val;
int rv;
rv = kstrtouint(buf, 0, &val);
if (rv < 0)
return rv;
if (val != 0 && (val < 500 || val > 3600000))
return -EINVAL;
hdev->idle_timeout = val;
return count;
}
static ssize_t show_sniff_max_interval(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%d\n", hdev->sniff_max_interval);
}
static ssize_t store_sniff_max_interval(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct hci_dev *hdev = to_hci_dev(dev);
u16 val;
int rv;
rv = kstrtou16(buf, 0, &val);
if (rv < 0)
return rv;
if (val == 0 || val % 2 || val < hdev->sniff_min_interval)
return -EINVAL;
hdev->sniff_max_interval = val;
return count;
}
static ssize_t show_sniff_min_interval(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct hci_dev *hdev = to_hci_dev(dev);
return sprintf(buf, "%d\n", hdev->sniff_min_interval);
}
static ssize_t store_sniff_min_interval(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct hci_dev *hdev = to_hci_dev(dev);
u16 val;
int rv;
rv = kstrtou16(buf, 0, &val);
if (rv < 0)
return rv;
if (val == 0 || val % 2 || val > hdev->sniff_max_interval)
return -EINVAL;
hdev->sniff_min_interval = val;
return count;
}
static DEVICE_ATTR(bus, S_IRUGO, show_bus, NULL);
static DEVICE_ATTR(type, S_IRUGO, show_type, NULL); static DEVICE_ATTR(type, S_IRUGO, show_type, NULL);
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
static DEVICE_ATTR(class, S_IRUGO, show_class, NULL);
static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); static DEVICE_ATTR(address, S_IRUGO, show_address, NULL);
static DEVICE_ATTR(features, S_IRUGO, show_features, NULL);
static DEVICE_ATTR(manufacturer, S_IRUGO, show_manufacturer, NULL);
static DEVICE_ATTR(hci_version, S_IRUGO, show_hci_version, NULL);
static DEVICE_ATTR(hci_revision, S_IRUGO, show_hci_revision, NULL);
static DEVICE_ATTR(idle_timeout, S_IRUGO | S_IWUSR,
show_idle_timeout, store_idle_timeout);
static DEVICE_ATTR(sniff_max_interval, S_IRUGO | S_IWUSR,
show_sniff_max_interval, store_sniff_max_interval);
static DEVICE_ATTR(sniff_min_interval, S_IRUGO | S_IWUSR,
show_sniff_min_interval, store_sniff_min_interval);
static struct attribute *bt_host_attrs[] = { static struct attribute *bt_host_attrs[] = {
&dev_attr_bus.attr,
&dev_attr_type.attr, &dev_attr_type.attr,
&dev_attr_name.attr, &dev_attr_name.attr,
&dev_attr_class.attr,
&dev_attr_address.attr, &dev_attr_address.attr,
&dev_attr_features.attr,
&dev_attr_manufacturer.attr,
&dev_attr_hci_version.attr,
&dev_attr_hci_revision.attr,
&dev_attr_idle_timeout.attr,
&dev_attr_sniff_max_interval.attr,
&dev_attr_sniff_min_interval.attr,
NULL NULL
}; };
...@@ -396,141 +204,6 @@ static struct device_type bt_host = { ...@@ -396,141 +204,6 @@ static struct device_type bt_host = {
.release = bt_host_release, .release = bt_host_release,
}; };
static int inquiry_cache_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
struct discovery_state *cache = &hdev->discovery;
struct inquiry_entry *e;
hci_dev_lock(hdev);
list_for_each_entry(e, &cache->all, all) {
struct inquiry_data *data = &e->data;
seq_printf(f, "%pMR %d %d %d 0x%.2x%.2x%.2x 0x%.4x %d %d %u\n",
&data->bdaddr,
data->pscan_rep_mode, data->pscan_period_mode,
data->pscan_mode, data->dev_class[2],
data->dev_class[1], data->dev_class[0],
__le16_to_cpu(data->clock_offset),
data->rssi, data->ssp_mode, e->timestamp);
}
hci_dev_unlock(hdev);
return 0;
}
static int inquiry_cache_open(struct inode *inode, struct file *file)
{
return single_open(file, inquiry_cache_show, inode->i_private);
}
static const struct file_operations inquiry_cache_fops = {
.open = inquiry_cache_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int blacklist_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
struct bdaddr_list *b;
hci_dev_lock(hdev);
list_for_each_entry(b, &hdev->blacklist, list)
seq_printf(f, "%pMR\n", &b->bdaddr);
hci_dev_unlock(hdev);
return 0;
}
static int blacklist_open(struct inode *inode, struct file *file)
{
return single_open(file, blacklist_show, inode->i_private);
}
static const struct file_operations blacklist_fops = {
.open = blacklist_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static void print_bt_uuid(struct seq_file *f, u8 *uuid)
{
u32 data0, data5;
u16 data1, data2, data3, data4;
data5 = get_unaligned_le32(uuid);
data4 = get_unaligned_le16(uuid + 4);
data3 = get_unaligned_le16(uuid + 6);
data2 = get_unaligned_le16(uuid + 8);
data1 = get_unaligned_le16(uuid + 10);
data0 = get_unaligned_le32(uuid + 12);
seq_printf(f, "%.8x-%.4x-%.4x-%.4x-%.4x%.8x\n",
data0, data1, data2, data3, data4, data5);
}
static int uuids_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
struct bt_uuid *uuid;
hci_dev_lock(hdev);
list_for_each_entry(uuid, &hdev->uuids, list)
print_bt_uuid(f, uuid->uuid);
hci_dev_unlock(hdev);
return 0;
}
static int uuids_open(struct inode *inode, struct file *file)
{
return single_open(file, uuids_show, inode->i_private);
}
static const struct file_operations uuids_fops = {
.open = uuids_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static int auto_accept_delay_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
hdev->auto_accept_delay = val;
hci_dev_unlock(hdev);
return 0;
}
static int auto_accept_delay_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->auto_accept_delay;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get,
auto_accept_delay_set, "%llu\n");
void hci_init_sysfs(struct hci_dev *hdev) void hci_init_sysfs(struct hci_dev *hdev)
{ {
struct device *dev = &hdev->dev; struct device *dev = &hdev->dev;
...@@ -542,52 +215,8 @@ void hci_init_sysfs(struct hci_dev *hdev) ...@@ -542,52 +215,8 @@ void hci_init_sysfs(struct hci_dev *hdev)
device_initialize(dev); device_initialize(dev);
} }
int hci_add_sysfs(struct hci_dev *hdev)
{
struct device *dev = &hdev->dev;
int err;
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
dev_set_name(dev, "%s", hdev->name);
err = device_add(dev);
if (err < 0)
return err;
if (!bt_debugfs)
return 0;
hdev->debugfs = debugfs_create_dir(hdev->name, bt_debugfs);
if (!hdev->debugfs)
return 0;
debugfs_create_file("inquiry_cache", 0444, hdev->debugfs,
hdev, &inquiry_cache_fops);
debugfs_create_file("blacklist", 0444, hdev->debugfs,
hdev, &blacklist_fops);
debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
debugfs_create_file("auto_accept_delay", 0444, hdev->debugfs, hdev,
&auto_accept_delay_fops);
return 0;
}
void hci_del_sysfs(struct hci_dev *hdev)
{
BT_DBG("%p name %s bus %d", hdev, hdev->name, hdev->bus);
debugfs_remove_recursive(hdev->debugfs);
device_del(&hdev->dev);
}
int __init bt_sysfs_init(void) int __init bt_sysfs_init(void)
{ {
bt_debugfs = debugfs_create_dir("bluetooth", NULL);
bt_class = class_create(THIS_MODULE, "bluetooth"); bt_class = class_create(THIS_MODULE, "bluetooth");
return PTR_ERR_OR_ZERO(bt_class); return PTR_ERR_OR_ZERO(bt_class);
...@@ -596,6 +225,4 @@ int __init bt_sysfs_init(void) ...@@ -596,6 +225,4 @@ int __init bt_sysfs_init(void)
void bt_sysfs_cleanup(void) void bt_sysfs_cleanup(void)
{ {
class_destroy(bt_class); class_destroy(bt_class);
debugfs_remove_recursive(bt_debugfs);
} }
...@@ -223,38 +223,25 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn) ...@@ -223,38 +223,25 @@ static u16 l2cap_alloc_cid(struct l2cap_conn *conn)
return 0; return 0;
} }
static void __l2cap_state_change(struct l2cap_chan *chan, int state) static void l2cap_state_change(struct l2cap_chan *chan, int state)
{ {
BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state), BT_DBG("chan %p %s -> %s", chan, state_to_string(chan->state),
state_to_string(state)); state_to_string(state));
chan->state = state; chan->state = state;
chan->ops->state_change(chan, state); chan->ops->state_change(chan, state, 0);
} }
static void l2cap_state_change(struct l2cap_chan *chan, int state) static inline void l2cap_state_change_and_error(struct l2cap_chan *chan,
int state, int err)
{ {
struct sock *sk = chan->sk; chan->state = state;
chan->ops->state_change(chan, chan->state, err);
lock_sock(sk);
__l2cap_state_change(chan, state);
release_sock(sk);
}
static inline void __l2cap_chan_set_err(struct l2cap_chan *chan, int err)
{
struct sock *sk = chan->sk;
sk->sk_err = err;
} }
static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err) static inline void l2cap_chan_set_err(struct l2cap_chan *chan, int err)
{ {
struct sock *sk = chan->sk; chan->ops->state_change(chan, chan->state, err);
lock_sock(sk);
__l2cap_chan_set_err(chan, err);
release_sock(sk);
} }
static void __set_retrans_timer(struct l2cap_chan *chan) static void __set_retrans_timer(struct l2cap_chan *chan)
...@@ -645,8 +632,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) ...@@ -645,8 +632,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason)
case BT_CONFIG: case BT_CONFIG:
if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED &&
conn->hcon->type == ACL_LINK) { conn->hcon->type == ACL_LINK) {
struct sock *sk = chan->sk; __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
__set_chan_timer(chan, sk->sk_sndtimeo);
l2cap_send_disconn_req(chan, reason); l2cap_send_disconn_req(chan, reason);
} else } else
l2cap_chan_del(chan, reason); l2cap_chan_del(chan, reason);
...@@ -1230,7 +1216,6 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask) ...@@ -1230,7 +1216,6 @@ static inline int l2cap_mode_supported(__u8 mode, __u32 feat_mask)
static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
{ {
struct sock *sk = chan->sk;
struct l2cap_conn *conn = chan->conn; struct l2cap_conn *conn = chan->conn;
struct l2cap_disconn_req req; struct l2cap_disconn_req req;
...@@ -1253,10 +1238,7 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) ...@@ -1253,10 +1238,7 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err)
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ, l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_DISCONN_REQ,
sizeof(req), &req); sizeof(req), &req);
lock_sock(sk); l2cap_state_change_and_error(chan, BT_DISCONN, err);
__l2cap_state_change(chan, BT_DISCONN);
__l2cap_chan_set_err(chan, err);
release_sock(sk);
} }
/* ---- L2CAP connections ---- */ /* ---- L2CAP connections ---- */
...@@ -1300,20 +1282,16 @@ static void l2cap_conn_start(struct l2cap_conn *conn) ...@@ -1300,20 +1282,16 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
rsp.dcid = cpu_to_le16(chan->scid); rsp.dcid = cpu_to_le16(chan->scid);
if (l2cap_chan_check_security(chan)) { if (l2cap_chan_check_security(chan)) {
struct sock *sk = chan->sk;
lock_sock(sk);
if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND);
chan->ops->defer(chan); chan->ops->defer(chan);
} else { } else {
__l2cap_state_change(chan, BT_CONFIG); l2cap_state_change(chan, BT_CONFIG);
rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS);
rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO);
} }
release_sock(sk);
} else { } else {
rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND);
rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND); rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND);
...@@ -1383,14 +1361,15 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, ...@@ -1383,14 +1361,15 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid,
static void l2cap_le_conn_ready(struct l2cap_conn *conn) static void l2cap_le_conn_ready(struct l2cap_conn *conn)
{ {
struct sock *parent; struct hci_conn *hcon = conn->hcon;
struct l2cap_chan *chan, *pchan; struct l2cap_chan *chan, *pchan;
u8 dst_type;
BT_DBG(""); BT_DBG("");
/* Check if we have socket listening on cid */ /* Check if we have socket listening on cid */
pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT,
&conn->hcon->src, &conn->hcon->dst); &hcon->src, &hcon->dst);
if (!pchan) if (!pchan)
return; return;
...@@ -1398,9 +1377,13 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) ...@@ -1398,9 +1377,13 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT)) if (__l2cap_get_chan_by_dcid(conn, L2CAP_CID_ATT))
return; return;
parent = pchan->sk; dst_type = bdaddr_type(hcon, hcon->dst_type);
/* If device is blocked, do not create a channel for it */
if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type))
return;
lock_sock(parent); l2cap_chan_lock(pchan);
chan = pchan->ops->new_connection(pchan); chan = pchan->ops->new_connection(pchan);
if (!chan) if (!chan)
...@@ -1408,15 +1391,15 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) ...@@ -1408,15 +1391,15 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn)
chan->dcid = L2CAP_CID_ATT; chan->dcid = L2CAP_CID_ATT;
bacpy(&chan->src, &conn->hcon->src); bacpy(&chan->src, &hcon->src);
bacpy(&chan->dst, &conn->hcon->dst); bacpy(&chan->dst, &hcon->dst);
chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); chan->src_type = bdaddr_type(hcon, hcon->src_type);
chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); chan->dst_type = dst_type;
__l2cap_chan_add(conn, chan); __l2cap_chan_add(conn, chan);
clean: clean:
release_sock(parent); l2cap_chan_unlock(pchan);
} }
static void l2cap_conn_ready(struct l2cap_conn *conn) static void l2cap_conn_ready(struct l2cap_conn *conn)
...@@ -1451,12 +1434,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) ...@@ -1451,12 +1434,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
l2cap_chan_ready(chan); l2cap_chan_ready(chan);
} else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
struct sock *sk = chan->sk; l2cap_chan_ready(chan);
__clear_chan_timer(chan);
lock_sock(sk);
__l2cap_state_change(chan, BT_CONNECTED);
sk->sk_state_change(sk);
release_sock(sk);
} else if (chan->state == BT_CONNECT) { } else if (chan->state == BT_CONNECT) {
l2cap_do_start(chan); l2cap_do_start(chan);
...@@ -1764,7 +1742,6 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, ...@@ -1764,7 +1742,6 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm,
int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
bdaddr_t *dst, u8 dst_type) bdaddr_t *dst, u8 dst_type)
{ {
struct sock *sk = chan->sk;
struct l2cap_conn *conn; struct l2cap_conn *conn;
struct hci_conn *hcon; struct hci_conn *hcon;
struct hci_dev *hdev; struct hci_dev *hdev;
...@@ -1876,7 +1853,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, ...@@ -1876,7 +1853,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
hci_conn_drop(hcon); hci_conn_drop(hcon);
l2cap_state_change(chan, BT_CONNECT); l2cap_state_change(chan, BT_CONNECT);
__set_chan_timer(chan, sk->sk_sndtimeo); __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
if (hcon->state == BT_CONNECTED) { if (hcon->state == BT_CONNECTED) {
if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
...@@ -1896,38 +1873,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, ...@@ -1896,38 +1873,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,
return err; return err;
} }
int __l2cap_wait_ack(struct sock *sk)
{
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
DECLARE_WAITQUEUE(wait, current);
int err = 0;
int timeo = HZ/5;
add_wait_queue(sk_sleep(sk), &wait);
set_current_state(TASK_INTERRUPTIBLE);
while (chan->unacked_frames > 0 && chan->conn) {
if (!timeo)
timeo = HZ/5;
if (signal_pending(current)) {
err = sock_intr_errno(timeo);
break;
}
release_sock(sk);
timeo = schedule_timeout(timeo);
lock_sock(sk);
set_current_state(TASK_INTERRUPTIBLE);
err = sock_error(sk);
if (err)
break;
}
set_current_state(TASK_RUNNING);
remove_wait_queue(sk_sleep(sk), &wait);
return err;
}
static void l2cap_monitor_timeout(struct work_struct *work) static void l2cap_monitor_timeout(struct work_struct *work)
{ {
struct l2cap_chan *chan = container_of(work, struct l2cap_chan, struct l2cap_chan *chan = container_of(work, struct l2cap_chan,
...@@ -2868,17 +2813,16 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -2868,17 +2813,16 @@ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb)
mutex_lock(&conn->chan_lock); mutex_lock(&conn->chan_lock);
list_for_each_entry(chan, &conn->chan_l, list) { list_for_each_entry(chan, &conn->chan_l, list) {
struct sock *sk = chan->sk;
if (chan->chan_type != L2CAP_CHAN_RAW) if (chan->chan_type != L2CAP_CHAN_RAW)
continue; continue;
/* Don't send frame to the socket it came from */ /* Don't send frame to the channel it came from */
if (skb->sk == sk) if (bt_cb(skb)->chan == chan)
continue; continue;
nskb = skb_clone(skb, GFP_KERNEL); nskb = skb_clone(skb, GFP_KERNEL);
if (!nskb) if (!nskb)
continue; continue;
if (chan->ops->recv(chan, nskb)) if (chan->ops->recv(chan, nskb))
kfree_skb(nskb); kfree_skb(nskb);
} }
...@@ -3757,7 +3701,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, ...@@ -3757,7 +3701,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; struct l2cap_conn_req *req = (struct l2cap_conn_req *) data;
struct l2cap_conn_rsp rsp; struct l2cap_conn_rsp rsp;
struct l2cap_chan *chan = NULL, *pchan; struct l2cap_chan *chan = NULL, *pchan;
struct sock *parent, *sk = NULL;
int result, status = L2CAP_CS_NO_INFO; int result, status = L2CAP_CS_NO_INFO;
u16 dcid = 0, scid = __le16_to_cpu(req->scid); u16 dcid = 0, scid = __le16_to_cpu(req->scid);
...@@ -3773,10 +3716,8 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, ...@@ -3773,10 +3716,8 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
goto sendresp; goto sendresp;
} }
parent = pchan->sk;
mutex_lock(&conn->chan_lock); mutex_lock(&conn->chan_lock);
lock_sock(parent); l2cap_chan_lock(pchan);
/* Check if the ACL is secure enough (if not SDP) */ /* Check if the ACL is secure enough (if not SDP) */
if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) &&
...@@ -3796,8 +3737,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, ...@@ -3796,8 +3737,6 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
if (!chan) if (!chan)
goto response; goto response;
sk = chan->sk;
/* For certain devices (ex: HID mouse), support for authentication, /* For certain devices (ex: HID mouse), support for authentication,
* pairing and bonding is optional. For such devices, inorder to avoid * pairing and bonding is optional. For such devices, inorder to avoid
* the ACL alive for too long after L2CAP disconnection, reset the ACL * the ACL alive for too long after L2CAP disconnection, reset the ACL
...@@ -3817,14 +3756,14 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, ...@@ -3817,14 +3756,14 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
dcid = chan->scid; dcid = chan->scid;
__set_chan_timer(chan, sk->sk_sndtimeo); __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
chan->ident = cmd->ident; chan->ident = cmd->ident;
if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) {
if (l2cap_chan_check_security(chan)) { if (l2cap_chan_check_security(chan)) {
if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
__l2cap_state_change(chan, BT_CONNECT2); l2cap_state_change(chan, BT_CONNECT2);
result = L2CAP_CR_PEND; result = L2CAP_CR_PEND;
status = L2CAP_CS_AUTHOR_PEND; status = L2CAP_CS_AUTHOR_PEND;
chan->ops->defer(chan); chan->ops->defer(chan);
...@@ -3834,27 +3773,27 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, ...@@ -3834,27 +3773,27 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
* physical link is up. * physical link is up.
*/ */
if (amp_id == AMP_ID_BREDR) { if (amp_id == AMP_ID_BREDR) {
__l2cap_state_change(chan, BT_CONFIG); l2cap_state_change(chan, BT_CONFIG);
result = L2CAP_CR_SUCCESS; result = L2CAP_CR_SUCCESS;
} else { } else {
__l2cap_state_change(chan, BT_CONNECT2); l2cap_state_change(chan, BT_CONNECT2);
result = L2CAP_CR_PEND; result = L2CAP_CR_PEND;
} }
status = L2CAP_CS_NO_INFO; status = L2CAP_CS_NO_INFO;
} }
} else { } else {
__l2cap_state_change(chan, BT_CONNECT2); l2cap_state_change(chan, BT_CONNECT2);
result = L2CAP_CR_PEND; result = L2CAP_CR_PEND;
status = L2CAP_CS_AUTHEN_PEND; status = L2CAP_CS_AUTHEN_PEND;
} }
} else { } else {
__l2cap_state_change(chan, BT_CONNECT2); l2cap_state_change(chan, BT_CONNECT2);
result = L2CAP_CR_PEND; result = L2CAP_CR_PEND;
status = L2CAP_CS_NO_INFO; status = L2CAP_CS_NO_INFO;
} }
response: response:
release_sock(parent); l2cap_chan_unlock(pchan);
mutex_unlock(&conn->chan_lock); mutex_unlock(&conn->chan_lock);
sendresp: sendresp:
...@@ -4010,6 +3949,18 @@ static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data, ...@@ -4010,6 +3949,18 @@ static void l2cap_send_efs_conf_rsp(struct l2cap_chan *chan, void *data,
L2CAP_CONF_SUCCESS, flags), data); L2CAP_CONF_SUCCESS, flags), data);
} }
static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident,
u16 scid, u16 dcid)
{
struct l2cap_cmd_rej_cid rej;
rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
rej.scid = __cpu_to_le16(scid);
rej.dcid = __cpu_to_le16(dcid);
l2cap_send_cmd(conn, ident, L2CAP_COMMAND_REJ, sizeof(rej), &rej);
}
static inline int l2cap_config_req(struct l2cap_conn *conn, static inline int l2cap_config_req(struct l2cap_conn *conn,
struct l2cap_cmd_hdr *cmd, u16 cmd_len, struct l2cap_cmd_hdr *cmd, u16 cmd_len,
u8 *data) u8 *data)
...@@ -4029,18 +3980,14 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, ...@@ -4029,18 +3980,14 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags); BT_DBG("dcid 0x%4.4x flags 0x%2.2x", dcid, flags);
chan = l2cap_get_chan_by_scid(conn, dcid); chan = l2cap_get_chan_by_scid(conn, dcid);
if (!chan) if (!chan) {
return -EBADSLT; cmd_reject_invalid_cid(conn, cmd->ident, dcid, 0);
return 0;
}
if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) { if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2) {
struct l2cap_cmd_rej_cid rej; cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
chan->dcid);
rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
rej.scid = cpu_to_le16(chan->scid);
rej.dcid = cpu_to_le16(chan->dcid);
l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
sizeof(rej), &rej);
goto unlock; goto unlock;
} }
...@@ -4243,7 +4190,6 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, ...@@ -4243,7 +4190,6 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
struct l2cap_disconn_rsp rsp; struct l2cap_disconn_rsp rsp;
u16 dcid, scid; u16 dcid, scid;
struct l2cap_chan *chan; struct l2cap_chan *chan;
struct sock *sk;
if (cmd_len != sizeof(*req)) if (cmd_len != sizeof(*req))
return -EPROTO; return -EPROTO;
...@@ -4258,20 +4204,17 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, ...@@ -4258,20 +4204,17 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn,
chan = __l2cap_get_chan_by_scid(conn, dcid); chan = __l2cap_get_chan_by_scid(conn, dcid);
if (!chan) { if (!chan) {
mutex_unlock(&conn->chan_lock); mutex_unlock(&conn->chan_lock);
return -EBADSLT; cmd_reject_invalid_cid(conn, cmd->ident, dcid, scid);
return 0;
} }
l2cap_chan_lock(chan); l2cap_chan_lock(chan);
sk = chan->sk;
rsp.dcid = cpu_to_le16(chan->scid); rsp.dcid = cpu_to_le16(chan->scid);
rsp.scid = cpu_to_le16(chan->dcid); rsp.scid = cpu_to_le16(chan->dcid);
l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp);
lock_sock(sk); chan->ops->set_shutdown(chan);
sk->sk_shutdown = SHUTDOWN_MASK;
release_sock(sk);
l2cap_chan_hold(chan); l2cap_chan_hold(chan);
l2cap_chan_del(chan, ECONNRESET); l2cap_chan_del(chan, ECONNRESET);
...@@ -4491,7 +4434,9 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn, ...@@ -4491,7 +4434,9 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn,
&conn->hcon->dst); &conn->hcon->dst);
if (!hs_hcon) { if (!hs_hcon) {
hci_dev_put(hdev); hci_dev_put(hdev);
return -EBADSLT; cmd_reject_invalid_cid(conn, cmd->ident, chan->scid,
chan->dcid);
return 0;
} }
BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon); BT_DBG("mgr %p bredr_chan %p hs_hcon %p", mgr, chan, hs_hcon);
...@@ -4769,7 +4714,7 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result, ...@@ -4769,7 +4714,7 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result,
sizeof(rsp), &rsp); sizeof(rsp), &rsp);
if (result == L2CAP_CR_SUCCESS) { if (result == L2CAP_CR_SUCCESS) {
__l2cap_state_change(chan, BT_CONFIG); l2cap_state_change(chan, BT_CONFIG);
set_bit(CONF_REQ_SENT, &chan->conf_state); set_bit(CONF_REQ_SENT, &chan->conf_state);
l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn), l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
L2CAP_CONF_REQ, L2CAP_CONF_REQ,
...@@ -5347,20 +5292,6 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, ...@@ -5347,20 +5292,6 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn,
} }
} }
static __le16 l2cap_err_to_reason(int err)
{
switch (err) {
case -EBADSLT:
return __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID);
case -EMSGSIZE:
return __constant_cpu_to_le16(L2CAP_REJ_MTU_EXCEEDED);
case -EINVAL:
case -EPROTO:
default:
return __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
}
}
static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
struct sk_buff *skb) struct sk_buff *skb)
{ {
...@@ -5393,7 +5324,7 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, ...@@ -5393,7 +5324,7 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn,
BT_ERR("Wrong link type (%d)", err); BT_ERR("Wrong link type (%d)", err);
rej.reason = l2cap_err_to_reason(err); rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ,
sizeof(rej), &rej); sizeof(rej), &rej);
} }
...@@ -5438,7 +5369,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, ...@@ -5438,7 +5369,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn,
BT_ERR("Wrong link type (%d)", err); BT_ERR("Wrong link type (%d)", err);
rej.reason = l2cap_err_to_reason(err); rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD);
l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ,
sizeof(rej), &rej); sizeof(rej), &rej);
} }
...@@ -6446,8 +6377,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, ...@@ -6446,8 +6377,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
if (hcon->type != ACL_LINK) if (hcon->type != ACL_LINK)
goto drop; goto drop;
chan = l2cap_global_chan_by_psm(0, psm, &conn->hcon->src, chan = l2cap_global_chan_by_psm(0, psm, &hcon->src, &hcon->dst);
&conn->hcon->dst);
if (!chan) if (!chan)
goto drop; goto drop;
...@@ -6460,7 +6390,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, ...@@ -6460,7 +6390,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm,
goto drop; goto drop;
/* Store remote BD_ADDR and PSM for msg_name */ /* Store remote BD_ADDR and PSM for msg_name */
bacpy(&bt_cb(skb)->bdaddr, &conn->hcon->dst); bacpy(&bt_cb(skb)->bdaddr, &hcon->dst);
bt_cb(skb)->psm = psm; bt_cb(skb)->psm = psm;
if (!chan->ops->recv(chan, skb)) if (!chan->ops->recv(chan, skb))
...@@ -6480,12 +6410,15 @@ static void l2cap_att_channel(struct l2cap_conn *conn, ...@@ -6480,12 +6410,15 @@ static void l2cap_att_channel(struct l2cap_conn *conn,
goto drop; goto drop;
chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT, chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT,
&conn->hcon->src, &conn->hcon->dst); &hcon->src, &hcon->dst);
if (!chan) if (!chan)
goto drop; goto drop;
BT_DBG("chan %p, len %d", chan, skb->len); BT_DBG("chan %p, len %d", chan, skb->len);
if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, hcon->dst_type))
goto drop;
if (chan->imtu < skb->len) if (chan->imtu < skb->len)
goto drop; goto drop;
...@@ -6682,31 +6615,26 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) ...@@ -6682,31 +6615,26 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
__set_chan_timer(chan, L2CAP_DISC_TIMEOUT); __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
} }
} else if (chan->state == BT_CONNECT2) { } else if (chan->state == BT_CONNECT2) {
struct sock *sk = chan->sk;
struct l2cap_conn_rsp rsp; struct l2cap_conn_rsp rsp;
__u16 res, stat; __u16 res, stat;
lock_sock(sk);
if (!status) { if (!status) {
if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) {
res = L2CAP_CR_PEND; res = L2CAP_CR_PEND;
stat = L2CAP_CS_AUTHOR_PEND; stat = L2CAP_CS_AUTHOR_PEND;
chan->ops->defer(chan); chan->ops->defer(chan);
} else { } else {
__l2cap_state_change(chan, BT_CONFIG); l2cap_state_change(chan, BT_CONFIG);
res = L2CAP_CR_SUCCESS; res = L2CAP_CR_SUCCESS;
stat = L2CAP_CS_NO_INFO; stat = L2CAP_CS_NO_INFO;
} }
} else { } else {
__l2cap_state_change(chan, BT_DISCONN); l2cap_state_change(chan, BT_DISCONN);
__set_chan_timer(chan, L2CAP_DISC_TIMEOUT); __set_chan_timer(chan, L2CAP_DISC_TIMEOUT);
res = L2CAP_CR_SEC_BLOCK; res = L2CAP_CR_SEC_BLOCK;
stat = L2CAP_CS_NO_INFO; stat = L2CAP_CS_NO_INFO;
} }
release_sock(sk);
rsp.scid = cpu_to_le16(chan->dcid); rsp.scid = cpu_to_le16(chan->dcid);
rsp.dcid = cpu_to_le16(chan->scid); rsp.dcid = cpu_to_le16(chan->scid);
rsp.result = cpu_to_le16(res); rsp.result = cpu_to_le16(res);
...@@ -6880,12 +6808,11 @@ int __init l2cap_init(void) ...@@ -6880,12 +6808,11 @@ int __init l2cap_init(void)
if (err < 0) if (err < 0)
return err; return err;
if (bt_debugfs) { if (IS_ERR_OR_NULL(bt_debugfs))
l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs, return 0;
NULL, &l2cap_debugfs_fops);
if (!l2cap_debugfs) l2cap_debugfs = debugfs_create_file("l2cap", 0444, bt_debugfs,
BT_ERR("Failed to create L2CAP debug file"); NULL, &l2cap_debugfs_fops);
}
return 0; return 0;
} }
......
...@@ -72,6 +72,15 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) ...@@ -72,6 +72,15 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) if (!bdaddr_type_is_valid(la.l2_bdaddr_type))
return -EINVAL; return -EINVAL;
if (bdaddr_type_is_le(la.l2_bdaddr_type)) {
/* Connection oriented channels are not supported on LE */
if (la.l2_psm)
return -EINVAL;
/* We only allow ATT user space socket */
if (la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
return -EINVAL;
}
lock_sock(sk); lock_sock(sk);
if (sk->sk_state != BT_OPEN) { if (sk->sk_state != BT_OPEN) {
...@@ -150,12 +159,44 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, ...@@ -150,12 +159,44 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr,
if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) if (!bdaddr_type_is_valid(la.l2_bdaddr_type))
return -EINVAL; return -EINVAL;
if (chan->src_type == BDADDR_BREDR && la.l2_bdaddr_type != BDADDR_BREDR) /* Check that the socket wasn't bound to something that
return -EINVAL; * conflicts with the address given to connect(). If chan->src
* is BDADDR_ANY it means bind() was never used, in which case
* chan->src_type and la.l2_bdaddr_type do not need to match.
*/
if (chan->src_type == BDADDR_BREDR && bacmp(&chan->src, BDADDR_ANY) &&
bdaddr_type_is_le(la.l2_bdaddr_type)) {
/* Old user space versions will try to incorrectly bind
* the ATT socket using BDADDR_BREDR. We need to accept
* this and fix up the source address type only when
* both the source CID and destination CID indicate
* ATT. Anything else is an invalid combination.
*/
if (chan->scid != L2CAP_CID_ATT ||
la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
return -EINVAL;
/* We don't have the hdev available here to make a
* better decision on random vs public, but since all
* user space versions that exhibit this issue anyway do
* not support random local addresses assuming public
* here is good enough.
*/
chan->src_type = BDADDR_LE_PUBLIC;
}
if (chan->src_type != BDADDR_BREDR && la.l2_bdaddr_type == BDADDR_BREDR) if (chan->src_type != BDADDR_BREDR && la.l2_bdaddr_type == BDADDR_BREDR)
return -EINVAL; return -EINVAL;
if (bdaddr_type_is_le(la.l2_bdaddr_type)) {
/* Connection oriented channels are not supported on LE */
if (la.l2_psm)
return -EINVAL;
/* We only allow ATT user space socket */
if (la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT))
return -EINVAL;
}
err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid), err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid),
&la.l2_bdaddr, la.l2_bdaddr_type); &la.l2_bdaddr, la.l2_bdaddr_type);
if (err) if (err)
...@@ -879,6 +920,38 @@ static void l2cap_sock_kill(struct sock *sk) ...@@ -879,6 +920,38 @@ static void l2cap_sock_kill(struct sock *sk)
sock_put(sk); sock_put(sk);
} }
static int __l2cap_wait_ack(struct sock *sk)
{
struct l2cap_chan *chan = l2cap_pi(sk)->chan;
DECLARE_WAITQUEUE(wait, current);
int err = 0;
int timeo = HZ/5;
add_wait_queue(sk_sleep(sk), &wait);
set_current_state(TASK_INTERRUPTIBLE);
while (chan->unacked_frames > 0 && chan->conn) {
if (!timeo)
timeo = HZ/5;
if (signal_pending(current)) {
err = sock_intr_errno(timeo);
break;
}
release_sock(sk);
timeo = schedule_timeout(timeo);
lock_sock(sk);
set_current_state(TASK_INTERRUPTIBLE);
err = sock_error(sk);
if (err)
break;
}
set_current_state(TASK_RUNNING);
remove_wait_queue(sk_sleep(sk), &wait);
return err;
}
static int l2cap_sock_shutdown(struct socket *sock, int how) static int l2cap_sock_shutdown(struct socket *sock, int how)
{ {
struct sock *sk = sock->sk; struct sock *sk = sock->sk;
...@@ -969,6 +1042,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) ...@@ -969,6 +1042,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
{ {
struct sock *sk, *parent = chan->data; struct sock *sk, *parent = chan->data;
lock_sock(parent);
/* Check for backlog size */ /* Check for backlog size */
if (sk_acceptq_is_full(parent)) { if (sk_acceptq_is_full(parent)) {
BT_DBG("backlog full %d", parent->sk_ack_backlog); BT_DBG("backlog full %d", parent->sk_ack_backlog);
...@@ -986,6 +1061,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) ...@@ -986,6 +1061,8 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
bt_accept_enqueue(parent, sk); bt_accept_enqueue(parent, sk);
release_sock(parent);
return l2cap_pi(sk)->chan; return l2cap_pi(sk)->chan;
} }
...@@ -1072,26 +1149,33 @@ static void l2cap_sock_teardown_cb(struct l2cap_chan *chan, int err) ...@@ -1072,26 +1149,33 @@ static void l2cap_sock_teardown_cb(struct l2cap_chan *chan, int err)
release_sock(sk); release_sock(sk);
} }
static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state) static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state,
int err)
{ {
struct sock *sk = chan->data; struct sock *sk = chan->data;
sk->sk_state = state; sk->sk_state = state;
if (err)
sk->sk_err = err;
} }
static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan,
unsigned long len, int nb) unsigned long len, int nb)
{ {
struct sock *sk = chan->data;
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
l2cap_chan_unlock(chan); l2cap_chan_unlock(chan);
skb = bt_skb_send_alloc(chan->sk, len, nb, &err); skb = bt_skb_send_alloc(sk, len, nb, &err);
l2cap_chan_lock(chan); l2cap_chan_lock(chan);
if (!skb) if (!skb)
return ERR_PTR(err); return ERR_PTR(err);
bt_cb(skb)->chan = chan;
return skb; return skb;
} }
...@@ -1117,11 +1201,15 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan) ...@@ -1117,11 +1201,15 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan)
static void l2cap_sock_defer_cb(struct l2cap_chan *chan) static void l2cap_sock_defer_cb(struct l2cap_chan *chan)
{ {
struct sock *sk = chan->data; struct sock *parent, *sk = chan->data;
struct sock *parent = bt_sk(sk)->parent;
lock_sock(sk);
parent = bt_sk(sk)->parent;
if (parent) if (parent)
parent->sk_data_ready(parent, 0); parent->sk_data_ready(parent, 0);
release_sock(sk);
} }
static void l2cap_sock_resume_cb(struct l2cap_chan *chan) static void l2cap_sock_resume_cb(struct l2cap_chan *chan)
...@@ -1132,6 +1220,22 @@ static void l2cap_sock_resume_cb(struct l2cap_chan *chan) ...@@ -1132,6 +1220,22 @@ static void l2cap_sock_resume_cb(struct l2cap_chan *chan)
sk->sk_state_change(sk); sk->sk_state_change(sk);
} }
static void l2cap_sock_set_shutdown_cb(struct l2cap_chan *chan)
{
struct sock *sk = chan->data;
lock_sock(sk);
sk->sk_shutdown = SHUTDOWN_MASK;
release_sock(sk);
}
static long l2cap_sock_get_sndtimeo_cb(struct l2cap_chan *chan)
{
struct sock *sk = chan->data;
return sk->sk_sndtimeo;
}
static struct l2cap_ops l2cap_chan_ops = { static struct l2cap_ops l2cap_chan_ops = {
.name = "L2CAP Socket Interface", .name = "L2CAP Socket Interface",
.new_connection = l2cap_sock_new_connection_cb, .new_connection = l2cap_sock_new_connection_cb,
...@@ -1142,6 +1246,8 @@ static struct l2cap_ops l2cap_chan_ops = { ...@@ -1142,6 +1246,8 @@ static struct l2cap_ops l2cap_chan_ops = {
.ready = l2cap_sock_ready_cb, .ready = l2cap_sock_ready_cb,
.defer = l2cap_sock_defer_cb, .defer = l2cap_sock_defer_cb,
.resume = l2cap_sock_resume_cb, .resume = l2cap_sock_resume_cb,
.set_shutdown = l2cap_sock_set_shutdown_cb,
.get_sndtimeo = l2cap_sock_get_sndtimeo_cb,
.alloc_skb = l2cap_sock_alloc_skb_cb, .alloc_skb = l2cap_sock_alloc_skb_cb,
}; };
...@@ -1268,8 +1374,6 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, ...@@ -1268,8 +1374,6 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
l2cap_chan_hold(chan); l2cap_chan_hold(chan);
chan->sk = sk;
l2cap_pi(sk)->chan = chan; l2cap_pi(sk)->chan = chan;
return sk; return sk;
......
...@@ -536,6 +536,156 @@ static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len) ...@@ -536,6 +536,156 @@ static u8 *create_uuid128_list(struct hci_dev *hdev, u8 *data, ptrdiff_t len)
return ptr; return ptr;
} }
static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
{
struct pending_cmd *cmd;
list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
if (cmd->opcode == opcode)
return cmd;
}
return NULL;
}
static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr)
{
u8 ad_len = 0;
size_t name_len;
name_len = strlen(hdev->dev_name);
if (name_len > 0) {
size_t max_len = HCI_MAX_AD_LENGTH - ad_len - 2;
if (name_len > max_len) {
name_len = max_len;
ptr[1] = EIR_NAME_SHORT;
} else
ptr[1] = EIR_NAME_COMPLETE;
ptr[0] = name_len + 1;
memcpy(ptr + 2, hdev->dev_name, name_len);
ad_len += (name_len + 2);
ptr += (name_len + 2);
}
return ad_len;
}
static void update_scan_rsp_data(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
struct hci_cp_le_set_scan_rsp_data cp;
u8 len;
if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
return;
memset(&cp, 0, sizeof(cp));
len = create_scan_rsp_data(hdev, cp.data);
if (hdev->scan_rsp_data_len == len &&
memcmp(cp.data, hdev->scan_rsp_data, len) == 0)
return;
memcpy(hdev->scan_rsp_data, cp.data, sizeof(cp.data));
hdev->scan_rsp_data_len = len;
cp.length = len;
hci_req_add(req, HCI_OP_LE_SET_SCAN_RSP_DATA, sizeof(cp), &cp);
}
static u8 get_adv_discov_flags(struct hci_dev *hdev)
{
struct pending_cmd *cmd;
/* If there's a pending mgmt command the flags will not yet have
* their final values, so check for this first.
*/
cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
if (cmd) {
struct mgmt_mode *cp = cmd->param;
if (cp->val == 0x01)
return LE_AD_GENERAL;
else if (cp->val == 0x02)
return LE_AD_LIMITED;
} else {
if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
return LE_AD_LIMITED;
else if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
return LE_AD_GENERAL;
}
return 0;
}
static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr)
{
u8 ad_len = 0, flags = 0;
flags |= get_adv_discov_flags(hdev);
if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
if (lmp_le_br_capable(hdev))
flags |= LE_AD_SIM_LE_BREDR_CTRL;
if (lmp_host_le_br_capable(hdev))
flags |= LE_AD_SIM_LE_BREDR_HOST;
} else {
flags |= LE_AD_NO_BREDR;
}
if (flags) {
BT_DBG("adv flags 0x%02x", flags);
ptr[0] = 2;
ptr[1] = EIR_FLAGS;
ptr[2] = flags;
ad_len += 3;
ptr += 3;
}
if (hdev->adv_tx_power != HCI_TX_POWER_INVALID) {
ptr[0] = 2;
ptr[1] = EIR_TX_POWER;
ptr[2] = (u8) hdev->adv_tx_power;
ad_len += 3;
ptr += 3;
}
return ad_len;
}
static void update_adv_data(struct hci_request *req)
{
struct hci_dev *hdev = req->hdev;
struct hci_cp_le_set_adv_data cp;
u8 len;
if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags))
return;
memset(&cp, 0, sizeof(cp));
len = create_adv_data(hdev, cp.data);
if (hdev->adv_data_len == len &&
memcmp(cp.data, hdev->adv_data, len) == 0)
return;
memcpy(hdev->adv_data, cp.data, sizeof(cp.data));
hdev->adv_data_len = len;
cp.length = len;
hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp);
}
static void create_eir(struct hci_dev *hdev, u8 *data) static void create_eir(struct hci_dev *hdev, u8 *data)
{ {
u8 *ptr = data; u8 *ptr = data;
...@@ -634,6 +784,9 @@ static void update_class(struct hci_request *req) ...@@ -634,6 +784,9 @@ static void update_class(struct hci_request *req)
if (!hdev_is_powered(hdev)) if (!hdev_is_powered(hdev))
return; return;
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
return;
if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags)) if (test_bit(HCI_SERVICE_CACHE, &hdev->dev_flags))
return; return;
...@@ -641,6 +794,9 @@ static void update_class(struct hci_request *req) ...@@ -641,6 +794,9 @@ static void update_class(struct hci_request *req)
cod[1] = hdev->major_class; cod[1] = hdev->major_class;
cod[2] = get_service_classes(hdev); cod[2] = get_service_classes(hdev);
if (test_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags))
cod[1] |= 0x20;
if (memcmp(cod, hdev->dev_class, 3) == 0) if (memcmp(cod, hdev->dev_class, 3) == 0)
return; return;
...@@ -765,18 +921,6 @@ static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev, ...@@ -765,18 +921,6 @@ static void mgmt_pending_foreach(u16 opcode, struct hci_dev *hdev,
} }
} }
static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev)
{
struct pending_cmd *cmd;
list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
if (cmd->opcode == opcode)
return cmd;
}
return NULL;
}
static void mgmt_pending_remove(struct pending_cmd *cmd) static void mgmt_pending_remove(struct pending_cmd *cmd)
{ {
list_del(&cmd->list); list_del(&cmd->list);
...@@ -939,6 +1083,7 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status) ...@@ -939,6 +1083,7 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
{ {
struct pending_cmd *cmd; struct pending_cmd *cmd;
struct mgmt_mode *cp; struct mgmt_mode *cp;
struct hci_request req;
bool changed; bool changed;
BT_DBG("status 0x%02x", status); BT_DBG("status 0x%02x", status);
...@@ -952,22 +1097,38 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status) ...@@ -952,22 +1097,38 @@ static void set_discoverable_complete(struct hci_dev *hdev, u8 status)
if (status) { if (status) {
u8 mgmt_err = mgmt_status(status); u8 mgmt_err = mgmt_status(status);
cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
goto remove_cmd; goto remove_cmd;
} }
cp = cmd->param; cp = cmd->param;
if (cp->val) if (cp->val) {
changed = !test_and_set_bit(HCI_DISCOVERABLE, changed = !test_and_set_bit(HCI_DISCOVERABLE,
&hdev->dev_flags); &hdev->dev_flags);
else
if (hdev->discov_timeout > 0) {
int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
queue_delayed_work(hdev->workqueue, &hdev->discov_off,
to);
}
} else {
changed = test_and_clear_bit(HCI_DISCOVERABLE, changed = test_and_clear_bit(HCI_DISCOVERABLE,
&hdev->dev_flags); &hdev->dev_flags);
}
send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev); send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
if (changed) if (changed)
new_settings(hdev, cmd->sk); new_settings(hdev, cmd->sk);
/* When the discoverable mode gets changed, make sure
* that class of device has the limited discoverable
* bit correctly set.
*/
hci_req_init(&req, hdev);
update_class(&req);
hci_req_run(&req, NULL);
remove_cmd: remove_cmd:
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
...@@ -982,22 +1143,27 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -982,22 +1143,27 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
struct pending_cmd *cmd; struct pending_cmd *cmd;
struct hci_request req; struct hci_request req;
u16 timeout; u16 timeout;
u8 scan, status; u8 scan;
int err; int err;
BT_DBG("request for %s", hdev->name); BT_DBG("request for %s", hdev->name);
status = mgmt_bredr_support(hdev); if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) &&
if (status) !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
status); MGMT_STATUS_REJECTED);
if (cp->val != 0x00 && cp->val != 0x01) if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
timeout = __le16_to_cpu(cp->timeout); timeout = __le16_to_cpu(cp->timeout);
if (!cp->val && timeout > 0)
/* Disabling discoverable requires that no timeout is set,
* and enabling limited discoverable requires a timeout.
*/
if ((cp->val == 0x00 && timeout > 0) ||
(cp->val == 0x02 && timeout == 0))
return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE, return cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_INVALID_PARAMS); MGMT_STATUS_INVALID_PARAMS);
...@@ -1025,6 +1191,10 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1025,6 +1191,10 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
bool changed = false; bool changed = false;
/* Setting limited discoverable when powered off is
* not a valid operation since it requires a timeout
* and so no need to check HCI_LIMITED_DISCOVERABLE.
*/
if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) { if (!!cp->val != test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) {
change_bit(HCI_DISCOVERABLE, &hdev->dev_flags); change_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
changed = true; changed = true;
...@@ -1040,16 +1210,20 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1040,16 +1210,20 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
goto failed; goto failed;
} }
if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) { /* If the current mode is the same, then just update the timeout
if (hdev->discov_timeout > 0) { * value with the new value. And if only the timeout gets updated,
cancel_delayed_work(&hdev->discov_off); * then no need for any HCI transactions.
hdev->discov_timeout = 0; */
} if (!!cp->val == test_bit(HCI_DISCOVERABLE, &hdev->dev_flags) &&
(cp->val == 0x02) == test_bit(HCI_LIMITED_DISCOVERABLE,
&hdev->dev_flags)) {
cancel_delayed_work(&hdev->discov_off);
hdev->discov_timeout = timeout;
if (cp->val && timeout > 0) { if (cp->val && hdev->discov_timeout > 0) {
hdev->discov_timeout = timeout; int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
queue_delayed_work(hdev->workqueue, &hdev->discov_off, queue_delayed_work(hdev->workqueue, &hdev->discov_off,
msecs_to_jiffies(hdev->discov_timeout * 1000)); to);
} }
err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev); err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
...@@ -1062,24 +1236,66 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1062,24 +1236,66 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
goto failed; goto failed;
} }
/* Cancel any potential discoverable timeout that might be
* still active and store new timeout value. The arming of
* the timeout happens in the complete handler.
*/
cancel_delayed_work(&hdev->discov_off);
hdev->discov_timeout = timeout;
/* Limited discoverable mode */
if (cp->val == 0x02)
set_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
else
clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
/* The procedure for LE-only controllers is much simpler - just
* update the advertising data.
*/
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
goto update_ad;
scan = SCAN_PAGE; scan = SCAN_PAGE;
if (cp->val) if (cp->val) {
struct hci_cp_write_current_iac_lap hci_cp;
if (cp->val == 0x02) {
/* Limited discoverable mode */
hci_cp.num_iac = 2;
hci_cp.iac_lap[0] = 0x00; /* LIAC */
hci_cp.iac_lap[1] = 0x8b;
hci_cp.iac_lap[2] = 0x9e;
hci_cp.iac_lap[3] = 0x33; /* GIAC */
hci_cp.iac_lap[4] = 0x8b;
hci_cp.iac_lap[5] = 0x9e;
} else {
/* General discoverable mode */
hci_cp.num_iac = 1;
hci_cp.iac_lap[0] = 0x33; /* GIAC */
hci_cp.iac_lap[1] = 0x8b;
hci_cp.iac_lap[2] = 0x9e;
}
hci_req_add(&req, HCI_OP_WRITE_CURRENT_IAC_LAP,
(hci_cp.num_iac * 3) + 1, &hci_cp);
scan |= SCAN_INQUIRY; scan |= SCAN_INQUIRY;
else } else {
cancel_delayed_work(&hdev->discov_off); clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
}
hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, sizeof(scan), &scan);
update_ad:
update_adv_data(&req);
err = hci_req_run(&req, set_discoverable_complete); err = hci_req_run(&req, set_discoverable_complete);
if (err < 0) if (err < 0)
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
if (cp->val)
hdev->discov_timeout = timeout;
failed: failed:
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
return err; return err;
...@@ -1091,6 +1307,9 @@ static void write_fast_connectable(struct hci_request *req, bool enable) ...@@ -1091,6 +1307,9 @@ static void write_fast_connectable(struct hci_request *req, bool enable)
struct hci_cp_write_page_scan_activity acp; struct hci_cp_write_page_scan_activity acp;
u8 type; u8 type;
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
return;
if (hdev->hci_ver < BLUETOOTH_VER_1_2) if (hdev->hci_ver < BLUETOOTH_VER_1_2)
return; return;
...@@ -1146,10 +1365,7 @@ static void enable_advertising(struct hci_request *req) ...@@ -1146,10 +1365,7 @@ static void enable_advertising(struct hci_request *req)
cp.min_interval = __constant_cpu_to_le16(0x0800); cp.min_interval = __constant_cpu_to_le16(0x0800);
cp.max_interval = __constant_cpu_to_le16(0x0800); cp.max_interval = __constant_cpu_to_le16(0x0800);
cp.type = get_adv_type(hdev); cp.type = get_adv_type(hdev);
if (bacmp(&hdev->bdaddr, BDADDR_ANY)) cp.own_address_type = hdev->own_addr_type;
cp.own_address_type = ADDR_LE_DEV_PUBLIC;
else
cp.own_address_type = ADDR_LE_DEV_RANDOM;
cp.channel_map = 0x07; cp.channel_map = 0x07;
hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp); hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp);
...@@ -1202,6 +1418,32 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status) ...@@ -1202,6 +1418,32 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status)
hci_dev_unlock(hdev); hci_dev_unlock(hdev);
} }
static int set_connectable_update_settings(struct hci_dev *hdev,
struct sock *sk, u8 val)
{
bool changed = false;
int err;
if (!!val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
changed = true;
if (val) {
set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
} else {
clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
}
err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
if (err < 0)
return err;
if (changed)
return new_settings(hdev, sk);
return 0;
}
static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len) u16 len)
{ {
...@@ -1225,25 +1467,7 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1225,25 +1467,7 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
hci_dev_lock(hdev); hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) { if (!hdev_is_powered(hdev)) {
bool changed = false; err = set_connectable_update_settings(hdev, sk, cp->val);
if (!!cp->val != test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
changed = true;
if (cp->val) {
set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
} else {
clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
}
err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
if (err < 0)
goto failed;
if (changed)
err = new_settings(hdev, sk);
goto failed; goto failed;
} }
...@@ -1262,16 +1486,24 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1262,16 +1486,24 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
hci_req_init(&req, hdev); hci_req_init(&req, hdev);
if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) && /* If BR/EDR is not enabled and we disable advertising as a
cp->val != test_bit(HCI_PSCAN, &hdev->flags)) { * by-product of disabling connectable, we need to update the
* advertising flags.
*/
if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
if (!cp->val) {
clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
}
update_adv_data(&req);
} else if (cp->val != test_bit(HCI_PSCAN, &hdev->flags)) {
if (cp->val) { if (cp->val) {
scan = SCAN_PAGE; scan = SCAN_PAGE;
} else { } else {
scan = 0; scan = 0;
if (test_bit(HCI_ISCAN, &hdev->flags) && if (test_bit(HCI_ISCAN, &hdev->flags) &&
hdev->discov_timeout > 0) hdev->discov_timeout > 0)
cancel_delayed_work(&hdev->discov_off); cancel_delayed_work(&hdev->discov_off);
} }
...@@ -1297,8 +1529,8 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -1297,8 +1529,8 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
if (err < 0) { if (err < 0) {
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
if (err == -ENODATA) if (err == -ENODATA)
err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, err = set_connectable_update_settings(hdev, sk,
hdev); cp->val);
goto failed; goto failed;
} }
...@@ -1556,6 +1788,24 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status) ...@@ -1556,6 +1788,24 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status)
if (match.sk) if (match.sk)
sock_put(match.sk); sock_put(match.sk);
/* Make sure the controller has a good default for
* advertising data. Restrict the update to when LE
* has actually been enabled. During power on, the
* update in powered_update_hci will take care of it.
*/
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
struct hci_request req;
hci_dev_lock(hdev);
hci_req_init(&req, hdev);
update_adv_data(&req);
update_scan_rsp_data(&req);
hci_req_run(&req, NULL);
hci_dev_unlock(hdev);
}
} }
static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
...@@ -1623,18 +1873,18 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -1623,18 +1873,18 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
goto unlock; goto unlock;
} }
hci_req_init(&req, hdev);
memset(&hci_cp, 0, sizeof(hci_cp)); memset(&hci_cp, 0, sizeof(hci_cp));
if (val) { if (val) {
hci_cp.le = val; hci_cp.le = val;
hci_cp.simul = lmp_le_br_capable(hdev); hci_cp.simul = lmp_le_br_capable(hdev);
} else {
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
disable_advertising(&req);
} }
hci_req_init(&req, hdev);
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) && !val)
disable_advertising(&req);
hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp),
&hci_cp); &hci_cp);
...@@ -2772,8 +3022,11 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data, ...@@ -2772,8 +3022,11 @@ static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
update_eir(&req); update_eir(&req);
} }
/* The name is stored in the scan response data and so
* no need to udpate the advertising data here.
*/
if (lmp_le_capable(hdev)) if (lmp_le_capable(hdev))
hci_update_ad(&req); update_scan_rsp_data(&req);
err = hci_req_run(&req, set_name_complete); err = hci_req_run(&req, set_name_complete);
if (err < 0) if (err < 0)
...@@ -3038,10 +3291,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, ...@@ -3038,10 +3291,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev,
param_cp.type = LE_SCAN_ACTIVE; param_cp.type = LE_SCAN_ACTIVE;
param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT); param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT);
param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN); param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN);
if (bacmp(&hdev->bdaddr, BDADDR_ANY)) param_cp.own_address_type = hdev->own_addr_type;
param_cp.own_address_type = ADDR_LE_DEV_PUBLIC;
else
param_cp.own_address_type = ADDR_LE_DEV_RANDOM;
hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp),
&param_cp); &param_cp);
...@@ -3725,7 +3975,7 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -3725,7 +3975,7 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
goto unlock; goto unlock;
} }
/* We need to flip the bit already here so that hci_update_ad /* We need to flip the bit already here so that update_adv_data
* generates the correct flags. * generates the correct flags.
*/ */
set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags);
...@@ -3735,7 +3985,10 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) ...@@ -3735,7 +3985,10 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags))
set_bredr_scan(&req); set_bredr_scan(&req);
hci_update_ad(&req); /* Since only the advertising data flags will change, there
* is no need to update the scan response data.
*/
update_adv_data(&req);
err = hci_req_run(&req, set_bredr_complete); err = hci_req_run(&req, set_bredr_complete);
if (err < 0) if (err < 0)
...@@ -4036,9 +4289,6 @@ static int powered_update_hci(struct hci_dev *hdev) ...@@ -4036,9 +4289,6 @@ static int powered_update_hci(struct hci_dev *hdev)
cp.simul != lmp_host_le_br_capable(hdev)) cp.simul != lmp_host_le_br_capable(hdev))
hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED,
sizeof(cp), &cp); sizeof(cp), &cp);
/* In case BR/EDR was toggled during the AUTO_OFF phase */
hci_update_ad(&req);
} }
if (lmp_le_capable(hdev)) { if (lmp_le_capable(hdev)) {
...@@ -4047,6 +4297,15 @@ static int powered_update_hci(struct hci_dev *hdev) ...@@ -4047,6 +4297,15 @@ static int powered_update_hci(struct hci_dev *hdev)
hci_req_add(&req, HCI_OP_LE_SET_RANDOM_ADDR, 6, hci_req_add(&req, HCI_OP_LE_SET_RANDOM_ADDR, 6,
&hdev->static_addr); &hdev->static_addr);
/* Make sure the controller has a good default for
* advertising data. This also applies to the case
* where BR/EDR was toggled during the AUTO_OFF phase.
*/
if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
update_adv_data(&req);
update_scan_rsp_data(&req);
}
if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) if (test_bit(HCI_ADVERTISING, &hdev->dev_flags))
enable_advertising(&req); enable_advertising(&req);
} }
...@@ -4121,59 +4380,91 @@ void mgmt_set_powered_failed(struct hci_dev *hdev, int err) ...@@ -4121,59 +4380,91 @@ void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
} }
int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) void mgmt_discoverable_timeout(struct hci_dev *hdev)
{ {
bool changed = false; struct hci_request req;
int err = 0;
hci_dev_lock(hdev);
/* When discoverable timeout triggers, then just make sure
* the limited discoverable flag is cleared. Even in the case
* of a timeout triggered from general discoverable, it is
* safe to unconditionally clear the flag.
*/
clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
hci_req_init(&req, hdev);
if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) {
u8 scan = SCAN_PAGE;
hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE,
sizeof(scan), &scan);
}
update_class(&req);
update_adv_data(&req);
hci_req_run(&req, NULL);
hdev->discov_timeout = 0;
new_settings(hdev, NULL);
hci_dev_unlock(hdev);
}
void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable)
{
bool changed;
/* Nothing needed here if there's a pending command since that /* Nothing needed here if there's a pending command since that
* commands request completion callback takes care of everything * commands request completion callback takes care of everything
* necessary. * necessary.
*/ */
if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev)) if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
return 0; return;
if (discoverable) { if (discoverable) {
if (!test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
changed = true;
} else { } else {
if (test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags);
changed = true; changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags);
} }
if (changed) if (changed) {
err = new_settings(hdev, NULL); struct hci_request req;
return err; /* In case this change in discoverable was triggered by
* a disabling of connectable there could be a need to
* update the advertising flags.
*/
hci_req_init(&req, hdev);
update_adv_data(&req);
hci_req_run(&req, NULL);
new_settings(hdev, NULL);
}
} }
int mgmt_connectable(struct hci_dev *hdev, u8 connectable) void mgmt_connectable(struct hci_dev *hdev, u8 connectable)
{ {
bool changed = false; bool changed;
int err = 0;
/* Nothing needed here if there's a pending command since that /* Nothing needed here if there's a pending command since that
* commands request completion callback takes care of everything * commands request completion callback takes care of everything
* necessary. * necessary.
*/ */
if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
return 0; return;
if (connectable) { if (connectable)
if (!test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags)) changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags);
changed = true; else
} else { changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags);
if (test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags))
changed = true;
}
if (changed) if (changed)
err = new_settings(hdev, NULL); new_settings(hdev, NULL);
return err;
} }
int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
{ {
u8 mgmt_err = mgmt_status(status); u8 mgmt_err = mgmt_status(status);
...@@ -4184,12 +4475,10 @@ int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) ...@@ -4184,12 +4475,10 @@ int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status)
if (scan & SCAN_INQUIRY) if (scan & SCAN_INQUIRY)
mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev,
cmd_status_rsp, &mgmt_err); cmd_status_rsp, &mgmt_err);
return 0;
} }
int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
bool persistent) bool persistent)
{ {
struct mgmt_ev_new_link_key ev; struct mgmt_ev_new_link_key ev;
...@@ -4202,10 +4491,10 @@ int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, ...@@ -4202,10 +4491,10 @@ int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE); memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
ev.key.pin_len = key->pin_len; ev.key.pin_len = key->pin_len;
return mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
} }
int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent) void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent)
{ {
struct mgmt_ev_new_long_term_key ev; struct mgmt_ev_new_long_term_key ev;
...@@ -4224,8 +4513,18 @@ int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent) ...@@ -4224,8 +4513,18 @@ int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent)
memcpy(ev.key.rand, key->rand, sizeof(key->rand)); memcpy(ev.key.rand, key->rand, sizeof(key->rand));
memcpy(ev.key.val, key->val, sizeof(key->val)); memcpy(ev.key.val, key->val, sizeof(key->val));
return mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
NULL); }
static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data,
u8 data_len)
{
eir[eir_len++] = sizeof(type) + data_len;
eir[eir_len++] = type;
memcpy(&eir[eir_len], data, data_len);
eir_len += data_len;
return eir_len;
} }
void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, void mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
...@@ -4345,7 +4644,7 @@ void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, ...@@ -4345,7 +4644,7 @@ void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL); mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
} }
int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure) void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
{ {
struct mgmt_ev_pin_code_request ev; struct mgmt_ev_pin_code_request ev;
...@@ -4353,52 +4652,45 @@ int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure) ...@@ -4353,52 +4652,45 @@ int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
ev.addr.type = BDADDR_BREDR; ev.addr.type = BDADDR_BREDR;
ev.secure = secure; ev.secure = secure;
return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
NULL);
} }
int mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 status) u8 status)
{ {
struct pending_cmd *cmd; struct pending_cmd *cmd;
struct mgmt_rp_pin_code_reply rp; struct mgmt_rp_pin_code_reply rp;
int err;
cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev); cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
if (!cmd) if (!cmd)
return -ENOENT; return;
bacpy(&rp.addr.bdaddr, bdaddr); bacpy(&rp.addr.bdaddr, bdaddr);
rp.addr.type = BDADDR_BREDR; rp.addr.type = BDADDR_BREDR;
err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY, cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
mgmt_status(status), &rp, sizeof(rp)); mgmt_status(status), &rp, sizeof(rp));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
return err;
} }
int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 status) u8 status)
{ {
struct pending_cmd *cmd; struct pending_cmd *cmd;
struct mgmt_rp_pin_code_reply rp; struct mgmt_rp_pin_code_reply rp;
int err;
cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev); cmd = mgmt_pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
if (!cmd) if (!cmd)
return -ENOENT; return;
bacpy(&rp.addr.bdaddr, bdaddr); bacpy(&rp.addr.bdaddr, bdaddr);
rp.addr.type = BDADDR_BREDR; rp.addr.type = BDADDR_BREDR;
err = cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY, cmd_complete(cmd->sk, hdev->id, MGMT_OP_PIN_CODE_NEG_REPLY,
mgmt_status(status), &rp, sizeof(rp)); mgmt_status(status), &rp, sizeof(rp));
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
return err;
} }
int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
...@@ -4500,8 +4792,8 @@ int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr, ...@@ -4500,8 +4792,8 @@ int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL); return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
} }
int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 status) u8 addr_type, u8 status)
{ {
struct mgmt_ev_auth_failed ev; struct mgmt_ev_auth_failed ev;
...@@ -4509,40 +4801,36 @@ int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, ...@@ -4509,40 +4801,36 @@ int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
ev.addr.type = link_to_bdaddr(link_type, addr_type); ev.addr.type = link_to_bdaddr(link_type, addr_type);
ev.status = mgmt_status(status); ev.status = mgmt_status(status);
return mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL); mgmt_event(MGMT_EV_AUTH_FAILED, hdev, &ev, sizeof(ev), NULL);
} }
int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status) void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
{ {
struct cmd_lookup match = { NULL, hdev }; struct cmd_lookup match = { NULL, hdev };
bool changed = false; bool changed;
int err = 0;
if (status) { if (status) {
u8 mgmt_err = mgmt_status(status); u8 mgmt_err = mgmt_status(status);
mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
cmd_status_rsp, &mgmt_err); cmd_status_rsp, &mgmt_err);
return 0; return;
} }
if (test_bit(HCI_AUTH, &hdev->flags)) { if (test_bit(HCI_AUTH, &hdev->flags))
if (!test_and_set_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) changed = !test_and_set_bit(HCI_LINK_SECURITY,
changed = true; &hdev->dev_flags);
} else { else
if (test_and_clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags)) changed = test_and_clear_bit(HCI_LINK_SECURITY,
changed = true; &hdev->dev_flags);
}
mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp, mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
&match); &match);
if (changed) if (changed)
err = new_settings(hdev, match.sk); new_settings(hdev, match.sk);
if (match.sk) if (match.sk)
sock_put(match.sk); sock_put(match.sk);
return err;
} }
static void clear_eir(struct hci_request *req) static void clear_eir(struct hci_request *req)
...@@ -4560,12 +4848,11 @@ static void clear_eir(struct hci_request *req) ...@@ -4560,12 +4848,11 @@ static void clear_eir(struct hci_request *req)
hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp); hci_req_add(req, HCI_OP_WRITE_EIR, sizeof(cp), &cp);
} }
int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
{ {
struct cmd_lookup match = { NULL, hdev }; struct cmd_lookup match = { NULL, hdev };
struct hci_request req; struct hci_request req;
bool changed = false; bool changed = false;
int err = 0;
if (status) { if (status) {
u8 mgmt_err = mgmt_status(status); u8 mgmt_err = mgmt_status(status);
...@@ -4573,13 +4860,12 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) ...@@ -4573,13 +4860,12 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
if (enable && test_and_clear_bit(HCI_SSP_ENABLED, if (enable && test_and_clear_bit(HCI_SSP_ENABLED,
&hdev->dev_flags)) { &hdev->dev_flags)) {
clear_bit(HCI_HS_ENABLED, &hdev->dev_flags); clear_bit(HCI_HS_ENABLED, &hdev->dev_flags);
err = new_settings(hdev, NULL); new_settings(hdev, NULL);
} }
mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp, mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
&mgmt_err); &mgmt_err);
return;
return err;
} }
if (enable) { if (enable) {
...@@ -4596,7 +4882,7 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) ...@@ -4596,7 +4882,7 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match); mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
if (changed) if (changed)
err = new_settings(hdev, match.sk); new_settings(hdev, match.sk);
if (match.sk) if (match.sk)
sock_put(match.sk); sock_put(match.sk);
...@@ -4609,8 +4895,6 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) ...@@ -4609,8 +4895,6 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status)
clear_eir(&req); clear_eir(&req);
hci_req_run(&req, NULL); hci_req_run(&req, NULL);
return err;
} }
static void sk_lookup(struct pending_cmd *cmd, void *data) static void sk_lookup(struct pending_cmd *cmd, void *data)
...@@ -4623,33 +4907,30 @@ static void sk_lookup(struct pending_cmd *cmd, void *data) ...@@ -4623,33 +4907,30 @@ static void sk_lookup(struct pending_cmd *cmd, void *data)
} }
} }
int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
u8 status) u8 status)
{ {
struct cmd_lookup match = { NULL, hdev, mgmt_status(status) }; struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
int err = 0;
mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match); mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match); mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match); mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
if (!status) if (!status)
err = mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, mgmt_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class, 3,
3, NULL); NULL);
if (match.sk) if (match.sk)
sock_put(match.sk); sock_put(match.sk);
return err;
} }
int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
{ {
struct mgmt_cp_set_local_name ev; struct mgmt_cp_set_local_name ev;
struct pending_cmd *cmd; struct pending_cmd *cmd;
if (status) if (status)
return 0; return;
memset(&ev, 0, sizeof(ev)); memset(&ev, 0, sizeof(ev));
memcpy(ev.name, name, HCI_MAX_NAME_LENGTH); memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
...@@ -4663,42 +4944,38 @@ int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) ...@@ -4663,42 +4944,38 @@ int mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
* HCI dev don't send any mgmt signals. * HCI dev don't send any mgmt signals.
*/ */
if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) if (mgmt_pending_find(MGMT_OP_SET_POWERED, hdev))
return 0; return;
} }
return mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev), mgmt_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
cmd ? cmd->sk : NULL); cmd ? cmd->sk : NULL);
} }
int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, void mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash,
u8 *randomizer, u8 status) u8 *randomizer, u8 status)
{ {
struct pending_cmd *cmd; struct pending_cmd *cmd;
int err;
BT_DBG("%s status %u", hdev->name, status); BT_DBG("%s status %u", hdev->name, status);
cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev); cmd = mgmt_pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
if (!cmd) if (!cmd)
return -ENOENT; return;
if (status) { if (status) {
err = cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
mgmt_status(status)); mgmt_status(status));
} else { } else {
struct mgmt_rp_read_local_oob_data rp; struct mgmt_rp_read_local_oob_data rp;
memcpy(rp.hash, hash, sizeof(rp.hash)); memcpy(rp.hash, hash, sizeof(rp.hash));
memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer)); memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer));
err = cmd_complete(cmd->sk, hdev->id, cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
MGMT_OP_READ_LOCAL_OOB_DATA, 0, &rp, 0, &rp, sizeof(rp));
sizeof(rp));
} }
mgmt_pending_remove(cmd); mgmt_pending_remove(cmd);
return err;
} }
void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
......
...@@ -2154,13 +2154,6 @@ static int __init rfcomm_init(void) ...@@ -2154,13 +2154,6 @@ static int __init rfcomm_init(void)
goto unregister; goto unregister;
} }
if (bt_debugfs) {
rfcomm_dlc_debugfs = debugfs_create_file("rfcomm_dlc", 0444,
bt_debugfs, NULL, &rfcomm_dlc_debugfs_fops);
if (!rfcomm_dlc_debugfs)
BT_ERR("Failed to create RFCOMM debug file");
}
err = rfcomm_init_ttys(); err = rfcomm_init_ttys();
if (err < 0) if (err < 0)
goto stop; goto stop;
...@@ -2171,6 +2164,13 @@ static int __init rfcomm_init(void) ...@@ -2171,6 +2164,13 @@ static int __init rfcomm_init(void)
BT_INFO("RFCOMM ver %s", VERSION); BT_INFO("RFCOMM ver %s", VERSION);
if (IS_ERR_OR_NULL(bt_debugfs))
return 0;
rfcomm_dlc_debugfs = debugfs_create_file("rfcomm_dlc", 0444,
bt_debugfs, NULL,
&rfcomm_dlc_debugfs_fops);
return 0; return 0;
cleanup: cleanup:
......
...@@ -1051,15 +1051,15 @@ int __init rfcomm_init_sockets(void) ...@@ -1051,15 +1051,15 @@ int __init rfcomm_init_sockets(void)
goto error; goto error;
} }
if (bt_debugfs) {
rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444,
bt_debugfs, NULL, &rfcomm_sock_debugfs_fops);
if (!rfcomm_sock_debugfs)
BT_ERR("Failed to create RFCOMM debug file");
}
BT_INFO("RFCOMM socket layer initialized"); BT_INFO("RFCOMM socket layer initialized");
if (IS_ERR_OR_NULL(bt_debugfs))
return 0;
rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444,
bt_debugfs, NULL,
&rfcomm_sock_debugfs_fops);
return 0; return 0;
error: error:
......
...@@ -1177,15 +1177,14 @@ int __init sco_init(void) ...@@ -1177,15 +1177,14 @@ int __init sco_init(void)
goto error; goto error;
} }
if (bt_debugfs) {
sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs,
NULL, &sco_debugfs_fops);
if (!sco_debugfs)
BT_ERR("Failed to create SCO debug file");
}
BT_INFO("SCO socket layer initialized"); BT_INFO("SCO socket layer initialized");
if (IS_ERR_OR_NULL(bt_debugfs))
return 0;
sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs,
NULL, &sco_debugfs_fops);
return 0; return 0;
error: error:
......
...@@ -856,7 +856,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -856,7 +856,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
if (hcon->type != LE_LINK) { if (hcon->type != LE_LINK) {
kfree_skb(skb); kfree_skb(skb);
return -ENOTSUPP; return 0;
} }
if (skb->len < 1) { if (skb->len < 1) {
...@@ -864,7 +864,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) ...@@ -864,7 +864,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb)
return -EILSEQ; return -EILSEQ;
} }
if (!test_bit(HCI_LE_ENABLED, &conn->hcon->hdev->dev_flags)) { if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) {
err = -ENOTSUPP; err = -ENOTSUPP;
reason = SMP_PAIRING_NOTSUPP; reason = SMP_PAIRING_NOTSUPP;
goto done; goto done;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment