Loading include/net/bluetooth/hci.h +9 −0 Original line number Diff line number Diff line Loading @@ -210,6 +210,7 @@ enum { #define LMP_EV4 0x01 #define LMP_EV5 0x02 #define LMP_NO_BREDR 0x20 #define LMP_LE 0x40 #define LMP_SNIFF_SUBR 0x02 Loading Loading @@ -745,6 +746,14 @@ struct hci_rp_read_bd_addr { bdaddr_t bdaddr; } __packed; #define HCI_OP_READ_DATA_BLOCK_SIZE 0x100a struct hci_rp_read_data_block_size { __u8 status; __le16 max_acl_len; __le16 block_len; __le16 num_blocks; } __packed; #define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c struct hci_cp_write_page_scan_activity { __le16 interval; Loading include/net/bluetooth/hci_core.h +57 −61 Original line number Diff line number Diff line Loading @@ -61,18 +61,11 @@ struct inquiry_cache { struct hci_conn_hash { struct list_head list; spinlock_t lock; unsigned int acl_num; unsigned int sco_num; unsigned int le_num; }; struct hci_chan_hash { struct list_head list; spinlock_t lock; unsigned int num; }; struct bdaddr_list { struct list_head list; bdaddr_t bdaddr; Loading Loading @@ -124,7 +117,7 @@ struct adv_entry { #define NUM_REASSEMBLY 4 struct hci_dev { struct list_head list; spinlock_t lock; struct mutex lock; atomic_t refcnt; char name[8]; Loading Loading @@ -188,6 +181,11 @@ struct hci_dev { unsigned int sco_pkts; unsigned int le_pkts; __u16 block_len; __u16 block_mtu; __u16 num_blocks; __u16 block_cnt; unsigned long acl_last_tx; unsigned long sco_last_tx; unsigned long le_last_tx; Loading @@ -200,10 +198,13 @@ struct hci_dev { __u16 discov_timeout; struct delayed_work discov_off; struct delayed_work service_cache; struct timer_list cmd_timer; struct tasklet_struct cmd_task; struct tasklet_struct rx_task; struct tasklet_struct tx_task; struct work_struct rx_work; struct work_struct cmd_work; struct work_struct tx_work; struct sk_buff_head rx_q; struct sk_buff_head raw_q; Loading Loading @@ -232,7 +233,7 @@ struct hci_dev { struct list_head remote_oob_data; struct list_head adv_entries; struct timer_list adv_timer; struct delayed_work adv_work; struct hci_dev_stats stat; Loading Loading @@ -301,15 +302,12 @@ struct hci_conn { unsigned int sent; struct sk_buff_head data_q; struct hci_chan_hash chan_hash; struct list_head chan_list; struct timer_list disc_timer; struct delayed_work disc_work; struct timer_list idle_timer; struct timer_list auto_accept_timer; struct work_struct work_add; struct work_struct work_del; struct device dev; atomic_t devref; Loading Loading @@ -390,15 +388,15 @@ static inline void hci_conn_hash_init(struct hci_dev *hdev) { struct hci_conn_hash *h = &hdev->conn_hash; INIT_LIST_HEAD(&h->list); spin_lock_init(&h->lock); h->acl_num = 0; h->sco_num = 0; h->le_num = 0; } static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) { struct hci_conn_hash *h = &hdev->conn_hash; list_add(&c->list, &h->list); list_add_rcu(&c->list, &h->list); switch (c->type) { case ACL_LINK: h->acl_num++; Loading @@ -416,7 +414,10 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) { struct hci_conn_hash *h = &hdev->conn_hash; list_del(&c->list); list_del_rcu(&c->list); synchronize_rcu(); switch (c->type) { case ACL_LINK: h->acl_num--; Loading Loading @@ -451,14 +452,18 @@ static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev, __u16 handle) { struct hci_conn_hash *h = &hdev->conn_hash; struct list_head *p; struct hci_conn *c; list_for_each(p, &h->list) { c = list_entry(p, struct hci_conn, list); if (c->handle == handle) rcu_read_lock(); list_for_each_entry_rcu(c, &h->list, list) { if (c->handle == handle) { rcu_read_unlock(); return c; } } rcu_read_unlock(); return NULL; } Loading @@ -466,14 +471,19 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev, __u8 type, bdaddr_t *ba) { struct hci_conn_hash *h = &hdev->conn_hash; struct list_head *p; struct hci_conn *c; list_for_each(p, &h->list) { c = list_entry(p, struct hci_conn, list); if (c->type == type && !bacmp(&c->dst, ba)) rcu_read_lock(); list_for_each_entry_rcu(c, &h->list, list) { if (c->type == type && !bacmp(&c->dst, ba)) { rcu_read_unlock(); return c; } } rcu_read_unlock(); return NULL; } Loading @@ -481,37 +491,20 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev, __u8 type, __u16 state) { struct hci_conn_hash *h = &hdev->conn_hash; struct list_head *p; struct hci_conn *c; list_for_each(p, &h->list) { c = list_entry(p, struct hci_conn, list); if (c->type == type && c->state == state) rcu_read_lock(); list_for_each_entry_rcu(c, &h->list, list) { if (c->type == type && c->state == state) { rcu_read_unlock(); return c; } return NULL; } static inline void hci_chan_hash_init(struct hci_conn *c) { struct hci_chan_hash *h = &c->chan_hash; INIT_LIST_HEAD(&h->list); spin_lock_init(&h->lock); h->num = 0; } static inline void hci_chan_hash_add(struct hci_conn *c, struct hci_chan *chan) { struct hci_chan_hash *h = &c->chan_hash; list_add(&chan->list, &h->list); h->num++; } rcu_read_unlock(); static inline void hci_chan_hash_del(struct hci_conn *c, struct hci_chan *chan) { struct hci_chan_hash *h = &c->chan_hash; list_del(&chan->list); h->num--; return NULL; } void hci_acl_connect(struct hci_conn *conn); Loading @@ -527,7 +520,7 @@ void hci_conn_check_pending(struct hci_dev *hdev); struct hci_chan *hci_chan_create(struct hci_conn *conn); int hci_chan_del(struct hci_chan *chan); void hci_chan_hash_flush(struct hci_conn *conn); void hci_chan_list_flush(struct hci_conn *conn); struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type); Loading @@ -538,7 +531,6 @@ int hci_conn_change_link_key(struct hci_conn *conn); int hci_conn_switch_role(struct hci_conn *conn, __u8 role); void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active); void hci_conn_enter_sniff_mode(struct hci_conn *conn); void hci_conn_hold_device(struct hci_conn *conn); void hci_conn_put_device(struct hci_conn *conn); Loading @@ -546,7 +538,7 @@ void hci_conn_put_device(struct hci_conn *conn); static inline void hci_conn_hold(struct hci_conn *conn) { atomic_inc(&conn->refcnt); del_timer(&conn->disc_timer); cancel_delayed_work_sync(&conn->disc_work); } static inline void hci_conn_put(struct hci_conn *conn) Loading @@ -565,7 +557,9 @@ static inline void hci_conn_put(struct hci_conn *conn) } else { timeo = msecs_to_jiffies(10); } mod_timer(&conn->disc_timer, jiffies + timeo); cancel_delayed_work_sync(&conn->disc_work); queue_delayed_work(conn->hdev->workqueue, &conn->disc_work, jiffies + timeo); } } Loading Loading @@ -597,10 +591,8 @@ static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d) try_module_get(d->owner) ? __hci_dev_hold(d) : NULL; \ }) #define hci_dev_lock(d) spin_lock(&d->lock) #define hci_dev_unlock(d) spin_unlock(&d->lock) #define hci_dev_lock_bh(d) spin_lock_bh(&d->lock) #define hci_dev_unlock_bh(d) spin_unlock_bh(&d->lock) #define hci_dev_lock(d) mutex_lock(&d->lock) #define hci_dev_unlock(d) mutex_unlock(&d->lock) struct hci_dev *hci_dev_get(int index); struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst); Loading Loading @@ -960,12 +952,16 @@ int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) /* HCI socket flags */ #define HCI_PI_MGMT_INIT 0 struct hci_pinfo { struct bt_sock bt; struct hci_dev *hdev; struct hci_filter filter; __u32 cmsg_mask; unsigned short channel; unsigned long flags; }; /* HCI security filter */ Loading include/net/bluetooth/l2cap.h +13 −11 Original line number Diff line number Diff line Loading @@ -482,10 +482,11 @@ struct l2cap_chan { __u32 remote_acc_lat; __u32 remote_flush_to; struct timer_list chan_timer; struct timer_list retrans_timer; struct timer_list monitor_timer; struct timer_list ack_timer; struct delayed_work chan_timer; struct delayed_work retrans_timer; struct delayed_work monitor_timer; struct delayed_work ack_timer; struct sk_buff *tx_send_head; struct sk_buff_head tx_q; struct sk_buff_head srej_q; Loading Loading @@ -521,7 +522,7 @@ struct l2cap_conn { __u8 info_state; __u8 info_ident; struct timer_list info_timer; struct delayed_work info_work; spinlock_t lock; Loading @@ -535,7 +536,7 @@ struct l2cap_conn { struct smp_chan *smp_chan; struct list_head chan_l; rwlock_t chan_lock; struct mutex chan_lock; }; #define L2CAP_INFO_CL_MTU_REQ_SENT 0x01 Loading Loading @@ -595,16 +596,16 @@ enum { }; #define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t)) #define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer) #define __clear_chan_timer(c) l2cap_clear_timer(&c->chan_timer) #define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \ L2CAP_DEFAULT_RETRANS_TO); #define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer) #define __clear_retrans_timer(c) l2cap_clear_timer(&c->retrans_timer) #define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \ L2CAP_DEFAULT_MONITOR_TO); #define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer) #define __clear_monitor_timer(c) l2cap_clear_timer(&c->monitor_timer) #define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \ L2CAP_DEFAULT_ACK_TO); #define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer) #define __clear_ack_timer(c) l2cap_clear_timer(&c->ack_timer) static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2) { Loading Loading @@ -805,7 +806,8 @@ int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); struct l2cap_chan *l2cap_chan_create(struct sock *sk); void l2cap_chan_close(struct l2cap_chan *chan, int reason); void l2cap_chan_destroy(struct l2cap_chan *chan); int l2cap_chan_connect(struct l2cap_chan *chan); inline int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst); int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u32 priority); void l2cap_chan_busy(struct l2cap_chan *chan, int busy); Loading include/net/bluetooth/mgmt.h +108 −83 Original line number Diff line number Diff line Loading @@ -61,22 +61,29 @@ struct mgmt_rp_read_index_list { /* Reserve one extra byte for names in management messages so that they * are always guaranteed to be nul-terminated */ #define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1) #define MGMT_MAX_SHORT_NAME_LENGTH (10 + 1) #define MGMT_SETTING_POWERED 0x00000001 #define MGMT_SETTING_CONNECTABLE 0x00000002 #define MGMT_SETTING_FAST_CONNECTABLE 0x00000004 #define MGMT_SETTING_DISCOVERABLE 0x00000008 #define MGMT_SETTING_PAIRABLE 0x00000010 #define MGMT_SETTING_LINK_SECURITY 0x00000020 #define MGMT_SETTING_SSP 0x00000040 #define MGMT_SETTING_BREDR 0x00000080 #define MGMT_SETTING_HS 0x00000100 #define MGMT_SETTING_LE 0x00000200 #define MGMT_OP_READ_INFO 0x0004 struct mgmt_rp_read_info { __u8 type; __u8 powered; __u8 connectable; __u8 discoverable; __u8 pairable; __u8 sec_mode; bdaddr_t bdaddr; __u8 version; __le16 manufacturer; __le32 supported_settings; __le32 current_settings; __u8 dev_class[3]; __u8 features[8]; __u16 manufacturer; __u8 hci_ver; __u16 hci_rev; __u8 name[MGMT_MAX_NAME_LENGTH]; __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH]; } __packed; struct mgmt_mode { Loading @@ -93,28 +100,38 @@ struct mgmt_cp_set_discoverable { #define MGMT_OP_SET_CONNECTABLE 0x0007 #define MGMT_OP_SET_PAIRABLE 0x0008 #define MGMT_OP_SET_FAST_CONNECTABLE 0x0008 #define MGMT_OP_ADD_UUID 0x0009 struct mgmt_cp_add_uuid { __u8 uuid[16]; __u8 svc_hint; } __packed; #define MGMT_OP_SET_PAIRABLE 0x0009 #define MGMT_OP_REMOVE_UUID 0x000A struct mgmt_cp_remove_uuid { __u8 uuid[16]; } __packed; #define MGMT_OP_SET_LINK_SECURITY 0x000A #define MGMT_OP_SET_DEV_CLASS 0x000B #define MGMT_OP_SET_SSP 0x000B #define MGMT_OP_SET_HS 0x000C #define MGMT_OP_SET_LE 0x000D #define MGMT_OP_SET_DEV_CLASS 0x000E struct mgmt_cp_set_dev_class { __u8 major; __u8 minor; } __packed; #define MGMT_OP_SET_SERVICE_CACHE 0x000C struct mgmt_cp_set_service_cache { __u8 enable; #define MGMT_OP_SET_LOCAL_NAME 0x000F struct mgmt_cp_set_local_name { __u8 name[MGMT_MAX_NAME_LENGTH]; } __packed; #define MGMT_OP_ADD_UUID 0x0010 struct mgmt_cp_add_uuid { __u8 uuid[16]; __u8 svc_hint; } __packed; #define MGMT_OP_REMOVE_UUID 0x0011 struct mgmt_cp_remove_uuid { __u8 uuid[16]; } __packed; struct mgmt_link_key_info { Loading @@ -124,14 +141,14 @@ struct mgmt_link_key_info { u8 pin_len; } __packed; #define MGMT_OP_LOAD_LINK_KEYS 0x000D #define MGMT_OP_LOAD_LINK_KEYS 0x0012 struct mgmt_cp_load_link_keys { __u8 debug_keys; __le16 key_count; struct mgmt_link_key_info keys[0]; } __packed; #define MGMT_OP_REMOVE_KEYS 0x000E #define MGMT_OP_REMOVE_KEYS 0x0013 struct mgmt_cp_remove_keys { bdaddr_t bdaddr; __u8 disconnect; Loading @@ -141,7 +158,7 @@ struct mgmt_rp_remove_keys { __u8 status; }; #define MGMT_OP_DISCONNECT 0x000F #define MGMT_OP_DISCONNECT 0x0014 struct mgmt_cp_disconnect { bdaddr_t bdaddr; } __packed; Loading @@ -160,13 +177,13 @@ struct mgmt_addr_info { __u8 type; } __packed; #define MGMT_OP_GET_CONNECTIONS 0x0010 #define MGMT_OP_GET_CONNECTIONS 0x0015 struct mgmt_rp_get_connections { __le16 conn_count; struct mgmt_addr_info addr[0]; } __packed; #define MGMT_OP_PIN_CODE_REPLY 0x0011 #define MGMT_OP_PIN_CODE_REPLY 0x0016 struct mgmt_cp_pin_code_reply { bdaddr_t bdaddr; __u8 pin_len; Loading @@ -177,17 +194,17 @@ struct mgmt_rp_pin_code_reply { uint8_t status; } __packed; #define MGMT_OP_PIN_CODE_NEG_REPLY 0x0012 #define MGMT_OP_PIN_CODE_NEG_REPLY 0x0017 struct mgmt_cp_pin_code_neg_reply { bdaddr_t bdaddr; } __packed; #define MGMT_OP_SET_IO_CAPABILITY 0x0013 #define MGMT_OP_SET_IO_CAPABILITY 0x0018 struct mgmt_cp_set_io_capability { __u8 io_capability; } __packed; #define MGMT_OP_PAIR_DEVICE 0x0014 #define MGMT_OP_PAIR_DEVICE 0x0019 struct mgmt_cp_pair_device { struct mgmt_addr_info addr; __u8 io_cap; Loading @@ -197,7 +214,7 @@ struct mgmt_rp_pair_device { __u8 status; } __packed; #define MGMT_OP_USER_CONFIRM_REPLY 0x0015 #define MGMT_OP_USER_CONFIRM_REPLY 0x001A struct mgmt_cp_user_confirm_reply { bdaddr_t bdaddr; } __packed; Loading @@ -206,61 +223,68 @@ struct mgmt_rp_user_confirm_reply { __u8 status; } __packed; #define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x0016 #define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x001B struct mgmt_cp_user_confirm_neg_reply { bdaddr_t bdaddr; } __packed; #define MGMT_OP_SET_LOCAL_NAME 0x0017 struct mgmt_cp_set_local_name { __u8 name[MGMT_MAX_NAME_LENGTH]; #define MGMT_OP_USER_PASSKEY_REPLY 0x001C struct mgmt_cp_user_passkey_reply { bdaddr_t bdaddr; __le32 passkey; } __packed; struct mgmt_rp_user_passkey_reply { bdaddr_t bdaddr; __u8 status; } __packed; #define MGMT_OP_READ_LOCAL_OOB_DATA 0x0018 #define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x001D struct mgmt_cp_user_passkey_neg_reply { bdaddr_t bdaddr; } __packed; #define MGMT_OP_READ_LOCAL_OOB_DATA 0x001E struct mgmt_rp_read_local_oob_data { __u8 hash[16]; __u8 randomizer[16]; } __packed; #define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0019 #define MGMT_OP_ADD_REMOTE_OOB_DATA 0x001F struct mgmt_cp_add_remote_oob_data { bdaddr_t bdaddr; __u8 hash[16]; __u8 randomizer[16]; } __packed; #define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x001A #define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x0020 struct mgmt_cp_remove_remote_oob_data { bdaddr_t bdaddr; } __packed; #define MGMT_OP_START_DISCOVERY 0x001B #define MGMT_OP_START_DISCOVERY 0x0021 struct mgmt_cp_start_discovery { __u8 type; } __packed; #define MGMT_OP_STOP_DISCOVERY 0x001C #define MGMT_OP_STOP_DISCOVERY 0x0022 #define MGMT_OP_BLOCK_DEVICE 0x001D struct mgmt_cp_block_device { #define MGMT_OP_CONFIRM_NAME 0x0023 struct mgmt_cp_confirm_name { bdaddr_t bdaddr; __u8 name_known; } __packed; #define MGMT_OP_UNBLOCK_DEVICE 0x001E struct mgmt_cp_unblock_device { struct mgmt_rp_confirm_name { bdaddr_t bdaddr; __u8 status; } __packed; #define MGMT_OP_SET_FAST_CONNECTABLE 0x001F struct mgmt_cp_set_fast_connectable { __u8 enable; } __packed; #define MGMT_OP_USER_PASSKEY_REPLY 0x0020 struct mgmt_cp_user_passkey_reply { #define MGMT_OP_BLOCK_DEVICE 0x0024 struct mgmt_cp_block_device { bdaddr_t bdaddr; __le32 passkey; } __packed; #define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x0021 struct mgmt_cp_user_passkey_neg_reply { #define MGMT_OP_UNBLOCK_DEVICE 0x0025 struct mgmt_cp_unblock_device { bdaddr_t bdaddr; } __packed; Loading @@ -285,81 +309,82 @@ struct mgmt_ev_controller_error { #define MGMT_EV_INDEX_REMOVED 0x0005 #define MGMT_EV_POWERED 0x0006 #define MGMT_EV_NEW_SETTINGS 0x0006 #define MGMT_EV_DISCOVERABLE 0x0007 #define MGMT_EV_CONNECTABLE 0x0008 #define MGMT_EV_CLASS_OF_DEV_CHANGED 0x0007 struct mgmt_ev_class_of_dev_changed { __u8 dev_class[3]; }; #define MGMT_EV_PAIRABLE 0x0009 #define MGMT_EV_LOCAL_NAME_CHANGED 0x0008 struct mgmt_ev_local_name_changed { __u8 name[MGMT_MAX_NAME_LENGTH]; __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH]; } __packed; #define MGMT_EV_NEW_LINK_KEY 0x000A #define MGMT_EV_NEW_LINK_KEY 0x0009 struct mgmt_ev_new_link_key { __u8 store_hint; struct mgmt_link_key_info key; } __packed; #define MGMT_EV_CONNECTED 0x000B #define MGMT_EV_CONNECTED 0x000A #define MGMT_EV_DISCONNECTED 0x000C #define MGMT_EV_DISCONNECTED 0x000B #define MGMT_EV_CONNECT_FAILED 0x000D #define MGMT_EV_CONNECT_FAILED 0x000C struct mgmt_ev_connect_failed { struct mgmt_addr_info addr; __u8 status; } __packed; #define MGMT_EV_PIN_CODE_REQUEST 0x000E #define MGMT_EV_PIN_CODE_REQUEST 0x000D struct mgmt_ev_pin_code_request { bdaddr_t bdaddr; __u8 secure; } __packed; #define MGMT_EV_USER_CONFIRM_REQUEST 0x000F #define MGMT_EV_USER_CONFIRM_REQUEST 0x000E struct mgmt_ev_user_confirm_request { bdaddr_t bdaddr; __u8 confirm_hint; __le32 value; } __packed; #define MGMT_EV_USER_PASSKEY_REQUEST 0x000F struct mgmt_ev_user_passkey_request { bdaddr_t bdaddr; } __packed; #define MGMT_EV_AUTH_FAILED 0x0010 struct mgmt_ev_auth_failed { bdaddr_t bdaddr; __u8 status; } __packed; #define MGMT_EV_LOCAL_NAME_CHANGED 0x0011 struct mgmt_ev_local_name_changed { __u8 name[MGMT_MAX_NAME_LENGTH]; } __packed; #define MGMT_EV_DEVICE_FOUND 0x0012 #define MGMT_EV_DEVICE_FOUND 0x0011 struct mgmt_ev_device_found { struct mgmt_addr_info addr; __u8 dev_class[3]; __s8 rssi; __u8 confirm_name; __u8 eir[HCI_MAX_EIR_LENGTH]; } __packed; #define MGMT_EV_REMOTE_NAME 0x0013 #define MGMT_EV_REMOTE_NAME 0x0012 struct mgmt_ev_remote_name { bdaddr_t bdaddr; __u8 name[MGMT_MAX_NAME_LENGTH]; } __packed; #define MGMT_EV_DISCOVERING 0x0014 #define MGMT_EV_DISCOVERING 0x0013 #define MGMT_EV_DEVICE_BLOCKED 0x0015 #define MGMT_EV_DEVICE_BLOCKED 0x0014 struct mgmt_ev_device_blocked { bdaddr_t bdaddr; } __packed; #define MGMT_EV_DEVICE_UNBLOCKED 0x0016 #define MGMT_EV_DEVICE_UNBLOCKED 0x0015 struct mgmt_ev_device_unblocked { bdaddr_t bdaddr; } __packed; #define MGMT_EV_USER_PASSKEY_REQUEST 0x0017 struct mgmt_ev_user_passkey_request { bdaddr_t bdaddr; } __packed; net/bluetooth/hci_conn.c +59 −78 Original line number Diff line number Diff line Loading @@ -275,9 +275,10 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status) } } static void hci_conn_timeout(unsigned long arg) static void hci_conn_timeout(struct work_struct *work) { struct hci_conn *conn = (void *) arg; struct hci_conn *conn = container_of(work, struct hci_conn, disc_work.work); struct hci_dev *hdev = conn->hdev; __u8 reason; Loading Loading @@ -311,6 +312,42 @@ static void hci_conn_timeout(unsigned long arg) hci_dev_unlock(hdev); } /* Enter sniff mode */ static void hci_conn_enter_sniff_mode(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; BT_DBG("conn %p mode %d", conn, conn->mode); if (test_bit(HCI_RAW, &hdev->flags)) return; if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn)) return; if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF)) return; if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) { struct hci_cp_sniff_subrate cp; cp.handle = cpu_to_le16(conn->handle); cp.max_latency = cpu_to_le16(0); cp.min_remote_timeout = cpu_to_le16(0); cp.min_local_timeout = cpu_to_le16(0); hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp); } if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { struct hci_cp_sniff_mode cp; cp.handle = cpu_to_le16(conn->handle); cp.max_interval = cpu_to_le16(hdev->sniff_max_interval); cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); cp.attempt = cpu_to_le16(4); cp.timeout = cpu_to_le16(1); hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp); } } static void hci_conn_idle(unsigned long arg) { struct hci_conn *conn = (void *) arg; Loading @@ -325,12 +362,8 @@ static void hci_conn_auto_accept(unsigned long arg) struct hci_conn *conn = (void *) arg; struct hci_dev *hdev = conn->hdev; hci_dev_lock(hdev); hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst), &conn->dst); hci_dev_unlock(hdev); } struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) Loading Loading @@ -374,9 +407,9 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) skb_queue_head_init(&conn->data_q); hci_chan_hash_init(conn); INIT_LIST_HEAD(&conn->chan_list);; setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn); INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn); setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept, (unsigned long) conn); Loading @@ -385,8 +418,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) hci_dev_hold(hdev); tasklet_disable(&hdev->tx_task); hci_conn_hash_add(hdev, conn); if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_CONN_ADD); Loading @@ -395,8 +426,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) hci_conn_init_sysfs(conn); tasklet_enable(&hdev->tx_task); return conn; } Loading @@ -408,7 +437,7 @@ int hci_conn_del(struct hci_conn *conn) del_timer(&conn->idle_timer); del_timer(&conn->disc_timer); cancel_delayed_work_sync(&conn->disc_work); del_timer(&conn->auto_accept_timer); Loading @@ -432,16 +461,13 @@ int hci_conn_del(struct hci_conn *conn) } } tasklet_disable(&hdev->tx_task); hci_chan_hash_flush(conn); hci_chan_list_flush(conn); hci_conn_hash_del(hdev, conn); if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_CONN_DEL); tasklet_enable(&hdev->tx_task); skb_queue_purge(&conn->data_q); hci_conn_put_device(conn); Loading Loading @@ -674,7 +700,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) goto encrypt; auth: if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) return 0; if (!hci_conn_auth(conn, sec_level, auth_type)) Loading Loading @@ -767,57 +793,15 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active) jiffies + msecs_to_jiffies(hdev->idle_timeout)); } /* Enter sniff mode */ void hci_conn_enter_sniff_mode(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; BT_DBG("conn %p mode %d", conn, conn->mode); if (test_bit(HCI_RAW, &hdev->flags)) return; if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn)) return; if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF)) return; if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) { struct hci_cp_sniff_subrate cp; cp.handle = cpu_to_le16(conn->handle); cp.max_latency = cpu_to_le16(0); cp.min_remote_timeout = cpu_to_le16(0); cp.min_local_timeout = cpu_to_le16(0); hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp); } if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { struct hci_cp_sniff_mode cp; cp.handle = cpu_to_le16(conn->handle); cp.max_interval = cpu_to_le16(hdev->sniff_max_interval); cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); cp.attempt = cpu_to_le16(4); cp.timeout = cpu_to_le16(1); hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp); } } /* Drop all connection on the device */ void hci_conn_hash_flush(struct hci_dev *hdev) { struct hci_conn_hash *h = &hdev->conn_hash; struct list_head *p; BT_DBG("hdev %s", hdev->name); p = h->list.next; while (p != &h->list) { struct hci_conn *c; c = list_entry(p, struct hci_conn, list); p = p->next; BT_DBG("hdev %s", hdev->name); list_for_each_entry_rcu(c, &h->list, list) { c->state = BT_CLOSED; hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM); Loading Loading @@ -882,7 +866,7 @@ int hci_get_conn_list(void __user *arg) ci = cl->conn_info; hci_dev_lock_bh(hdev); hci_dev_lock(hdev); list_for_each_entry(c, &hdev->conn_hash.list, list) { bacpy(&(ci + n)->bdaddr, &c->dst); (ci + n)->handle = c->handle; Loading @@ -893,7 +877,7 @@ int hci_get_conn_list(void __user *arg) if (++n >= req.conn_num) break; } hci_dev_unlock_bh(hdev); hci_dev_unlock(hdev); cl->dev_id = hdev->id; cl->conn_num = n; Loading @@ -917,7 +901,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg) if (copy_from_user(&req, arg, sizeof(req))) return -EFAULT; hci_dev_lock_bh(hdev); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr); if (conn) { bacpy(&ci.bdaddr, &conn->dst); Loading @@ -927,7 +911,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg) ci.state = conn->state; ci.link_mode = conn->link_mode; } hci_dev_unlock_bh(hdev); hci_dev_unlock(hdev); if (!conn) return -ENOENT; Loading @@ -943,11 +927,11 @@ int hci_get_auth_info(struct hci_dev *hdev, void __user *arg) if (copy_from_user(&req, arg, sizeof(req))) return -EFAULT; hci_dev_lock_bh(hdev); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr); if (conn) req.type = conn->auth_type; hci_dev_unlock_bh(hdev); hci_dev_unlock(hdev); if (!conn) return -ENOENT; Loading @@ -969,9 +953,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn) chan->conn = conn; skb_queue_head_init(&chan->data_q); tasklet_disable(&hdev->tx_task); hci_chan_hash_add(conn, chan); tasklet_enable(&hdev->tx_task); list_add_rcu(&chan->list, &conn->chan_list); return chan; } Loading @@ -983,9 +965,9 @@ int hci_chan_del(struct hci_chan *chan) BT_DBG("%s conn %p chan %p", hdev->name, conn, chan); tasklet_disable(&hdev->tx_task); hci_chan_hash_del(conn, chan); tasklet_enable(&hdev->tx_task); list_del_rcu(&chan->list); synchronize_rcu(); skb_queue_purge(&chan->data_q); kfree(chan); Loading @@ -993,13 +975,12 @@ int hci_chan_del(struct hci_chan *chan) return 0; } void hci_chan_hash_flush(struct hci_conn *conn) void hci_chan_list_flush(struct hci_conn *conn) { struct hci_chan_hash *h = &conn->chan_hash; struct hci_chan *chan, *tmp; struct hci_chan *chan; BT_DBG("conn %p", conn); list_for_each_entry_safe(chan, tmp, &h->list, list) list_for_each_entry_rcu(chan, &conn->chan_list, list) hci_chan_del(chan); } Loading
include/net/bluetooth/hci.h +9 −0 Original line number Diff line number Diff line Loading @@ -210,6 +210,7 @@ enum { #define LMP_EV4 0x01 #define LMP_EV5 0x02 #define LMP_NO_BREDR 0x20 #define LMP_LE 0x40 #define LMP_SNIFF_SUBR 0x02 Loading Loading @@ -745,6 +746,14 @@ struct hci_rp_read_bd_addr { bdaddr_t bdaddr; } __packed; #define HCI_OP_READ_DATA_BLOCK_SIZE 0x100a struct hci_rp_read_data_block_size { __u8 status; __le16 max_acl_len; __le16 block_len; __le16 num_blocks; } __packed; #define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c struct hci_cp_write_page_scan_activity { __le16 interval; Loading
include/net/bluetooth/hci_core.h +57 −61 Original line number Diff line number Diff line Loading @@ -61,18 +61,11 @@ struct inquiry_cache { struct hci_conn_hash { struct list_head list; spinlock_t lock; unsigned int acl_num; unsigned int sco_num; unsigned int le_num; }; struct hci_chan_hash { struct list_head list; spinlock_t lock; unsigned int num; }; struct bdaddr_list { struct list_head list; bdaddr_t bdaddr; Loading Loading @@ -124,7 +117,7 @@ struct adv_entry { #define NUM_REASSEMBLY 4 struct hci_dev { struct list_head list; spinlock_t lock; struct mutex lock; atomic_t refcnt; char name[8]; Loading Loading @@ -188,6 +181,11 @@ struct hci_dev { unsigned int sco_pkts; unsigned int le_pkts; __u16 block_len; __u16 block_mtu; __u16 num_blocks; __u16 block_cnt; unsigned long acl_last_tx; unsigned long sco_last_tx; unsigned long le_last_tx; Loading @@ -200,10 +198,13 @@ struct hci_dev { __u16 discov_timeout; struct delayed_work discov_off; struct delayed_work service_cache; struct timer_list cmd_timer; struct tasklet_struct cmd_task; struct tasklet_struct rx_task; struct tasklet_struct tx_task; struct work_struct rx_work; struct work_struct cmd_work; struct work_struct tx_work; struct sk_buff_head rx_q; struct sk_buff_head raw_q; Loading Loading @@ -232,7 +233,7 @@ struct hci_dev { struct list_head remote_oob_data; struct list_head adv_entries; struct timer_list adv_timer; struct delayed_work adv_work; struct hci_dev_stats stat; Loading Loading @@ -301,15 +302,12 @@ struct hci_conn { unsigned int sent; struct sk_buff_head data_q; struct hci_chan_hash chan_hash; struct list_head chan_list; struct timer_list disc_timer; struct delayed_work disc_work; struct timer_list idle_timer; struct timer_list auto_accept_timer; struct work_struct work_add; struct work_struct work_del; struct device dev; atomic_t devref; Loading Loading @@ -390,15 +388,15 @@ static inline void hci_conn_hash_init(struct hci_dev *hdev) { struct hci_conn_hash *h = &hdev->conn_hash; INIT_LIST_HEAD(&h->list); spin_lock_init(&h->lock); h->acl_num = 0; h->sco_num = 0; h->le_num = 0; } static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) { struct hci_conn_hash *h = &hdev->conn_hash; list_add(&c->list, &h->list); list_add_rcu(&c->list, &h->list); switch (c->type) { case ACL_LINK: h->acl_num++; Loading @@ -416,7 +414,10 @@ static inline void hci_conn_hash_add(struct hci_dev *hdev, struct hci_conn *c) static inline void hci_conn_hash_del(struct hci_dev *hdev, struct hci_conn *c) { struct hci_conn_hash *h = &hdev->conn_hash; list_del(&c->list); list_del_rcu(&c->list); synchronize_rcu(); switch (c->type) { case ACL_LINK: h->acl_num--; Loading Loading @@ -451,14 +452,18 @@ static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev, __u16 handle) { struct hci_conn_hash *h = &hdev->conn_hash; struct list_head *p; struct hci_conn *c; list_for_each(p, &h->list) { c = list_entry(p, struct hci_conn, list); if (c->handle == handle) rcu_read_lock(); list_for_each_entry_rcu(c, &h->list, list) { if (c->handle == handle) { rcu_read_unlock(); return c; } } rcu_read_unlock(); return NULL; } Loading @@ -466,14 +471,19 @@ static inline struct hci_conn *hci_conn_hash_lookup_ba(struct hci_dev *hdev, __u8 type, bdaddr_t *ba) { struct hci_conn_hash *h = &hdev->conn_hash; struct list_head *p; struct hci_conn *c; list_for_each(p, &h->list) { c = list_entry(p, struct hci_conn, list); if (c->type == type && !bacmp(&c->dst, ba)) rcu_read_lock(); list_for_each_entry_rcu(c, &h->list, list) { if (c->type == type && !bacmp(&c->dst, ba)) { rcu_read_unlock(); return c; } } rcu_read_unlock(); return NULL; } Loading @@ -481,37 +491,20 @@ static inline struct hci_conn *hci_conn_hash_lookup_state(struct hci_dev *hdev, __u8 type, __u16 state) { struct hci_conn_hash *h = &hdev->conn_hash; struct list_head *p; struct hci_conn *c; list_for_each(p, &h->list) { c = list_entry(p, struct hci_conn, list); if (c->type == type && c->state == state) rcu_read_lock(); list_for_each_entry_rcu(c, &h->list, list) { if (c->type == type && c->state == state) { rcu_read_unlock(); return c; } return NULL; } static inline void hci_chan_hash_init(struct hci_conn *c) { struct hci_chan_hash *h = &c->chan_hash; INIT_LIST_HEAD(&h->list); spin_lock_init(&h->lock); h->num = 0; } static inline void hci_chan_hash_add(struct hci_conn *c, struct hci_chan *chan) { struct hci_chan_hash *h = &c->chan_hash; list_add(&chan->list, &h->list); h->num++; } rcu_read_unlock(); static inline void hci_chan_hash_del(struct hci_conn *c, struct hci_chan *chan) { struct hci_chan_hash *h = &c->chan_hash; list_del(&chan->list); h->num--; return NULL; } void hci_acl_connect(struct hci_conn *conn); Loading @@ -527,7 +520,7 @@ void hci_conn_check_pending(struct hci_dev *hdev); struct hci_chan *hci_chan_create(struct hci_conn *conn); int hci_chan_del(struct hci_chan *chan); void hci_chan_hash_flush(struct hci_conn *conn); void hci_chan_list_flush(struct hci_conn *conn); struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 sec_level, __u8 auth_type); Loading @@ -538,7 +531,6 @@ int hci_conn_change_link_key(struct hci_conn *conn); int hci_conn_switch_role(struct hci_conn *conn, __u8 role); void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active); void hci_conn_enter_sniff_mode(struct hci_conn *conn); void hci_conn_hold_device(struct hci_conn *conn); void hci_conn_put_device(struct hci_conn *conn); Loading @@ -546,7 +538,7 @@ void hci_conn_put_device(struct hci_conn *conn); static inline void hci_conn_hold(struct hci_conn *conn) { atomic_inc(&conn->refcnt); del_timer(&conn->disc_timer); cancel_delayed_work_sync(&conn->disc_work); } static inline void hci_conn_put(struct hci_conn *conn) Loading @@ -565,7 +557,9 @@ static inline void hci_conn_put(struct hci_conn *conn) } else { timeo = msecs_to_jiffies(10); } mod_timer(&conn->disc_timer, jiffies + timeo); cancel_delayed_work_sync(&conn->disc_work); queue_delayed_work(conn->hdev->workqueue, &conn->disc_work, jiffies + timeo); } } Loading Loading @@ -597,10 +591,8 @@ static inline struct hci_dev *__hci_dev_hold(struct hci_dev *d) try_module_get(d->owner) ? __hci_dev_hold(d) : NULL; \ }) #define hci_dev_lock(d) spin_lock(&d->lock) #define hci_dev_unlock(d) spin_unlock(&d->lock) #define hci_dev_lock_bh(d) spin_lock_bh(&d->lock) #define hci_dev_unlock_bh(d) spin_unlock_bh(&d->lock) #define hci_dev_lock(d) mutex_lock(&d->lock) #define hci_dev_unlock(d) mutex_unlock(&d->lock) struct hci_dev *hci_dev_get(int index); struct hci_dev *hci_get_route(bdaddr_t *src, bdaddr_t *dst); Loading Loading @@ -960,12 +952,16 @@ int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) /* HCI socket flags */ #define HCI_PI_MGMT_INIT 0 struct hci_pinfo { struct bt_sock bt; struct hci_dev *hdev; struct hci_filter filter; __u32 cmsg_mask; unsigned short channel; unsigned long flags; }; /* HCI security filter */ Loading
include/net/bluetooth/l2cap.h +13 −11 Original line number Diff line number Diff line Loading @@ -482,10 +482,11 @@ struct l2cap_chan { __u32 remote_acc_lat; __u32 remote_flush_to; struct timer_list chan_timer; struct timer_list retrans_timer; struct timer_list monitor_timer; struct timer_list ack_timer; struct delayed_work chan_timer; struct delayed_work retrans_timer; struct delayed_work monitor_timer; struct delayed_work ack_timer; struct sk_buff *tx_send_head; struct sk_buff_head tx_q; struct sk_buff_head srej_q; Loading Loading @@ -521,7 +522,7 @@ struct l2cap_conn { __u8 info_state; __u8 info_ident; struct timer_list info_timer; struct delayed_work info_work; spinlock_t lock; Loading @@ -535,7 +536,7 @@ struct l2cap_conn { struct smp_chan *smp_chan; struct list_head chan_l; rwlock_t chan_lock; struct mutex chan_lock; }; #define L2CAP_INFO_CL_MTU_REQ_SENT 0x01 Loading Loading @@ -595,16 +596,16 @@ enum { }; #define __set_chan_timer(c, t) l2cap_set_timer(c, &c->chan_timer, (t)) #define __clear_chan_timer(c) l2cap_clear_timer(c, &c->chan_timer) #define __clear_chan_timer(c) l2cap_clear_timer(&c->chan_timer) #define __set_retrans_timer(c) l2cap_set_timer(c, &c->retrans_timer, \ L2CAP_DEFAULT_RETRANS_TO); #define __clear_retrans_timer(c) l2cap_clear_timer(c, &c->retrans_timer) #define __clear_retrans_timer(c) l2cap_clear_timer(&c->retrans_timer) #define __set_monitor_timer(c) l2cap_set_timer(c, &c->monitor_timer, \ L2CAP_DEFAULT_MONITOR_TO); #define __clear_monitor_timer(c) l2cap_clear_timer(c, &c->monitor_timer) #define __clear_monitor_timer(c) l2cap_clear_timer(&c->monitor_timer) #define __set_ack_timer(c) l2cap_set_timer(c, &chan->ack_timer, \ L2CAP_DEFAULT_ACK_TO); #define __clear_ack_timer(c) l2cap_clear_timer(c, &c->ack_timer) #define __clear_ack_timer(c) l2cap_clear_timer(&c->ack_timer) static inline int __seq_offset(struct l2cap_chan *chan, __u16 seq1, __u16 seq2) { Loading Loading @@ -805,7 +806,8 @@ int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid); struct l2cap_chan *l2cap_chan_create(struct sock *sk); void l2cap_chan_close(struct l2cap_chan *chan, int reason); void l2cap_chan_destroy(struct l2cap_chan *chan); int l2cap_chan_connect(struct l2cap_chan *chan); inline int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst); int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, u32 priority); void l2cap_chan_busy(struct l2cap_chan *chan, int busy); Loading
include/net/bluetooth/mgmt.h +108 −83 Original line number Diff line number Diff line Loading @@ -61,22 +61,29 @@ struct mgmt_rp_read_index_list { /* Reserve one extra byte for names in management messages so that they * are always guaranteed to be nul-terminated */ #define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1) #define MGMT_MAX_SHORT_NAME_LENGTH (10 + 1) #define MGMT_SETTING_POWERED 0x00000001 #define MGMT_SETTING_CONNECTABLE 0x00000002 #define MGMT_SETTING_FAST_CONNECTABLE 0x00000004 #define MGMT_SETTING_DISCOVERABLE 0x00000008 #define MGMT_SETTING_PAIRABLE 0x00000010 #define MGMT_SETTING_LINK_SECURITY 0x00000020 #define MGMT_SETTING_SSP 0x00000040 #define MGMT_SETTING_BREDR 0x00000080 #define MGMT_SETTING_HS 0x00000100 #define MGMT_SETTING_LE 0x00000200 #define MGMT_OP_READ_INFO 0x0004 struct mgmt_rp_read_info { __u8 type; __u8 powered; __u8 connectable; __u8 discoverable; __u8 pairable; __u8 sec_mode; bdaddr_t bdaddr; __u8 version; __le16 manufacturer; __le32 supported_settings; __le32 current_settings; __u8 dev_class[3]; __u8 features[8]; __u16 manufacturer; __u8 hci_ver; __u16 hci_rev; __u8 name[MGMT_MAX_NAME_LENGTH]; __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH]; } __packed; struct mgmt_mode { Loading @@ -93,28 +100,38 @@ struct mgmt_cp_set_discoverable { #define MGMT_OP_SET_CONNECTABLE 0x0007 #define MGMT_OP_SET_PAIRABLE 0x0008 #define MGMT_OP_SET_FAST_CONNECTABLE 0x0008 #define MGMT_OP_ADD_UUID 0x0009 struct mgmt_cp_add_uuid { __u8 uuid[16]; __u8 svc_hint; } __packed; #define MGMT_OP_SET_PAIRABLE 0x0009 #define MGMT_OP_REMOVE_UUID 0x000A struct mgmt_cp_remove_uuid { __u8 uuid[16]; } __packed; #define MGMT_OP_SET_LINK_SECURITY 0x000A #define MGMT_OP_SET_DEV_CLASS 0x000B #define MGMT_OP_SET_SSP 0x000B #define MGMT_OP_SET_HS 0x000C #define MGMT_OP_SET_LE 0x000D #define MGMT_OP_SET_DEV_CLASS 0x000E struct mgmt_cp_set_dev_class { __u8 major; __u8 minor; } __packed; #define MGMT_OP_SET_SERVICE_CACHE 0x000C struct mgmt_cp_set_service_cache { __u8 enable; #define MGMT_OP_SET_LOCAL_NAME 0x000F struct mgmt_cp_set_local_name { __u8 name[MGMT_MAX_NAME_LENGTH]; } __packed; #define MGMT_OP_ADD_UUID 0x0010 struct mgmt_cp_add_uuid { __u8 uuid[16]; __u8 svc_hint; } __packed; #define MGMT_OP_REMOVE_UUID 0x0011 struct mgmt_cp_remove_uuid { __u8 uuid[16]; } __packed; struct mgmt_link_key_info { Loading @@ -124,14 +141,14 @@ struct mgmt_link_key_info { u8 pin_len; } __packed; #define MGMT_OP_LOAD_LINK_KEYS 0x000D #define MGMT_OP_LOAD_LINK_KEYS 0x0012 struct mgmt_cp_load_link_keys { __u8 debug_keys; __le16 key_count; struct mgmt_link_key_info keys[0]; } __packed; #define MGMT_OP_REMOVE_KEYS 0x000E #define MGMT_OP_REMOVE_KEYS 0x0013 struct mgmt_cp_remove_keys { bdaddr_t bdaddr; __u8 disconnect; Loading @@ -141,7 +158,7 @@ struct mgmt_rp_remove_keys { __u8 status; }; #define MGMT_OP_DISCONNECT 0x000F #define MGMT_OP_DISCONNECT 0x0014 struct mgmt_cp_disconnect { bdaddr_t bdaddr; } __packed; Loading @@ -160,13 +177,13 @@ struct mgmt_addr_info { __u8 type; } __packed; #define MGMT_OP_GET_CONNECTIONS 0x0010 #define MGMT_OP_GET_CONNECTIONS 0x0015 struct mgmt_rp_get_connections { __le16 conn_count; struct mgmt_addr_info addr[0]; } __packed; #define MGMT_OP_PIN_CODE_REPLY 0x0011 #define MGMT_OP_PIN_CODE_REPLY 0x0016 struct mgmt_cp_pin_code_reply { bdaddr_t bdaddr; __u8 pin_len; Loading @@ -177,17 +194,17 @@ struct mgmt_rp_pin_code_reply { uint8_t status; } __packed; #define MGMT_OP_PIN_CODE_NEG_REPLY 0x0012 #define MGMT_OP_PIN_CODE_NEG_REPLY 0x0017 struct mgmt_cp_pin_code_neg_reply { bdaddr_t bdaddr; } __packed; #define MGMT_OP_SET_IO_CAPABILITY 0x0013 #define MGMT_OP_SET_IO_CAPABILITY 0x0018 struct mgmt_cp_set_io_capability { __u8 io_capability; } __packed; #define MGMT_OP_PAIR_DEVICE 0x0014 #define MGMT_OP_PAIR_DEVICE 0x0019 struct mgmt_cp_pair_device { struct mgmt_addr_info addr; __u8 io_cap; Loading @@ -197,7 +214,7 @@ struct mgmt_rp_pair_device { __u8 status; } __packed; #define MGMT_OP_USER_CONFIRM_REPLY 0x0015 #define MGMT_OP_USER_CONFIRM_REPLY 0x001A struct mgmt_cp_user_confirm_reply { bdaddr_t bdaddr; } __packed; Loading @@ -206,61 +223,68 @@ struct mgmt_rp_user_confirm_reply { __u8 status; } __packed; #define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x0016 #define MGMT_OP_USER_CONFIRM_NEG_REPLY 0x001B struct mgmt_cp_user_confirm_neg_reply { bdaddr_t bdaddr; } __packed; #define MGMT_OP_SET_LOCAL_NAME 0x0017 struct mgmt_cp_set_local_name { __u8 name[MGMT_MAX_NAME_LENGTH]; #define MGMT_OP_USER_PASSKEY_REPLY 0x001C struct mgmt_cp_user_passkey_reply { bdaddr_t bdaddr; __le32 passkey; } __packed; struct mgmt_rp_user_passkey_reply { bdaddr_t bdaddr; __u8 status; } __packed; #define MGMT_OP_READ_LOCAL_OOB_DATA 0x0018 #define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x001D struct mgmt_cp_user_passkey_neg_reply { bdaddr_t bdaddr; } __packed; #define MGMT_OP_READ_LOCAL_OOB_DATA 0x001E struct mgmt_rp_read_local_oob_data { __u8 hash[16]; __u8 randomizer[16]; } __packed; #define MGMT_OP_ADD_REMOTE_OOB_DATA 0x0019 #define MGMT_OP_ADD_REMOTE_OOB_DATA 0x001F struct mgmt_cp_add_remote_oob_data { bdaddr_t bdaddr; __u8 hash[16]; __u8 randomizer[16]; } __packed; #define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x001A #define MGMT_OP_REMOVE_REMOTE_OOB_DATA 0x0020 struct mgmt_cp_remove_remote_oob_data { bdaddr_t bdaddr; } __packed; #define MGMT_OP_START_DISCOVERY 0x001B #define MGMT_OP_START_DISCOVERY 0x0021 struct mgmt_cp_start_discovery { __u8 type; } __packed; #define MGMT_OP_STOP_DISCOVERY 0x001C #define MGMT_OP_STOP_DISCOVERY 0x0022 #define MGMT_OP_BLOCK_DEVICE 0x001D struct mgmt_cp_block_device { #define MGMT_OP_CONFIRM_NAME 0x0023 struct mgmt_cp_confirm_name { bdaddr_t bdaddr; __u8 name_known; } __packed; #define MGMT_OP_UNBLOCK_DEVICE 0x001E struct mgmt_cp_unblock_device { struct mgmt_rp_confirm_name { bdaddr_t bdaddr; __u8 status; } __packed; #define MGMT_OP_SET_FAST_CONNECTABLE 0x001F struct mgmt_cp_set_fast_connectable { __u8 enable; } __packed; #define MGMT_OP_USER_PASSKEY_REPLY 0x0020 struct mgmt_cp_user_passkey_reply { #define MGMT_OP_BLOCK_DEVICE 0x0024 struct mgmt_cp_block_device { bdaddr_t bdaddr; __le32 passkey; } __packed; #define MGMT_OP_USER_PASSKEY_NEG_REPLY 0x0021 struct mgmt_cp_user_passkey_neg_reply { #define MGMT_OP_UNBLOCK_DEVICE 0x0025 struct mgmt_cp_unblock_device { bdaddr_t bdaddr; } __packed; Loading @@ -285,81 +309,82 @@ struct mgmt_ev_controller_error { #define MGMT_EV_INDEX_REMOVED 0x0005 #define MGMT_EV_POWERED 0x0006 #define MGMT_EV_NEW_SETTINGS 0x0006 #define MGMT_EV_DISCOVERABLE 0x0007 #define MGMT_EV_CONNECTABLE 0x0008 #define MGMT_EV_CLASS_OF_DEV_CHANGED 0x0007 struct mgmt_ev_class_of_dev_changed { __u8 dev_class[3]; }; #define MGMT_EV_PAIRABLE 0x0009 #define MGMT_EV_LOCAL_NAME_CHANGED 0x0008 struct mgmt_ev_local_name_changed { __u8 name[MGMT_MAX_NAME_LENGTH]; __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH]; } __packed; #define MGMT_EV_NEW_LINK_KEY 0x000A #define MGMT_EV_NEW_LINK_KEY 0x0009 struct mgmt_ev_new_link_key { __u8 store_hint; struct mgmt_link_key_info key; } __packed; #define MGMT_EV_CONNECTED 0x000B #define MGMT_EV_CONNECTED 0x000A #define MGMT_EV_DISCONNECTED 0x000C #define MGMT_EV_DISCONNECTED 0x000B #define MGMT_EV_CONNECT_FAILED 0x000D #define MGMT_EV_CONNECT_FAILED 0x000C struct mgmt_ev_connect_failed { struct mgmt_addr_info addr; __u8 status; } __packed; #define MGMT_EV_PIN_CODE_REQUEST 0x000E #define MGMT_EV_PIN_CODE_REQUEST 0x000D struct mgmt_ev_pin_code_request { bdaddr_t bdaddr; __u8 secure; } __packed; #define MGMT_EV_USER_CONFIRM_REQUEST 0x000F #define MGMT_EV_USER_CONFIRM_REQUEST 0x000E struct mgmt_ev_user_confirm_request { bdaddr_t bdaddr; __u8 confirm_hint; __le32 value; } __packed; #define MGMT_EV_USER_PASSKEY_REQUEST 0x000F struct mgmt_ev_user_passkey_request { bdaddr_t bdaddr; } __packed; #define MGMT_EV_AUTH_FAILED 0x0010 struct mgmt_ev_auth_failed { bdaddr_t bdaddr; __u8 status; } __packed; #define MGMT_EV_LOCAL_NAME_CHANGED 0x0011 struct mgmt_ev_local_name_changed { __u8 name[MGMT_MAX_NAME_LENGTH]; } __packed; #define MGMT_EV_DEVICE_FOUND 0x0012 #define MGMT_EV_DEVICE_FOUND 0x0011 struct mgmt_ev_device_found { struct mgmt_addr_info addr; __u8 dev_class[3]; __s8 rssi; __u8 confirm_name; __u8 eir[HCI_MAX_EIR_LENGTH]; } __packed; #define MGMT_EV_REMOTE_NAME 0x0013 #define MGMT_EV_REMOTE_NAME 0x0012 struct mgmt_ev_remote_name { bdaddr_t bdaddr; __u8 name[MGMT_MAX_NAME_LENGTH]; } __packed; #define MGMT_EV_DISCOVERING 0x0014 #define MGMT_EV_DISCOVERING 0x0013 #define MGMT_EV_DEVICE_BLOCKED 0x0015 #define MGMT_EV_DEVICE_BLOCKED 0x0014 struct mgmt_ev_device_blocked { bdaddr_t bdaddr; } __packed; #define MGMT_EV_DEVICE_UNBLOCKED 0x0016 #define MGMT_EV_DEVICE_UNBLOCKED 0x0015 struct mgmt_ev_device_unblocked { bdaddr_t bdaddr; } __packed; #define MGMT_EV_USER_PASSKEY_REQUEST 0x0017 struct mgmt_ev_user_passkey_request { bdaddr_t bdaddr; } __packed;
net/bluetooth/hci_conn.c +59 −78 Original line number Diff line number Diff line Loading @@ -275,9 +275,10 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status) } } static void hci_conn_timeout(unsigned long arg) static void hci_conn_timeout(struct work_struct *work) { struct hci_conn *conn = (void *) arg; struct hci_conn *conn = container_of(work, struct hci_conn, disc_work.work); struct hci_dev *hdev = conn->hdev; __u8 reason; Loading Loading @@ -311,6 +312,42 @@ static void hci_conn_timeout(unsigned long arg) hci_dev_unlock(hdev); } /* Enter sniff mode */ static void hci_conn_enter_sniff_mode(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; BT_DBG("conn %p mode %d", conn, conn->mode); if (test_bit(HCI_RAW, &hdev->flags)) return; if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn)) return; if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF)) return; if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) { struct hci_cp_sniff_subrate cp; cp.handle = cpu_to_le16(conn->handle); cp.max_latency = cpu_to_le16(0); cp.min_remote_timeout = cpu_to_le16(0); cp.min_local_timeout = cpu_to_le16(0); hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp); } if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { struct hci_cp_sniff_mode cp; cp.handle = cpu_to_le16(conn->handle); cp.max_interval = cpu_to_le16(hdev->sniff_max_interval); cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); cp.attempt = cpu_to_le16(4); cp.timeout = cpu_to_le16(1); hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp); } } static void hci_conn_idle(unsigned long arg) { struct hci_conn *conn = (void *) arg; Loading @@ -325,12 +362,8 @@ static void hci_conn_auto_accept(unsigned long arg) struct hci_conn *conn = (void *) arg; struct hci_dev *hdev = conn->hdev; hci_dev_lock(hdev); hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY, sizeof(conn->dst), &conn->dst); hci_dev_unlock(hdev); } struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) Loading Loading @@ -374,9 +407,9 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) skb_queue_head_init(&conn->data_q); hci_chan_hash_init(conn); INIT_LIST_HEAD(&conn->chan_list);; setup_timer(&conn->disc_timer, hci_conn_timeout, (unsigned long)conn); INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); setup_timer(&conn->idle_timer, hci_conn_idle, (unsigned long)conn); setup_timer(&conn->auto_accept_timer, hci_conn_auto_accept, (unsigned long) conn); Loading @@ -385,8 +418,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) hci_dev_hold(hdev); tasklet_disable(&hdev->tx_task); hci_conn_hash_add(hdev, conn); if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_CONN_ADD); Loading @@ -395,8 +426,6 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) hci_conn_init_sysfs(conn); tasklet_enable(&hdev->tx_task); return conn; } Loading @@ -408,7 +437,7 @@ int hci_conn_del(struct hci_conn *conn) del_timer(&conn->idle_timer); del_timer(&conn->disc_timer); cancel_delayed_work_sync(&conn->disc_work); del_timer(&conn->auto_accept_timer); Loading @@ -432,16 +461,13 @@ int hci_conn_del(struct hci_conn *conn) } } tasklet_disable(&hdev->tx_task); hci_chan_hash_flush(conn); hci_chan_list_flush(conn); hci_conn_hash_del(hdev, conn); if (hdev->notify) hdev->notify(hdev, HCI_NOTIFY_CONN_DEL); tasklet_enable(&hdev->tx_task); skb_queue_purge(&conn->data_q); hci_conn_put_device(conn); Loading Loading @@ -674,7 +700,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) goto encrypt; auth: if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->pend)) return 0; if (!hci_conn_auth(conn, sec_level, auth_type)) Loading Loading @@ -767,57 +793,15 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active) jiffies + msecs_to_jiffies(hdev->idle_timeout)); } /* Enter sniff mode */ void hci_conn_enter_sniff_mode(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; BT_DBG("conn %p mode %d", conn, conn->mode); if (test_bit(HCI_RAW, &hdev->flags)) return; if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn)) return; if (conn->mode != HCI_CM_ACTIVE || !(conn->link_policy & HCI_LP_SNIFF)) return; if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) { struct hci_cp_sniff_subrate cp; cp.handle = cpu_to_le16(conn->handle); cp.max_latency = cpu_to_le16(0); cp.min_remote_timeout = cpu_to_le16(0); cp.min_local_timeout = cpu_to_le16(0); hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp); } if (!test_and_set_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->pend)) { struct hci_cp_sniff_mode cp; cp.handle = cpu_to_le16(conn->handle); cp.max_interval = cpu_to_le16(hdev->sniff_max_interval); cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); cp.attempt = cpu_to_le16(4); cp.timeout = cpu_to_le16(1); hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp); } } /* Drop all connection on the device */ void hci_conn_hash_flush(struct hci_dev *hdev) { struct hci_conn_hash *h = &hdev->conn_hash; struct list_head *p; BT_DBG("hdev %s", hdev->name); p = h->list.next; while (p != &h->list) { struct hci_conn *c; c = list_entry(p, struct hci_conn, list); p = p->next; BT_DBG("hdev %s", hdev->name); list_for_each_entry_rcu(c, &h->list, list) { c->state = BT_CLOSED; hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM); Loading Loading @@ -882,7 +866,7 @@ int hci_get_conn_list(void __user *arg) ci = cl->conn_info; hci_dev_lock_bh(hdev); hci_dev_lock(hdev); list_for_each_entry(c, &hdev->conn_hash.list, list) { bacpy(&(ci + n)->bdaddr, &c->dst); (ci + n)->handle = c->handle; Loading @@ -893,7 +877,7 @@ int hci_get_conn_list(void __user *arg) if (++n >= req.conn_num) break; } hci_dev_unlock_bh(hdev); hci_dev_unlock(hdev); cl->dev_id = hdev->id; cl->conn_num = n; Loading @@ -917,7 +901,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg) if (copy_from_user(&req, arg, sizeof(req))) return -EFAULT; hci_dev_lock_bh(hdev); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, req.type, &req.bdaddr); if (conn) { bacpy(&ci.bdaddr, &conn->dst); Loading @@ -927,7 +911,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg) ci.state = conn->state; ci.link_mode = conn->link_mode; } hci_dev_unlock_bh(hdev); hci_dev_unlock(hdev); if (!conn) return -ENOENT; Loading @@ -943,11 +927,11 @@ int hci_get_auth_info(struct hci_dev *hdev, void __user *arg) if (copy_from_user(&req, arg, sizeof(req))) return -EFAULT; hci_dev_lock_bh(hdev); hci_dev_lock(hdev); conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &req.bdaddr); if (conn) req.type = conn->auth_type; hci_dev_unlock_bh(hdev); hci_dev_unlock(hdev); if (!conn) return -ENOENT; Loading @@ -969,9 +953,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn) chan->conn = conn; skb_queue_head_init(&chan->data_q); tasklet_disable(&hdev->tx_task); hci_chan_hash_add(conn, chan); tasklet_enable(&hdev->tx_task); list_add_rcu(&chan->list, &conn->chan_list); return chan; } Loading @@ -983,9 +965,9 @@ int hci_chan_del(struct hci_chan *chan) BT_DBG("%s conn %p chan %p", hdev->name, conn, chan); tasklet_disable(&hdev->tx_task); hci_chan_hash_del(conn, chan); tasklet_enable(&hdev->tx_task); list_del_rcu(&chan->list); synchronize_rcu(); skb_queue_purge(&chan->data_q); kfree(chan); Loading @@ -993,13 +975,12 @@ int hci_chan_del(struct hci_chan *chan) return 0; } void hci_chan_hash_flush(struct hci_conn *conn) void hci_chan_list_flush(struct hci_conn *conn) { struct hci_chan_hash *h = &conn->chan_hash; struct hci_chan *chan, *tmp; struct hci_chan *chan; BT_DBG("conn %p", conn); list_for_each_entry_safe(chan, tmp, &h->list, list) list_for_each_entry_rcu(chan, &conn->chan_list, list) hci_chan_del(chan); }