Loading include/net/bluetooth/hci.h +25 −2 Original line number Diff line number Diff line Loading @@ -126,6 +126,8 @@ enum { HCI_SSP_ENABLED, HCI_SC_ENABLED, HCI_SC_ONLY, HCI_PRIVACY, HCI_RPA_EXPIRED, HCI_RPA_RESOLVING, HCI_HS_ENABLED, HCI_LE_ENABLED, Loading @@ -138,6 +140,7 @@ enum { HCI_FAST_CONNECTABLE, HCI_BREDR_ENABLED, HCI_6LOWPAN_ENABLED, HCI_LE_SCAN_INTERRUPTED, }; /* A mask for the flags that are supposed to remain when a reset happens Loading Loading @@ -180,6 +183,8 @@ enum { #define HCI_CMD_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ #define HCI_ACL_TX_TIMEOUT msecs_to_jiffies(45000) /* 45 seconds */ #define HCI_AUTO_OFF_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ #define HCI_POWER_OFF_TIMEOUT msecs_to_jiffies(5000) /* 5 seconds */ #define HCI_LE_CONN_TIMEOUT msecs_to_jiffies(20000) /* 20 seconds */ /* HCI data types */ #define HCI_COMMAND_PKT 0x01 Loading Loading @@ -354,6 +359,7 @@ enum { /* ---- HCI Error Codes ---- */ #define HCI_ERROR_AUTH_FAILURE 0x05 #define HCI_ERROR_MEMORY_EXCEEDED 0x07 #define HCI_ERROR_CONNECTION_TIMEOUT 0x08 #define HCI_ERROR_REJ_BAD_ADDR 0x0f #define HCI_ERROR_REMOTE_USER_TERM 0x13 Loading Loading @@ -1178,6 +1184,9 @@ struct hci_cp_le_set_scan_enable { __u8 filter_dup; } __packed; #define HCI_LE_USE_PEER_ADDR 0x00 #define HCI_LE_USE_WHITELIST 0x01 #define HCI_OP_LE_CREATE_CONN 0x200d struct hci_cp_le_create_conn { __le16 scan_interval; Loading @@ -1202,6 +1211,20 @@ struct hci_rp_le_read_white_list_size { __u8 size; } __packed; #define HCI_OP_LE_CLEAR_WHITE_LIST 0x2010 #define HCI_OP_LE_ADD_TO_WHITE_LIST 0x2011 struct hci_cp_le_add_to_white_list { __u8 bdaddr_type; bdaddr_t bdaddr; } __packed; #define HCI_OP_LE_DEL_FROM_WHITE_LIST 0x2012 struct hci_cp_le_del_from_white_list { __u8 bdaddr_type; bdaddr_t bdaddr; } __packed; #define HCI_OP_LE_CONN_UPDATE 0x2013 struct hci_cp_le_conn_update { __le16 handle; Loading @@ -1216,7 +1239,7 @@ struct hci_cp_le_conn_update { #define HCI_OP_LE_START_ENC 0x2019 struct hci_cp_le_start_enc { __le16 handle; __u8 rand[8]; __le64 rand; __le16 ediv; __u8 ltk[16]; } __packed; Loading Loading @@ -1628,7 +1651,7 @@ struct hci_ev_le_conn_complete { #define HCI_EV_LE_LTK_REQ 0x05 struct hci_ev_le_ltk_req { __le16 handle; __u8 random[8]; __le64 rand; __le16 ediv; } __packed; Loading include/net/bluetooth/hci_core.h +67 −11 Original line number Diff line number Diff line Loading @@ -99,7 +99,7 @@ struct smp_ltk { u8 type; u8 enc_size; __le16 ediv; u8 rand[8]; __le64 rand; u8 val[16]; }; Loading Loading @@ -130,6 +130,9 @@ struct oob_data { #define HCI_MAX_SHORT_NAME_LENGTH 10 /* Default LE RPA expiry time, 15 minutes */ #define HCI_DEFAULT_RPA_TIMEOUT (15 * 60) struct amp_assoc { __u16 len; __u16 offset; Loading @@ -153,7 +156,7 @@ struct hci_dev { bdaddr_t bdaddr; bdaddr_t random_addr; bdaddr_t static_addr; __u8 own_addr_type; __u8 adv_addr_type; __u8 dev_name[HCI_MAX_NAME_LENGTH]; __u8 short_name[HCI_MAX_SHORT_NAME_LENGTH]; __u8 eir[HCI_MAX_EIR_LENGTH]; Loading Loading @@ -281,7 +284,9 @@ struct hci_dev { struct list_head long_term_keys; struct list_head identity_resolving_keys; struct list_head remote_oob_data; struct list_head le_white_list; struct list_head le_conn_params; struct list_head pend_le_conns; struct hci_dev_stats stat; Loading @@ -303,6 +308,11 @@ struct hci_dev { __u8 scan_rsp_data[HCI_MAX_AD_LENGTH]; __u8 scan_rsp_data_len; __u8 irk[16]; __u32 rpa_timeout; struct delayed_work rpa_expired; bdaddr_t rpa; int (*open)(struct hci_dev *hdev); int (*close)(struct hci_dev *hdev); int (*flush)(struct hci_dev *hdev); Loading @@ -322,6 +332,10 @@ struct hci_conn { __u8 dst_type; bdaddr_t src; __u8 src_type; bdaddr_t init_addr; __u8 init_addr_type; bdaddr_t resp_addr; __u8 resp_addr_type; __u16 handle; __u16 state; __u8 mode; Loading Loading @@ -361,6 +375,7 @@ struct hci_conn { struct delayed_work disc_work; struct delayed_work auto_accept_work; struct delayed_work idle_work; struct delayed_work le_conn_timeout; struct device dev; Loading Loading @@ -394,6 +409,12 @@ struct hci_conn_params { u16 conn_min_interval; u16 conn_max_interval; enum { HCI_AUTO_CONN_DISABLED, HCI_AUTO_CONN_ALWAYS, HCI_AUTO_CONN_LINK_LOSS, } auto_connect; }; extern struct list_head hci_dev_list; Loading Loading @@ -554,6 +575,13 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type) } } static inline unsigned int hci_conn_count(struct hci_dev *hdev) { struct hci_conn_hash *c = &hdev->conn_hash; return c->acl_num + c->amp_num + c->sco_num + c->le_num; } static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev, __u16 handle) { Loading Loading @@ -627,8 +655,10 @@ void hci_chan_del(struct hci_chan *chan); void hci_chan_list_flush(struct hci_conn *conn); struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle); struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 dst_type, __u8 sec_level, __u8 auth_type); struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, u8 dst_type, u8 sec_level, u8 auth_type); struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, u8 sec_level, u8 auth_type); struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, __u16 setting); int hci_conn_check_link_mode(struct hci_conn *conn); Loading @@ -639,6 +669,8 @@ 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_le_conn_failed(struct hci_conn *conn, u8 status); /* * hci_conn_get() and hci_conn_put() are used to control the life-time of an * "hci_conn" object. They do not guarantee that the hci_conn object is running, Loading Loading @@ -770,28 +802,42 @@ int hci_inquiry(void __user *arg); struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); void hci_blacklist_clear(struct hci_dev *hdev); 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); struct bdaddr_list *hci_white_list_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); void hci_white_list_clear(struct hci_dev *hdev); int hci_white_list_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int hci_white_list_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type); void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, u16 conn_min_interval, u16 conn_max_interval); int hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, u8 auto_connect, u16 conn_min_interval, u16 conn_max_interval); void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type); void hci_conn_params_clear(struct hci_dev *hdev); struct bdaddr_list *hci_pend_le_conn_lookup(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type); void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type); void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type); void hci_pend_le_conns_clear(struct hci_dev *hdev); void hci_update_background_scan(struct hci_dev *hdev); void hci_uuids_clear(struct hci_dev *hdev); void hci_link_keys_clear(struct hci_dev *hdev); struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len); struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8], struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand, bool master); struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type, u8 authenticated, u8 tk[16], u8 enc_size, __le16 ediv, u8 rand[8]); u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand); struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, bool master); int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type); Loading Loading @@ -1115,6 +1161,9 @@ void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, const void *param, u8 event); void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status); void hci_req_add_le_scan_disable(struct hci_request *req); void hci_req_add_le_passive_scan(struct hci_request *req); struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen, const void *param, u32 timeout); struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen, Loading Loading @@ -1160,6 +1209,7 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered); void mgmt_discoverable_timeout(struct hci_dev *hdev); void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); void mgmt_connectable(struct hci_dev *hdev, u8 connectable); void mgmt_advertising(struct hci_dev *hdev, u8 advertising); void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, bool persistent); Loading @@ -1167,7 +1217,8 @@ 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 *dev_class); void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 reason); u8 link_type, u8 addr_type, u8 reason, bool mgmt_connected); void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 status); void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, Loading Loading @@ -1247,9 +1298,14 @@ struct hci_sec_filter { void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, 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, __le64 rand, __u8 ltk[16]); int hci_update_random_address(struct hci_request *req, bool require_privacy, u8 *own_addr_type); void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *bdaddr_type); #define SCO_AIRMODE_MASK 0x0003 #define SCO_AIRMODE_CVSD 0x0000 #define SCO_AIRMODE_TRANSP 0x0003 Loading include/net/bluetooth/mgmt.h +9 −1 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ struct mgmt_rp_read_index_list { #define MGMT_SETTING_ADVERTISING 0x00000400 #define MGMT_SETTING_SECURE_CONN 0x00000800 #define MGMT_SETTING_DEBUG_KEYS 0x00001000 #define MGMT_SETTING_PRIVACY 0x00002000 #define MGMT_OP_READ_INFO 0x0004 #define MGMT_READ_INFO_SIZE 0 Loading Loading @@ -186,7 +187,7 @@ struct mgmt_ltk_info { __u8 master; __u8 enc_size; __le16 ediv; __u8 rand[8]; __le64 rand; __u8 val[16]; } __packed; Loading Loading @@ -389,6 +390,13 @@ struct mgmt_cp_set_scan_params { #define MGMT_OP_SET_DEBUG_KEYS 0x002E #define MGMT_OP_SET_PRIVACY 0x002F struct mgmt_cp_set_privacy { __u8 privacy; __u8 irk[16]; } __packed; #define MGMT_SET_PRIVACY_SIZE 17 struct mgmt_irk_info { struct mgmt_addr_info addr; __u8 val[16]; Loading net/bluetooth/hci_conn.c +66 −50 Original line number Diff line number Diff line Loading @@ -231,7 +231,7 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp); } 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, __le64 rand, __u8 ltk[16]) { struct hci_dev *hdev = conn->hdev; Loading @@ -242,9 +242,9 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], memset(&cp, 0, sizeof(cp)); cp.handle = cpu_to_le16(conn->handle); memcpy(cp.ltk, ltk, sizeof(cp.ltk)); cp.rand = rand; cp.ediv = ediv; memcpy(cp.rand, rand, sizeof(cp.rand)); memcpy(cp.ltk, ltk, sizeof(cp.ltk)); hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp); } Loading Loading @@ -363,6 +363,16 @@ static void hci_conn_auto_accept(struct work_struct *work) &conn->dst); } static void le_conn_timeout(struct work_struct *work) { struct hci_conn *conn = container_of(work, struct hci_conn, le_conn_timeout.work); BT_DBG(""); hci_le_create_connection_cancel(conn); } struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) { struct hci_conn *conn; Loading Loading @@ -410,6 +420,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); INIT_DELAYED_WORK(&conn->auto_accept_work, hci_conn_auto_accept); INIT_DELAYED_WORK(&conn->idle_work, hci_conn_idle); INIT_DELAYED_WORK(&conn->le_conn_timeout, le_conn_timeout); atomic_set(&conn->refcnt, 0); Loading Loading @@ -442,6 +453,8 @@ int hci_conn_del(struct hci_conn *conn) /* Unacked frames */ hdev->acl_cnt += conn->sent; } else if (conn->type == LE_LINK) { cancel_delayed_work_sync(&conn->le_conn_timeout); if (hdev->le_pkts) hdev->le_cnt += conn->sent; else Loading Loading @@ -515,7 +528,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) EXPORT_SYMBOL(hci_get_route); /* This function requires the caller holds hdev->lock */ static void le_conn_failed(struct hci_conn *conn, u8 status) void hci_le_conn_failed(struct hci_conn *conn, u8 status) { struct hci_dev *hdev = conn->hdev; Loading @@ -527,6 +540,11 @@ static void le_conn_failed(struct hci_conn *conn, u8 status) hci_proto_connect_cfm(conn, status); hci_conn_del(conn); /* Since we may have temporarily stopped the background scanning in * favor of connection establishment, we should restart it. */ hci_update_background_scan(hdev); } static void create_le_conn_complete(struct hci_dev *hdev, u8 status) Loading @@ -545,50 +563,55 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status) if (!conn) goto done; le_conn_failed(conn, status); hci_le_conn_failed(conn, status); done: hci_dev_unlock(hdev); } static int hci_create_le_conn(struct hci_conn *conn) static void hci_req_add_le_create_conn(struct hci_request *req, struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; struct hci_cp_le_create_conn cp; struct hci_request req; int err; hci_req_init(&req, hdev); struct hci_dev *hdev = conn->hdev; u8 own_addr_type; memset(&cp, 0, sizeof(cp)); /* Update random address, but set require_privacy to false so * that we never connect with an unresolvable address. */ if (hci_update_random_address(req, false, &own_addr_type)) return; /* Save the address type used for this connnection attempt so we able * to retrieve this information if we need it. */ conn->src_type = own_addr_type; cp.scan_interval = cpu_to_le16(hdev->le_scan_interval); cp.scan_window = cpu_to_le16(hdev->le_scan_window); bacpy(&cp.peer_addr, &conn->dst); cp.peer_addr_type = conn->dst_type; cp.own_address_type = conn->src_type; cp.own_address_type = own_addr_type; cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval); cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval); cp.supervision_timeout = __constant_cpu_to_le16(0x002a); cp.min_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); err = hci_req_run(&req, create_le_conn_complete); if (err) { hci_conn_del(conn); return err; } hci_req_add(req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); return 0; conn->state = BT_CONNECT; } static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, u8 dst_type, u8 sec_level, u8 auth_type) { struct hci_conn_params *params; struct hci_conn *conn; struct smp_irk *irk; struct hci_request req; int err; if (test_bit(HCI_ADVERTISING, &hdev->flags)) Loading Loading @@ -617,12 +640,6 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, if (conn) return ERR_PTR(-EBUSY); /* Convert from L2CAP channel address type to HCI address type */ if (dst_type == BDADDR_LE_PUBLIC) dst_type = ADDR_LE_DEV_PUBLIC; else dst_type = ADDR_LE_DEV_RANDOM; /* When given an identity address with existing identity * resolving key, the connection needs to be established * to a resolvable random address. Loading @@ -647,9 +664,7 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, return ERR_PTR(-ENOMEM); conn->dst_type = dst_type; conn->src_type = hdev->own_addr_type; conn->state = BT_CONNECT; conn->out = true; conn->link_mode |= HCI_LM_MASTER; conn->sec_level = BT_SECURITY_LOW; Loading @@ -665,16 +680,33 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, conn->le_conn_max_interval = hdev->le_conn_max_interval; } err = hci_create_le_conn(conn); if (err) hci_req_init(&req, hdev); /* If controller is scanning, we stop it since some controllers are * not able to scan and connect at the same time. Also set the * HCI_LE_SCAN_INTERRUPTED flag so that the command complete * handler for scan disabling knows to set the correct discovery * state. */ if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) { hci_req_add_le_scan_disable(&req); set_bit(HCI_LE_SCAN_INTERRUPTED, &hdev->dev_flags); } hci_req_add_le_create_conn(&req, conn); err = hci_req_run(&req, create_le_conn_complete); if (err) { hci_conn_del(conn); return ERR_PTR(err); } done: hci_conn_hold(conn); return conn; } static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, u8 sec_level, u8 auth_type) { struct hci_conn *acl; Loading Loading @@ -744,22 +776,6 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, return sco; } /* Create SCO, ACL or LE connection. */ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 dst_type, __u8 sec_level, __u8 auth_type) { BT_DBG("%s dst %pMR type 0x%x", hdev->name, dst, type); switch (type) { case LE_LINK: return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); case ACL_LINK: return hci_connect_acl(hdev, dst, sec_level, auth_type); } return ERR_PTR(-EINVAL); } /* Check link security requirement */ int hci_conn_check_link_mode(struct hci_conn *conn) { Loading Loading
include/net/bluetooth/hci.h +25 −2 Original line number Diff line number Diff line Loading @@ -126,6 +126,8 @@ enum { HCI_SSP_ENABLED, HCI_SC_ENABLED, HCI_SC_ONLY, HCI_PRIVACY, HCI_RPA_EXPIRED, HCI_RPA_RESOLVING, HCI_HS_ENABLED, HCI_LE_ENABLED, Loading @@ -138,6 +140,7 @@ enum { HCI_FAST_CONNECTABLE, HCI_BREDR_ENABLED, HCI_6LOWPAN_ENABLED, HCI_LE_SCAN_INTERRUPTED, }; /* A mask for the flags that are supposed to remain when a reset happens Loading Loading @@ -180,6 +183,8 @@ enum { #define HCI_CMD_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ #define HCI_ACL_TX_TIMEOUT msecs_to_jiffies(45000) /* 45 seconds */ #define HCI_AUTO_OFF_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ #define HCI_POWER_OFF_TIMEOUT msecs_to_jiffies(5000) /* 5 seconds */ #define HCI_LE_CONN_TIMEOUT msecs_to_jiffies(20000) /* 20 seconds */ /* HCI data types */ #define HCI_COMMAND_PKT 0x01 Loading Loading @@ -354,6 +359,7 @@ enum { /* ---- HCI Error Codes ---- */ #define HCI_ERROR_AUTH_FAILURE 0x05 #define HCI_ERROR_MEMORY_EXCEEDED 0x07 #define HCI_ERROR_CONNECTION_TIMEOUT 0x08 #define HCI_ERROR_REJ_BAD_ADDR 0x0f #define HCI_ERROR_REMOTE_USER_TERM 0x13 Loading Loading @@ -1178,6 +1184,9 @@ struct hci_cp_le_set_scan_enable { __u8 filter_dup; } __packed; #define HCI_LE_USE_PEER_ADDR 0x00 #define HCI_LE_USE_WHITELIST 0x01 #define HCI_OP_LE_CREATE_CONN 0x200d struct hci_cp_le_create_conn { __le16 scan_interval; Loading @@ -1202,6 +1211,20 @@ struct hci_rp_le_read_white_list_size { __u8 size; } __packed; #define HCI_OP_LE_CLEAR_WHITE_LIST 0x2010 #define HCI_OP_LE_ADD_TO_WHITE_LIST 0x2011 struct hci_cp_le_add_to_white_list { __u8 bdaddr_type; bdaddr_t bdaddr; } __packed; #define HCI_OP_LE_DEL_FROM_WHITE_LIST 0x2012 struct hci_cp_le_del_from_white_list { __u8 bdaddr_type; bdaddr_t bdaddr; } __packed; #define HCI_OP_LE_CONN_UPDATE 0x2013 struct hci_cp_le_conn_update { __le16 handle; Loading @@ -1216,7 +1239,7 @@ struct hci_cp_le_conn_update { #define HCI_OP_LE_START_ENC 0x2019 struct hci_cp_le_start_enc { __le16 handle; __u8 rand[8]; __le64 rand; __le16 ediv; __u8 ltk[16]; } __packed; Loading Loading @@ -1628,7 +1651,7 @@ struct hci_ev_le_conn_complete { #define HCI_EV_LE_LTK_REQ 0x05 struct hci_ev_le_ltk_req { __le16 handle; __u8 random[8]; __le64 rand; __le16 ediv; } __packed; Loading
include/net/bluetooth/hci_core.h +67 −11 Original line number Diff line number Diff line Loading @@ -99,7 +99,7 @@ struct smp_ltk { u8 type; u8 enc_size; __le16 ediv; u8 rand[8]; __le64 rand; u8 val[16]; }; Loading Loading @@ -130,6 +130,9 @@ struct oob_data { #define HCI_MAX_SHORT_NAME_LENGTH 10 /* Default LE RPA expiry time, 15 minutes */ #define HCI_DEFAULT_RPA_TIMEOUT (15 * 60) struct amp_assoc { __u16 len; __u16 offset; Loading @@ -153,7 +156,7 @@ struct hci_dev { bdaddr_t bdaddr; bdaddr_t random_addr; bdaddr_t static_addr; __u8 own_addr_type; __u8 adv_addr_type; __u8 dev_name[HCI_MAX_NAME_LENGTH]; __u8 short_name[HCI_MAX_SHORT_NAME_LENGTH]; __u8 eir[HCI_MAX_EIR_LENGTH]; Loading Loading @@ -281,7 +284,9 @@ struct hci_dev { struct list_head long_term_keys; struct list_head identity_resolving_keys; struct list_head remote_oob_data; struct list_head le_white_list; struct list_head le_conn_params; struct list_head pend_le_conns; struct hci_dev_stats stat; Loading @@ -303,6 +308,11 @@ struct hci_dev { __u8 scan_rsp_data[HCI_MAX_AD_LENGTH]; __u8 scan_rsp_data_len; __u8 irk[16]; __u32 rpa_timeout; struct delayed_work rpa_expired; bdaddr_t rpa; int (*open)(struct hci_dev *hdev); int (*close)(struct hci_dev *hdev); int (*flush)(struct hci_dev *hdev); Loading @@ -322,6 +332,10 @@ struct hci_conn { __u8 dst_type; bdaddr_t src; __u8 src_type; bdaddr_t init_addr; __u8 init_addr_type; bdaddr_t resp_addr; __u8 resp_addr_type; __u16 handle; __u16 state; __u8 mode; Loading Loading @@ -361,6 +375,7 @@ struct hci_conn { struct delayed_work disc_work; struct delayed_work auto_accept_work; struct delayed_work idle_work; struct delayed_work le_conn_timeout; struct device dev; Loading Loading @@ -394,6 +409,12 @@ struct hci_conn_params { u16 conn_min_interval; u16 conn_max_interval; enum { HCI_AUTO_CONN_DISABLED, HCI_AUTO_CONN_ALWAYS, HCI_AUTO_CONN_LINK_LOSS, } auto_connect; }; extern struct list_head hci_dev_list; Loading Loading @@ -554,6 +575,13 @@ static inline unsigned int hci_conn_num(struct hci_dev *hdev, __u8 type) } } static inline unsigned int hci_conn_count(struct hci_dev *hdev) { struct hci_conn_hash *c = &hdev->conn_hash; return c->acl_num + c->amp_num + c->sco_num + c->le_num; } static inline struct hci_conn *hci_conn_hash_lookup_handle(struct hci_dev *hdev, __u16 handle) { Loading Loading @@ -627,8 +655,10 @@ void hci_chan_del(struct hci_chan *chan); void hci_chan_list_flush(struct hci_conn *conn); struct hci_chan *hci_chan_lookup_handle(struct hci_dev *hdev, __u16 handle); struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 dst_type, __u8 sec_level, __u8 auth_type); struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, u8 dst_type, u8 sec_level, u8 auth_type); struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, u8 sec_level, u8 auth_type); struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, __u16 setting); int hci_conn_check_link_mode(struct hci_conn *conn); Loading @@ -639,6 +669,8 @@ 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_le_conn_failed(struct hci_conn *conn, u8 status); /* * hci_conn_get() and hci_conn_put() are used to control the life-time of an * "hci_conn" object. They do not guarantee that the hci_conn object is running, Loading Loading @@ -770,28 +802,42 @@ int hci_inquiry(void __user *arg); struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); void hci_blacklist_clear(struct hci_dev *hdev); 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); struct bdaddr_list *hci_white_list_lookup(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); void hci_white_list_clear(struct hci_dev *hdev); int hci_white_list_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); int hci_white_list_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type); void hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, u16 conn_min_interval, u16 conn_max_interval); int hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, u8 auto_connect, u16 conn_min_interval, u16 conn_max_interval); void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type); void hci_conn_params_clear(struct hci_dev *hdev); struct bdaddr_list *hci_pend_le_conn_lookup(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type); void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type); void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type); void hci_pend_le_conns_clear(struct hci_dev *hdev); void hci_update_background_scan(struct hci_dev *hdev); void hci_uuids_clear(struct hci_dev *hdev); void hci_link_keys_clear(struct hci_dev *hdev); struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr); int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len); struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8], struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand, bool master); struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type, u8 authenticated, u8 tk[16], u8 enc_size, __le16 ediv, u8 rand[8]); u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand); struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, bool master); int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type); Loading Loading @@ -1115,6 +1161,9 @@ void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, const void *param, u8 event); void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status); void hci_req_add_le_scan_disable(struct hci_request *req); void hci_req_add_le_passive_scan(struct hci_request *req); struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen, const void *param, u32 timeout); struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen, Loading Loading @@ -1160,6 +1209,7 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered); void mgmt_discoverable_timeout(struct hci_dev *hdev); void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); void mgmt_connectable(struct hci_dev *hdev, u8 connectable); void mgmt_advertising(struct hci_dev *hdev, u8 advertising); void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, bool persistent); Loading @@ -1167,7 +1217,8 @@ 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 *dev_class); void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 reason); u8 link_type, u8 addr_type, u8 reason, bool mgmt_connected); void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 status); void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, Loading Loading @@ -1247,9 +1298,14 @@ struct hci_sec_filter { void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, 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, __le64 rand, __u8 ltk[16]); int hci_update_random_address(struct hci_request *req, bool require_privacy, u8 *own_addr_type); void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *bdaddr_type); #define SCO_AIRMODE_MASK 0x0003 #define SCO_AIRMODE_CVSD 0x0000 #define SCO_AIRMODE_TRANSP 0x0003 Loading
include/net/bluetooth/mgmt.h +9 −1 Original line number Diff line number Diff line Loading @@ -96,6 +96,7 @@ struct mgmt_rp_read_index_list { #define MGMT_SETTING_ADVERTISING 0x00000400 #define MGMT_SETTING_SECURE_CONN 0x00000800 #define MGMT_SETTING_DEBUG_KEYS 0x00001000 #define MGMT_SETTING_PRIVACY 0x00002000 #define MGMT_OP_READ_INFO 0x0004 #define MGMT_READ_INFO_SIZE 0 Loading Loading @@ -186,7 +187,7 @@ struct mgmt_ltk_info { __u8 master; __u8 enc_size; __le16 ediv; __u8 rand[8]; __le64 rand; __u8 val[16]; } __packed; Loading Loading @@ -389,6 +390,13 @@ struct mgmt_cp_set_scan_params { #define MGMT_OP_SET_DEBUG_KEYS 0x002E #define MGMT_OP_SET_PRIVACY 0x002F struct mgmt_cp_set_privacy { __u8 privacy; __u8 irk[16]; } __packed; #define MGMT_SET_PRIVACY_SIZE 17 struct mgmt_irk_info { struct mgmt_addr_info addr; __u8 val[16]; Loading
net/bluetooth/hci_conn.c +66 −50 Original line number Diff line number Diff line Loading @@ -231,7 +231,7 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp); } 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, __le64 rand, __u8 ltk[16]) { struct hci_dev *hdev = conn->hdev; Loading @@ -242,9 +242,9 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], memset(&cp, 0, sizeof(cp)); cp.handle = cpu_to_le16(conn->handle); memcpy(cp.ltk, ltk, sizeof(cp.ltk)); cp.rand = rand; cp.ediv = ediv; memcpy(cp.rand, rand, sizeof(cp.rand)); memcpy(cp.ltk, ltk, sizeof(cp.ltk)); hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp); } Loading Loading @@ -363,6 +363,16 @@ static void hci_conn_auto_accept(struct work_struct *work) &conn->dst); } static void le_conn_timeout(struct work_struct *work) { struct hci_conn *conn = container_of(work, struct hci_conn, le_conn_timeout.work); BT_DBG(""); hci_le_create_connection_cancel(conn); } struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) { struct hci_conn *conn; Loading Loading @@ -410,6 +420,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); INIT_DELAYED_WORK(&conn->auto_accept_work, hci_conn_auto_accept); INIT_DELAYED_WORK(&conn->idle_work, hci_conn_idle); INIT_DELAYED_WORK(&conn->le_conn_timeout, le_conn_timeout); atomic_set(&conn->refcnt, 0); Loading Loading @@ -442,6 +453,8 @@ int hci_conn_del(struct hci_conn *conn) /* Unacked frames */ hdev->acl_cnt += conn->sent; } else if (conn->type == LE_LINK) { cancel_delayed_work_sync(&conn->le_conn_timeout); if (hdev->le_pkts) hdev->le_cnt += conn->sent; else Loading Loading @@ -515,7 +528,7 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) EXPORT_SYMBOL(hci_get_route); /* This function requires the caller holds hdev->lock */ static void le_conn_failed(struct hci_conn *conn, u8 status) void hci_le_conn_failed(struct hci_conn *conn, u8 status) { struct hci_dev *hdev = conn->hdev; Loading @@ -527,6 +540,11 @@ static void le_conn_failed(struct hci_conn *conn, u8 status) hci_proto_connect_cfm(conn, status); hci_conn_del(conn); /* Since we may have temporarily stopped the background scanning in * favor of connection establishment, we should restart it. */ hci_update_background_scan(hdev); } static void create_le_conn_complete(struct hci_dev *hdev, u8 status) Loading @@ -545,50 +563,55 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status) if (!conn) goto done; le_conn_failed(conn, status); hci_le_conn_failed(conn, status); done: hci_dev_unlock(hdev); } static int hci_create_le_conn(struct hci_conn *conn) static void hci_req_add_le_create_conn(struct hci_request *req, struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; struct hci_cp_le_create_conn cp; struct hci_request req; int err; hci_req_init(&req, hdev); struct hci_dev *hdev = conn->hdev; u8 own_addr_type; memset(&cp, 0, sizeof(cp)); /* Update random address, but set require_privacy to false so * that we never connect with an unresolvable address. */ if (hci_update_random_address(req, false, &own_addr_type)) return; /* Save the address type used for this connnection attempt so we able * to retrieve this information if we need it. */ conn->src_type = own_addr_type; cp.scan_interval = cpu_to_le16(hdev->le_scan_interval); cp.scan_window = cpu_to_le16(hdev->le_scan_window); bacpy(&cp.peer_addr, &conn->dst); cp.peer_addr_type = conn->dst_type; cp.own_address_type = conn->src_type; cp.own_address_type = own_addr_type; cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval); cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval); cp.supervision_timeout = __constant_cpu_to_le16(0x002a); cp.min_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); err = hci_req_run(&req, create_le_conn_complete); if (err) { hci_conn_del(conn); return err; } hci_req_add(req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); return 0; conn->state = BT_CONNECT; } static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, u8 dst_type, u8 sec_level, u8 auth_type) { struct hci_conn_params *params; struct hci_conn *conn; struct smp_irk *irk; struct hci_request req; int err; if (test_bit(HCI_ADVERTISING, &hdev->flags)) Loading Loading @@ -617,12 +640,6 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, if (conn) return ERR_PTR(-EBUSY); /* Convert from L2CAP channel address type to HCI address type */ if (dst_type == BDADDR_LE_PUBLIC) dst_type = ADDR_LE_DEV_PUBLIC; else dst_type = ADDR_LE_DEV_RANDOM; /* When given an identity address with existing identity * resolving key, the connection needs to be established * to a resolvable random address. Loading @@ -647,9 +664,7 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, return ERR_PTR(-ENOMEM); conn->dst_type = dst_type; conn->src_type = hdev->own_addr_type; conn->state = BT_CONNECT; conn->out = true; conn->link_mode |= HCI_LM_MASTER; conn->sec_level = BT_SECURITY_LOW; Loading @@ -665,16 +680,33 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, conn->le_conn_max_interval = hdev->le_conn_max_interval; } err = hci_create_le_conn(conn); if (err) hci_req_init(&req, hdev); /* If controller is scanning, we stop it since some controllers are * not able to scan and connect at the same time. Also set the * HCI_LE_SCAN_INTERRUPTED flag so that the command complete * handler for scan disabling knows to set the correct discovery * state. */ if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) { hci_req_add_le_scan_disable(&req); set_bit(HCI_LE_SCAN_INTERRUPTED, &hdev->dev_flags); } hci_req_add_le_create_conn(&req, conn); err = hci_req_run(&req, create_le_conn_complete); if (err) { hci_conn_del(conn); return ERR_PTR(err); } done: hci_conn_hold(conn); return conn; } static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, u8 sec_level, u8 auth_type) { struct hci_conn *acl; Loading Loading @@ -744,22 +776,6 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, return sco; } /* Create SCO, ACL or LE connection. */ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 dst_type, __u8 sec_level, __u8 auth_type) { BT_DBG("%s dst %pMR type 0x%x", hdev->name, dst, type); switch (type) { case LE_LINK: return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); case ACL_LINK: return hci_connect_acl(hdev, dst, sec_level, auth_type); } return ERR_PTR(-EINVAL); } /* Check link security requirement */ int hci_conn_check_link_mode(struct hci_conn *conn) { Loading