diff options
author | John W. Linville <linville@tuxdriver.com> | 2014-07-10 21:00:34 (GMT) |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-07-10 21:00:34 (GMT) |
commit | ca424b2022410b6c2cd0bc0f9a0438ed0b75f95f (patch) | |
tree | 3d3a06bdddc3940b06241095a1ae5c7072080d98 /include/net | |
parent | 5c4d5e816c2cc86e17d09677b649be47fbc30e51 (diff) | |
parent | 6fea7ad1d338dba592d65423427a997f1b7ff485 (diff) | |
download | linux-ca424b2022410b6c2cd0bc0f9a0438ed0b75f95f.tar.xz |
Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next
Diffstat (limited to 'include/net')
-rw-r--r-- | include/net/bluetooth/bluetooth.h | 18 | ||||
-rw-r--r-- | include/net/bluetooth/hci.h | 135 | ||||
-rw-r--r-- | include/net/bluetooth/hci_core.h | 134 | ||||
-rw-r--r-- | include/net/bluetooth/l2cap.h | 36 | ||||
-rw-r--r-- | include/net/bluetooth/mgmt.h | 99 |
5 files changed, 353 insertions, 69 deletions
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 904777c1..373000d 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -260,15 +260,15 @@ struct sock *bt_accept_dequeue(struct sock *parent, struct socket *newsock); /* Skb helpers */ struct l2cap_ctrl { - unsigned int sframe:1, - poll:1, - final:1, - fcs:1, - sar:2, - super:2; - __u16 reqseq; - __u16 txseq; - __u8 retries; + __u8 sframe:1, + poll:1, + final:1, + fcs:1, + sar:2, + super:2; + __u16 reqseq; + __u16 txseq; + __u8 retries; }; struct hci_dev; diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 16587dc..a01236e 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -81,10 +81,54 @@ /* HCI device quirks */ enum { + /* When this quirk is set, the HCI Reset command is send when + * closing the transport instead of when opening it. + * + * This quirk must be set before hci_register_dev is called. + */ HCI_QUIRK_RESET_ON_CLOSE, + + /* When this quirk is set, the device is turned into a raw-only + * device and it will stay in unconfigured state. + * + * This quirk must be set before hci_register_dev is called. + */ HCI_QUIRK_RAW_DEVICE, + + /* When this quirk is set, the buffer sizes reported by + * HCI Read Buffer Size command are corrected if invalid. + * + * This quirk must be set before hci_register_dev is called. + */ HCI_QUIRK_FIXUP_BUFFER_SIZE, + + /* When this quirk is set, then no stored link key handling + * is performed. This is mainly due to the fact that the + * HCI Delete Stored Link Key command is advertised, but + * not supported. + * + * This quirk must be set before hci_register_dev is called. + */ HCI_QUIRK_BROKEN_STORED_LINK_KEY, + + /* When this quirk is set, an external configuration step + * is required and will be indicated with the controller + * configuation. + * + * This quirk can be set before hci_register_dev is called or + * during the hdev->setup vendor callback. + */ + HCI_QUIRK_EXTERNAL_CONFIG, + + /* When this quirk is set, the public Bluetooth address + * initially reported by HCI Read BD Address command + * is considered invalid. Controller configuration is + * required before this device can be used. + * + * This quirk can be set before hci_register_dev is called or + * during the hdev->setup vendor callback. + */ + HCI_QUIRK_INVALID_BDADDR, }; /* HCI device flags */ @@ -104,24 +148,34 @@ 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. + */ +enum { + HCI_DUT_MODE, + HCI_FORCE_SC, + HCI_FORCE_STATIC_ADDR, +}; + /* * BR/EDR and/or LE controller flags: the flags defined here should represent * states from the controller. */ enum { HCI_SETUP, + HCI_CONFIG, HCI_AUTO_OFF, HCI_RFKILLED, HCI_MGMT, HCI_PAIRABLE, HCI_SERVICE_CACHE, - HCI_DEBUG_KEYS, - HCI_DUT_MODE, - HCI_FORCE_SC, - HCI_FORCE_STATIC_ADDR, + HCI_KEEP_DEBUG_KEYS, + HCI_USE_DEBUG_KEYS, HCI_UNREGISTER, + HCI_UNCONFIGURED, HCI_USER_CHANNEL, - + HCI_EXT_CONFIGURED, + HCI_LE_ADV, HCI_LE_SCAN, HCI_SSP_ENABLED, HCI_SC_ENABLED, @@ -139,7 +193,6 @@ enum { HCI_PERIODIC_INQ, HCI_FAST_CONNECTABLE, HCI_BREDR_ENABLED, - HCI_6LOWPAN_ENABLED, HCI_LE_SCAN_INTERRUPTED, }; @@ -147,7 +200,7 @@ enum { * or the HCI device is closed. */ #define HCI_PERSISTENT_MASK (BIT(HCI_LE_SCAN) | BIT(HCI_PERIODIC_INQ) | \ - BIT(HCI_FAST_CONNECTABLE)) + BIT(HCI_FAST_CONNECTABLE) | BIT(HCI_LE_ADV)) /* HCI ioctl defines */ #define HCIDEVUP _IOW('H', 201, int) @@ -185,6 +238,7 @@ enum { #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 */ +#define HCI_LE_AUTOCONN_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ /* HCI data types */ #define HCI_COMMAND_PKT 0x01 @@ -301,6 +355,10 @@ enum { #define LMP_HOST_LE_BREDR 0x04 #define LMP_HOST_SC 0x08 +/* LE features */ +#define HCI_LE_CONN_PARAM_REQ_PROC 0x02 +#define HCI_LE_PING 0x10 + /* Connection modes */ #define HCI_CM_ACTIVE 0x0000 #define HCI_CM_HOLD 0x0001 @@ -347,17 +405,9 @@ enum { #define HCI_LK_CHANGED_COMBINATION 0x06 #define HCI_LK_UNAUTH_COMBINATION_P256 0x07 #define HCI_LK_AUTH_COMBINATION_P256 0x08 -/* The spec doesn't define types for SMP keys, the _MASTER suffix is implied */ -#define HCI_SMP_STK 0x80 -#define HCI_SMP_STK_SLAVE 0x81 -#define HCI_SMP_LTK 0x82 -#define HCI_SMP_LTK_SLAVE 0x83 - -/* Long Term Key types */ -#define HCI_LTK_UNAUTH 0x00 -#define HCI_LTK_AUTH 0x01 /* ---- HCI Error Codes ---- */ +#define HCI_ERROR_UNKNOWN_CONN_ID 0x02 #define HCI_ERROR_AUTH_FAILURE 0x05 #define HCI_ERROR_MEMORY_EXCEEDED 0x07 #define HCI_ERROR_CONNECTION_TIMEOUT 0x08 @@ -367,6 +417,7 @@ enum { #define HCI_ERROR_REMOTE_POWER_OFF 0x15 #define HCI_ERROR_LOCAL_HOST_TERM 0x16 #define HCI_ERROR_PAIRING_NOT_ALLOWED 0x18 +#define HCI_ERROR_INVALID_LL_PARAMS 0x1E #define HCI_ERROR_ADVERTISING_TIMEOUT 0x3c /* Flow control modes */ @@ -536,6 +587,11 @@ struct hci_cp_read_remote_version { __le16 handle; } __packed; +#define HCI_OP_READ_CLOCK_OFFSET 0x041f +struct hci_cp_read_clock_offset { + __le16 handle; +} __packed; + #define HCI_OP_SETUP_SYNC_CONN 0x0428 struct hci_cp_setup_sync_conn { __le16 handle; @@ -1085,6 +1141,18 @@ struct hci_rp_read_rssi { __s8 rssi; } __packed; +#define HCI_OP_READ_CLOCK 0x1407 +struct hci_cp_read_clock { + __le16 handle; + __u8 which; +} __packed; +struct hci_rp_read_clock { + __u8 status; + __le16 handle; + __le32 clock; + __le16 accuracy; +} __packed; + #define HCI_OP_READ_LOCAL_AMP_INFO 0x1409 struct hci_rp_read_local_amp_info { __u8 status; @@ -1291,6 +1359,23 @@ struct hci_rp_le_read_supported_states { __u8 le_states[8]; } __packed; +#define HCI_OP_LE_CONN_PARAM_REQ_REPLY 0x2020 +struct hci_cp_le_conn_param_req_reply { + __le16 handle; + __le16 interval_min; + __le16 interval_max; + __le16 latency; + __le16 timeout; + __le16 min_ce_len; + __le16 max_ce_len; +} __packed; + +#define HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY 0x2021 +struct hci_cp_le_conn_param_req_neg_reply { + __le16 handle; + __u8 reason; +} __packed; + /* ---- HCI Events ---- */ #define HCI_EV_INQUIRY_COMPLETE 0x01 @@ -1670,6 +1755,15 @@ struct hci_ev_le_conn_complete { __u8 clk_accurancy; } __packed; +#define HCI_EV_LE_CONN_UPDATE_COMPLETE 0x03 +struct hci_ev_le_conn_update_complete { + __u8 status; + __le16 handle; + __le16 interval; + __le16 latency; + __le16 supervision_timeout; +} __packed; + #define HCI_EV_LE_LTK_REQ 0x05 struct hci_ev_le_ltk_req { __le16 handle; @@ -1677,6 +1771,15 @@ struct hci_ev_le_ltk_req { __le16 ediv; } __packed; +#define HCI_EV_LE_REMOTE_CONN_PARAM_REQ 0x06 +struct hci_ev_le_remote_conn_param_req { + __le16 handle; + __le16 interval_min; + __le16 interval_max; + __le16 latency; + __le16 timeout; +} __packed; + /* Advertising report event types */ #define LE_ADV_IND 0x00 #define LE_ADV_DIRECT_IND 0x01 diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index b386bf1..e69c2b0 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -71,6 +71,7 @@ struct discovery_state { bdaddr_t last_adv_addr; u8 last_adv_addr_type; s8 last_adv_rssi; + u32 last_adv_flags; u8 last_adv_data[HCI_MAX_AD_LENGTH]; u8 last_adv_data_len; }; @@ -170,6 +171,8 @@ struct hci_dev { __u8 bus; __u8 dev_type; bdaddr_t bdaddr; + bdaddr_t setup_addr; + bdaddr_t public_addr; bdaddr_t random_addr; bdaddr_t static_addr; __u8 adv_addr_type; @@ -203,10 +206,13 @@ struct hci_dev { __u16 le_scan_window; __u16 le_conn_min_interval; __u16 le_conn_max_interval; + __u16 le_conn_latency; + __u16 le_supv_timeout; __u16 discov_interleaved_timeout; __u16 conn_info_min_age; __u16 conn_info_max_age; __u8 ssp_debug_mode; + __u32 clock; __u16 devid_source; __u16 devid_vendor; @@ -273,7 +279,7 @@ struct hci_dev { struct delayed_work service_cache; - struct timer_list cmd_timer; + struct delayed_work cmd_timer; struct work_struct rx_work; struct work_struct cmd_work; @@ -299,6 +305,7 @@ struct hci_dev { struct list_head mgmt_pending; struct list_head blacklist; + struct list_head whitelist; struct list_head uuids; struct list_head link_keys; struct list_head long_term_keys; @@ -307,6 +314,7 @@ struct hci_dev { struct list_head le_white_list; struct list_head le_conn_params; struct list_head pend_le_conns; + struct list_head pend_le_reports; struct hci_dev_stats stat; @@ -318,6 +326,7 @@ struct hci_dev { struct rfkill *rfkill; + unsigned long dbg_flags; unsigned long dev_flags; struct delayed_work le_scan_disable; @@ -339,6 +348,7 @@ struct hci_dev { int (*setup)(struct hci_dev *hdev); int (*send)(struct hci_dev *hdev, struct sk_buff *skb); void (*notify)(struct hci_dev *hdev, unsigned int evt); + int (*set_bdaddr)(struct hci_dev *hdev, const bdaddr_t *bdaddr); }; #define HCI_PHY_HANDLE(handle) (handle & 0xff) @@ -366,7 +376,6 @@ struct hci_conn { __u8 features[HCI_MAX_PAGES][8]; __u16 pkt_type; __u16 link_policy; - __u32 link_mode; __u8 key_type; __u8 auth_type; __u8 sec_level; @@ -377,20 +386,26 @@ struct hci_conn { __u32 passkey_notify; __u8 passkey_entered; __u16 disc_timeout; + __u16 conn_timeout; __u16 setting; __u16 le_conn_min_interval; __u16 le_conn_max_interval; + __u16 le_conn_interval; + __u16 le_conn_latency; + __u16 le_supv_timeout; __s8 rssi; __s8 tx_power; __s8 max_tx_power; unsigned long flags; + __u32 clock; + __u16 clock_accuracy; + unsigned long conn_info_timestamp; __u8 remote_cap; __u8 remote_auth; __u8 remote_id; - bool flush_key; unsigned int sent; @@ -407,7 +422,6 @@ struct hci_conn { struct hci_dev *hdev; void *l2cap_data; void *sco_data; - void *smp_conn; struct amp_mgr *amp_mgr; struct hci_conn *link; @@ -428,15 +442,19 @@ struct hci_chan { struct hci_conn_params { struct list_head list; + struct list_head action; bdaddr_t addr; u8 addr_type; u16 conn_min_interval; u16 conn_max_interval; + u16 conn_latency; + u16 supervision_timeout; enum { HCI_AUTO_CONN_DISABLED, + HCI_AUTO_CONN_REPORT, HCI_AUTO_CONN_ALWAYS, HCI_AUTO_CONN_LINK_LOSS, } auto_connect; @@ -501,8 +519,8 @@ struct inquiry_entry *hci_inquiry_cache_lookup_resolve(struct hci_dev *hdev, int state); void hci_inquiry_cache_update_resolve(struct hci_dev *hdev, struct inquiry_entry *ie); -bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, - bool name_known, bool *ssp); +u32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, + bool name_known); void hci_inquiry_cache_flush(struct hci_dev *hdev); /* ----- HCI Connections ----- */ @@ -520,7 +538,13 @@ enum { HCI_CONN_AES_CCM, HCI_CONN_POWER_SAVE, HCI_CONN_REMOTE_OOB, - HCI_CONN_6LOWPAN, + HCI_CONN_FLUSH_KEY, + HCI_CONN_MASTER, + HCI_CONN_ENCRYPT, + HCI_CONN_AUTH, + HCI_CONN_SECURE, + HCI_CONN_FIPS, + HCI_CONN_STK_ENCRYPT, }; static inline bool hci_conn_ssp_enabled(struct hci_conn *conn) @@ -681,7 +705,8 @@ 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_le(struct hci_dev *hdev, bdaddr_t *dst, - u8 dst_type, u8 sec_level, u8 auth_type); + u8 dst_type, u8 sec_level, u16 conn_timeout, + bool master); 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, @@ -825,30 +850,25 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg); 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); -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 bdaddr_list *hci_bdaddr_list_lookup(struct list_head *list, + bdaddr_t *bdaddr, u8 type); +int hci_bdaddr_list_add(struct list_head *list, bdaddr_t *bdaddr, u8 type); +int hci_bdaddr_list_del(struct list_head *list, bdaddr_t *bdaddr, u8 type); +void hci_bdaddr_list_clear(struct list_head *list); struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type); -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); +struct hci_conn_params *hci_conn_params_add(struct hci_dev *hdev, + bdaddr_t *addr, u8 addr_type); +int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, + u8 auto_connect); void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type); -void hci_conn_params_clear(struct hci_dev *hdev); +void hci_conn_params_clear_all(struct hci_dev *hdev); +void hci_conn_params_clear_disabled(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); +struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list, + bdaddr_t *addr, + u8 addr_type); void hci_update_background_scan(struct hci_dev *hdev); @@ -856,8 +876,9 @@ 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 link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, + bdaddr_t *bdaddr, u8 *val, u8 type, + u8 pin_len, bool *persistent); 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, @@ -1021,7 +1042,7 @@ static inline void hci_proto_auth_cfm(struct hci_conn *conn, __u8 status) if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) return; - encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00; + encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00; l2cap_security_cfm(conn, status, encrypt); if (conn->security_cfm_cb) @@ -1062,7 +1083,7 @@ static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status) if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) return; - encrypt = (conn->link_mode & HCI_LM_ENCRYPT) ? 0x01 : 0x00; + encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00; read_lock(&hci_cb_list_lock); list_for_each_entry(cb, &hci_cb_list, list) { @@ -1147,7 +1168,7 @@ static inline bool eir_has_data_type(u8 *data, size_t data_len, u8 type) static inline bool hci_bdaddr_is_rpa(bdaddr_t *bdaddr, u8 addr_type) { - if (addr_type != 0x01) + if (addr_type != ADDR_LE_DEV_RANDOM) return false; if ((bdaddr->b[5] & 0xc0) == 0x40) @@ -1156,6 +1177,18 @@ static inline bool hci_bdaddr_is_rpa(bdaddr_t *bdaddr, u8 addr_type) return false; } +static inline bool hci_is_identity_address(bdaddr_t *addr, u8 addr_type) +{ + if (addr_type == ADDR_LE_DEV_PUBLIC) + return true; + + /* Check for Random Static address type */ + if ((addr->b[5] & 0xc0) == 0xc0) + return true; + + return false; +} + static inline struct smp_irk *hci_get_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type) { @@ -1165,6 +1198,27 @@ static inline struct smp_irk *hci_get_irk(struct hci_dev *hdev, return hci_find_irk_by_rpa(hdev, bdaddr); } +static inline int hci_check_conn_params(u16 min, u16 max, u16 latency, + u16 to_multiplier) +{ + u16 max_latency; + + if (min > max || min < 6 || max > 3200) + return -EINVAL; + + if (to_multiplier < 10 || to_multiplier > 3200) + return -EINVAL; + + if (max >= to_multiplier * 8) + return -EINVAL; + + max_latency = (to_multiplier * 8 / max) - 1; + if (latency > 499 || latency > max_latency) + return -EINVAL; + + return 0; +} + int hci_register_cb(struct hci_cb *hcb); int hci_unregister_cb(struct hci_cb *hcb); @@ -1227,6 +1281,7 @@ 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); +int mgmt_new_settings(struct hci_dev *hdev); 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); @@ -1234,7 +1289,6 @@ 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); @@ -1281,18 +1335,18 @@ void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192, u8 *randomizer192, u8 *hash256, u8 *randomizer256, 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, u8 *scan_rsp, - u8 scan_rsp_len); + u8 addr_type, u8 *dev_class, s8 rssi, u32 flags, + u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_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_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, bool persistent); void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk); void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk, bool persistent); +void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr, + u8 bdaddr_type, u8 store_hint, u16 min_interval, + u16 max_interval, u16 latency, u16 timeout); void mgmt_reenable_advertising(struct hci_dev *hdev); void mgmt_smp_complete(struct hci_conn *conn, bool complete); @@ -1324,8 +1378,8 @@ 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_le_conn_update(struct hci_conn *conn, u16 min, u16 max, - u16 latency, u16 to_multiplier); +u8 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, __le64 rand, __u8 ltk[16]); diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 4abdcb2..e0c6a9a 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -137,7 +137,6 @@ struct l2cap_conninfo { #define L2CAP_FC_L2CAP 0x02 #define L2CAP_FC_CONNLESS 0x04 #define L2CAP_FC_A2MP 0x08 -#define L2CAP_FC_6LOWPAN 0x3e /* reserved and temporary value */ /* L2CAP Control Field bit masks */ #define L2CAP_CTRL_SAR 0xC000 @@ -579,7 +578,7 @@ struct l2cap_chan { struct list_head global_l; void *data; - struct l2cap_ops *ops; + const struct l2cap_ops *ops; struct mutex lock; }; @@ -600,7 +599,12 @@ struct l2cap_ops { void (*set_shutdown) (struct l2cap_chan *chan); long (*get_sndtimeo) (struct l2cap_chan *chan); struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, + unsigned long hdr_len, unsigned long len, int nb); + int (*memcpy_fromiovec) (struct l2cap_chan *chan, + unsigned char *kdata, + struct iovec *iov, + int len); }; struct l2cap_conn { @@ -856,6 +860,31 @@ static inline long l2cap_chan_no_get_sndtimeo(struct l2cap_chan *chan) return 0; } +static inline int l2cap_chan_no_memcpy_fromiovec(struct l2cap_chan *chan, + unsigned char *kdata, + struct iovec *iov, + int len) +{ + /* Following is safe since for compiler definitions of kvec and + * iovec are identical, yielding the same in-core layout and alignment + */ + struct kvec *vec = (struct kvec *)iov; + + while (len > 0) { + if (vec->iov_len) { + int copy = min_t(unsigned int, len, vec->iov_len); + memcpy(kdata, vec->iov_base, copy); + len -= copy; + kdata += copy; + vec->iov_base += copy; + vec->iov_len -= copy; + } + vec++; + } + + return 0; +} + extern bool disable_ertm; int l2cap_init_sockets(void); @@ -872,8 +901,7 @@ struct l2cap_chan *l2cap_chan_create(void); void l2cap_chan_close(struct l2cap_chan *chan, int reason); int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst, u8 dst_type); -int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, - u32 priority); +int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len); void l2cap_chan_busy(struct l2cap_chan *chan, int busy); int l2cap_chan_check_security(struct l2cap_chan *chan); void l2cap_chan_set_defaults(struct l2cap_chan *chan); diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index bcffc9a..623d520 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -97,6 +97,7 @@ struct mgmt_rp_read_index_list { #define MGMT_SETTING_SECURE_CONN 0x00000800 #define MGMT_SETTING_DEBUG_KEYS 0x00001000 #define MGMT_SETTING_PRIVACY 0x00002000 +#define MGMT_SETTING_CONFIGURATION 0x00004000 #define MGMT_OP_READ_INFO 0x0004 #define MGMT_READ_INFO_SIZE 0 @@ -424,6 +425,76 @@ struct mgmt_rp_get_conn_info { __s8 max_tx_power; } __packed; +#define MGMT_OP_GET_CLOCK_INFO 0x0032 +struct mgmt_cp_get_clock_info { + struct mgmt_addr_info addr; +} __packed; +#define MGMT_GET_CLOCK_INFO_SIZE MGMT_ADDR_INFO_SIZE +struct mgmt_rp_get_clock_info { + struct mgmt_addr_info addr; + __le32 local_clock; + __le32 piconet_clock; + __le16 accuracy; +} __packed; + +#define MGMT_OP_ADD_DEVICE 0x0033 +struct mgmt_cp_add_device { + struct mgmt_addr_info addr; + __u8 action; +} __packed; +#define MGMT_ADD_DEVICE_SIZE (MGMT_ADDR_INFO_SIZE + 1) + +#define MGMT_OP_REMOVE_DEVICE 0x0034 +struct mgmt_cp_remove_device { + struct mgmt_addr_info addr; +} __packed; +#define MGMT_REMOVE_DEVICE_SIZE MGMT_ADDR_INFO_SIZE + +struct mgmt_conn_param { + struct mgmt_addr_info addr; + __le16 min_interval; + __le16 max_interval; + __le16 latency; + __le16 timeout; +} __packed; + +#define MGMT_OP_LOAD_CONN_PARAM 0x0035 +struct mgmt_cp_load_conn_param { + __le16 param_count; + struct mgmt_conn_param params[0]; +} __packed; +#define MGMT_LOAD_CONN_PARAM_SIZE 2 + +#define MGMT_OP_READ_UNCONF_INDEX_LIST 0x0036 +#define MGMT_READ_UNCONF_INDEX_LIST_SIZE 0 +struct mgmt_rp_read_unconf_index_list { + __le16 num_controllers; + __le16 index[0]; +} __packed; + +#define MGMT_OPTION_EXTERNAL_CONFIG 0x00000001 +#define MGMT_OPTION_PUBLIC_ADDRESS 0x00000002 + +#define MGMT_OP_READ_CONFIG_INFO 0x0037 +#define MGMT_READ_CONFIG_INFO_SIZE 0 +struct mgmt_rp_read_config_info { + __le16 manufacturer; + __le32 supported_options; + __le32 missing_options; +} __packed; + +#define MGMT_OP_SET_EXTERNAL_CONFIG 0x0038 +struct mgmt_cp_set_external_config { + __u8 config; +} __packed; +#define MGMT_SET_EXTERNAL_CONFIG_SIZE 1 + +#define MGMT_OP_SET_PUBLIC_ADDRESS 0x0039 +struct mgmt_cp_set_public_address { + bdaddr_t bdaddr; +} __packed; +#define MGMT_SET_PUBLIC_ADDRESS_SIZE 6 + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; @@ -522,6 +593,7 @@ struct mgmt_ev_auth_failed { #define MGMT_DEV_FOUND_CONFIRM_NAME 0x01 #define MGMT_DEV_FOUND_LEGACY_PAIRING 0x02 +#define MGMT_DEV_FOUND_NOT_CONNECTABLE 0x04 #define MGMT_EV_DEVICE_FOUND 0x0012 struct mgmt_ev_device_found { @@ -578,3 +650,30 @@ struct mgmt_ev_new_csrk { __u8 store_hint; struct mgmt_csrk_info key; } __packed; + +#define MGMT_EV_DEVICE_ADDED 0x001a +struct mgmt_ev_device_added { + struct mgmt_addr_info addr; + __u8 action; +} __packed; + +#define MGMT_EV_DEVICE_REMOVED 0x001b +struct mgmt_ev_device_removed { + struct mgmt_addr_info addr; +} __packed; + +#define MGMT_EV_NEW_CONN_PARAM 0x001c +struct mgmt_ev_new_conn_param { + struct mgmt_addr_info addr; + __u8 store_hint; + __le16 min_interval; + __le16 max_interval; + __le16 latency; + __le16 timeout; +} __packed; + +#define MGMT_EV_UNCONF_INDEX_ADDED 0x001d + +#define MGMT_EV_UNCONF_INDEX_REMOVED 0x001e + +#define MGMT_EV_NEW_CONFIG_OPTIONS 0x001f |