diff options
Diffstat (limited to 'include/net/bluetooth')
-rw-r--r-- | include/net/bluetooth/bluetooth.h | 45 | ||||
-rw-r--r-- | include/net/bluetooth/hci.h | 59 | ||||
-rw-r--r-- | include/net/bluetooth/hci_core.h | 233 | ||||
-rw-r--r-- | include/net/bluetooth/mgmt.h | 101 |
4 files changed, 292 insertions, 146 deletions
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index e00455aab18c..7dba80546f16 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -245,10 +245,10 @@ int bt_sock_register(int proto, const struct net_proto_family *ops); void bt_sock_unregister(int proto); void bt_sock_link(struct bt_sock_list *l, struct sock *s); void bt_sock_unlink(struct bt_sock_list *l, struct sock *s); -int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, size_t len, int flags); -int bt_sock_stream_recvmsg(struct kiocb *iocb, struct socket *sock, - struct msghdr *msg, size_t len, int flags); +int bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, + int flags); +int bt_sock_stream_recvmsg(struct socket *sock, struct msghdr *msg, + size_t len, int flags); uint bt_sock_poll(struct file *file, struct socket *sock, poll_table *wait); int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg); int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo); @@ -269,29 +269,34 @@ struct l2cap_ctrl { __u16 reqseq; __u16 txseq; __u8 retries; + __le16 psm; + bdaddr_t bdaddr; + struct l2cap_chan *chan; }; struct hci_dev; typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status, u16 opcode); - -struct hci_req_ctrl { - bool start; - u8 event; - hci_req_complete_t complete; +typedef void (*hci_req_complete_skb_t)(struct hci_dev *hdev, u8 status, + u16 opcode, struct sk_buff *skb); + +struct req_ctrl { + bool start; + u8 event; + hci_req_complete_t complete; + hci_req_complete_skb_t complete_skb; }; struct bt_skb_cb { __u8 pkt_type; - __u8 incoming; + __u8 force_active; __u16 opcode; __u16 expect; - __u8 force_active; - struct l2cap_chan *chan; - struct l2cap_ctrl control; - struct hci_req_ctrl req; - bdaddr_t bdaddr; - __le16 psm; + __u8 incoming:1; + union { + struct l2cap_ctrl l2cap; + struct req_ctrl req; + }; }; #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) @@ -339,6 +344,11 @@ out: int bt_to_errno(__u16 code); +void hci_sock_set_flag(struct sock *sk, int nr); +void hci_sock_clear_flag(struct sock *sk, int nr); +int hci_sock_test_flag(struct sock *sk, int nr); +unsigned short hci_sock_get_channel(struct sock *sk); + int hci_sock_init(void); void hci_sock_cleanup(void); @@ -358,6 +368,9 @@ void l2cap_exit(void); int sco_init(void); void sco_exit(void); +int mgmt_init(void); +void mgmt_exit(void); + void bt_sock_reclassify_lock(struct sock *sk, int proto); #endif /* __BLUETOOTH_H */ diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 8e54f825153c..d95da83cb1b0 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -160,6 +160,14 @@ enum { * during the hdev->setup vendor callback. */ HCI_QUIRK_STRICT_DUPLICATE_FILTER, + + /* When this quirk is set, LE scan and BR/EDR inquiry is done + * simultaneously, otherwise it's interleaved. + * + * This quirk can be set before hci_register_dev is called or + * during the hdev->setup vendor callback. + */ + HCI_QUIRK_SIMULTANEOUS_DISCOVERY, }; /* HCI device flags */ @@ -179,13 +187,14 @@ enum { HCI_RESET, }; -/* BR/EDR and/or LE controller flags: the flags defined here should represent - * states configured via debugfs for debugging and testing purposes only. - */ +/* HCI socket flags */ enum { - HCI_DUT_MODE, - HCI_FORCE_BREDR_SMP, - HCI_FORCE_STATIC_ADDR, + HCI_SOCK_TRUSTED, + HCI_MGMT_INDEX_EVENTS, + HCI_MGMT_UNCONF_INDEX_EVENTS, + HCI_MGMT_EXT_INDEX_EVENTS, + HCI_MGMT_GENERIC_EVENTS, + HCI_MGMT_OOB_DATA_EVENTS, }; /* @@ -217,6 +226,8 @@ enum { HCI_HS_ENABLED, HCI_LE_ENABLED, HCI_ADVERTISING, + HCI_ADVERTISING_CONNECTABLE, + HCI_ADVERTISING_INSTANCE, HCI_CONNECTABLE, HCI_DISCOVERABLE, HCI_LIMITED_DISCOVERABLE, @@ -225,13 +236,13 @@ enum { HCI_FAST_CONNECTABLE, HCI_BREDR_ENABLED, HCI_LE_SCAN_INTERRUPTED, -}; -/* A mask for the flags that are supposed to remain when a reset happens - * or the HCI device is closed. - */ -#define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ) | \ - BIT(HCI_FAST_CONNECTABLE) | BIT(HCI_LE_ADV)) + HCI_DUT_MODE, + HCI_FORCE_BREDR_SMP, + HCI_FORCE_STATIC_ADDR, + + __HCI_NUM_FLAGS, +}; /* HCI timeouts */ #define HCI_DISCONN_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ @@ -363,6 +374,7 @@ enum { /* LE features */ #define HCI_LE_ENCRYPTION 0x01 #define HCI_LE_CONN_PARAM_REQ_PROC 0x02 +#define HCI_LE_SLAVE_FEATURES 0x08 #define HCI_LE_PING 0x10 #define HCI_LE_DATA_LEN_EXT 0x20 #define HCI_LE_EXT_SCAN_POLICY 0x80 @@ -452,9 +464,16 @@ enum { #define EIR_NAME_COMPLETE 0x09 /* complete local name */ #define EIR_TX_POWER 0x0A /* transmit power level */ #define EIR_CLASS_OF_DEV 0x0D /* Class of Device */ -#define EIR_SSP_HASH_C 0x0E /* Simple Pairing Hash C */ -#define EIR_SSP_RAND_R 0x0F /* Simple Pairing Randomizer R */ +#define EIR_SSP_HASH_C192 0x0E /* Simple Pairing Hash C-192 */ +#define EIR_SSP_RAND_R192 0x0F /* Simple Pairing Randomizer R-192 */ #define EIR_DEVICE_ID 0x10 /* device ID */ +#define EIR_APPEARANCE 0x19 /* Device appearance */ +#define EIR_LE_BDADDR 0x1B /* LE Bluetooth device address */ +#define EIR_LE_ROLE 0x1C /* LE role */ +#define EIR_SSP_HASH_C256 0x1D /* Simple Pairing Hash C-256 */ +#define EIR_SSP_RAND_R256 0x1E /* Simple Pairing Rand R-256 */ +#define EIR_LE_SC_CONFIRM 0x22 /* LE SC Confirmation Value */ +#define EIR_LE_SC_RANDOM 0x23 /* LE SC Random Value */ /* Low Energy Advertising Flags */ #define LE_AD_LIMITED 0x01 /* Limited Discoverable */ @@ -1358,6 +1377,11 @@ struct hci_cp_le_conn_update { __le16 max_ce_len; } __packed; +#define HCI_OP_LE_READ_REMOTE_FEATURES 0x2016 +struct hci_cp_le_read_remote_features { + __le16 handle; +} __packed; + #define HCI_OP_LE_START_ENC 0x2019 struct hci_cp_le_start_enc { __le16 handle; @@ -1850,6 +1874,13 @@ struct hci_ev_le_conn_update_complete { __le16 supervision_timeout; } __packed; +#define HCI_EV_LE_REMOTE_FEAT_COMPLETE 0x04 +struct hci_ev_le_remote_feat_complete { + __u8 status; + __le16 handle; + __u8 features[8]; +} __packed; + #define HCI_EV_LE_LTK_REQ 0x05 struct hci_ev_le_ltk_req { __le16 handle; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 52863c3e0b13..a056c2bfeb81 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -76,6 +76,7 @@ struct discovery_state { u8 last_adv_data[HCI_MAX_AD_LENGTH]; u8 last_adv_data_len; bool report_invalid_rssi; + bool result_filtering; s8 rssi; u16 uuid_count; u8 (*uuids)[16]; @@ -108,7 +109,7 @@ struct bt_uuid { struct smp_csrk { bdaddr_t bdaddr; u8 bdaddr_type; - u8 master; + u8 type; u8 val[16]; }; @@ -154,6 +155,17 @@ struct oob_data { u8 rand256[16]; }; +struct adv_info { + struct delayed_work timeout_exp; + __u8 instance; + __u32 flags; + __u16 timeout; + __u16 adv_data_len; + __u8 adv_data[HCI_MAX_AD_LENGTH]; + __u16 scan_rsp_len; + __u8 scan_rsp_data[HCI_MAX_AD_LENGTH]; +}; + #define HCI_MAX_SHORT_NAME_LENGTH 10 /* Default LE RPA expiry time, 15 minutes */ @@ -173,7 +185,6 @@ struct amp_assoc { #define HCI_MAX_PAGES 3 -#define NUM_REASSEMBLY 4 struct hci_dev { struct list_head list; struct mutex lock; @@ -314,14 +325,13 @@ struct hci_dev { struct sk_buff_head raw_q; struct sk_buff_head cmd_q; - struct sk_buff *recv_evt; struct sk_buff *sent_cmd; - struct sk_buff *reassembly[NUM_REASSEMBLY]; struct mutex req_lock; wait_queue_head_t req_wait_q; __u32 req_status; __u32 req_result; + struct sk_buff *req_skb; void *smp_data; void *smp_bredr_data; @@ -352,8 +362,7 @@ struct hci_dev { struct rfkill *rfkill; - unsigned long dbg_flags; - unsigned long dev_flags; + DECLARE_BITMAP(dev_flags, __HCI_NUM_FLAGS); struct delayed_work le_scan_disable; struct delayed_work le_scan_restart; @@ -364,6 +373,8 @@ struct hci_dev { __u8 scan_rsp_data[HCI_MAX_AD_LENGTH]; __u8 scan_rsp_data_len; + struct adv_info adv_instance; + __u8 irk[16]; __u32 rpa_timeout; struct delayed_work rpa_expired; @@ -373,6 +384,7 @@ struct hci_dev { int (*close)(struct hci_dev *hdev); int (*flush)(struct hci_dev *hdev); int (*setup)(struct hci_dev *hdev); + int (*shutdown)(struct hci_dev *hdev); int (*send)(struct hci_dev *hdev, struct sk_buff *skb); void (*notify)(struct hci_dev *hdev, unsigned int evt); void (*hw_error)(struct hci_dev *hdev, u8 code); @@ -498,19 +510,29 @@ struct hci_conn_params { extern struct list_head hci_dev_list; extern struct list_head hci_cb_list; extern rwlock_t hci_dev_list_lock; -extern rwlock_t hci_cb_list_lock; +extern struct mutex hci_cb_list_lock; + +#define hci_dev_set_flag(hdev, nr) set_bit((nr), (hdev)->dev_flags) +#define hci_dev_clear_flag(hdev, nr) clear_bit((nr), (hdev)->dev_flags) +#define hci_dev_change_flag(hdev, nr) change_bit((nr), (hdev)->dev_flags) +#define hci_dev_test_flag(hdev, nr) test_bit((nr), (hdev)->dev_flags) +#define hci_dev_test_and_set_flag(hdev, nr) test_and_set_bit((nr), (hdev)->dev_flags) +#define hci_dev_test_and_clear_flag(hdev, nr) test_and_clear_bit((nr), (hdev)->dev_flags) +#define hci_dev_test_and_change_flag(hdev, nr) test_and_change_bit((nr), (hdev)->dev_flags) + +#define hci_dev_clear_volatile_flags(hdev) \ + do { \ + hci_dev_clear_flag(hdev, HCI_LE_SCAN); \ + hci_dev_clear_flag(hdev, HCI_LE_ADV); \ + hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ); \ + } while (0) /* ----- 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); /* ----- Inquiry cache ----- */ @@ -529,6 +551,7 @@ static inline void discovery_init(struct hci_dev *hdev) static inline void hci_discovery_filter_clear(struct hci_dev *hdev) { + hdev->discovery.result_filtering = false; hdev->discovery.report_invalid_rssi = true; hdev->discovery.rssi = HCI_RSSI_INVALID; hdev->discovery.uuid_count = 0; @@ -538,6 +561,11 @@ static inline void hci_discovery_filter_clear(struct hci_dev *hdev) hdev->discovery.scan_duration = 0; } +static inline void adv_info_init(struct hci_dev *hdev) +{ + memset(&hdev->adv_instance, 0, sizeof(struct adv_info)); +} + bool hci_discovery_active(struct hci_dev *hdev); void hci_discovery_set_state(struct hci_dev *hdev, int state); @@ -584,7 +612,6 @@ enum { HCI_CONN_SC_ENABLED, HCI_CONN_AES_CCM, HCI_CONN_POWER_SAVE, - HCI_CONN_REMOTE_OOB, HCI_CONN_FLUSH_KEY, HCI_CONN_ENCRYPT, HCI_CONN_AUTH, @@ -600,14 +627,14 @@ enum { static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; - return test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) && + return hci_dev_test_flag(hdev, HCI_SSP_ENABLED) && test_bit(HCI_CONN_SSP_ENABLED, &conn->flags); } static inline bool hci_conn_sc_enabled(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; - return test_bit(HCI_SC_ENABLED, &hdev->dev_flags) && + return hci_dev_test_flag(hdev, HCI_SC_ENABLED) && test_bit(HCI_CONN_SC_ENABLED, &conn->flags); } @@ -969,6 +996,8 @@ struct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type); void hci_smp_irks_clear(struct hci_dev *hdev); +bool hci_bdaddr_is_paired(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type); + void hci_remote_oob_data_clear(struct hci_dev *hdev); struct oob_data *hci_find_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type); @@ -981,7 +1010,6 @@ 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_stream_fragment(struct hci_dev *hdev, void *data, int count); void hci_init_sysfs(struct hci_dev *hdev); void hci_conn_init_sysfs(struct hci_conn *conn); @@ -1025,10 +1053,10 @@ 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)) -#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \ - !test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) -#define bredr_sc_enabled(dev) (lmp_sc_capable(dev) && \ - test_bit(HCI_SC_ENABLED, &(dev)->dev_flags)) +#define hdev_is_powered(dev) (test_bit(HCI_UP, &(dev)->flags) && \ + !hci_dev_test_flag(dev, HCI_AUTO_OFF)) +#define bredr_sc_enabled(dev) (lmp_sc_capable(dev) && \ + hci_dev_test_flag(dev, HCI_SC_ENABLED)) /* ----- HCI protocols ----- */ #define HCI_PROTO_DEFER 0x01 @@ -1050,28 +1078,6 @@ static inline int hci_proto_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, } } -static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status) -{ - switch (conn->type) { - case ACL_LINK: - case LE_LINK: - l2cap_connect_cfm(conn, status); - break; - - case SCO_LINK: - case ESCO_LINK: - sco_connect_cfm(conn, status); - break; - - default: - BT_ERR("unknown link type %d", conn->type); - break; - } - - if (conn->connect_cfm_cb) - conn->connect_cfm_cb(conn, status); -} - static inline int hci_proto_disconn_ind(struct hci_conn *conn) { if (conn->type != ACL_LINK && conn->type != LE_LINK) @@ -1080,91 +1086,69 @@ static inline int hci_proto_disconn_ind(struct hci_conn *conn) return l2cap_disconn_ind(conn); } -static inline void hci_proto_disconn_cfm(struct hci_conn *conn, __u8 reason) -{ - switch (conn->type) { - case ACL_LINK: - case LE_LINK: - l2cap_disconn_cfm(conn, reason); - break; - - case SCO_LINK: - case ESCO_LINK: - sco_disconn_cfm(conn, reason); - break; - - /* L2CAP would be handled for BREDR chan */ - case AMP_LINK: - break; +/* ----- HCI callbacks ----- */ +struct hci_cb { + struct list_head list; - default: - BT_ERR("unknown link type %d", conn->type); - break; - } + char *name; - if (conn->disconn_cfm_cb) - conn->disconn_cfm_cb(conn, reason); -} + void (*connect_cfm) (struct hci_conn *conn, __u8 status); + void (*disconn_cfm) (struct hci_conn *conn, __u8 status); + void (*security_cfm) (struct hci_conn *conn, __u8 status, + __u8 encrypt); + void (*key_change_cfm) (struct hci_conn *conn, __u8 status); + void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role); +}; -static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status) +static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status) { - __u8 encrypt; - - if (conn->type != ACL_LINK && conn->type != LE_LINK) - return; - - if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) - return; + struct hci_cb *cb; - encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00; - l2cap_security_cfm(conn, status, encrypt); + mutex_lock(&hci_cb_list_lock); + list_for_each_entry(cb, &hci_cb_list, list) { + if (cb->connect_cfm) + cb->connect_cfm(conn, status); + } + mutex_unlock(&hci_cb_list_lock); - if (conn->security_cfm_cb) - conn->security_cfm_cb(conn, status); + if (conn->connect_cfm_cb) + conn->connect_cfm_cb(conn, status); } -static inline void hci_proto_encrypt_cfm(struct hci_conn *conn, __u8 status, - __u8 encrypt) +static inline void hci_disconn_cfm(struct hci_conn *conn, __u8 reason) { - if (conn->type != ACL_LINK && conn->type != LE_LINK) - return; + struct hci_cb *cb; - l2cap_security_cfm(conn, status, encrypt); + mutex_lock(&hci_cb_list_lock); + list_for_each_entry(cb, &hci_cb_list, list) { + if (cb->disconn_cfm) + cb->disconn_cfm(conn, reason); + } + mutex_unlock(&hci_cb_list_lock); - if (conn->security_cfm_cb) - conn->security_cfm_cb(conn, status); + if (conn->disconn_cfm_cb) + conn->disconn_cfm_cb(conn, reason); } -/* ----- HCI callbacks ----- */ -struct hci_cb { - struct list_head list; - - char *name; - - void (*security_cfm) (struct hci_conn *conn, __u8 status, - __u8 encrypt); - void (*key_change_cfm) (struct hci_conn *conn, __u8 status); - void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role); -}; - static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) { struct hci_cb *cb; __u8 encrypt; - hci_proto_auth_cfm(conn, status); - if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) return; encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00; - read_lock(&hci_cb_list_lock); + mutex_lock(&hci_cb_list_lock); list_for_each_entry(cb, &hci_cb_list, list) { if (cb->security_cfm) cb->security_cfm(conn, status, encrypt); } - read_unlock(&hci_cb_list_lock); + mutex_unlock(&hci_cb_list_lock); + + if (conn->security_cfm_cb) + conn->security_cfm_cb(conn, status); } static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, @@ -1178,26 +1162,27 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status, if (conn->pending_sec_level > conn->sec_level) conn->sec_level = conn->pending_sec_level; - hci_proto_encrypt_cfm(conn, status, encrypt); - - read_lock(&hci_cb_list_lock); + mutex_lock(&hci_cb_list_lock); list_for_each_entry(cb, &hci_cb_list, list) { if (cb->security_cfm) cb->security_cfm(conn, status, encrypt); } - read_unlock(&hci_cb_list_lock); + mutex_unlock(&hci_cb_list_lock); + + if (conn->security_cfm_cb) + conn->security_cfm_cb(conn, status); } static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status) { struct hci_cb *cb; - read_lock(&hci_cb_list_lock); + mutex_lock(&hci_cb_list_lock); list_for_each_entry(cb, &hci_cb_list, list) { if (cb->key_change_cfm) cb->key_change_cfm(conn, status); } - read_unlock(&hci_cb_list_lock); + mutex_unlock(&hci_cb_list_lock); } static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, @@ -1205,12 +1190,12 @@ static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status, { struct hci_cb *cb; - read_lock(&hci_cb_list_lock); + mutex_lock(&hci_cb_list_lock); list_for_each_entry(cb, &hci_cb_list, list) { if (cb->role_switch_cfm) cb->role_switch_cfm(conn, status, role); } - read_unlock(&hci_cb_list_lock); + mutex_unlock(&hci_cb_list_lock); } static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type) @@ -1296,8 +1281,6 @@ static inline int hci_check_conn_params(u16 min, u16 max, u16 latency, int hci_register_cb(struct hci_cb *hcb); int hci_unregister_cb(struct hci_cb *hcb); -bool hci_req_pending(struct hci_dev *hdev); - 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, @@ -1312,11 +1295,35 @@ void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode); /* ----- HCI Sockets ----- */ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb); -void hci_send_to_control(struct sk_buff *skb, struct sock *skip_sk); +void hci_send_to_channel(unsigned short channel, struct sk_buff *skb, + int flag, struct sock *skip_sk); void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb); void hci_sock_dev_event(struct hci_dev *hdev, int event); +#define HCI_MGMT_VAR_LEN BIT(0) +#define HCI_MGMT_NO_HDEV BIT(1) +#define HCI_MGMT_UNTRUSTED BIT(2) +#define HCI_MGMT_UNCONFIGURED BIT(3) + +struct hci_mgmt_handler { + int (*func) (struct sock *sk, struct hci_dev *hdev, void *data, + u16 data_len); + size_t data_len; + unsigned long flags; +}; + +struct hci_mgmt_chan { + struct list_head list; + unsigned short channel; + size_t handler_count; + const struct hci_mgmt_handler *handlers; + void (*hdev_init) (struct sock *sk, struct hci_dev *hdev); +}; + +int hci_mgmt_chan_register(struct hci_mgmt_chan *c); +void hci_mgmt_chan_unregister(struct hci_mgmt_chan *c); + /* Management interface */ #define DISCOV_TYPE_BREDR (BIT(BDADDR_BREDR)) #define DISCOV_TYPE_LE (BIT(BDADDR_LE_PUBLIC) | \ @@ -1336,7 +1343,6 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event); #define DISCOV_BREDR_INQUIRY_LEN 0x08 #define DISCOV_LE_RESTART_DELAY msecs_to_jiffies(200) /* msec */ -int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); int mgmt_new_settings(struct hci_dev *hdev); void mgmt_index_added(struct hci_dev *hdev); void mgmt_index_removed(struct hci_dev *hdev); @@ -1382,9 +1388,6 @@ 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_complete(struct hci_dev *hdev, u8 *hash192, - u8 *rand192, u8 *hash256, u8 *rand256, - u8 status); void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 *dev_class, s8 rssi, u32 flags, u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len); diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index e218a30f2061..b831242d48a4 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -43,6 +43,8 @@ #define MGMT_STATUS_CANCELLED 0x10 #define MGMT_STATUS_INVALID_INDEX 0x11 #define MGMT_STATUS_RFKILLED 0x12 +#define MGMT_STATUS_ALREADY_PAIRED 0x13 +#define MGMT_STATUS_PERMISSION_DENIED 0x14 struct mgmt_hdr { __le16 opcode; @@ -98,6 +100,7 @@ struct mgmt_rp_read_index_list { #define MGMT_SETTING_DEBUG_KEYS 0x00001000 #define MGMT_SETTING_PRIVACY 0x00002000 #define MGMT_SETTING_CONFIGURATION 0x00004000 +#define MGMT_SETTING_STATIC_ADDRESS 0x00008000 #define MGMT_OP_READ_INFO 0x0004 #define MGMT_READ_INFO_SIZE 0 @@ -503,6 +506,71 @@ struct mgmt_cp_start_service_discovery { } __packed; #define MGMT_START_SERVICE_DISCOVERY_SIZE 4 +#define MGMT_OP_READ_LOCAL_OOB_EXT_DATA 0x003B +struct mgmt_cp_read_local_oob_ext_data { + __u8 type; +} __packed; +#define MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE 1 +struct mgmt_rp_read_local_oob_ext_data { + __u8 type; + __le16 eir_len; + __u8 eir[0]; +} __packed; + +#define MGMT_OP_READ_EXT_INDEX_LIST 0x003C +#define MGMT_READ_EXT_INDEX_LIST_SIZE 0 +struct mgmt_rp_read_ext_index_list { + __le16 num_controllers; + struct { + __le16 index; + __u8 type; + __u8 bus; + } entry[0]; +} __packed; + +#define MGMT_OP_READ_ADV_FEATURES 0x0003D +#define MGMT_READ_ADV_FEATURES_SIZE 0 +struct mgmt_rp_read_adv_features { + __le32 supported_flags; + __u8 max_adv_data_len; + __u8 max_scan_rsp_len; + __u8 max_instances; + __u8 num_instances; + __u8 instance[0]; +} __packed; + +#define MGMT_OP_ADD_ADVERTISING 0x003E +struct mgmt_cp_add_advertising { + __u8 instance; + __le32 flags; + __le16 duration; + __le16 timeout; + __u8 adv_data_len; + __u8 scan_rsp_len; + __u8 data[0]; +} __packed; +#define MGMT_ADD_ADVERTISING_SIZE 11 +struct mgmt_rp_add_advertising { + __u8 instance; +} __packed; + +#define MGMT_ADV_FLAG_CONNECTABLE BIT(0) +#define MGMT_ADV_FLAG_DISCOV BIT(1) +#define MGMT_ADV_FLAG_LIMITED_DISCOV BIT(2) +#define MGMT_ADV_FLAG_MANAGED_FLAGS BIT(3) +#define MGMT_ADV_FLAG_TX_POWER BIT(4) +#define MGMT_ADV_FLAG_APPEARANCE BIT(5) +#define MGMT_ADV_FLAG_LOCAL_NAME BIT(6) + +#define MGMT_OP_REMOVE_ADVERTISING 0x003F +struct mgmt_cp_remove_advertising { + __u8 instance; +} __packed; +#define MGMT_REMOVE_ADVERTISING_SIZE 1 +struct mgmt_rp_remove_advertising { + __u8 instance; +} __packed; + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; @@ -647,9 +715,14 @@ struct mgmt_ev_new_irk { struct mgmt_irk_info irk; } __packed; +#define MGMT_CSRK_LOCAL_UNAUTHENTICATED 0x00 +#define MGMT_CSRK_REMOTE_UNAUTHENTICATED 0x01 +#define MGMT_CSRK_LOCAL_AUTHENTICATED 0x02 +#define MGMT_CSRK_REMOTE_AUTHENTICATED 0x03 + struct mgmt_csrk_info { struct mgmt_addr_info addr; - __u8 master; + __u8 type; __u8 val[16]; } __packed; @@ -685,3 +758,29 @@ struct mgmt_ev_new_conn_param { #define MGMT_EV_UNCONF_INDEX_REMOVED 0x001e #define MGMT_EV_NEW_CONFIG_OPTIONS 0x001f + +struct mgmt_ev_ext_index { + __u8 type; + __u8 bus; +} __packed; + +#define MGMT_EV_EXT_INDEX_ADDED 0x0020 + +#define MGMT_EV_EXT_INDEX_REMOVED 0x0021 + +#define MGMT_EV_LOCAL_OOB_DATA_UPDATED 0x0022 +struct mgmt_ev_local_oob_data_updated { + __u8 type; + __le16 eir_len; + __u8 eir[0]; +} __packed; + +#define MGMT_EV_ADVERTISING_ADDED 0x0023 +struct mgmt_ev_advertising_added { + __u8 instance; +} __packed; + +#define MGMT_EV_ADVERTISING_REMOVED 0x0024 +struct mgmt_ev_advertising_removed { + __u8 instance; +} __packed; |