diff options
Diffstat (limited to 'include/net/bluetooth/hci_core.h')
-rw-r--r-- | include/net/bluetooth/hci_core.h | 193 |
1 files changed, 123 insertions, 70 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index f8555ad7..3ede820 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -81,7 +81,6 @@ struct hci_conn_hash { struct bdaddr_list { struct list_head list; bdaddr_t bdaddr; - u8 bdaddr_type; }; struct bt_uuid { @@ -141,8 +140,6 @@ struct hci_dev { __u8 bus; __u8 dev_type; bdaddr_t bdaddr; - bdaddr_t static_addr; - __u8 own_addr_type; __u8 dev_name[HCI_MAX_NAME_LENGTH]; __u8 short_name[HCI_MAX_SHORT_NAME_LENGTH]; __u8 eir[HCI_MAX_EIR_LENGTH]; @@ -161,17 +158,11 @@ struct hci_dev { __u16 manufacturer; __u16 lmp_subver; __u16 voice_setting; - __u8 num_iac; __u8 io_capability; __s8 inq_tx_power; __u16 page_scan_interval; __u16 page_scan_window; __u8 page_scan_type; - __u16 le_scan_interval; - __u16 le_scan_window; - __u16 le_conn_min_interval; - __u16 le_conn_max_interval; - __u8 ssp_debug_mode; __u16 devid_source; __u16 devid_vendor; @@ -288,15 +279,14 @@ struct hci_dev { __s8 adv_tx_power; __u8 adv_data[HCI_MAX_AD_LENGTH]; __u8 adv_data_len; - __u8 scan_rsp_data[HCI_MAX_AD_LENGTH]; - __u8 scan_rsp_data_len; int (*open)(struct hci_dev *hdev); int (*close)(struct hci_dev *hdev); int (*flush)(struct hci_dev *hdev); int (*setup)(struct hci_dev *hdev); - int (*send)(struct hci_dev *hdev, struct sk_buff *skb); + int (*send)(struct sk_buff *skb); void (*notify)(struct hci_dev *hdev, unsigned int evt); + int (*ioctl)(struct hci_dev *hdev, unsigned int cmd, unsigned long arg); }; #define HCI_PHY_HANDLE(handle) (handle & 0xff) @@ -308,8 +298,6 @@ struct hci_conn { bdaddr_t dst; __u8 dst_type; - bdaddr_t src; - __u8 src_type; __u16 handle; __u16 state; __u8 mode; @@ -318,6 +306,7 @@ struct hci_conn { __u8 attempt; __u8 dev_class[3]; __u8 features[HCI_MAX_PAGES][8]; + __u16 interval; __u16 pkt_type; __u16 link_policy; __u32 link_mode; @@ -345,8 +334,8 @@ struct hci_conn { struct list_head chan_list; struct delayed_work disc_work; - struct delayed_work auto_accept_work; - struct delayed_work idle_work; + struct timer_list idle_timer; + struct timer_list auto_accept_timer; struct device dev; @@ -378,17 +367,18 @@ extern rwlock_t hci_dev_list_lock; extern rwlock_t hci_cb_list_lock; /* ----- HCI interface to upper protocols ----- */ -int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); -void l2cap_connect_cfm(struct hci_conn *hcon, u8 status); -int l2cap_disconn_ind(struct hci_conn *hcon); -void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason); -int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt); -int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags); - -int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags); -void sco_connect_cfm(struct hci_conn *hcon, __u8 status); -void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason); -int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb); +extern int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr); +extern void l2cap_connect_cfm(struct hci_conn *hcon, u8 status); +extern int l2cap_disconn_ind(struct hci_conn *hcon); +extern void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason); +extern int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt); +extern int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, + u16 flags); + +extern int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags); +extern void sco_connect_cfm(struct hci_conn *hcon, __u8 status); +extern void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason); +extern int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb); /* ----- Inquiry cache ----- */ #define INQUIRY_CACHE_AGE_MAX (HZ*30) /* 30 seconds */ @@ -654,7 +644,7 @@ static inline void hci_conn_drop(struct hci_conn *conn) switch (conn->type) { case ACL_LINK: case LE_LINK: - cancel_delayed_work(&conn->idle_work); + del_timer(&conn->idle_timer); if (conn->state == BT_CONNECTED) { timeo = conn->disc_timeout; if (!conn->out) @@ -713,6 +703,19 @@ static inline void hci_set_drvdata(struct hci_dev *hdev, void *data) dev_set_drvdata(&hdev->dev, data); } +/* hci_dev_list shall be locked */ +static inline uint8_t __hci_num_ctrl(void) +{ + uint8_t count = 0; + struct list_head *p; + + list_for_each(p, &hci_dev_list) { + count++; + } + + return count; +} + struct hci_dev *hci_dev_get(int index); struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src); @@ -735,7 +738,7 @@ int hci_get_auth_info(struct hci_dev *hdev, void __user *arg); int hci_inquiry(void __user *arg); struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, - bdaddr_t *bdaddr, u8 type); + bdaddr_t *bdaddr); int 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); @@ -765,11 +768,13 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr); void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb); -int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb); +int hci_recv_frame(struct sk_buff *skb); 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); 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_add_sysfs(struct hci_conn *conn); void hci_conn_del_sysfs(struct hci_conn *conn); @@ -802,6 +807,22 @@ void hci_conn_del_sysfs(struct hci_conn *conn); #define lmp_host_le_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE)) #define lmp_host_le_br_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE_BREDR)) +/* returns true if at least one AMP active */ +static inline bool hci_amp_capable(void) +{ + struct hci_dev *hdev; + bool ret = false; + + read_lock(&hci_dev_list_lock); + list_for_each_entry(hdev, &hci_dev_list, list) + if (hdev->amp_type == HCI_AMP && + test_bit(HCI_UP, &hdev->flags)) + ret = true; + read_unlock(&hci_dev_list_lock); + + return ret; +} + /* ----- HCI protocols ----- */ #define HCI_PROTO_DEFER 0x01 @@ -1012,6 +1033,34 @@ static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type) 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_unregister_cb(struct hci_cb *hcb); @@ -1071,30 +1120,29 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event); #define DISCOV_BREDR_INQUIRY_LEN 0x08 int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); -void mgmt_index_added(struct hci_dev *hdev); -void mgmt_index_removed(struct hci_dev *hdev); -void mgmt_set_powered_failed(struct hci_dev *hdev, int err); +int mgmt_index_added(struct hci_dev *hdev); +int mgmt_index_removed(struct hci_dev *hdev); +int mgmt_set_powered_failed(struct hci_dev *hdev, int err); 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_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); -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); -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, - u8 addr_type, u8 status); -void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure); -void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, - u8 status); -void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, - u8 status); +int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); +int mgmt_connectable(struct hci_dev *hdev, u8 connectable); +int mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status); +int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, + bool persistent); +int 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); +int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, + u8 link_type, u8 addr_type, u8 reason); +int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, + u8 link_type, u8 addr_type, u8 status); +int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, + u8 addr_type, u8 status); +int 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, + u8 status); +int mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, + u8 status); int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, __le32 value, u8 confirm_hint); @@ -1111,25 +1159,26 @@ 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, u8 link_type, u8 addr_type, u32 passkey, u8 entered); -void mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, - u8 addr_type, u8 status); -void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status); -void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status); -void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, - u8 status); -void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status); -void mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, - u8 *randomizer, u8 status); -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 ssp, u8 *eir, u16 eir_len); -void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, - u8 addr_type, s8 rssi, u8 *name, u8 name_len); -void mgmt_discovering(struct hci_dev *hdev, u8 discovering); +int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, + u8 addr_type, u8 status); +int mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status); +int 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, + u8 status); +int 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, + u8 *randomizer, u8 status); +int mgmt_le_enable_complete(struct hci_dev *hdev, u8 enable, u8 status); +int 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 ssp, u8 *eir, u16 eir_len); +int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, + u8 addr_type, s8 rssi, u8 *name, u8 name_len); +int mgmt_discovering(struct hci_dev *hdev, u8 discovering); 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); -void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent); -void mgmt_reenable_advertising(struct hci_dev *hdev); +bool mgmt_valid_hdev(struct hci_dev *hdev); +int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) @@ -1159,11 +1208,15 @@ struct hci_sec_filter { #define hci_req_lock(d) mutex_lock(&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, u16 latency, u16 to_multiplier); void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], __u8 ltk[16]); +u8 bdaddr_to_le(u8 bdaddr_type); + #define SCO_AIRMODE_MASK 0x0003 #define SCO_AIRMODE_CVSD 0x0000 #define SCO_AIRMODE_TRANSP 0x0003 |