From 928abaa777501ddab94b1b49aae485a2c730d303 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Wed, 12 Oct 2011 10:53:57 +0300 Subject: Bluetooth: AMP: read local amp info HCI command Implementation of Read Local AMP Info Command Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'include/net/bluetooth/hci.h') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index aaf79af72432..c5fcd13b9edf 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -726,6 +726,21 @@ struct hci_cp_write_page_scan_activity { #define PAGE_SCAN_TYPE_STANDARD 0x00 #define PAGE_SCAN_TYPE_INTERLACED 0x01 +#define HCI_OP_READ_LOCAL_AMP_INFO 0x1409 +struct hci_rp_read_local_amp_info { + __u8 status; + __u8 amp_status; + __le32 total_bw; + __le32 max_bw; + __le32 min_latency; + __le32 max_pdu; + __u8 amp_type; + __le16 pal_cap; + __le16 max_assoc_size; + __le32 max_flush_to; + __le32 be_flush_to; +} __packed; + #define HCI_OP_LE_SET_EVENT_MASK 0x2001 struct hci_cp_le_set_event_mask { __u8 mask[8]; -- cgit v1.2.3 From 9f5a0d7bf079e9e26771ad13ff1c2cb3adf80963 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Mon, 7 Nov 2011 14:20:25 +0200 Subject: Bluetooth: Define HCI reasons instead of magic number Use HCI error reasons instead of magic numbers. Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 7 +++++++ include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/hci_conn.c | 2 +- net/bluetooth/hci_event.c | 4 ++-- net/bluetooth/l2cap_core.c | 8 ++++---- 5 files changed, 15 insertions(+), 8 deletions(-) (limited to 'include/net/bluetooth/hci.h') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index c5fcd13b9edf..139ce2aa6eee 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -264,6 +264,13 @@ enum { #define HCI_LK_SMP_IRK 0x82 #define HCI_LK_SMP_CSRK 0x83 +/* ---- HCI Error Codes ---- */ +#define HCI_ERROR_AUTH_FAILURE 0x05 +#define HCI_ERROR_REJ_BAD_ADDR 0x0f +#define HCI_ERROR_REMOTE_USER_TERM 0x13 +#define HCI_ERROR_LOCAL_HOST_TERM 0x16 +#define HCI_ERROR_PAIRING_NOT_ALLOWED 0x18 + /* ----- HCI Commands ---- */ #define HCI_OP_NOP 0x0000 diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index f97792c972f3..006a7699abac 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -730,7 +730,7 @@ static inline void hci_proto_connect_cfm(struct hci_conn *conn, __u8 status) static inline int hci_proto_disconn_ind(struct hci_conn *conn) { register struct hci_proto *hp; - int reason = 0x13; + int reason = HCI_ERROR_REMOTE_USER_TERM; hp = hci_proto[HCI_PROTO_L2CAP]; if (hp && hp->disconn_ind) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index e545376379c5..ac943676f78d 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -820,7 +820,7 @@ void hci_conn_hash_flush(struct hci_dev *hdev) c->state = BT_CLOSED; - hci_proto_disconn_cfm(c, 0x16); + hci_proto_disconn_cfm(c, HCI_ERROR_LOCAL_HOST_TERM); hci_conn_del(c); } } diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 8c81a75381fb..9dc54db693a3 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1559,7 +1559,7 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk struct hci_cp_reject_conn_req cp; bacpy(&cp.bdaddr, &ev->bdaddr); - cp.reason = 0x0f; + cp.reason = HCI_ERROR_REJ_BAD_ADDR; hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); } } @@ -2646,7 +2646,7 @@ static inline void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff struct hci_cp_io_capability_neg_reply cp; bacpy(&cp.bdaddr, &ev->bdaddr); - cp.reason = 0x18; /* Pairing not allowed */ + cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED; hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY, sizeof(cp), &cp); diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index fe5666e15298..a50610b8a00c 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -313,7 +313,7 @@ static void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, chan->psm, chan->dcid); - conn->disc_reason = 0x13; + conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; chan->conn = conn; @@ -1082,7 +1082,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon, u8 status) setup_timer(&conn->info_timer, l2cap_info_timeout, (unsigned long) conn); - conn->disc_reason = 0x13; + conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; return conn; } @@ -2535,7 +2535,7 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd /* Check if the ACL is secure enough (if not SDP) */ if (psm != cpu_to_le16(0x0001) && !hci_conn_check_link_mode(conn->hcon)) { - conn->disc_reason = 0x05; + conn->disc_reason = HCI_ERROR_AUTH_FAILURE; result = L2CAP_CR_SEC_BLOCK; goto response; } @@ -4411,7 +4411,7 @@ static int l2cap_disconn_ind(struct hci_conn *hcon) BT_DBG("hcon %p", hcon); if ((hcon->type != ACL_LINK && hcon->type != LE_LINK) || !conn) - return 0x13; + return HCI_ERROR_REMOTE_USER_TERM; return conn->disc_reason; } -- cgit v1.2.3 From 9ad4019a716ca31584abac7c2f30b36d212c6a9e Mon Sep 17 00:00:00 2001 From: Brian Gix Date: Sat, 12 Nov 2011 22:01:11 -0800 Subject: Bluetooth: Add HCI defines for User Passkey entry Signed-off-by: Brian Gix Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'include/net/bluetooth/hci.h') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 139ce2aa6eee..e284dd906b9e 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -453,6 +453,14 @@ struct hci_rp_user_confirm_reply { #define HCI_OP_USER_CONFIRM_NEG_REPLY 0x042d +#define HCI_OP_USER_PASSKEY_REPLY 0x042e +struct hci_cp_user_passkey_reply { + bdaddr_t bdaddr; + __le32 passkey; +} __packed; + +#define HCI_OP_USER_PASSKEY_NEG_REPLY 0x042f + #define HCI_OP_REMOTE_OOB_DATA_REPLY 0x0430 struct hci_cp_remote_oob_data_reply { bdaddr_t bdaddr; @@ -1076,6 +1084,11 @@ struct hci_ev_user_confirm_req { __le32 passkey; } __packed; +#define HCI_EV_USER_PASSKEY_REQUEST 0x34 +struct hci_ev_user_passkey_req { + bdaddr_t bdaddr; +} __packed; + #define HCI_EV_REMOTE_OOB_DATA_REQUEST 0x35 struct hci_ev_remote_oob_data_request { bdaddr_t bdaddr; -- cgit v1.2.3 From 8830f514106fbd09ba5bbbaae043a8624ceb9d67 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Fri, 11 Nov 2011 17:02:14 +0200 Subject: Bluetooth: Move scope of kernel parameter enable_hs Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 2 ++ include/net/bluetooth/l2cap.h | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'include/net/bluetooth/hci.h') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index e284dd906b9e..376c57420abe 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1344,4 +1344,6 @@ struct hci_inquiry_req { }; #define IREQ_CACHE_FLUSH 0x0001 +extern int enable_hs; + #endif /* __HCI_H */ diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 1e6fda438130..30719eb2e77c 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -792,7 +792,6 @@ static inline __u8 __ctrl_size(struct l2cap_chan *chan) } extern int disable_ertm; -extern int enable_hs; int l2cap_init_sockets(void); void l2cap_cleanup_sockets(void); -- cgit v1.2.3 From 1e89cffb44a94e1937e5ec16125ae866dbba7b2e Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 24 Nov 2011 14:52:02 +0200 Subject: Bluetooth: Add HCI Read Flow Control Mode function Upstream Code Aurora function with minor trivial fixes. Origin: git://codeaurora.org/kernel/msm.git Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 6 ++++++ include/net/bluetooth/hci_core.h | 2 ++ net/bluetooth/hci_event.c | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+) (limited to 'include/net/bluetooth/hci.h') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 376c57420abe..ee83c36d35aa 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -677,6 +677,12 @@ struct hci_rp_read_local_oob_data { #define HCI_OP_READ_INQ_RSP_TX_POWER 0x0c58 +#define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66 +struct hci_rp_read_flow_control_mode { + __u8 status; + __u8 mode; +} __packed; + #define HCI_OP_WRITE_LE_HOST_SUPPORTED 0x0c6d struct hci_cp_write_le_host_supported { __u8 le; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index e7b2e25397d7..44f130f6fb5e 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -170,6 +170,8 @@ struct hci_dev { __u32 amp_max_flush_to; __u32 amp_be_flush_to; + __u8 flow_ctl_mode; + unsigned int auto_accept_delay; unsigned long quirks; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 980da08e253e..ab4922831b9a 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -717,6 +717,21 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, hci_req_complete(hdev, HCI_OP_READ_LOCAL_EXT_FEATURES, rp->status); } +static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_rp_read_flow_control_mode *rp = (void *) skb->data; + + BT_DBG("%s status 0x%x", hdev->name, rp->status); + + if (rp->status) + return; + + hdev->flow_ctl_mode = rp->mode; + + hci_req_complete(hdev, HCI_OP_READ_FLOW_CONTROL_MODE, rp->status); +} + static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_rp_read_buffer_size *rp = (void *) skb->data; @@ -1998,6 +2013,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk hci_cc_write_ca_timeout(hdev, skb); break; + case HCI_OP_READ_FLOW_CONTROL_MODE: + hci_cc_read_flow_control_mode(hdev, skb); + break; + case HCI_OP_READ_LOCAL_AMP_INFO: hci_cc_read_local_amp_info(hdev, skb); break; -- cgit v1.2.3 From d23264a896a931c4b355c102d8e9d46649195ba4 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 25 Nov 2011 20:53:38 -0300 Subject: Bluetooth: Add dev_flags to struct hci_dev This patch adds the dev_flags field to struct hci_dev. This new flags variable should be used to define flags related to BR/EDR and/or LE controller itself. It should be used to define flags which represents states from the controller. The dev_flags is cleared in case the controller sends a Reset Command Complete Event to the host. Also, this patch adds the HCI_LE_SCAN flag which was created to track if the controller is performing LE scan or not. The flag is set/cleared when the controller starts/stops scanning. This is an initial effort to stop using hdev->flags to define internal flags since it is exported to userspace by an ioctl. Signed-off-by: Andre Guedes Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 8 ++++++++ include/net/bluetooth/hci_core.h | 2 ++ net/bluetooth/hci_core.c | 1 + net/bluetooth/hci_event.c | 6 ++++++ 4 files changed, 17 insertions(+) (limited to 'include/net/bluetooth/hci.h') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index ee83c36d35aa..e2ed3683f1c5 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -88,6 +88,14 @@ enum { HCI_RESET, }; +/* + * BR/EDR and/or LE controller flags: the flags defined here should represent + * states from the controller. + */ +enum { + HCI_LE_SCAN, +}; + /* HCI ioctl defines */ #define HCIDEVUP _IOW('H', 201, int) #define HCIDEVDOWN _IOW('H', 202, int) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 44f130f6fb5e..e34cd71a586e 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -252,6 +252,8 @@ struct hci_dev { struct module *owner; + unsigned long dev_flags; + int (*open)(struct hci_dev *hdev); int (*close)(struct hci_dev *hdev); int (*flush)(struct hci_dev *hdev); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index ef0423e62a22..dcbe1d29bb8e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1458,6 +1458,7 @@ int hci_register_dev(struct hci_dev *hdev) spin_lock_init(&hdev->lock); hdev->flags = 0; + hdev->dev_flags = 0; hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); hdev->esco_type = (ESCO_HV1); hdev->link_mode = (HCI_LM_ACCEPT); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index ab4922831b9a..acbdfbeeb920 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -194,6 +194,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) clear_bit(HCI_RESET, &hdev->flags); hci_req_complete(hdev, HCI_OP_RESET, status); + + hdev->dev_flags = 0; } static void hci_cc_write_local_name(struct hci_dev *hdev, struct sk_buff *skb) @@ -1006,12 +1008,16 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, return; if (cp->enable == 0x01) { + set_bit(HCI_LE_SCAN, &hdev->dev_flags); + del_timer(&hdev->adv_timer); hci_dev_lock(hdev); hci_adv_entries_clear(hdev); hci_dev_unlock(hdev); } else if (cp->enable == 0x00) { + clear_bit(HCI_LE_SCAN, &hdev->dev_flags); + mod_timer(&hdev->adv_timer, jiffies + ADV_CLEAR_TIMEOUT); } } -- cgit v1.2.3 From 07f7fa5db1e65a27066c8ebf9fc676a4168e07f4 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Fri, 2 Dec 2011 21:13:31 +0900 Subject: Bluetooth: LE Set Scan Parameter Command This patch adds the parameter struct and the command complete event handler to the LE Set Scan Parameter HCI command. Signed-off-by: Andre Guedes Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 9 +++++++++ net/bluetooth/hci_event.c | 10 ++++++++++ 2 files changed, 19 insertions(+) (limited to 'include/net/bluetooth/hci.h') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index e2ed3683f1c5..67ad98430348 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -782,6 +782,15 @@ struct hci_rp_le_read_buffer_size { __u8 le_max_pkt; } __packed; +#define HCI_OP_LE_SET_SCAN_PARAM 0x200b +struct hci_cp_le_set_scan_param { + __u8 type; + __le16 interval; + __le16 window; + __u8 own_address_type; + __u8 filter_policy; +} __packed; + #define HCI_OP_LE_SET_SCAN_ENABLE 0x200c struct hci_cp_le_set_scan_enable { __u8 enable; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index acbdfbeeb920..4f35ecdc6c62 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -992,6 +992,13 @@ static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, hci_dev_unlock(hdev); } +static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) +{ + __u8 status = *((__u8 *) skb->data); + + BT_DBG("%s status 0x%x", hdev->name, status); +} + static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) { @@ -2077,6 +2084,9 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk case HCI_OP_USER_PASSKEY_NEG_REPLY: hci_cc_user_passkey_neg_reply(hdev, skb); + + case HCI_OP_LE_SET_SCAN_PARAM: + hci_cc_le_set_scan_param(hdev, skb); break; case HCI_OP_LE_SET_SCAN_ENABLE: -- cgit v1.2.3 From 69ab39ea5da03e632a51b31534da713aff8d1e3b Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 15 Dec 2011 00:47:35 +0200 Subject: Bluetooth: Update mgmt_read_info and related mgmt messages This patch updates the mgmt_read_info and related messages to the latest management API which uses a bitfield of settings instead of individual boolean values. Signed-off-by: Johan Hedberg Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 1 + include/net/bluetooth/mgmt.h | 29 +++++---- net/bluetooth/mgmt.c | 146 ++++++++++++++++++++++++++++--------------- 3 files changed, 113 insertions(+), 63 deletions(-) (limited to 'include/net/bluetooth/hci.h') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 67ad98430348..c9ad56fe58f4 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -210,6 +210,7 @@ enum { #define LMP_EV4 0x01 #define LMP_EV5 0x02 +#define LMP_NO_BREDR 0x20 #define LMP_LE 0x40 #define LMP_SNIFF_SUBR 0x02 diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 3b6880690a78..85e9c6e9d221 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -61,22 +61,29 @@ struct mgmt_rp_read_index_list { /* Reserve one extra byte for names in management messages so that they * are always guaranteed to be nul-terminated */ #define MGMT_MAX_NAME_LENGTH (HCI_MAX_NAME_LENGTH + 1) +#define MGMT_MAX_SHORT_NAME_LENGTH (10 + 1) + +#define MGMT_SETTING_POWERED 0x00000001 +#define MGMT_SETTING_CONNECTABLE 0x00000002 +#define MGMT_SETTING_FAST_CONNECTABLE 0x00000004 +#define MGMT_SETTING_DISCOVERABLE 0x00000008 +#define MGMT_SETTING_PAIRABLE 0x00000010 +#define MGMT_SETTING_LINK_SECURITY 0x00000020 +#define MGMT_SETTING_SSP 0x00000040 +#define MGMT_SETTING_BREDR 0x00000080 +#define MGMT_SETTING_HS 0x00000100 +#define MGMT_SETTING_LE 0x00000200 #define MGMT_OP_READ_INFO 0x0004 struct mgmt_rp_read_info { - __u8 type; - __u8 powered; - __u8 connectable; - __u8 discoverable; - __u8 pairable; - __u8 sec_mode; bdaddr_t bdaddr; + __u8 version; + __le16 manufacturer; + __le32 supported_settings; + __le32 current_settings; __u8 dev_class[3]; - __u8 features[8]; - __u16 manufacturer; - __u8 hci_ver; - __u16 hci_rev; __u8 name[MGMT_MAX_NAME_LENGTH]; + __u8 short_name[MGMT_MAX_SHORT_NAME_LENGTH]; } __packed; struct mgmt_mode { @@ -285,7 +292,7 @@ struct mgmt_ev_controller_error { #define MGMT_EV_INDEX_REMOVED 0x0005 -#define MGMT_EV_POWERED 0x0006 +#define MGMT_EV_NEW_SETTINGS 0x0006 #define MGMT_EV_DISCOVERABLE 0x0007 diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ffd1c01c7d0e..087cf00a443d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -242,6 +242,63 @@ static int read_index_list(struct sock *sk) return err; } +static u32 get_supported_settings(struct hci_dev *hdev) +{ + u32 settings = 0; + + settings |= MGMT_SETTING_POWERED; + settings |= MGMT_SETTING_CONNECTABLE; + settings |= MGMT_SETTING_FAST_CONNECTABLE; + settings |= MGMT_SETTING_DISCOVERABLE; + settings |= MGMT_SETTING_PAIRABLE; + + if (hdev->features[6] & LMP_SIMPLE_PAIR) + settings |= MGMT_SETTING_SSP; + + if (!(hdev->features[4] & LMP_NO_BREDR)) { + settings |= MGMT_SETTING_BREDR; + settings |= MGMT_SETTING_LINK_SECURITY; + } + + if (hdev->features[4] & LMP_LE) + settings |= MGMT_SETTING_LE; + + return settings; +} + +static u32 get_current_settings(struct hci_dev *hdev) +{ + u32 settings = 0; + + if (test_bit(HCI_UP, &hdev->flags)) + settings |= MGMT_SETTING_POWERED; + else + return settings; + + if (test_bit(HCI_PSCAN, &hdev->flags)) + settings |= MGMT_SETTING_CONNECTABLE; + + if (test_bit(HCI_ISCAN, &hdev->flags)) + settings |= MGMT_SETTING_DISCOVERABLE; + + if (test_bit(HCI_PAIRABLE, &hdev->flags)) + settings |= MGMT_SETTING_PAIRABLE; + + if (!(hdev->features[4] & LMP_NO_BREDR)) + settings |= MGMT_SETTING_BREDR; + + if (hdev->extfeatures[0] & LMP_HOST_LE) + settings |= MGMT_SETTING_LE; + + if (test_bit(HCI_AUTH, &hdev->flags)) + settings |= MGMT_SETTING_LINK_SECURITY; + + if (hdev->ssp_mode > 0) + settings |= MGMT_SETTING_SSP; + + return settings; +} + static int read_controller_info(struct sock *sk, u16 index) { struct mgmt_rp_read_info rp; @@ -263,26 +320,16 @@ static int read_controller_info(struct sock *sk, u16 index) memset(&rp, 0, sizeof(rp)); - rp.type = hdev->dev_type; + bacpy(&rp.bdaddr, &hdev->bdaddr); - rp.powered = test_bit(HCI_UP, &hdev->flags); - rp.connectable = test_bit(HCI_PSCAN, &hdev->flags); - rp.discoverable = test_bit(HCI_ISCAN, &hdev->flags); - rp.pairable = test_bit(HCI_PSCAN, &hdev->flags); + rp.version = hdev->hci_ver; - if (test_bit(HCI_AUTH, &hdev->flags)) - rp.sec_mode = 3; - else if (hdev->ssp_mode > 0) - rp.sec_mode = 4; - else - rp.sec_mode = 2; + put_unaligned_le16(hdev->manufacturer, &rp.manufacturer); + + rp.supported_settings = cpu_to_le32(get_supported_settings(hdev)); + rp.current_settings = cpu_to_le32(get_current_settings(hdev)); - bacpy(&rp.bdaddr, &hdev->bdaddr); - memcpy(rp.features, hdev->features, 8); memcpy(rp.dev_class, hdev->dev_class, 3); - put_unaligned_le16(hdev->manufacturer, &rp.manufacturer); - rp.hci_ver = hdev->hci_ver; - put_unaligned_le16(hdev->hci_rev, &rp.hci_rev); memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name)); @@ -365,13 +412,11 @@ static void mgmt_pending_remove(struct pending_cmd *cmd) mgmt_pending_free(cmd); } -static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val) +static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev) { - struct mgmt_mode rp; + __le32 settings = cpu_to_le32(get_current_settings(hdev)); - rp.val = val; - - return cmd_complete(sk, index, opcode, &rp, sizeof(rp)); + return cmd_complete(sk, hdev->id, opcode, &settings, sizeof(settings)); } static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) @@ -398,7 +443,7 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len) up = test_bit(HCI_UP, &hdev->flags); if ((cp->val && up) || (!cp->val && !up)) { - err = send_mode_rsp(sk, index, MGMT_OP_SET_POWERED, cp->val); + err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev); goto failed; } @@ -466,8 +511,7 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data, if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) && test_bit(HCI_PSCAN, &hdev->flags)) { - err = send_mode_rsp(sk, index, MGMT_OP_SET_DISCOVERABLE, - cp->val); + err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev); goto failed; } @@ -536,8 +580,7 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data, } if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) { - err = send_mode_rsp(sk, index, MGMT_OP_SET_CONNECTABLE, - cp->val); + err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev); goto failed; } @@ -595,8 +638,9 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, static int set_pairable(struct sock *sk, u16 index, unsigned char *data, u16 len) { - struct mgmt_mode *cp, ev; + struct mgmt_mode *cp; struct hci_dev *hdev; + __le32 ev; int err; cp = (void *) data; @@ -619,13 +663,13 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data, else clear_bit(HCI_PAIRABLE, &hdev->flags); - err = send_mode_rsp(sk, MGMT_OP_SET_PAIRABLE, index, cp->val); + err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev); if (err < 0) goto failed; - ev.val = cp->val; + ev = cpu_to_le32(get_current_settings(hdev)); - err = mgmt_event(MGMT_EV_PAIRABLE, hdev, &ev, sizeof(ev), sk); + err = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), sk); failed: hci_dev_unlock(hdev); @@ -2234,17 +2278,14 @@ int mgmt_index_removed(struct hci_dev *hdev) struct cmd_lookup { u8 val; struct sock *sk; + struct hci_dev *hdev; }; -static void mode_rsp(struct pending_cmd *cmd, void *data) +static void settings_rsp(struct pending_cmd *cmd, void *data) { - struct mgmt_mode *cp = cmd->param; struct cmd_lookup *match = data; - if (cp->val != match->val) - return; - - send_mode_rsp(cmd->sk, cmd->opcode, cmd->index, cp->val); + send_settings_rsp(cmd->sk, cmd->opcode, match->hdev); list_del(&cmd->list); @@ -2258,20 +2299,21 @@ static void mode_rsp(struct pending_cmd *cmd, void *data) int mgmt_powered(struct hci_dev *hdev, u8 powered) { - struct mgmt_mode ev; - struct cmd_lookup match = { powered, NULL }; + struct cmd_lookup match = { powered, NULL, hdev }; + __le32 ev; int ret; - mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, mode_rsp, &match); + mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); if (!powered) { u8 status = ENETDOWN; mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); } - ev.val = powered; + ev = cpu_to_le32(get_current_settings(hdev)); - ret = mgmt_event(MGMT_EV_POWERED, hdev, &ev, sizeof(ev), match.sk); + ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), + match.sk); if (match.sk) sock_put(match.sk); @@ -2281,17 +2323,16 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered) int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) { - struct mgmt_mode ev; - struct cmd_lookup match = { discoverable, NULL }; + struct cmd_lookup match = { discoverable, NULL, hdev }; + __le32 ev; int ret; - mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, mode_rsp, &match); + mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, settings_rsp, &match); - ev.val = discoverable; + ev = cpu_to_le32(get_current_settings(hdev)); - ret = mgmt_event(MGMT_EV_DISCOVERABLE, hdev, &ev, sizeof(ev), + ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), match.sk); - if (match.sk) sock_put(match.sk); @@ -2300,15 +2341,16 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) int mgmt_connectable(struct hci_dev *hdev, u8 connectable) { - struct mgmt_mode ev; - struct cmd_lookup match = { connectable, NULL }; + __le32 ev; + struct cmd_lookup match = { connectable, NULL, hdev }; int ret; - mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, mode_rsp, &match); + mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, settings_rsp, + &match); - ev.val = connectable; + ev = cpu_to_le32(get_current_settings(hdev)); - ret = mgmt_event(MGMT_EV_CONNECTABLE, hdev, &ev, sizeof(ev), match.sk); + ret = mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), match.sk); if (match.sk) sock_put(match.sk); -- cgit v1.2.3 From 350ee4cfc0ea620bd1126ad4daa295586d6aa3a9 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Wed, 7 Dec 2011 15:56:51 +0200 Subject: Bluetooth: Add HCI Read Data Block Size function Implement block size read function. Use different variables for packet-based and block-based flow control. Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 8 ++++++++ include/net/bluetooth/hci_core.h | 5 +++++ net/bluetooth/hci_event.c | 26 ++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) (limited to 'include/net/bluetooth/hci.h') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index c9ad56fe58f4..2e48d326e365 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -746,6 +746,14 @@ struct hci_rp_read_bd_addr { bdaddr_t bdaddr; } __packed; +#define HCI_OP_READ_DATA_BLOCK_SIZE 0x100a +struct hci_rp_read_data_block_size { + __u8 status; + __le16 max_acl_len; + __le16 block_len; + __le16 num_blocks; +} __packed; + #define HCI_OP_WRITE_PAGE_SCAN_ACTIVITY 0x0c1c struct hci_cp_write_page_scan_activity { __le16 interval; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 105eaa251034..74f8356b9ff1 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -181,6 +181,11 @@ struct hci_dev { unsigned int sco_pkts; unsigned int le_pkts; + __u16 block_len; + __u16 block_mtu; + __u16 num_blocks; + __u16 block_cnt; + unsigned long acl_last_tx; unsigned long sco_last_tx; unsigned long le_last_tx; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 74f758363c2d..48796832fdf0 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -767,6 +767,28 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) hci_req_complete(hdev, HCI_OP_READ_BD_ADDR, rp->status); } +static void hci_cc_read_data_block_size(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_rp_read_data_block_size *rp = (void *) skb->data; + + BT_DBG("%s status 0x%x", hdev->name, rp->status); + + if (rp->status) + return; + + hdev->block_mtu = __le16_to_cpu(rp->max_acl_len); + hdev->block_len = __le16_to_cpu(rp->block_len); + hdev->num_blocks = __le16_to_cpu(rp->num_blocks); + + hdev->block_cnt = hdev->num_blocks; + + BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu, + hdev->block_cnt, hdev->block_len); + + hci_req_complete(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, rp->status); +} + static void hci_cc_write_ca_timeout(struct hci_dev *hdev, struct sk_buff *skb) { __u8 status = *((__u8 *) skb->data); @@ -2018,6 +2040,10 @@ static inline void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *sk hci_cc_read_bd_addr(hdev, skb); break; + case HCI_OP_READ_DATA_BLOCK_SIZE: + hci_cc_read_data_block_size(hdev, skb); + break; + case HCI_OP_WRITE_CA_TIMEOUT: hci_cc_write_ca_timeout(hdev, skb); break; -- cgit v1.2.3 From 2455a3ea0c0235fe3c32b67649ff7db3fb892d90 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Mon, 19 Dec 2011 16:31:28 +0200 Subject: Bluetooth: Initialize default flow control mode Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 4 ++++ net/bluetooth/hci_core.c | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'include/net/bluetooth/hci.h') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 2e48d326e365..66b26399a1ca 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -280,6 +280,10 @@ enum { #define HCI_ERROR_LOCAL_HOST_TERM 0x16 #define HCI_ERROR_PAIRING_NOT_ALLOWED 0x18 +/* Flow control modes */ +#define HCI_FLOW_CTL_MODE_PACKET_BASED 0x00 +#define HCI_FLOW_CTL_MODE_BLOCK_BASED 0x01 + /* ----- HCI Commands ---- */ #define HCI_OP_NOP 0x0000 diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index bb089e3bccef..884eb85a136a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -199,6 +199,8 @@ static void bredr_init(struct hci_dev *hdev) __le16 param; __u8 flt_type; + hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED; + /* Mandatory initialization */ /* Reset */ @@ -245,6 +247,8 @@ static void bredr_init(struct hci_dev *hdev) static void amp_init(struct hci_dev *hdev) { + hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_BLOCK_BASED; + /* Reset */ hci_send_cmd(hdev, HCI_OP_RESET, 0, NULL); -- cgit v1.2.3 From 613a1c0c595fe2f2d9148a705f140a53bc9f56e1 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Mon, 19 Dec 2011 16:31:30 +0200 Subject: Bluetooth: Clean up magic pointers Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 7 ++++++- net/bluetooth/hci_event.c | 8 ++++---- 2 files changed, 10 insertions(+), 5 deletions(-) (limited to 'include/net/bluetooth/hci.h') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 66b26399a1ca..6127ca8bd1d1 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -979,9 +979,14 @@ struct hci_ev_role_change { } __packed; #define HCI_EV_NUM_COMP_PKTS 0x13 +struct hci_comp_pkts_info { + __le16 handle; + __le16 count; +} __packed; + struct hci_ev_num_comp_pkts { __u8 num_hndl; - /* variable length part */ + struct hci_comp_pkts_info handles[0]; } __packed; #define HCI_EV_MODE_CHANGE 0x14 diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 5a204aefc035..b9d77be92d3b 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2256,7 +2256,6 @@ static inline void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_num_comp_pkts *ev = (void *) skb->data; - __le16 *ptr; int i; skb_pull(skb, sizeof(*ev)); @@ -2273,12 +2272,13 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s return; } - for (i = 0, ptr = (__le16 *) skb->data; i < ev->num_hndl; i++) { + for (i = 0; i < ev->num_hndl; i++) { + struct hci_comp_pkts_info *info = &ev->handles[i]; struct hci_conn *conn; __u16 handle, count; - handle = get_unaligned_le16(ptr++); - count = get_unaligned_le16(ptr++); + handle = __le16_to_cpu(info->handle); + count = __le16_to_cpu(info->count); conn = hci_conn_hash_lookup_handle(hdev, handle); if (!conn) -- cgit v1.2.3 From 68a8aea45973c8d0bc05f58389ce9e82e04bb5f6 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Mon, 19 Dec 2011 16:14:18 +0200 Subject: Bluetooth: Remove magic numbers from le scan cmd Make code readable by removing magic numbers. Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo F. Padovan --- include/net/bluetooth/hci.h | 3 +++ net/bluetooth/hci_event.c | 12 ++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'include/net/bluetooth/hci.h') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 6127ca8bd1d1..5b2fed5eebf2 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -804,6 +804,9 @@ struct hci_cp_le_set_scan_param { __u8 filter_policy; } __packed; +#define LE_SCANNING_DISABLED 0x00 +#define LE_SCANNING_ENABLED 0x01 + #define HCI_OP_LE_SET_SCAN_ENABLE 0x200c struct hci_cp_le_set_scan_enable { __u8 enable; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index b9d77be92d3b..919e3c0e74aa 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1033,7 +1033,8 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, if (!cp) return; - if (cp->enable == 0x01) { + switch (cp->enable) { + case LE_SCANNING_ENABLED: set_bit(HCI_LE_SCAN, &hdev->dev_flags); cancel_delayed_work_sync(&hdev->adv_work); @@ -1041,12 +1042,19 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, hci_dev_lock(hdev); hci_adv_entries_clear(hdev); hci_dev_unlock(hdev); - } else if (cp->enable == 0x00) { + break; + + case LE_SCANNING_DISABLED: clear_bit(HCI_LE_SCAN, &hdev->dev_flags); cancel_delayed_work_sync(&hdev->adv_work); queue_delayed_work(hdev->workqueue, &hdev->adv_work, jiffies + ADV_CLEAR_TIMEOUT); + break; + + default: + BT_ERR("Used reserved LE_Scan_Enable param %d", cp->enable); + break; } } -- cgit v1.2.3