From f1e5d54743b99cbbea0e0cfb2b3f8053f045b3d7 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Thu, 3 Oct 2013 18:25:44 -0300 Subject: Bluetooth: Rename hci_conn variable in hci_connect_le() This patch simply rename the hci_conn variable "le" to "conn" since it is a better name. Signed-off-by: Andre Guedes Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 514148b7a66b..5aba520cddfe 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -549,31 +549,31 @@ EXPORT_SYMBOL(hci_get_route); static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, u8 dst_type, u8 sec_level, u8 auth_type) { - struct hci_conn *le; + struct hci_conn *conn; if (test_bit(HCI_LE_PERIPHERAL, &hdev->flags)) return ERR_PTR(-ENOTSUPP); - le = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); - if (!le) { - le = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); - if (le) + conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); + if (!conn) { + conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); + if (conn) return ERR_PTR(-EBUSY); - le = hci_conn_add(hdev, LE_LINK, dst); - if (!le) + conn = hci_conn_add(hdev, LE_LINK, dst); + if (!conn) return ERR_PTR(-ENOMEM); - le->dst_type = bdaddr_to_le(dst_type); - hci_le_create_connection(le); + conn->dst_type = bdaddr_to_le(dst_type); + hci_le_create_connection(conn); } - le->pending_sec_level = sec_level; - le->auth_type = auth_type; + conn->pending_sec_level = sec_level; + conn->auth_type = auth_type; - hci_conn_hold(le); + hci_conn_hold(conn); - return le; + return conn; } static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, -- cgit v1.2.3-73-gaa49b From 46a190cbd3d8992a017664367e9227dcd357ce53 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Thu, 3 Oct 2013 18:25:45 -0300 Subject: Bluetooth: Initialize hci_conn fields in hci_connect_le This patch moves some hci_conn fields initialization from hci_le_ create_connection() to hci_connect_le(). It makes more sense to initialize these fields within the function that creates the hci_ conn object. Signed-off-by: Andre Guedes Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 5aba520cddfe..08e601c68314 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -54,11 +54,6 @@ static void hci_le_create_connection(struct hci_conn *conn) struct hci_dev *hdev = conn->hdev; struct hci_cp_le_create_conn cp; - conn->state = BT_CONNECT; - conn->out = true; - conn->link_mode |= HCI_LM_MASTER; - conn->sec_level = BT_SECURITY_LOW; - memset(&cp, 0, sizeof(cp)); cp.scan_interval = __constant_cpu_to_le16(0x0060); cp.scan_window = __constant_cpu_to_le16(0x0030); @@ -565,6 +560,11 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, return ERR_PTR(-ENOMEM); conn->dst_type = bdaddr_to_le(dst_type); + conn->state = BT_CONNECT; + conn->out = true; + conn->link_mode |= HCI_LM_MASTER; + conn->sec_level = BT_SECURITY_LOW; + hci_le_create_connection(conn); } -- cgit v1.2.3-73-gaa49b From f3d3444a4d7f76e79841c59c78105a45295cc4b0 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 5 Oct 2013 12:01:04 +0200 Subject: Bluetooth: Rename HCI_LE_PERIPHERAL to HCI_ADVERTISING This flag is used to indicate whether we want to have advertising enabled or not, so give it a more suitable name. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci.h | 2 +- net/bluetooth/hci_conn.c | 2 +- net/bluetooth/hci_core.c | 2 +- net/bluetooth/hci_event.c | 6 +++--- net/bluetooth/mgmt.c | 18 +++++++++--------- 5 files changed, 15 insertions(+), 15 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index b90eec5e9c06..e8bba05686d1 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -118,7 +118,7 @@ enum { HCI_SSP_ENABLED, HCI_HS_ENABLED, HCI_LE_ENABLED, - HCI_LE_PERIPHERAL, + HCI_ADVERTISING, HCI_CONNECTABLE, HCI_DISCOVERABLE, HCI_LINK_SECURITY, diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 08e601c68314..8b0d08fb6158 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -546,7 +546,7 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, { struct hci_conn *conn; - if (test_bit(HCI_LE_PERIPHERAL, &hdev->flags)) + if (test_bit(HCI_ADVERTISING, &hdev->flags)) return ERR_PTR(-ENOTSUPP); conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 82dbdc6a7e9e..aa63ebb114d4 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1105,7 +1105,7 @@ static u8 create_ad(struct hci_dev *hdev, u8 *ptr) u8 ad_len = 0, flags = 0; size_t name_len; - if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) + if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) flags |= LE_AD_GENERAL; if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 4785ab0795f5..e1ad858b1fb6 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -918,9 +918,9 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) if (!status) { if (*sent) - set_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); + set_bit(HCI_ADVERTISING, &hdev->dev_flags); else - clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); + clear_bit(HCI_ADVERTISING, &hdev->dev_flags); } if (!test_bit(HCI_INIT, &hdev->flags)) { @@ -1005,7 +1005,7 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, } else { hdev->features[1][0] &= ~LMP_HOST_LE; clear_bit(HCI_LE_ENABLED, &hdev->dev_flags); - clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); + clear_bit(HCI_ADVERTISING, &hdev->dev_flags); } if (sent->simul) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 16125ff918f1..7e43d376e2e6 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -425,7 +425,7 @@ static u32 get_current_settings(struct hci_dev *hdev) if (test_bit(HCI_HS_ENABLED, &hdev->dev_flags)) settings |= MGMT_SETTING_HS; - if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) + if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) settings |= MGMT_SETTING_ADVERTISING; return settings; @@ -1463,8 +1463,8 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) changed = true; } - if (!val && test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) { - clear_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); + if (!val && test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { + clear_bit(HCI_ADVERTISING, &hdev->dev_flags); changed = true; } @@ -1500,7 +1500,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) hci_req_init(&req, hdev); - if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags) && !val) + if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) && !val) hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(val), &val); hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), @@ -2888,7 +2888,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, goto failed; } - if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) { + if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, MGMT_STATUS_REJECTED); mgmt_pending_remove(cmd); @@ -3236,13 +3236,13 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, u1 hci_dev_lock(hdev); val = !!cp->val; - enabled = test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); + enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags); if (!hdev_is_powered(hdev) || val == enabled) { bool changed = false; - if (val != test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) { - change_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags); + if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { + change_bit(HCI_ADVERTISING, &hdev->dev_flags); changed = true; } @@ -3851,7 +3851,7 @@ static int powered_update_hci(struct hci_dev *hdev) &hdev->static_addr); } - if (test_bit(HCI_LE_PERIPHERAL, &hdev->dev_flags)) { + if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { u8 adv = 0x01; hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(adv), &adv); -- cgit v1.2.3-73-gaa49b From d2f5a196d7b401b79e2321b24cc0ac8636ffbc17 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 5 Oct 2013 12:01:05 +0200 Subject: Bluetooth: Add public mgmt function to send New Settings event A function is needed so that the HCI event processing can ask the mgmt code to emit a new settings event. This is necessary e.g. when the event processing does updates to mgmt related states without any dependency of actual mgmt commands. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci_core.h | 1 + net/bluetooth/mgmt.c | 5 +++++ 2 files changed, 6 insertions(+) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index e09c30577b3a..079c5c55c829 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1123,6 +1123,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event); int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); int mgmt_index_added(struct hci_dev *hdev); int mgmt_index_removed(struct hci_dev *hdev); +int mgmt_new_settings(struct hci_dev *hdev); int mgmt_set_powered_failed(struct hci_dev *hdev, int err); int mgmt_powered(struct hci_dev *hdev, u8 powered); int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 7e43d376e2e6..6e808d1d78f3 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -890,6 +890,11 @@ static int new_settings(struct hci_dev *hdev, struct sock *skip) return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip); } +int mgmt_new_settings(struct hci_dev *hdev) +{ + return new_settings(hdev, NULL); +} + struct cmd_lookup { struct sock *sk; struct hci_dev *hdev; -- cgit v1.2.3-73-gaa49b From 2210246cf52bd60e8af452f8e184d1cb53e1e4b1 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 5 Oct 2013 12:01:06 +0200 Subject: Bluetooth: Fix re-enabling advertising after a connection LE controllers will automatically disable advertising whenever they accept a new connection. In order not to fall out of sync with the advertising setting we need to re-enable advertising whenever the last LE connection drops. A failure to re-enable advertising should cause the setting to be disabled, so this patch also calls mgmt_new_settings() when this happens. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_event.c | 51 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index e1ad858b1fb6..6eaef6ed9522 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1796,6 +1796,40 @@ static u8 hci_to_mgmt_reason(u8 err) } } +static void adv_enable_complete(struct hci_dev *hdev, u8 status) +{ + BT_DBG("%s status %u", hdev->name, status); + + /* Clear the advertising mgmt setting if we failed to re-enable it */ + if (status) { + clear_bit(HCI_ADVERTISING, &hdev->dev_flags); + mgmt_new_settings(hdev); + } +} + +static void reenable_advertising(struct hci_dev *hdev) +{ + struct hci_request req; + u8 enable = 0x01; + + if (hdev->conn_hash.le_num) + return; + + if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags)) + return; + + hci_req_init(&req, hdev); + hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); + + /* If this fails we have no option but to let user space know + * that we've disabled advertising. + */ + if (hci_req_run(&req, adv_enable_complete) < 0) { + clear_bit(HCI_ADVERTISING, &hdev->dev_flags); + mgmt_new_settings(hdev); + } +} + static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_disconn_complete *ev = (void *) skb->data; @@ -1826,10 +1860,25 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) } if (ev->status == 0) { - if (conn->type == ACL_LINK && conn->flush_key) + u8 type = conn->type; + + if (type == ACL_LINK && conn->flush_key) hci_remove_link_key(hdev, &conn->dst); hci_proto_disconn_cfm(conn, ev->reason); hci_conn_del(conn); + + /* Re-enable advertising if necessary, since it might + * have been disabled by the connection. From the + * HCI_LE_Set_Advertise_Enable command description in + * the core specification (v4.0): + * "The Controller shall continue advertising until the Host + * issues an LE_Set_Advertise_Enable command with + * Advertising_Enable set to 0x00 (Advertising is disabled) + * or until a connection is created or until the Advertising + * is timed out due to Directed Advertising." + */ + if (type == LE_LINK) + reenable_advertising(hdev); } unlock: -- cgit v1.2.3-73-gaa49b From 23b9003b9ae8dac111460597ba683844e9195e4e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 5 Oct 2013 11:47:40 -0700 Subject: Bluetooth: Fix controller list for AMP discover response The AMP discover response should list exactly one BR/EDR controller and ignore all other BR/EDR controller. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/a2mp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 17f33a62f6db..eb0f05e09cd5 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -92,7 +92,7 @@ static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl, u8 num_ctrl) list_for_each_entry(hdev, &hci_dev_list, list) { /* Iterate through AMP controllers */ - if (hdev->id == HCI_BREDR_ID) + if (hdev->dev_type != HCI_AMP) continue; /* Starting from second entry */ -- cgit v1.2.3-73-gaa49b From f822c411b26ce0353c8b97877e53a12e4f895ca1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 5 Oct 2013 11:47:41 -0700 Subject: Bluetooth: Remove useless external function to count controllers The list of controllers can be counted ahead of time and inline inside the AMP discover handling. There is no need to export such a function at all. In addition just count the AMP controller and only allocated space for a single mandatory BR/EDR controller. No need to allocate more space than needed. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 13 ------------- net/bluetooth/a2mp.c | 10 +++++++++- 2 files changed, 9 insertions(+), 14 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 079c5c55c829..db650baf8177 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -704,19 +704,6 @@ 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); diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index eb0f05e09cd5..a6e45e177b3d 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -129,6 +129,7 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb, struct a2mp_discov_rsp *rsp; u16 ext_feat; u8 num_ctrl; + struct hci_dev *hdev; if (len < sizeof(*req)) return -EINVAL; @@ -152,7 +153,14 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb, read_lock(&hci_dev_list_lock); - num_ctrl = __hci_num_ctrl(); + /* at minimum the BR/EDR needs to be listed */ + num_ctrl = 1; + + list_for_each_entry(hdev, &hci_dev_list, list) { + if (hdev->dev_type == HCI_AMP) + num_ctrl++; + } + len = num_ctrl * sizeof(struct a2mp_cl) + sizeof(*rsp); rsp = kmalloc(len, GFP_ATOMIC); if (!rsp) { -- cgit v1.2.3-73-gaa49b From ece6912648da3fcf257a40774e3aad531c3e5fac Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 5 Oct 2013 11:47:43 -0700 Subject: Bluetooth: Separate AMP controller type from HCI device type There are two defined HCI device types. One is for BR/EDR controllers and the other is for AMP controllers. The HCI device type is not the same as the AMP controller type. It just happens that currently the defined types match, but that is not guaranteed. Split the usage of AMP controller type into its own domain so that it is possible to separate between BR/EDR controllers, 802.11 AMP controllers and any other AMP technology that might be defined in the future. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/a2mp.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index db650baf8177..4cb355b023a4 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -803,7 +803,7 @@ static inline bool hci_amp_capable(void) read_lock(&hci_dev_list_lock); list_for_each_entry(hdev, &hci_dev_list, list) - if (hdev->amp_type == HCI_AMP && + if (hdev->amp_type != AMP_TYPE_BREDR && test_bit(HCI_UP, &hdev->flags)) ret = true; read_unlock(&hci_dev_list_lock); diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index a6e45e177b3d..b2ef3d392a0e 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -78,7 +78,7 @@ u8 __next_ident(struct amp_mgr *mgr) static inline void __a2mp_cl_bredr(struct a2mp_cl *cl) { cl->id = 0; - cl->type = 0; + cl->type = AMP_TYPE_BREDR; cl->status = 1; } @@ -352,7 +352,7 @@ static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb, tmp = amp_mgr_lookup_by_state(READ_LOC_AMP_ASSOC); hdev = hci_dev_get(req->id); - if (!hdev || hdev->amp_type == HCI_BREDR || tmp) { + if (!hdev || hdev->amp_type == AMP_TYPE_BREDR || tmp) { struct a2mp_amp_assoc_rsp rsp; rsp.id = req->id; @@ -459,7 +459,7 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, rsp.remote_id = req->local_id; hdev = hci_dev_get(req->remote_id); - if (!hdev || hdev->amp_type != HCI_AMP) { + if (!hdev || hdev->amp_type == AMP_TYPE_BREDR) { rsp.status = A2MP_STATUS_INVALID_CTRL_ID; goto send_rsp; } @@ -879,7 +879,7 @@ void a2mp_send_getinfo_rsp(struct hci_dev *hdev) rsp.id = hdev->id; rsp.status = A2MP_STATUS_INVALID_CTRL_ID; - if (hdev->amp_type != HCI_BREDR) { + if (hdev->amp_type != AMP_TYPE_BREDR) { rsp.status = 0; rsp.total_bw = cpu_to_le32(hdev->amp_total_bw); rsp.max_bw = cpu_to_le32(hdev->amp_max_bw); -- cgit v1.2.3-73-gaa49b From 6ed971ca4f6bd96e26b3166cb5a94f7f8158fe77 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 5 Oct 2013 11:47:44 -0700 Subject: Bluetooth: Use explicit AMP controller id value for BR/EDR The special AMP controller id 0 is reserved for the BR/EDR controller that has the main link. It is a fixed value and so use a constant for this throughout the code to make it more visible when the handling is for the BR/EDR channel or when it is for the AMP channel. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci.h | 2 +- net/bluetooth/a2mp.c | 4 ++-- net/bluetooth/l2cap_core.c | 28 ++++++++++++++-------------- 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 8e3076ebb8ad..393eabc0d21f 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -64,7 +64,7 @@ #define HCI_AMP 0x01 /* First BR/EDR Controller shall have ID = 0 */ -#define HCI_BREDR_ID 0 +#define AMP_ID_BREDR 0x00 /* AMP controller types */ #define AMP_TYPE_BREDR 0x00 diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index b2ef3d392a0e..6d62d3140cf8 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -77,7 +77,7 @@ u8 __next_ident(struct amp_mgr *mgr) static inline void __a2mp_cl_bredr(struct a2mp_cl *cl) { - cl->id = 0; + cl->id = AMP_ID_BREDR; cl->type = AMP_TYPE_BREDR; cl->status = 1; } @@ -216,7 +216,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb, BT_DBG("Remote AMP id %d type %d status %d", cl->id, cl->type, cl->status); - if (cl->id != HCI_BREDR_ID && cl->type == HCI_AMP) { + if (cl->id != AMP_ID_BREDR && cl->type == HCI_AMP) { struct a2mp_info_req req; found = true; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 02dba4e6df96..b0208e20390c 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -3046,8 +3046,8 @@ int l2cap_ertm_init(struct l2cap_chan *chan) skb_queue_head_init(&chan->tx_q); - chan->local_amp_id = 0; - chan->move_id = 0; + chan->local_amp_id = AMP_ID_BREDR; + chan->move_id = AMP_ID_BREDR; chan->move_state = L2CAP_MOVE_STABLE; chan->move_role = L2CAP_MOVE_ROLE_NONE; @@ -3100,7 +3100,7 @@ static inline bool __l2cap_efs_supported(struct l2cap_conn *conn) static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, struct l2cap_conf_rfc *rfc) { - if (chan->local_amp_id && chan->hs_hcon) { + if (chan->local_amp_id != AMP_ID_BREDR && chan->hs_hcon) { u64 ertm_to = chan->hs_hcon->hdev->amp_be_flush_to; /* Class 1 devices have must have ERTM timeouts @@ -3791,12 +3791,12 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, * The connection will succeed after the * physical link is up. */ - if (amp_id) { - __l2cap_state_change(chan, BT_CONNECT2); - result = L2CAP_CR_PEND; - } else { + if (amp_id == AMP_ID_BREDR) { __l2cap_state_change(chan, BT_CONFIG); result = L2CAP_CR_SUCCESS; + } else { + __l2cap_state_change(chan, BT_CONNECT2); + result = L2CAP_CR_PEND; } status = L2CAP_CS_NO_INFO; } @@ -4423,7 +4423,7 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn, BT_DBG("psm 0x%2.2x, scid 0x%4.4x, amp_id %d", psm, scid, req->amp_id); /* For controller id 0 make BR/EDR connection */ - if (req->amp_id == HCI_BREDR_ID) { + if (req->amp_id == AMP_ID_BREDR) { l2cap_connect(conn, cmd, data, L2CAP_CREATE_CHAN_RSP, req->amp_id); return 0; @@ -4658,7 +4658,7 @@ void l2cap_logical_cfm(struct l2cap_chan *chan, struct hci_chan *hchan, if (chan->state != BT_CONNECTED) { /* Ignore logical link if channel is on BR/EDR */ - if (chan->local_amp_id) + if (chan->local_amp_id != AMP_ID_BREDR) l2cap_logical_finish_create(chan, hchan); } else { l2cap_logical_finish_move(chan, hchan); @@ -4669,7 +4669,7 @@ void l2cap_move_start(struct l2cap_chan *chan) { BT_DBG("chan %p", chan); - if (chan->local_amp_id == HCI_BREDR_ID) { + if (chan->local_amp_id == AMP_ID_BREDR) { if (chan->chan_policy != BT_CHANNEL_POLICY_AMP_PREFERRED) return; chan->move_role = L2CAP_MOVE_ROLE_INITIATOR; @@ -4868,7 +4868,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn, goto send_move_response; } - if (req->dest_amp_id) { + if (req->dest_amp_id != AMP_ID_BREDR) { struct hci_dev *hdev; hdev = hci_dev_get(req->dest_amp_id); if (!hdev || hdev->dev_type != HCI_AMP || @@ -4898,7 +4898,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn, chan->move_id = req->dest_amp_id; icid = chan->dcid; - if (!req->dest_amp_id) { + if (req->dest_amp_id == AMP_ID_BREDR) { /* Moving to BR/EDR */ if (test_bit(CONN_LOCAL_BUSY, &chan->conn_state)) { chan->move_state = L2CAP_MOVE_WAIT_LOCAL_BUSY; @@ -5090,7 +5090,7 @@ static int l2cap_move_channel_confirm(struct l2cap_conn *conn, if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM) { if (result == L2CAP_MC_CONFIRMED) { chan->local_amp_id = chan->move_id; - if (!chan->local_amp_id) + if (chan->local_amp_id == AMP_ID_BREDR) __release_logical_link(chan); } else { chan->move_id = chan->local_amp_id; @@ -5130,7 +5130,7 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, if (chan->move_state == L2CAP_MOVE_WAIT_CONFIRM_RSP) { chan->local_amp_id = chan->move_id; - if (!chan->local_amp_id && chan->hs_hchan) + if (chan->local_amp_id == AMP_ID_BREDR && chan->hs_hchan) __release_logical_link(chan); l2cap_move_done(chan); -- cgit v1.2.3-73-gaa49b From 536619e86d9398a20063f7c3d15deb9dcc234097 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 5 Oct 2013 11:47:45 -0700 Subject: Bluetooth: Rename AMP status constants and use them The AMP controller status constants need to be actually used to avoid crypted hardcoded numbers. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci.h | 14 +++++++------- net/bluetooth/a2mp.c | 2 +- net/bluetooth/hci_core.c | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 393eabc0d21f..9f8d1c1f0414 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -71,13 +71,13 @@ #define AMP_TYPE_80211 0x01 /* AMP controller status */ -#define AMP_CTRL_POWERED_DOWN 0x00 -#define AMP_CTRL_BLUETOOTH_ONLY 0x01 -#define AMP_CTRL_NO_CAPACITY 0x02 -#define AMP_CTRL_LOW_CAPACITY 0x03 -#define AMP_CTRL_MEDIUM_CAPACITY 0x04 -#define AMP_CTRL_HIGH_CAPACITY 0x05 -#define AMP_CTRL_FULL_CAPACITY 0x06 +#define AMP_STATUS_POWERED_DOWN 0x00 +#define AMP_STATUS_BLUETOOTH_ONLY 0x01 +#define AMP_STATUS_NO_CAPACITY 0x02 +#define AMP_STATUS_LOW_CAPACITY 0x03 +#define AMP_STATUS_MEDIUM_CAPACITY 0x04 +#define AMP_STATUS_HIGH_CAPACITY 0x05 +#define AMP_STATUS_FULL_CAPACITY 0x06 /* HCI device quirks */ enum { diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 6d62d3140cf8..6dfef731825f 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -79,7 +79,7 @@ static inline void __a2mp_cl_bredr(struct a2mp_cl *cl) { cl->id = AMP_ID_BREDR; cl->type = AMP_TYPE_BREDR; - cl->status = 1; + cl->status = AMP_STATUS_BLUETOOTH_ONLY; } /* hci_dev_list shall be locked */ diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index aa63ebb114d4..0d5fe0843f5e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1381,7 +1381,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) } /* Controller radio is available but is currently powered down */ - hdev->amp_status = 0; + hdev->amp_status = AMP_STATUS_POWERED_DOWN; memset(hdev->eir, 0, sizeof(hdev->eir)); memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); -- cgit v1.2.3-73-gaa49b From 346e7099c299eae085efd9b4aeda813d69bc364b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 5 Oct 2013 11:47:46 -0700 Subject: Bluetooth: Remove pointless inline function The inline function for BR/EDR controller AMP discover response info is rather useless. Just include the code into the function that builds the whole response. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/a2mp.c | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 6dfef731825f..a1aae5c45b7e 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -75,20 +75,15 @@ u8 __next_ident(struct amp_mgr *mgr) return mgr->ident; } -static inline void __a2mp_cl_bredr(struct a2mp_cl *cl) -{ - cl->id = AMP_ID_BREDR; - cl->type = AMP_TYPE_BREDR; - cl->status = AMP_STATUS_BLUETOOTH_ONLY; -} - /* hci_dev_list shall be locked */ static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl, u8 num_ctrl) { int i = 0; struct hci_dev *hdev; - __a2mp_cl_bredr(cl); + cl[0].id = AMP_ID_BREDR; + cl[0].type = AMP_TYPE_BREDR; + cl[0].status = AMP_STATUS_BLUETOOTH_ONLY; list_for_each_entry(hdev, &hci_dev_list, list) { /* Iterate through AMP controllers */ -- cgit v1.2.3-73-gaa49b From 23f0cb41a20e9850513fa4943f6a19525000cce2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 5 Oct 2013 11:47:47 -0700 Subject: Bluetooth: Remove check for number of AMP controller The number of controllers for the AMP discover response has already been calculated. And since the hci_dev_list lock is held, it can not change. So there is no need for any extra checks. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/a2mp.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index a1aae5c45b7e..529789d81159 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -76,7 +76,7 @@ u8 __next_ident(struct amp_mgr *mgr) } /* hci_dev_list shall be locked */ -static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl, u8 num_ctrl) +static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl) { int i = 0; struct hci_dev *hdev; @@ -91,8 +91,7 @@ static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl, u8 num_ctrl) continue; /* Starting from second entry */ - if (++i >= num_ctrl) - return; + ++i; cl[i].id = hdev->id; cl[i].type = hdev->amp_type; @@ -166,7 +165,7 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb, rsp->mtu = __constant_cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU); rsp->ext_feat = 0; - __a2mp_add_cl(mgr, rsp->cl, num_ctrl); + __a2mp_add_cl(mgr, rsp->cl); read_unlock(&hci_dev_list_lock); -- cgit v1.2.3-73-gaa49b From 80d58d0b5b18b68addad61e228ced167f8b80dd3 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 5 Oct 2013 11:47:48 -0700 Subject: Bluetooth: Move hci_amp_capable() function into L2CAP core The hci_amp_capable() function has only a single user inside the L2CAP core. Instead of exporting the function, place it next to its user. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 16 ---------------- net/bluetooth/l2cap_core.c | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 4cb355b023a4..82c397451261 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -795,22 +795,6 @@ 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 != AMP_TYPE_BREDR && - test_bit(HCI_UP, &hdev->flags)) - ret = true; - read_unlock(&hci_dev_list_lock); - - return ret; -} - /* ----- HCI protocols ----- */ #define HCI_PROTO_DEFER 0x01 diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b0208e20390c..2efdb17d87a3 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1012,6 +1012,22 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); } +/* 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 != AMP_TYPE_BREDR && + test_bit(HCI_UP, &hdev->flags)) + ret = true; + read_unlock(&hci_dev_list_lock); + + return ret; +} + static bool __amp_capable(struct l2cap_chan *chan) { struct l2cap_conn *conn = chan->conn; -- cgit v1.2.3-73-gaa49b From 1df7b17a87b1aa4d08c461fce06226d33910bf94 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 5 Oct 2013 11:47:49 -0700 Subject: Bluetooth: Simplify check if L2CAP connection is AMP capable The check if a L2CAP connection is AMP capable was a little bit complicated. This changes the code to make it simpler and more readable. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/l2cap_core.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 2efdb17d87a3..a9a7df6639a7 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1012,30 +1012,30 @@ static inline int __l2cap_no_conn_pending(struct l2cap_chan *chan) return !test_bit(CONF_CONNECT_PEND, &chan->conf_state); } -/* returns true if at least one AMP active */ -static inline bool hci_amp_capable(void) +static bool __amp_capable(struct l2cap_chan *chan) { + struct l2cap_conn *conn = chan->conn; struct hci_dev *hdev; - bool ret = false; + bool amp_available = false; + + if (!conn->hs_enabled) + return false; + + if (!(conn->fixed_chan_mask & L2CAP_FC_A2MP)) + return false; read_lock(&hci_dev_list_lock); - list_for_each_entry(hdev, &hci_dev_list, list) + list_for_each_entry(hdev, &hci_dev_list, list) { if (hdev->amp_type != AMP_TYPE_BREDR && - test_bit(HCI_UP, &hdev->flags)) - ret = true; + test_bit(HCI_UP, &hdev->flags)) { + amp_available = true; + break; + } + } read_unlock(&hci_dev_list_lock); - return ret; -} - -static bool __amp_capable(struct l2cap_chan *chan) -{ - struct l2cap_conn *conn = chan->conn; - - if (conn->hs_enabled && hci_amp_capable() && - chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED && - conn->fixed_chan_mask & L2CAP_FC_A2MP) - return true; + if (chan->chan_policy == BT_CHANNEL_POLICY_AMP_PREFERRED) + return amp_available; return false; } -- cgit v1.2.3-73-gaa49b From a646bd81945b337b1cf37dea4734847947a0d9ad Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 5 Oct 2013 13:57:53 -0700 Subject: Bluetooth: Check for non BR/EDR controller in AMP discover response Within the AMP discover response, all controllers that are not the primary BR/EDR controller are valid. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/a2mp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 529789d81159..ad8bda3a6fd1 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -210,7 +210,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb, BT_DBG("Remote AMP id %d type %d status %d", cl->id, cl->type, cl->status); - if (cl->id != AMP_ID_BREDR && cl->type == HCI_AMP) { + if (cl->id != AMP_ID_BREDR && cl->type != AMP_TYPE_BREDR) { struct a2mp_info_req req; found = true; -- cgit v1.2.3-73-gaa49b From a5c8f270e4dae14ea5cb88e477ed1092955f8722 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 01:08:57 -0700 Subject: Bluetooth: Reject enabling controllers without valid addresses In case of a single mode LE-only controller it is possible that no public address is used. These type of controllers require a random address to be configured. Without a configured static random address, such a controller is not functional. So reject powering on the controller in this case until it gets configured with a random address. The controller setup stage is still run since it is the only way to determinate if a public address is available or not. So it is similar on how RFKILL gets handled during initial setup of the controller. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 0d5fe0843f5e..4a9b8dda754e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1196,13 +1196,29 @@ static int hci_dev_do_open(struct hci_dev *hdev) goto done; } - /* Check for rfkill but allow the HCI setup stage to proceed - * (which in itself doesn't cause any RF activity). - */ - if (test_bit(HCI_RFKILLED, &hdev->dev_flags) && - !test_bit(HCI_SETUP, &hdev->dev_flags)) { - ret = -ERFKILL; - goto done; + if (!test_bit(HCI_SETUP, &hdev->dev_flags)) { + /* Check for rfkill but allow the HCI setup stage to + * proceed (which in itself doesn't cause any RF activity). + */ + if (test_bit(HCI_RFKILLED, &hdev->dev_flags)) { + ret = -ERFKILL; + goto done; + } + + /* Check for valid public address or a configured static + * random adddress, but let the HCI setup proceed to + * be able to determine if there is a public address + * or not. + * + * This check is only valid for BR/EDR controllers + * since AMP controllers do not have an address. + */ + if (hdev->dev_type == HCI_BREDR && + !bacmp(&hdev->bdaddr, BDADDR_ANY) && + !bacmp(&hdev->static_addr, BDADDR_ANY)) { + ret = -EADDRNOTAVAIL; + goto done; + } } if (test_bit(HCI_UP, &hdev->flags)) { @@ -1288,6 +1304,10 @@ int hci_dev_open(__u16 dev) if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) cancel_delayed_work(&hdev->power_off); + /* After this call it is guaranteed that the setup procedure + * has finished. This means that error conditions like RFKILL + * or no valid public or static random address apply. + */ flush_workqueue(hdev->req_workqueue); err = hci_dev_do_open(hdev); @@ -1703,7 +1723,14 @@ static void hci_power_on(struct work_struct *work) return; } - if (test_bit(HCI_RFKILLED, &hdev->dev_flags)) { + /* During the HCI setup phase, a few error conditions are + * ignored and they need to be checked now. If they are still + * valid, it is important to turn the device back off. + */ + if (test_bit(HCI_RFKILLED, &hdev->dev_flags) || + (hdev->dev_type == HCI_BREDR && + !bacmp(&hdev->bdaddr, BDADDR_ANY) && + !bacmp(&hdev->static_addr, BDADDR_ANY))) { clear_bit(HCI_AUTO_OFF, &hdev->dev_flags); hci_dev_do_close(hdev); } else if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { -- cgit v1.2.3-73-gaa49b From 01cd340427ab01a744a539981bcc4ef00e5ad133 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 01:16:22 -0700 Subject: Bluetooth: Use explicit check for BR/EDR device type The BR/EDR and LE setup procedures apply only to BR/EDR device types and so check for that explicitly. Checking that it is not an AMP controller is dangerous in case there will be ever a third device type. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 4a9b8dda754e..bf3c5b0c22b9 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2357,7 +2357,7 @@ int hci_register_dev(struct hci_dev *hdev) set_bit(HCI_SETUP, &hdev->dev_flags); - if (hdev->dev_type != HCI_AMP) { + if (hdev->dev_type == HCI_BREDR) { set_bit(HCI_AUTO_OFF, &hdev->dev_flags); /* Assume BR/EDR support until proven otherwise (such as * through reading supported features during init. -- cgit v1.2.3-73-gaa49b From e8803534a03ddfcb37bd3d6cb981c5131a5bd993 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 02:08:35 -0700 Subject: Bluetooth: Simplify device type check for AMP discover response When counting the number for AMP controllers, a positive check is used. To be consistent, use the same check when actually adding the data for the AMP contollers. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/a2mp.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index ad8bda3a6fd1..9410e272d8b6 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -78,24 +78,20 @@ u8 __next_ident(struct amp_mgr *mgr) /* hci_dev_list shall be locked */ static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl) { - int i = 0; struct hci_dev *hdev; + int i = 1; cl[0].id = AMP_ID_BREDR; cl[0].type = AMP_TYPE_BREDR; cl[0].status = AMP_STATUS_BLUETOOTH_ONLY; list_for_each_entry(hdev, &hci_dev_list, list) { - /* Iterate through AMP controllers */ - if (hdev->dev_type != HCI_AMP) - continue; - - /* Starting from second entry */ - ++i; - - cl[i].id = hdev->id; - cl[i].type = hdev->amp_type; - cl[i].status = hdev->amp_status; + if (hdev->dev_type == HCI_AMP) { + cl[i].id = hdev->id; + cl[i].type = hdev->amp_type; + cl[i].status = hdev->amp_status; + i++; + } } } -- cgit v1.2.3-73-gaa49b From c25dfc610b983f74f05b3c12d9ad4ff4af6cd858 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 02:08:36 -0700 Subject: Bluetooth: Use random address if public address is not available For single mode LE-only controllers, it is possible that they come without a public address. If a public address is not available, then use the random address for connection establishment and scanning. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_conn.c | 4 ++++ net/bluetooth/mgmt.c | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 8b0d08fb6158..2a220a8c9869 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -59,6 +59,10 @@ static void hci_le_create_connection(struct hci_conn *conn) cp.scan_window = __constant_cpu_to_le16(0x0030); bacpy(&cp.peer_addr, &conn->dst); cp.peer_addr_type = conn->dst_type; + if (bacmp(&hdev->bdaddr, BDADDR_ANY)) + cp.own_address_type = ADDR_LE_DEV_PUBLIC; + else + cp.own_address_type = ADDR_LE_DEV_RANDOM; cp.conn_interval_min = __constant_cpu_to_le16(0x0028); cp.conn_interval_max = __constant_cpu_to_le16(0x0038); cp.supervision_timeout = __constant_cpu_to_le16(0x002a); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 6e808d1d78f3..719672203d02 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -2911,6 +2911,10 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, param_cp.type = LE_SCAN_ACTIVE; param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT); param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN); + if (bacmp(&hdev->bdaddr, BDADDR_ANY)) + param_cp.own_address_type = ADDR_LE_DEV_PUBLIC; + else + param_cp.own_address_type = ADDR_LE_DEV_RANDOM; hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), ¶m_cp); -- cgit v1.2.3-73-gaa49b From 03d87419defc809261c4953e5b44f9e0c8f9029a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 02:40:43 -0700 Subject: Bluetooth: Make it clear that disabling LE disables advertising This is not a functional change, just change the code to make it easy to understand that advertising gets disabled before LE support will be turned off. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 719672203d02..e09ceff5979b 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1505,8 +1505,11 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) hci_req_init(&req, hdev); - if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) && !val) - hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(val), &val); + if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) && !val) { + u8 adv = 0x00; + + hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(adv), &adv); + } hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), &hci_cp); -- cgit v1.2.3-73-gaa49b From bba3aa550f614b8abf6614f6696a095030ce2ff6 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 02:55:21 -0700 Subject: Bluetooth: Use helper functions for enabling/disabling advertising The tasks of enabling and disabling advertising are required in many cases. So refactor the actual HCI operations into two common helpers to make the code simpler. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 33 ++++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index e09ceff5979b..83866848a215 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1411,6 +1411,20 @@ unlock: return err; } +static void enable_advertising(struct hci_request *req) +{ + u8 adv = 0x01; + + hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(adv), &adv); +} + +static void disable_advertising(struct hci_request *req) +{ + u8 adv = 0x00; + + hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(adv), &adv); +} + static void le_enable_complete(struct hci_dev *hdev, u8 status) { struct cmd_lookup match = { NULL, hdev }; @@ -1505,11 +1519,8 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) hci_req_init(&req, hdev); - if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) && !val) { - u8 adv = 0x00; - - hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(adv), &adv); - } + if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) && !val) + disable_advertising(&req); hci_req_add(&req, HCI_OP_WRITE_LE_HOST_SUPPORTED, sizeof(hci_cp), &hci_cp); @@ -3283,7 +3294,10 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, u1 hci_req_init(&req, hdev); - hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(val), &val); + if (val) + enable_advertising(&req); + else + disable_advertising(&req); err = hci_req_run(&req, set_advertising_complete); if (err < 0) @@ -3861,12 +3875,9 @@ static int powered_update_hci(struct hci_dev *hdev) if (bacmp(&hdev->static_addr, BDADDR_ANY)) hci_req_add(&req, HCI_OP_LE_SET_RANDOM_ADDR, 6, &hdev->static_addr); - } - - if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { - u8 adv = 0x01; - hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(adv), &adv); + if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) + enable_advertising(&req); } link_sec = test_bit(HCI_LINK_SECURITY, &hdev->dev_flags); -- cgit v1.2.3-73-gaa49b From b4faf30096c3deb618392a88feaa7674cd55c257 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 03:17:56 -0700 Subject: Bluetooth: Set LE advertising parameters before enabling it The LE advertising parameters can only be modified when advertising is disabled. So before enabling it, make sure the controller has all the right parameters. Right now all default values are used and thus this does no change any existing behavior. One minor exception is that in case of single mode LE-only controllers without a public address, now the random address is used for advertising. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 83866848a215..b78a0eefe03e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1413,16 +1413,30 @@ unlock: static void enable_advertising(struct hci_request *req) { - u8 adv = 0x01; + struct hci_dev *hdev = req->hdev; + struct hci_cp_le_set_adv_param cp; + u8 enable = 0x01; + + memset(&cp, 0, sizeof(cp)); + cp.min_interval = __constant_cpu_to_le16(0x0800); + cp.max_interval = __constant_cpu_to_le16(0x0800); + cp.type = LE_ADV_IND; + if (bacmp(&hdev->bdaddr, BDADDR_ANY)) + cp.own_address_type = ADDR_LE_DEV_PUBLIC; + else + cp.own_address_type = ADDR_LE_DEV_RANDOM; + cp.channel_map = 0x07; + + hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp); - hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(adv), &adv); + hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); } static void disable_advertising(struct hci_request *req) { - u8 adv = 0x00; + u8 enable = 0x00; - hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(adv), &adv); + hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); } static void le_enable_complete(struct hci_dev *hdev, u8 status) -- cgit v1.2.3-73-gaa49b From 5976e60811723220678ebdb2ea06fbb52fe900bd Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 04:08:14 -0700 Subject: Bluetooth: Use helper function for re-enabling advertising When the all LE connections have been disconneted, then it is up to the host to re-enable advertising at that point. To ensure that the correct advertising parameters are used, force the usage of the common helper to enable advertising. The change just moves the manual enabling of advertising from the event handler into the management core so that the helper can be actually shared. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 1 + net/bluetooth/hci_event.c | 36 +----------------------------------- net/bluetooth/mgmt.c | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 35 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 82c397451261..869f6ad602d1 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1151,6 +1151,7 @@ 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); bool mgmt_valid_hdev(struct hci_dev *hdev); int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent); +void mgmt_reenable_advertising(struct hci_dev *hdev); /* HCI info for socket */ #define hci_pi(sk) ((struct hci_pinfo *) sk) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 6eaef6ed9522..224210ce82fc 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1796,40 +1796,6 @@ static u8 hci_to_mgmt_reason(u8 err) } } -static void adv_enable_complete(struct hci_dev *hdev, u8 status) -{ - BT_DBG("%s status %u", hdev->name, status); - - /* Clear the advertising mgmt setting if we failed to re-enable it */ - if (status) { - clear_bit(HCI_ADVERTISING, &hdev->dev_flags); - mgmt_new_settings(hdev); - } -} - -static void reenable_advertising(struct hci_dev *hdev) -{ - struct hci_request req; - u8 enable = 0x01; - - if (hdev->conn_hash.le_num) - return; - - if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags)) - return; - - hci_req_init(&req, hdev); - hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); - - /* If this fails we have no option but to let user space know - * that we've disabled advertising. - */ - if (hci_req_run(&req, adv_enable_complete) < 0) { - clear_bit(HCI_ADVERTISING, &hdev->dev_flags); - mgmt_new_settings(hdev); - } -} - static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_disconn_complete *ev = (void *) skb->data; @@ -1878,7 +1844,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) * is timed out due to Directed Advertising." */ if (type == LE_LINK) - reenable_advertising(hdev); + mgmt_reenable_advertising(hdev); } unlock: diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index b78a0eefe03e..381faf600195 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4660,3 +4660,36 @@ int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev), cmd ? cmd->sk : NULL); } + +static void adv_enable_complete(struct hci_dev *hdev, u8 status) +{ + BT_DBG("%s status %u", hdev->name, status); + + /* Clear the advertising mgmt setting if we failed to re-enable it */ + if (status) { + clear_bit(HCI_ADVERTISING, &hdev->dev_flags); + mgmt_new_settings(hdev); + } +} + +void mgmt_reenable_advertising(struct hci_dev *hdev) +{ + struct hci_request req; + + if (hdev->conn_hash.le_num) + return; + + if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags)) + return; + + hci_req_init(&req, hdev); + enable_advertising(&req); + + /* If this fails we have no option but to let user space know + * that we've disabled advertising. + */ + if (hci_req_run(&req, adv_enable_complete) < 0) { + clear_bit(HCI_ADVERTISING, &hdev->dev_flags); + mgmt_new_settings(hdev); + } +} -- cgit v1.2.3-73-gaa49b From a6d811ed28f7c49e869b4076a00969c4028cda0d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 04:11:12 -0700 Subject: Bluetooth: Remove no longer needed mgmt_new_settings() function The mgmt_new_settings() function was only needed to handle the error case when re-enabling advertising failed. Since that is now handled internally inside the management core, this function is not needed anymore. So just remove it. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 1 - net/bluetooth/mgmt.c | 9 ++------- 2 files changed, 2 insertions(+), 8 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 869f6ad602d1..30e0fbb92b0a 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1094,7 +1094,6 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event); int mgmt_control(struct sock *sk, struct msghdr *msg, size_t len); int mgmt_index_added(struct hci_dev *hdev); int mgmt_index_removed(struct hci_dev *hdev); -int mgmt_new_settings(struct hci_dev *hdev); int mgmt_set_powered_failed(struct hci_dev *hdev, int err); int mgmt_powered(struct hci_dev *hdev, u8 powered); int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 381faf600195..dd48e2a88c50 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -890,11 +890,6 @@ static int new_settings(struct hci_dev *hdev, struct sock *skip) return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip); } -int mgmt_new_settings(struct hci_dev *hdev) -{ - return new_settings(hdev, NULL); -} - struct cmd_lookup { struct sock *sk; struct hci_dev *hdev; @@ -4668,7 +4663,7 @@ static void adv_enable_complete(struct hci_dev *hdev, u8 status) /* Clear the advertising mgmt setting if we failed to re-enable it */ if (status) { clear_bit(HCI_ADVERTISING, &hdev->dev_flags); - mgmt_new_settings(hdev); + new_settings(hdev, NULL); } } @@ -4690,6 +4685,6 @@ void mgmt_reenable_advertising(struct hci_dev *hdev) */ if (hci_req_run(&req, adv_enable_complete) < 0) { clear_bit(HCI_ADVERTISING, &hdev->dev_flags); - mgmt_new_settings(hdev); + new_settings(hdev, NULL); } } -- cgit v1.2.3-73-gaa49b From 1514b8928e5d8273920b26276cd9617b6dbc7760 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 08:25:01 -0700 Subject: Bluetooth: Remove mgmt_valid_hdev() helper function The helper function mgmt_valid_hdev() is more obfuscating the code then it makes it easier to read. So intead of this helper, use the direct check for BR/EDR device type. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 1 - net/bluetooth/hci_core.c | 4 ++-- net/bluetooth/mgmt.c | 24 ++++++++---------------- 3 files changed, 10 insertions(+), 19 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 30e0fbb92b0a..d80d4311ccb0 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1148,7 +1148,6 @@ int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, 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); -bool mgmt_valid_hdev(struct hci_dev *hdev); int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent); void mgmt_reenable_advertising(struct hci_dev *hdev); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index bf3c5b0c22b9..d9626aad7ade 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1254,7 +1254,7 @@ static int hci_dev_do_open(struct hci_dev *hdev) hci_notify(hdev, HCI_DEV_UP); if (!test_bit(HCI_SETUP, &hdev->dev_flags) && !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) && - mgmt_valid_hdev(hdev)) { + hdev->dev_type == HCI_BREDR) { hci_dev_lock(hdev); mgmt_powered(hdev, 1); hci_dev_unlock(hdev); @@ -1394,7 +1394,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) hdev->dev_flags &= ~HCI_PERSISTENT_MASK; if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) && - mgmt_valid_hdev(hdev)) { + hdev->dev_type == HCI_BREDR) { hci_dev_lock(hdev); mgmt_powered(hdev, 0); hci_dev_unlock(hdev); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index dd48e2a88c50..9702079833fc 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -182,11 +182,6 @@ static u8 mgmt_status_table[] = { MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */ }; -bool mgmt_valid_hdev(struct hci_dev *hdev) -{ - return hdev->dev_type == HCI_BREDR; -} - static u8 mgmt_status(u8 hci_status) { if (hci_status < ARRAY_SIZE(mgmt_status_table)) @@ -322,10 +317,8 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, count = 0; list_for_each_entry(d, &hci_dev_list, list) { - if (!mgmt_valid_hdev(d)) - continue; - - count++; + if (d->dev_type == HCI_BREDR) + count++; } rp_len = sizeof(*rp) + (2 * count); @@ -343,11 +336,10 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, if (test_bit(HCI_USER_CHANNEL, &d->dev_flags)) continue; - if (!mgmt_valid_hdev(d)) - continue; - - rp->index[count++] = cpu_to_le16(d->id); - BT_DBG("Added hci%u", d->id); + if (d->dev_type == HCI_BREDR) { + rp->index[count++] = cpu_to_le16(d->id); + BT_DBG("Added hci%u", d->id); + } } rp->num_controllers = cpu_to_le16(count); @@ -3790,7 +3782,7 @@ done: int mgmt_index_added(struct hci_dev *hdev) { - if (!mgmt_valid_hdev(hdev)) + if (hdev->dev_type != HCI_BREDR) return -ENOTSUPP; return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); @@ -3800,7 +3792,7 @@ int mgmt_index_removed(struct hci_dev *hdev) { u8 status = MGMT_STATUS_INVALID_INDEX; - if (!mgmt_valid_hdev(hdev)) + if (hdev->dev_type != HCI_BREDR) return -ENOTSUPP; mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); -- cgit v1.2.3-73-gaa49b From 5559435654776359679613f69f1c0a2895603a69 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 16:11:57 -0700 Subject: Bluetooth: Send new settings only when pairable changes In case the current value of pairable is already configured, do not send a new settings event indicating that something has changed while in reality everything is the same. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 9702079833fc..3f628fd71b4e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1188,6 +1188,7 @@ static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) { struct mgmt_mode *cp = data; + bool changed; int err; BT_DBG("request for %s", hdev->name); @@ -1199,17 +1200,18 @@ static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data, hci_dev_lock(hdev); if (cp->val) - set_bit(HCI_PAIRABLE, &hdev->dev_flags); + changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags); else - clear_bit(HCI_PAIRABLE, &hdev->dev_flags); + changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags); err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev); if (err < 0) - goto failed; + goto unlock; - err = new_settings(hdev, sk); + if (changed) + err = new_settings(hdev, sk); -failed: +unlock: hci_dev_unlock(hdev); return err; } -- cgit v1.2.3-73-gaa49b From bf6b56db0acbe844c96fe36ab65eb7a53c6d8654 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 23:55:45 -0700 Subject: Bluetooth: Make mgmt_index_added() and mgmt_index_removed() return void The return value from mgmt_index_added() and mgmt_index_removed() functions is never used. So do not pretend that returning an error would actually be handled and just make both functions return void. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 4 ++-- net/bluetooth/mgmt.c | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index d80d4311ccb0..1e6f584d5149 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1092,8 +1092,8 @@ 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_index_added(struct hci_dev *hdev); -int mgmt_index_removed(struct hci_dev *hdev); +void mgmt_index_added(struct hci_dev *hdev); +void 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); int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 3f628fd71b4e..811c41192ec7 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3782,24 +3782,24 @@ done: return err; } -int mgmt_index_added(struct hci_dev *hdev) +void mgmt_index_added(struct hci_dev *hdev) { if (hdev->dev_type != HCI_BREDR) - return -ENOTSUPP; + return; - return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); + mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); } -int mgmt_index_removed(struct hci_dev *hdev) +void mgmt_index_removed(struct hci_dev *hdev) { u8 status = MGMT_STATUS_INVALID_INDEX; if (hdev->dev_type != HCI_BREDR) - return -ENOTSUPP; + return; mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); - return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); + mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); } static void set_bredr_scan(struct hci_request *req) -- cgit v1.2.3-73-gaa49b From 3eec705e42d19b3d3e367fcb88693c24175bdbc6 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 23:55:46 -0700 Subject: Bluetooth: Make mgmt_set_powered_failed() return void The return value of mgmt_set_powered_failed() function is never used and so make the function just return void. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/mgmt.c | 8 +++----- 2 files changed, 4 insertions(+), 6 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 1e6f584d5149..62e2fc1bc7cc 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1094,7 +1094,7 @@ void hci_sock_dev_event(struct hci_dev *hdev, int event); 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); -int mgmt_set_powered_failed(struct hci_dev *hdev, int err); +void mgmt_set_powered_failed(struct hci_dev *hdev, int err); int mgmt_powered(struct hci_dev *hdev, u8 powered); int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable); int mgmt_connectable(struct hci_dev *hdev, u8 connectable); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 811c41192ec7..5da7464e57a5 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3934,25 +3934,23 @@ new_settings: return err; } -int mgmt_set_powered_failed(struct hci_dev *hdev, int err) +void mgmt_set_powered_failed(struct hci_dev *hdev, int err) { struct pending_cmd *cmd; u8 status; cmd = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev); if (!cmd) - return -ENOENT; + return; if (err == -ERFKILL) status = MGMT_STATUS_RFKILLED; else status = MGMT_STATUS_FAILED; - err = cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status); + cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status); mgmt_pending_remove(cmd); - - return err; } int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) -- cgit v1.2.3-73-gaa49b From 7892924c7d5d74be8ad52316000a78fe96379044 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 23:55:47 -0700 Subject: Bluetooth: Make mgmt_disconnect_failed() return void The return value of mgmt_disconnect_failed() function is not used so change it to just return void. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 4 ++-- net/bluetooth/mgmt.c | 13 +++++-------- 2 files changed, 7 insertions(+), 10 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 62e2fc1bc7cc..429969fdb9f3 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1106,8 +1106,8 @@ int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, 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); +void 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); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 5da7464e57a5..a35f28e9172e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4143,29 +4143,26 @@ int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, return err; } -int mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, - u8 link_type, u8 addr_type, u8 status) +void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, + u8 link_type, u8 addr_type, u8 status) { struct mgmt_rp_disconnect rp; struct pending_cmd *cmd; - int err; mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, hdev); cmd = mgmt_pending_find(MGMT_OP_DISCONNECT, hdev); if (!cmd) - return -ENOENT; + return; bacpy(&rp.addr.bdaddr, bdaddr); rp.addr.type = link_to_bdaddr(link_type, addr_type); - err = cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, - mgmt_status(status), &rp, sizeof(rp)); + cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, + mgmt_status(status), &rp, sizeof(rp)); mgmt_pending_remove(cmd); - - return err; } int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, -- cgit v1.2.3-73-gaa49b From 445608d078bf7f7fe975792a940ffac83f495fa9 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 23:55:48 -0700 Subject: Bluetooth: Make mgmt_connect_failed() return void The return value of mgmt_connect_failed() function is not used so change it to just return void. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 4 ++-- net/bluetooth/mgmt.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 429969fdb9f3..d982458a96e3 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1108,8 +1108,8 @@ int 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); -int mgmt_connect_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); 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); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a35f28e9172e..bd32c430cdfe 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4165,8 +4165,8 @@ void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, mgmt_pending_remove(cmd); } -int mgmt_connect_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) { struct mgmt_ev_connect_failed ev; @@ -4174,7 +4174,7 @@ int mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, ev.addr.type = link_to_bdaddr(link_type, addr_type); ev.status = mgmt_status(status); - return mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL); + mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL); } int mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure) -- cgit v1.2.3-73-gaa49b From ecd90ae7f600270d68b471f87c66d5b41ce5a974 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 23:55:49 -0700 Subject: Bluetooth: Make mgmt_device_connected() return void The return value of mgmt_device_connected() function is not used and so just change it to return void. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 6 +++--- net/bluetooth/mgmt.c | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index d982458a96e3..48569442ec17 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1101,9 +1101,9 @@ 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); +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); int 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, diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index bd32c430cdfe..9029e67b3341 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4056,9 +4056,9 @@ int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent) NULL); } -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) +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) { char buf[512]; struct mgmt_ev_device_connected *ev = (void *) buf; @@ -4079,8 +4079,8 @@ int mgmt_device_connected(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, ev->eir_len = cpu_to_le16(eir_len); - return mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf, - sizeof(*ev) + eir_len, NULL); + mgmt_event(MGMT_EV_DEVICE_CONNECTED, hdev, buf, + sizeof(*ev) + eir_len, NULL); } static void disconnect_rsp(struct pending_cmd *cmd, void *data) -- cgit v1.2.3-73-gaa49b From 9b80ec5e8e66ada404ad65ce61a1de70fee0fbbd Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 23:55:50 -0700 Subject: Bluetooth: Make mgmt_device_disconnected() return void The return value of mgmt_device_disconnected() function is not used and so just change it to return void. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 4 ++-- net/bluetooth/mgmt.c | 10 +++------- 2 files changed, 5 insertions(+), 9 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 48569442ec17..2b0bc31ec785 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1104,8 +1104,8 @@ int mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, 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); -int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, - u8 link_type, u8 addr_type, u8 reason); +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, diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 9029e67b3341..b9cd5829672e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4118,12 +4118,11 @@ static void unpair_device_rsp(struct pending_cmd *cmd, void *data) mgmt_pending_remove(cmd); } -int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, - u8 link_type, u8 addr_type, u8 reason) +void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, + u8 link_type, u8 addr_type, u8 reason) { struct mgmt_ev_device_disconnected ev; struct sock *sk = NULL; - int err; mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk); @@ -4131,16 +4130,13 @@ int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, ev.addr.type = link_to_bdaddr(link_type, addr_type); ev.reason = reason; - err = mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), - sk); + mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk); if (sk) sock_put(sk); mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp, hdev); - - return err; } void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, -- cgit v1.2.3-73-gaa49b From 901801b9a420e58969e039731dd007ae104842d3 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 23:55:51 -0700 Subject: Bluetooth: Make mgmt_device_found() return void The return value of mgmt_device_found() function is not used and so just change it to return void. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 6 +++--- net/bluetooth/mgmt.c | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 2b0bc31ec785..5b738a2d1786 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1140,9 +1140,9 @@ int mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class, 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_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_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); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index b9cd5829672e..abf500b3b265 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4524,20 +4524,20 @@ int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, return err; } -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) +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) { char buf[512]; struct mgmt_ev_device_found *ev = (void *) buf; size_t ev_size; if (!hci_discovery_active(hdev)) - return -EPERM; + return; /* Leave 5 bytes for a potential CoD field */ if (sizeof(*ev) + eir_len + 5 > sizeof(buf)) - return -EINVAL; + return; memset(buf, 0, sizeof(buf)); @@ -4559,7 +4559,7 @@ int mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, ev->eir_len = cpu_to_le16(eir_len); ev_size = sizeof(*ev) + eir_len; - return mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL); + mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL); } int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, -- cgit v1.2.3-73-gaa49b From 9cf12aee8bf5eb219c79089fb4556ad1d2066585 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 23:55:52 -0700 Subject: Bluetooth: Make mgmt_remote_name() return void The return value of mgmt_remote_name() function is not used and so just change it to return void. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 4 ++-- net/bluetooth/mgmt.c | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 5b738a2d1786..960c64b92415 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1143,8 +1143,8 @@ int mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, 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); -int 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_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); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index abf500b3b265..4a4545e1e44d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4562,8 +4562,8 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, ev_size, NULL); } -int 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_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, + u8 addr_type, s8 rssi, u8 *name, u8 name_len) { struct mgmt_ev_device_found *ev; char buf[sizeof(*ev) + HCI_MAX_NAME_LENGTH + 2]; @@ -4582,8 +4582,7 @@ int mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, ev->eir_len = cpu_to_le16(eir_len); - return mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, - sizeof(*ev) + eir_len, NULL); + mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL); } int mgmt_discovering(struct hci_dev *hdev, u8 discovering) -- cgit v1.2.3-73-gaa49b From 2f1e063bc035dbbdb9174cc5f55f073a28780aa8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 6 Oct 2013 23:55:53 -0700 Subject: Bluetooth: Make mgmt_discovering() return void The return value of mgmt_discovering() function is not used and so just change it to return void. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/mgmt.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 960c64b92415..c06552769644 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1145,7 +1145,7 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, 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); -int mgmt_discovering(struct hci_dev *hdev, u8 discovering); +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); int mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 4a4545e1e44d..4070bb05d304 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4585,7 +4585,7 @@ void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, mgmt_event(MGMT_EV_DEVICE_FOUND, hdev, ev, sizeof(*ev) + eir_len, NULL); } -int mgmt_discovering(struct hci_dev *hdev, u8 discovering) +void mgmt_discovering(struct hci_dev *hdev, u8 discovering) { struct mgmt_ev_discovering ev; struct pending_cmd *cmd; @@ -4609,7 +4609,7 @@ int mgmt_discovering(struct hci_dev *hdev, u8 discovering) ev.type = hdev->discovery.type; ev.discovering = discovering; - return mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL); + mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL); } int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) -- cgit v1.2.3-73-gaa49b From 004b02589c5394a75660a00829086460cc3e4366 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 7 Oct 2013 00:58:32 -0700 Subject: Bluetooth: Power off AMP controllers after setup phase Even AMP controllers should be powered off after the setup phase. It is not a good idea to keep AMP controllers powered on all the time if they are not in use. Power on of the AMP controller can either be done manually via command line commands or directly via A2MP. Especially since there is an indication in A2MP for powered down controllers that can be activated. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index d9626aad7ade..2ee5a8ee75c5 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2356,9 +2356,9 @@ int hci_register_dev(struct hci_dev *hdev) set_bit(HCI_RFKILLED, &hdev->dev_flags); set_bit(HCI_SETUP, &hdev->dev_flags); + set_bit(HCI_AUTO_OFF, &hdev->dev_flags); if (hdev->dev_type == HCI_BREDR) { - set_bit(HCI_AUTO_OFF, &hdev->dev_flags); /* Assume BR/EDR support until proven otherwise (such as * through reading supported features during init. */ -- cgit v1.2.3-73-gaa49b From 93c311a044442db62717ae509e09047f34dc3583 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 7 Oct 2013 00:58:33 -0700 Subject: Bluetooth: Make mgmt power down notification for BR/EDR explicit The management interface only operates on BR/EDR controllers. The check for the power down notification is a bit intermixed with the check if controller auto power off is active. Since there are more than just BR/EDR controllers supported, make this check explicit since the auto power off check also applies to AMP controllers and it has to happen in this exact order. Otherwise the bit will not be cleared. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 2ee5a8ee75c5..3572611c0297 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1393,11 +1393,12 @@ static int hci_dev_do_close(struct hci_dev *hdev) hdev->flags = 0; hdev->dev_flags &= ~HCI_PERSISTENT_MASK; - if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) && - hdev->dev_type == HCI_BREDR) { - hci_dev_lock(hdev); - mgmt_powered(hdev, 0); - hci_dev_unlock(hdev); + if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { + if (hdev->dev_type == HCI_BREDR) { + hci_dev_lock(hdev); + mgmt_powered(hdev, 0); + hci_dev_unlock(hdev); + } } /* Controller radio is available but is currently powered down */ -- cgit v1.2.3-73-gaa49b From cd0a85c22cd39f040ef4cff07a6c249bf1023137 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 7 Oct 2013 00:58:34 -0700 Subject: Bluetooth: List powered down AMP controllers correctly Within the AMP discover response, list powered down AMP controllers as powered down. No point in trying to make them look any different. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/a2mp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 9410e272d8b6..b38d07477c20 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -89,7 +89,10 @@ static void __a2mp_add_cl(struct amp_mgr *mgr, struct a2mp_cl *cl) if (hdev->dev_type == HCI_AMP) { cl[i].id = hdev->id; cl[i].type = hdev->amp_type; - cl[i].status = hdev->amp_status; + if (test_bit(HCI_UP, &hdev->flags)) + cl[i].status = hdev->amp_status; + else + cl[i].status = AMP_STATUS_POWERED_DOWN; i++; } } -- cgit v1.2.3-73-gaa49b From f6996cfe2f1db60a74765449f9b53c7591bcdc87 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 7 Oct 2013 02:31:39 -0700 Subject: Bluetooth: Read supported features and commands on AMP controllers The commands for reading supported features and commands are both supported by AMP controllers. Issue them during controller init phase so their values are known. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 3572611c0297..99f83abbcaa6 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -307,6 +307,12 @@ static void amp_init(struct hci_request *req) /* Read Local Version */ hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL); + /* Read Local Supported Commands */ + hci_req_add(req, HCI_OP_READ_LOCAL_COMMANDS, 0, NULL); + + /* Read Local Supported Features */ + hci_req_add(req, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); + /* Read Local AMP Info */ hci_req_add(req, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); -- cgit v1.2.3-73-gaa49b From 7528ca1c5a3821951695e0e55daf192097a9925a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 7 Oct 2013 03:55:52 -0700 Subject: Bluetooth: Read location data on AMP controller init When initializing an AMP controller, read its current known location data so that it can be analyzed later on. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci.h | 2 ++ net/bluetooth/hci_core.c | 3 +++ 2 files changed, 5 insertions(+) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 3616ea794eb1..c8a91cb20173 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -851,6 +851,8 @@ struct hci_rp_read_inq_rsp_tx_power { #define HCI_OP_SET_EVENT_MASK_PAGE_2 0x0c63 +#define HCI_OP_READ_LOCATION_DATA 0x0c64 + #define HCI_OP_READ_FLOW_CONTROL_MODE 0x0c66 struct hci_rp_read_flow_control_mode { __u8 status; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 99f83abbcaa6..967739c0285b 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -318,6 +318,9 @@ static void amp_init(struct hci_request *req) /* Read Data Blk size */ hci_req_add(req, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL); + + /* Read Location Data */ + hci_req_add(req, HCI_OP_READ_LOCATION_DATA, 0, NULL); } static void hci_init1_req(struct hci_request *req, unsigned long opt) -- cgit v1.2.3-73-gaa49b From f38ba94147dd568b635be83b2fb571303ce3404c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 7 Oct 2013 03:55:53 -0700 Subject: Bluetooth: Read flow control mode on AMP controller init When initializing an AMP controller, read its current flow control mode so that the correct value is used. The AMP controller defaults to block based flow control and this extra command is just to double check. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 967739c0285b..0c636ba1ba16 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -319,6 +319,9 @@ static void amp_init(struct hci_request *req) /* Read Data Blk size */ hci_req_add(req, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL); + /* Read Flow Control Mode */ + hci_req_add(req, HCI_OP_READ_FLOW_CONTROL_MODE, 0, NULL); + /* Read Location Data */ hci_req_add(req, HCI_OP_READ_LOCATION_DATA, 0, NULL); } -- cgit v1.2.3-73-gaa49b From c1f23a2bfc89a886776dc141130ca995ea16a826 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Mon, 7 Oct 2013 18:19:16 +0200 Subject: Bluetooth: Fix variable shadow warnings Sparse points out three places where variables are shadowed, rename two of the variables and remove the duplicate third. Signed-off-by: Johannes Berg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_event.c | 12 +++++++----- net/bluetooth/l2cap_sock.c | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 224210ce82fc..221a185cc951 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1296,9 +1296,11 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) goto unlock; if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { - struct hci_cp_auth_requested cp; - cp.handle = __cpu_to_le16(conn->handle); - hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); + struct hci_cp_auth_requested auth_cp; + + auth_cp.handle = __cpu_to_le16(conn->handle); + hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, + sizeof(auth_cp), &auth_cp); } unlock: @@ -3660,8 +3662,8 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) skb_pull(skb, HCI_EVENT_HDR_SIZE); if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) { - struct hci_command_hdr *hdr = (void *) hdev->sent_cmd->data; - u16 opcode = __le16_to_cpu(hdr->opcode); + struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data; + u16 opcode = __le16_to_cpu(cmd_hdr->opcode); hci_req_cmd_complete(hdev, opcode, 0); } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 9119898ef040..1daa4c579eb2 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -678,7 +678,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, } if (opt == BT_FLUSHABLE_OFF) { - struct l2cap_conn *conn = chan->conn; + conn = chan->conn; /* proceed further only when we have l2cap_conn and No Flush support in the LM */ if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) { -- cgit v1.2.3-73-gaa49b From f74ca9b8094b1b067a0b4069732065f2e1595c73 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Tue, 8 Oct 2013 15:52:18 +0200 Subject: Bluetooth: Fix changing advertising setting while LE is connected We only (re)enable advertising when LE is disconnected. Trying to enable advertising using mgmt_set_advertising while connected should simply change the flag but not do anything else (until the connection gets dropped). This patch fixes this by making an LE connection lookup to determine whether there are any connected devices or not. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 4070bb05d304..a9d7506be1a3 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3264,7 +3264,13 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, u1 val = !!cp->val; enabled = test_bit(HCI_ADVERTISING, &hdev->dev_flags); - if (!hdev_is_powered(hdev) || val == enabled) { + /* The following conditions are ones which mean that we should + * not do any HCI communication but directly send a mgmt + * response to user space (after toggling the flag if + * necessary). + */ + if (!hdev_is_powered(hdev) || val == enabled || + hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECTED)) { bool changed = false; if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { -- cgit v1.2.3-73-gaa49b From 1d399ae5c74619c841fa13834c4f79506aaf6957 Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 8 Oct 2013 08:21:17 -0300 Subject: Bluetooth: Use HCI request for LE connection This patch introduces a new helper, which uses the HCI request framework, for creating LE connectons. All the handling is now done by this function so we can remove the hci_cs_le_create_conn() event handler. This patch also removes the old hci_le_create_connection() since it is not used anymore. Signed-off-by: Andre Guedes Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 91 ++++++++++++++++++++++++++++++++++------------- net/bluetooth/hci_event.c | 31 ---------------- 2 files changed, 67 insertions(+), 55 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 2a220a8c9869..1800b50558e4 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -49,29 +49,6 @@ static const struct sco_param sco_param_wideband[] = { { EDR_ESCO_MASK | ESCO_EV3, 0x0008 }, /* T1 */ }; -static void hci_le_create_connection(struct hci_conn *conn) -{ - struct hci_dev *hdev = conn->hdev; - struct hci_cp_le_create_conn cp; - - memset(&cp, 0, sizeof(cp)); - cp.scan_interval = __constant_cpu_to_le16(0x0060); - cp.scan_window = __constant_cpu_to_le16(0x0030); - bacpy(&cp.peer_addr, &conn->dst); - cp.peer_addr_type = conn->dst_type; - if (bacmp(&hdev->bdaddr, BDADDR_ANY)) - cp.own_address_type = ADDR_LE_DEV_PUBLIC; - else - cp.own_address_type = ADDR_LE_DEV_RANDOM; - cp.conn_interval_min = __constant_cpu_to_le16(0x0028); - cp.conn_interval_max = __constant_cpu_to_le16(0x0038); - cp.supervision_timeout = __constant_cpu_to_le16(0x002a); - cp.min_ce_len = __constant_cpu_to_le16(0x0000); - cp.max_ce_len = __constant_cpu_to_le16(0x0000); - - hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); -} - static void hci_le_create_connection_cancel(struct hci_conn *conn) { hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL); @@ -545,10 +522,74 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) } EXPORT_SYMBOL(hci_get_route); +static void create_le_conn_complete(struct hci_dev *hdev, u8 status) +{ + struct hci_conn *conn; + + if (status == 0) + return; + + BT_ERR("HCI request failed to create LE connection: status 0x%2.2x", + status); + + hci_dev_lock(hdev); + + conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); + if (!conn) + goto done; + + conn->state = BT_CLOSED; + + mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type, + status); + + hci_proto_connect_cfm(conn, status); + + hci_conn_del(conn); + +done: + hci_dev_unlock(hdev); +} + +static int hci_create_le_conn(struct hci_conn *conn) +{ + struct hci_dev *hdev = conn->hdev; + struct hci_cp_le_create_conn cp; + struct hci_request req; + int err; + + hci_req_init(&req, hdev); + + memset(&cp, 0, sizeof(cp)); + cp.scan_interval = __constant_cpu_to_le16(0x0060); + cp.scan_window = __constant_cpu_to_le16(0x0030); + bacpy(&cp.peer_addr, &conn->dst); + cp.peer_addr_type = conn->dst_type; + if (bacmp(&hdev->bdaddr, BDADDR_ANY)) + cp.own_address_type = ADDR_LE_DEV_PUBLIC; + else + cp.own_address_type = ADDR_LE_DEV_RANDOM; + cp.conn_interval_min = __constant_cpu_to_le16(0x0028); + cp.conn_interval_max = __constant_cpu_to_le16(0x0038); + cp.supervision_timeout = __constant_cpu_to_le16(0x002a); + cp.min_ce_len = __constant_cpu_to_le16(0x0000); + cp.max_ce_len = __constant_cpu_to_le16(0x0000); + hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); + + err = hci_req_run(&req, create_le_conn_complete); + if (err) { + hci_conn_del(conn); + return err; + } + + return 0; +} + static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, u8 dst_type, u8 sec_level, u8 auth_type) { struct hci_conn *conn; + int err; if (test_bit(HCI_ADVERTISING, &hdev->flags)) return ERR_PTR(-ENOTSUPP); @@ -569,7 +610,9 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, conn->link_mode |= HCI_LM_MASTER; conn->sec_level = BT_SECURITY_LOW; - hci_le_create_connection(conn); + err = hci_create_le_conn(conn); + if (err) + return ERR_PTR(err); } conn->pending_sec_level = sec_level; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 221a185cc951..ada3bf4d7e2a 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1472,33 +1472,6 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) hci_dev_unlock(hdev); } -static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) -{ - struct hci_conn *conn; - - BT_DBG("%s status 0x%2.2x", hdev->name, status); - - if (status) { - hci_dev_lock(hdev); - - conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); - if (!conn) { - hci_dev_unlock(hdev); - return; - } - - BT_DBG("%s bdaddr %pMR conn %p", hdev->name, &conn->dst, conn); - - conn->state = BT_CLOSED; - mgmt_connect_failed(hdev, &conn->dst, conn->type, - conn->dst_type, status); - hci_proto_connect_cfm(conn, status); - hci_conn_del(conn); - - hci_dev_unlock(hdev); - } -} - static void hci_cs_create_phylink(struct hci_dev *hdev, u8 status) { struct hci_cp_create_phy_link *cp; @@ -2364,10 +2337,6 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_cs_disconnect(hdev, ev->status); break; - case HCI_OP_LE_CREATE_CONN: - hci_cs_le_create_conn(hdev, ev->status); - break; - case HCI_OP_CREATE_PHY_LINK: hci_cs_create_phylink(hdev, ev->status); break; -- cgit v1.2.3-73-gaa49b From 620ad5219c0f0aa43731b2fd8fd9efac78c10deb Mon Sep 17 00:00:00 2001 From: Andre Guedes Date: Tue, 8 Oct 2013 08:21:18 -0300 Subject: Bluetooth: Refactor hci_connect_le This patch does some code refactoring in hci_connect_le() by moving the exception code into if statements and letting the main flow in first level of function scope. It also adds extra comments to improve the code readability. Signed-off-by: Andre Guedes Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 51 +++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 18 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 1800b50558e4..dedd1ea5dd4c 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -594,32 +594,47 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, if (test_bit(HCI_ADVERTISING, &hdev->flags)) return ERR_PTR(-ENOTSUPP); + /* Some devices send ATT messages as soon as the physical link is + * established. To be able to handle these ATT messages, the user- + * space first establishes the connection and then starts the pairing + * process. + * + * So if a hci_conn object already exists for the following connection + * attempt, we simply update pending_sec_level and auth_type fields + * and return the object found. + */ conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); - if (!conn) { - conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); - if (conn) - return ERR_PTR(-EBUSY); - - conn = hci_conn_add(hdev, LE_LINK, dst); - if (!conn) - return ERR_PTR(-ENOMEM); + if (conn) { + conn->pending_sec_level = sec_level; + conn->auth_type = auth_type; + goto done; + } - conn->dst_type = bdaddr_to_le(dst_type); - conn->state = BT_CONNECT; - conn->out = true; - conn->link_mode |= HCI_LM_MASTER; - conn->sec_level = BT_SECURITY_LOW; + /* Since the controller supports only one LE connection attempt at a + * time, we return -EBUSY if there is any connection attempt running. + */ + conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); + if (conn) + return ERR_PTR(-EBUSY); - err = hci_create_le_conn(conn); - if (err) - return ERR_PTR(err); - } + conn = hci_conn_add(hdev, LE_LINK, dst); + if (!conn) + return ERR_PTR(-ENOMEM); + conn->dst_type = bdaddr_to_le(dst_type); + conn->state = BT_CONNECT; + conn->out = true; + conn->link_mode |= HCI_LM_MASTER; + conn->sec_level = BT_SECURITY_LOW; conn->pending_sec_level = sec_level; conn->auth_type = auth_type; - hci_conn_hold(conn); + err = hci_create_le_conn(conn); + if (err) + return ERR_PTR(err); +done: + hci_conn_hold(conn); return conn; } -- cgit v1.2.3-73-gaa49b From 72ef0c1a9e62c3dd3b4841c8c8a1f259bf7b5d94 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Oct 2013 03:08:10 -0700 Subject: Bluetooth: Remove unneeded val variable when setting SSP The variable val in the set_ssp() function of the management interface is not needed. Just use cp->val directly since its input values have already been validated. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a9d7506be1a3..2fb4d35e04dc 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1290,7 +1290,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) { struct mgmt_mode *cp = data; struct pending_cmd *cmd; - u8 val, status; + u8 status; int err; BT_DBG("request for %s", hdev->name); @@ -1309,8 +1309,6 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) hci_dev_lock(hdev); - val = !!cp->val; - if (!hdev_is_powered(hdev)) { bool changed = false; @@ -1335,7 +1333,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) goto failed; } - if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags) == val) { + if (!!cp->val == test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev); goto failed; } @@ -1346,7 +1344,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) goto failed; } - err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, sizeof(val), &val); + err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val); if (err < 0) { mgmt_pending_remove(cmd); goto failed; -- cgit v1.2.3-73-gaa49b From 9ecb3e24258f1ff4b9937602962ae12e3b57f98d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Oct 2013 03:08:11 -0700 Subject: Bluetooth: Restrict high speed support to SSP enabled controllers The support for Bluetooth High Speed can only be enabled on controllers where also Secure Simple Pairing has been enabled. Trying to enable high speed when SSP is disabled will result into an error. Disabling SSP will at the same time disable high speed as well. It is required to enforce this dependency on SSP since high speed support is only defined for authenticated, unauthenticated and debug link keys. These link key types require SSP. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 42 ++++++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 2fb4d35e04dc..e7ffd39100a0 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1310,11 +1310,19 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) hci_dev_lock(hdev); if (!hdev_is_powered(hdev)) { - bool changed = false; + bool changed; - if (val != test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { - change_bit(HCI_SSP_ENABLED, &hdev->dev_flags); - changed = true; + if (cp->val) { + changed = !test_and_set_bit(HCI_SSP_ENABLED, + &hdev->dev_flags); + } else { + changed = test_and_clear_bit(HCI_SSP_ENABLED, + &hdev->dev_flags); + if (!changed) + changed = test_and_clear_bit(HCI_HS_ENABLED, + &hdev->dev_flags); + else + clear_bit(HCI_HS_ENABLED, &hdev->dev_flags); } err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev); @@ -1327,7 +1335,8 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) goto failed; } - if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev)) { + if (mgmt_pending_find(MGMT_OP_SET_SSP, hdev) || + mgmt_pending_find(MGMT_OP_SET_HS, hdev)) { err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, MGMT_STATUS_BUSY); goto failed; @@ -1368,6 +1377,14 @@ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) if (status) return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status); + if (!lmp_ssp_capable(hdev)) + return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, + MGMT_STATUS_NOT_SUPPORTED); + + if (!test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) + return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, + MGMT_STATUS_REJECTED); + if (cp->val != 0x00 && cp->val != 0x01) return cmd_status(sk, hdev->id, MGMT_OP_SET_HS, MGMT_STATUS_INVALID_PARAMS); @@ -4403,8 +4420,10 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) u8 mgmt_err = mgmt_status(status); if (enable && test_and_clear_bit(HCI_SSP_ENABLED, - &hdev->dev_flags)) + &hdev->dev_flags)) { + clear_bit(HCI_HS_ENABLED, &hdev->dev_flags); err = new_settings(hdev, NULL); + } mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp, &mgmt_err); @@ -4413,11 +4432,14 @@ int mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) } if (enable) { - if (!test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) - changed = true; + changed = !test_and_set_bit(HCI_SSP_ENABLED, &hdev->dev_flags); } else { - if (test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) - changed = true; + changed = test_and_clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); + if (!changed) + changed = test_and_clear_bit(HCI_HS_ENABLED, + &hdev->dev_flags); + else + clear_bit(HCI_HS_ENABLED, &hdev->dev_flags); } mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match); -- cgit v1.2.3-73-gaa49b From c4e5bafa661126b7b42459ad32d4c2cc589ef8fb Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 10 Oct 2013 13:33:37 +0200 Subject: Bluetooth: Fix potential double-frees of L2CAP skbs The l2cap_recv_frame function is expected to take ownership and eventually free the skb passed to it. We need to ensure that the conn->rx_skb pointer is no longer reachable when calling l2cap_recv_frame so that no other function, such as l2cap_conn_del, may think that it can free conn->rx_skb. An actual situation when this can happen is when smp_sig_channel (called from l2cap_recv_frame) fails and l2cap_conn_del gets called as a consequence. The l2cap_conn_del function would then try to free conn->rx_skb, but as the same skb was just passed to smp_sig_channel and freed we get a double-free. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/l2cap_core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a9a7df6639a7..06e7173c2d13 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -6798,9 +6798,13 @@ int l2cap_recv_acldata(struct hci_conn *hcon, struct sk_buff *skb, u16 flags) conn->rx_len -= skb->len; if (!conn->rx_len) { - /* Complete frame received */ - l2cap_recv_frame(conn, conn->rx_skb); + /* Complete frame received. l2cap_recv_frame + * takes ownership of the skb so set the global + * rx_skb pointer to NULL first. + */ + struct sk_buff *rx_skb = conn->rx_skb; conn->rx_skb = NULL; + l2cap_recv_frame(conn, rx_skb); } break; } -- cgit v1.2.3-73-gaa49b From cebf4cfd8608cbcc941750801217988f0a8fc848 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 10 Oct 2013 18:06:04 +0200 Subject: Bluetooth: Fix checking for HCI_SETUP flag when receiving mgmt commands When the HCI_SETUP flag is set the controller has not yet been announced over mgmt and therefore doesn't exist from that perspective. If we nevertheless get a mgmt command for it we should respond with the appropriate INVALID_INDEX error. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index e7ffd39100a0..7d25d6dcd79d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3753,7 +3753,8 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) goto done; } - if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { + if (test_bit(HCI_SETUP, &hdev->dev_flags) || + test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { err = cmd_status(sk, index, opcode, MGMT_STATUS_INVALID_INDEX); goto done; -- cgit v1.2.3-73-gaa49b From 21b5187f23206c0343214194711c8f63e7003d0c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Oct 2013 09:47:53 -0700 Subject: Bluetooth: Fix too long line with set_advertising() function The function declaration goes over 80 characters, so break it down. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 7d25d6dcd79d..2793bfe48707 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3255,7 +3255,8 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status) sock_put(match.sk); } -static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) +static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, + u16 len) { struct mgmt_mode *cp = data; struct pending_cmd *cmd; -- cgit v1.2.3-73-gaa49b From b145edcd1642d55a8eb7d08c954b815cb1478981 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Oct 2013 09:47:54 -0700 Subject: Bluetooth: Use hci_conn_num() for checking number of LE connections When checking for the current number of LE connections, use hci_conn_num() function instead of a full blown lookup within the connection hash or direct access of the counters. In the case of re-enabling advertising, it is more useful to check for any connection attempt or existing connection. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 2793bfe48707..9a069b532bde 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3286,7 +3286,7 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, * necessary). */ if (!hdev_is_powered(hdev) || val == enabled || - hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECTED)) { + hci_conn_num(hdev, LE_LINK) > 0) { bool changed = false; if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { @@ -4683,7 +4683,7 @@ void mgmt_reenable_advertising(struct hci_dev *hdev) { struct hci_request req; - if (hdev->conn_hash.le_num) + if (hci_conn_num(hdev, LE_LINK) > 0) return; if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags)) -- cgit v1.2.3-73-gaa49b From 5b69bef541318857881c84958e01c7d96bfaf8d3 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Oct 2013 10:02:08 -0700 Subject: Bluetooth: AMP contollers do not support the legacy ioctls The legacy ioctls for device specific commands including inquiry are not support by AMP controllers. So just reject them right away instead of trying to send the HCI command and wait for failure from the actual hardware. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 10 ++++++++++ net/bluetooth/hci_sock.c | 3 +++ 2 files changed, 13 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 0c636ba1ba16..593b4efb1d7f 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1048,6 +1048,11 @@ int hci_inquiry(void __user *arg) goto done; } + if (hdev->dev_type != HCI_BREDR) { + err = -EOPNOTSUPP; + goto done; + } + if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { err = -EOPNOTSUPP; goto done; @@ -1533,6 +1538,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) goto done; } + if (hdev->dev_type != HCI_BREDR) { + err = -EOPNOTSUPP; + goto done; + } + if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { err = -EOPNOTSUPP; goto done; diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 579886186c3a..5b2d3f3c9b67 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -518,6 +518,9 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) return -EBUSY; + if (hdev->dev_type != HCI_BREDR) + return -EOPNOTSUPP; + switch (cmd) { case HCISETRAW: if (!capable(CAP_NET_ADMIN)) -- cgit v1.2.3-73-gaa49b From 324d36ed26a22bc14b2dd4505f3dba3fb2676bcc Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Oct 2013 10:50:06 -0700 Subject: Bluetooth: Remove hdev->ioctl driver callback Since there is no use of hdev->ioctl by any Bluetooth driver since ever, so just lets remove it. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 1 - net/bluetooth/hci_sock.c | 5 +---- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index c06552769644..237bf8c03fb4 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -287,7 +287,6 @@ struct hci_dev { int (*setup)(struct hci_dev *hdev); 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) diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 5b2d3f3c9b67..3beaa0594009 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -553,10 +553,7 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, return hci_sock_blacklist_del(hdev, (void __user *) arg); } - if (hdev->ioctl) - return hdev->ioctl(hdev, cmd, arg); - - return -EINVAL; + return -ENOIOCTLCMD; } static int hci_sock_ioctl(struct socket *sock, unsigned int cmd, -- cgit v1.2.3-73-gaa49b From 7ef9fbf08818fa1cb8ae89fca29f193dd78d5dd8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Oct 2013 14:54:14 -0700 Subject: Bluetooth: Move amp.h header file into net/bluetooth/ The amp.h header file is only used internally by the bluetooth.ko module and is not a public API. So make it local to the core Bluetooth module. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/amp.h | 54 --------------------------------------------- net/bluetooth/a2mp.c | 3 ++- net/bluetooth/amp.c | 3 ++- net/bluetooth/amp.h | 54 +++++++++++++++++++++++++++++++++++++++++++++ net/bluetooth/hci_event.c | 3 ++- net/bluetooth/l2cap_core.c | 3 ++- 6 files changed, 62 insertions(+), 58 deletions(-) delete mode 100644 include/net/bluetooth/amp.h create mode 100644 net/bluetooth/amp.h (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/amp.h b/include/net/bluetooth/amp.h deleted file mode 100644 index 7ea3db77ba89..000000000000 --- a/include/net/bluetooth/amp.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - Copyright (c) 2011,2012 Intel Corp. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 and - only version 2 as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ - -#ifndef __AMP_H -#define __AMP_H - -struct amp_ctrl { - struct list_head list; - struct kref kref; - __u8 id; - __u16 assoc_len_so_far; - __u16 assoc_rem_len; - __u16 assoc_len; - __u8 *assoc; -}; - -int amp_ctrl_put(struct amp_ctrl *ctrl); -void amp_ctrl_get(struct amp_ctrl *ctrl); -struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id); -struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id); -void amp_ctrl_list_flush(struct amp_mgr *mgr); - -struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, - u8 remote_id, bool out); - -int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type); - -void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr); -void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle); -void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr); -void amp_read_loc_assoc_final_data(struct hci_dev *hdev, - struct hci_conn *hcon); -void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, - struct hci_conn *hcon); -void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, - struct hci_conn *hcon); -void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle); -void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle); -void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon); -void amp_create_logical_link(struct l2cap_chan *chan); -void amp_disconnect_logical_link(struct hci_chan *hchan); -void amp_destroy_logical_link(struct hci_chan *hchan, u8 reason); - -#endif /* __AMP_H */ diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index b38d07477c20..9ae32cef1762 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -16,7 +16,8 @@ #include #include #include -#include + +#include "amp.h" /* Global AMP Manager list */ LIST_HEAD(amp_mgr_list); diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c index d459ed43c779..b7b8f4eed661 100644 --- a/net/bluetooth/amp.c +++ b/net/bluetooth/amp.c @@ -15,9 +15,10 @@ #include #include #include -#include #include +#include "amp.h" + /* Remote AMP Controllers interface */ void amp_ctrl_get(struct amp_ctrl *ctrl) { diff --git a/net/bluetooth/amp.h b/net/bluetooth/amp.h new file mode 100644 index 000000000000..7ea3db77ba89 --- /dev/null +++ b/net/bluetooth/amp.h @@ -0,0 +1,54 @@ +/* + Copyright (c) 2011,2012 Intel Corp. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 and + only version 2 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +*/ + +#ifndef __AMP_H +#define __AMP_H + +struct amp_ctrl { + struct list_head list; + struct kref kref; + __u8 id; + __u16 assoc_len_so_far; + __u16 assoc_rem_len; + __u16 assoc_len; + __u8 *assoc; +}; + +int amp_ctrl_put(struct amp_ctrl *ctrl); +void amp_ctrl_get(struct amp_ctrl *ctrl); +struct amp_ctrl *amp_ctrl_add(struct amp_mgr *mgr, u8 id); +struct amp_ctrl *amp_ctrl_lookup(struct amp_mgr *mgr, u8 id); +void amp_ctrl_list_flush(struct amp_mgr *mgr); + +struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, + u8 remote_id, bool out); + +int phylink_gen_key(struct hci_conn *hcon, u8 *data, u8 *len, u8 *type); + +void amp_read_loc_info(struct hci_dev *hdev, struct amp_mgr *mgr); +void amp_read_loc_assoc_frag(struct hci_dev *hdev, u8 phy_handle); +void amp_read_loc_assoc(struct hci_dev *hdev, struct amp_mgr *mgr); +void amp_read_loc_assoc_final_data(struct hci_dev *hdev, + struct hci_conn *hcon); +void amp_create_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, + struct hci_conn *hcon); +void amp_accept_phylink(struct hci_dev *hdev, struct amp_mgr *mgr, + struct hci_conn *hcon); +void amp_write_remote_assoc(struct hci_dev *hdev, u8 handle); +void amp_write_rem_assoc_continue(struct hci_dev *hdev, u8 handle); +void amp_physical_cfm(struct hci_conn *bredr_hcon, struct hci_conn *hs_hcon); +void amp_create_logical_link(struct l2cap_chan *chan); +void amp_disconnect_logical_link(struct hci_chan *hchan); +void amp_destroy_logical_link(struct hci_chan *hchan, u8 reason); + +#endif /* __AMP_H */ diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index ada3bf4d7e2a..67316b3e9304 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -30,7 +30,8 @@ #include #include #include -#include + +#include "amp.h" /* Handle HCI Event packets */ diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 06e7173c2d13..09f6f61423ff 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -38,7 +38,8 @@ #include #include #include -#include + +#include "amp.h" bool disable_ertm; -- cgit v1.2.3-73-gaa49b From 7024728ee534d739380dc4fd31f020cfc6e86c28 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Oct 2013 14:54:15 -0700 Subject: Bluetooth: Move a2mp.h header file into net/bluetooth/ The a2mp.h header file is only used internally by the bluetooth.ko module and is not a public API. So make it local to the core Bluetooth module. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/a2mp.h | 150 ------------------------------------------- net/bluetooth/a2mp.c | 2 +- net/bluetooth/a2mp.h | 150 +++++++++++++++++++++++++++++++++++++++++++ net/bluetooth/amp.c | 2 +- net/bluetooth/hci_conn.c | 3 +- net/bluetooth/hci_event.c | 2 +- net/bluetooth/l2cap_core.c | 2 +- 7 files changed, 156 insertions(+), 155 deletions(-) delete mode 100644 include/net/bluetooth/a2mp.h create mode 100644 net/bluetooth/a2mp.h (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/a2mp.h b/include/net/bluetooth/a2mp.h deleted file mode 100644 index 487b54c1308f..000000000000 --- a/include/net/bluetooth/a2mp.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - Copyright (c) 2010,2011 Code Aurora Forum. All rights reserved. - Copyright (c) 2011,2012 Intel Corp. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 and - only version 2 as published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. -*/ - -#ifndef __A2MP_H -#define __A2MP_H - -#include - -#define A2MP_FEAT_EXT 0x8000 - -enum amp_mgr_state { - READ_LOC_AMP_INFO, - READ_LOC_AMP_ASSOC, - READ_LOC_AMP_ASSOC_FINAL, - WRITE_REMOTE_AMP_ASSOC, -}; - -struct amp_mgr { - struct list_head list; - struct l2cap_conn *l2cap_conn; - struct l2cap_chan *a2mp_chan; - struct l2cap_chan *bredr_chan; - struct kref kref; - __u8 ident; - __u8 handle; - unsigned long state; - unsigned long flags; - - struct list_head amp_ctrls; - struct mutex amp_ctrls_lock; -}; - -struct a2mp_cmd { - __u8 code; - __u8 ident; - __le16 len; - __u8 data[0]; -} __packed; - -/* A2MP command codes */ -#define A2MP_COMMAND_REJ 0x01 -struct a2mp_cmd_rej { - __le16 reason; - __u8 data[0]; -} __packed; - -#define A2MP_DISCOVER_REQ 0x02 -struct a2mp_discov_req { - __le16 mtu; - __le16 ext_feat; -} __packed; - -struct a2mp_cl { - __u8 id; - __u8 type; - __u8 status; -} __packed; - -#define A2MP_DISCOVER_RSP 0x03 -struct a2mp_discov_rsp { - __le16 mtu; - __le16 ext_feat; - struct a2mp_cl cl[0]; -} __packed; - -#define A2MP_CHANGE_NOTIFY 0x04 -#define A2MP_CHANGE_RSP 0x05 - -#define A2MP_GETINFO_REQ 0x06 -struct a2mp_info_req { - __u8 id; -} __packed; - -#define A2MP_GETINFO_RSP 0x07 -struct a2mp_info_rsp { - __u8 id; - __u8 status; - __le32 total_bw; - __le32 max_bw; - __le32 min_latency; - __le16 pal_cap; - __le16 assoc_size; -} __packed; - -#define A2MP_GETAMPASSOC_REQ 0x08 -struct a2mp_amp_assoc_req { - __u8 id; -} __packed; - -#define A2MP_GETAMPASSOC_RSP 0x09 -struct a2mp_amp_assoc_rsp { - __u8 id; - __u8 status; - __u8 amp_assoc[0]; -} __packed; - -#define A2MP_CREATEPHYSLINK_REQ 0x0A -#define A2MP_DISCONNPHYSLINK_REQ 0x0C -struct a2mp_physlink_req { - __u8 local_id; - __u8 remote_id; - __u8 amp_assoc[0]; -} __packed; - -#define A2MP_CREATEPHYSLINK_RSP 0x0B -#define A2MP_DISCONNPHYSLINK_RSP 0x0D -struct a2mp_physlink_rsp { - __u8 local_id; - __u8 remote_id; - __u8 status; -} __packed; - -/* A2MP response status */ -#define A2MP_STATUS_SUCCESS 0x00 -#define A2MP_STATUS_INVALID_CTRL_ID 0x01 -#define A2MP_STATUS_UNABLE_START_LINK_CREATION 0x02 -#define A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS 0x02 -#define A2MP_STATUS_COLLISION_OCCURED 0x03 -#define A2MP_STATUS_DISCONN_REQ_RECVD 0x04 -#define A2MP_STATUS_PHYS_LINK_EXISTS 0x05 -#define A2MP_STATUS_SECURITY_VIOLATION 0x06 - -extern struct list_head amp_mgr_list; -extern struct mutex amp_mgr_list_lock; - -struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr); -int amp_mgr_put(struct amp_mgr *mgr); -u8 __next_ident(struct amp_mgr *mgr); -struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, - struct sk_buff *skb); -struct amp_mgr *amp_mgr_lookup_by_state(u8 state); -void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data); -void a2mp_discover_amp(struct l2cap_chan *chan); -void a2mp_send_getinfo_rsp(struct hci_dev *hdev); -void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status); -void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status); -void a2mp_send_create_phy_link_rsp(struct hci_dev *hdev, u8 status); - -#endif /* __A2MP_H */ diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 9ae32cef1762..7e25be3e8a79 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -15,8 +15,8 @@ #include #include #include -#include +#include "a2mp.h" #include "amp.h" /* Global AMP Manager list */ diff --git a/net/bluetooth/a2mp.h b/net/bluetooth/a2mp.h new file mode 100644 index 000000000000..487b54c1308f --- /dev/null +++ b/net/bluetooth/a2mp.h @@ -0,0 +1,150 @@ +/* + Copyright (c) 2010,2011 Code Aurora Forum. All rights reserved. + Copyright (c) 2011,2012 Intel Corp. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 and + only version 2 as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +*/ + +#ifndef __A2MP_H +#define __A2MP_H + +#include + +#define A2MP_FEAT_EXT 0x8000 + +enum amp_mgr_state { + READ_LOC_AMP_INFO, + READ_LOC_AMP_ASSOC, + READ_LOC_AMP_ASSOC_FINAL, + WRITE_REMOTE_AMP_ASSOC, +}; + +struct amp_mgr { + struct list_head list; + struct l2cap_conn *l2cap_conn; + struct l2cap_chan *a2mp_chan; + struct l2cap_chan *bredr_chan; + struct kref kref; + __u8 ident; + __u8 handle; + unsigned long state; + unsigned long flags; + + struct list_head amp_ctrls; + struct mutex amp_ctrls_lock; +}; + +struct a2mp_cmd { + __u8 code; + __u8 ident; + __le16 len; + __u8 data[0]; +} __packed; + +/* A2MP command codes */ +#define A2MP_COMMAND_REJ 0x01 +struct a2mp_cmd_rej { + __le16 reason; + __u8 data[0]; +} __packed; + +#define A2MP_DISCOVER_REQ 0x02 +struct a2mp_discov_req { + __le16 mtu; + __le16 ext_feat; +} __packed; + +struct a2mp_cl { + __u8 id; + __u8 type; + __u8 status; +} __packed; + +#define A2MP_DISCOVER_RSP 0x03 +struct a2mp_discov_rsp { + __le16 mtu; + __le16 ext_feat; + struct a2mp_cl cl[0]; +} __packed; + +#define A2MP_CHANGE_NOTIFY 0x04 +#define A2MP_CHANGE_RSP 0x05 + +#define A2MP_GETINFO_REQ 0x06 +struct a2mp_info_req { + __u8 id; +} __packed; + +#define A2MP_GETINFO_RSP 0x07 +struct a2mp_info_rsp { + __u8 id; + __u8 status; + __le32 total_bw; + __le32 max_bw; + __le32 min_latency; + __le16 pal_cap; + __le16 assoc_size; +} __packed; + +#define A2MP_GETAMPASSOC_REQ 0x08 +struct a2mp_amp_assoc_req { + __u8 id; +} __packed; + +#define A2MP_GETAMPASSOC_RSP 0x09 +struct a2mp_amp_assoc_rsp { + __u8 id; + __u8 status; + __u8 amp_assoc[0]; +} __packed; + +#define A2MP_CREATEPHYSLINK_REQ 0x0A +#define A2MP_DISCONNPHYSLINK_REQ 0x0C +struct a2mp_physlink_req { + __u8 local_id; + __u8 remote_id; + __u8 amp_assoc[0]; +} __packed; + +#define A2MP_CREATEPHYSLINK_RSP 0x0B +#define A2MP_DISCONNPHYSLINK_RSP 0x0D +struct a2mp_physlink_rsp { + __u8 local_id; + __u8 remote_id; + __u8 status; +} __packed; + +/* A2MP response status */ +#define A2MP_STATUS_SUCCESS 0x00 +#define A2MP_STATUS_INVALID_CTRL_ID 0x01 +#define A2MP_STATUS_UNABLE_START_LINK_CREATION 0x02 +#define A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS 0x02 +#define A2MP_STATUS_COLLISION_OCCURED 0x03 +#define A2MP_STATUS_DISCONN_REQ_RECVD 0x04 +#define A2MP_STATUS_PHYS_LINK_EXISTS 0x05 +#define A2MP_STATUS_SECURITY_VIOLATION 0x06 + +extern struct list_head amp_mgr_list; +extern struct mutex amp_mgr_list_lock; + +struct amp_mgr *amp_mgr_get(struct amp_mgr *mgr); +int amp_mgr_put(struct amp_mgr *mgr); +u8 __next_ident(struct amp_mgr *mgr); +struct l2cap_chan *a2mp_channel_create(struct l2cap_conn *conn, + struct sk_buff *skb); +struct amp_mgr *amp_mgr_lookup_by_state(u8 state); +void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data); +void a2mp_discover_amp(struct l2cap_chan *chan); +void a2mp_send_getinfo_rsp(struct hci_dev *hdev); +void a2mp_send_getampassoc_rsp(struct hci_dev *hdev, u8 status); +void a2mp_send_create_phy_link_req(struct hci_dev *hdev, u8 status); +void a2mp_send_create_phy_link_rsp(struct hci_dev *hdev, u8 status); + +#endif /* __A2MP_H */ diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c index b7b8f4eed661..5497ed3f2e3d 100644 --- a/net/bluetooth/amp.c +++ b/net/bluetooth/amp.c @@ -14,9 +14,9 @@ #include #include #include -#include #include +#include "a2mp.h" #include "amp.h" /* Remote AMP Controllers interface */ diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index dedd1ea5dd4c..8141c8d83139 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -28,9 +28,10 @@ #include #include -#include #include +#include "a2mp.h" + struct sco_param { u16 pkt_type; u16 max_latency; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 67316b3e9304..bbe2d292c4a9 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -29,8 +29,8 @@ #include #include #include -#include +#include "a2mp.h" #include "amp.h" /* Handle HCI Event packets */ diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 09f6f61423ff..947e18691e92 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -37,8 +37,8 @@ #include #include #include -#include +#include "a2mp.h" #include "amp.h" bool disable_ertm; -- cgit v1.2.3-73-gaa49b From ac4b7236610cef99821f40f44a74030b85d85270 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Oct 2013 14:54:16 -0700 Subject: Bluetooth: Move smp.h header file into net/bluetooth/ The smp.h header file is only used internally by the bluetooth.ko module and is not a public API. So make it local to the core Bluetooth module. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/smp.h | 146 -------------------------------------------- net/bluetooth/hci_conn.c | 2 +- net/bluetooth/l2cap_core.c | 2 +- net/bluetooth/l2cap_sock.c | 3 +- net/bluetooth/mgmt.c | 3 +- net/bluetooth/smp.c | 3 +- net/bluetooth/smp.h | 146 ++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 154 insertions(+), 151 deletions(-) delete mode 100644 include/net/bluetooth/smp.h create mode 100644 net/bluetooth/smp.h (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/smp.h b/include/net/bluetooth/smp.h deleted file mode 100644 index f8ba07f3e5fa..000000000000 --- a/include/net/bluetooth/smp.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - BlueZ - Bluetooth protocol stack for Linux - Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 as - published by the Free Software Foundation; - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. - IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY - CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - - ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, - COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS - SOFTWARE IS DISCLAIMED. -*/ - -#ifndef __SMP_H -#define __SMP_H - -struct smp_command_hdr { - __u8 code; -} __packed; - -#define SMP_CMD_PAIRING_REQ 0x01 -#define SMP_CMD_PAIRING_RSP 0x02 -struct smp_cmd_pairing { - __u8 io_capability; - __u8 oob_flag; - __u8 auth_req; - __u8 max_key_size; - __u8 init_key_dist; - __u8 resp_key_dist; -} __packed; - -#define SMP_IO_DISPLAY_ONLY 0x00 -#define SMP_IO_DISPLAY_YESNO 0x01 -#define SMP_IO_KEYBOARD_ONLY 0x02 -#define SMP_IO_NO_INPUT_OUTPUT 0x03 -#define SMP_IO_KEYBOARD_DISPLAY 0x04 - -#define SMP_OOB_NOT_PRESENT 0x00 -#define SMP_OOB_PRESENT 0x01 - -#define SMP_DIST_ENC_KEY 0x01 -#define SMP_DIST_ID_KEY 0x02 -#define SMP_DIST_SIGN 0x04 - -#define SMP_AUTH_NONE 0x00 -#define SMP_AUTH_BONDING 0x01 -#define SMP_AUTH_MITM 0x04 - -#define SMP_CMD_PAIRING_CONFIRM 0x03 -struct smp_cmd_pairing_confirm { - __u8 confirm_val[16]; -} __packed; - -#define SMP_CMD_PAIRING_RANDOM 0x04 -struct smp_cmd_pairing_random { - __u8 rand_val[16]; -} __packed; - -#define SMP_CMD_PAIRING_FAIL 0x05 -struct smp_cmd_pairing_fail { - __u8 reason; -} __packed; - -#define SMP_CMD_ENCRYPT_INFO 0x06 -struct smp_cmd_encrypt_info { - __u8 ltk[16]; -} __packed; - -#define SMP_CMD_MASTER_IDENT 0x07 -struct smp_cmd_master_ident { - __le16 ediv; - __u8 rand[8]; -} __packed; - -#define SMP_CMD_IDENT_INFO 0x08 -struct smp_cmd_ident_info { - __u8 irk[16]; -} __packed; - -#define SMP_CMD_IDENT_ADDR_INFO 0x09 -struct smp_cmd_ident_addr_info { - __u8 addr_type; - bdaddr_t bdaddr; -} __packed; - -#define SMP_CMD_SIGN_INFO 0x0a -struct smp_cmd_sign_info { - __u8 csrk[16]; -} __packed; - -#define SMP_CMD_SECURITY_REQ 0x0b -struct smp_cmd_security_req { - __u8 auth_req; -} __packed; - -#define SMP_PASSKEY_ENTRY_FAILED 0x01 -#define SMP_OOB_NOT_AVAIL 0x02 -#define SMP_AUTH_REQUIREMENTS 0x03 -#define SMP_CONFIRM_FAILED 0x04 -#define SMP_PAIRING_NOTSUPP 0x05 -#define SMP_ENC_KEY_SIZE 0x06 -#define SMP_CMD_NOTSUPP 0x07 -#define SMP_UNSPECIFIED 0x08 -#define SMP_REPEATED_ATTEMPTS 0x09 - -#define SMP_MIN_ENC_KEY_SIZE 7 -#define SMP_MAX_ENC_KEY_SIZE 16 - -#define SMP_FLAG_TK_VALID 1 -#define SMP_FLAG_CFM_PENDING 2 -#define SMP_FLAG_MITM_AUTH 3 - -struct smp_chan { - struct l2cap_conn *conn; - u8 preq[7]; /* SMP Pairing Request */ - u8 prsp[7]; /* SMP Pairing Response */ - u8 prnd[16]; /* SMP Pairing Random (local) */ - u8 rrnd[16]; /* SMP Pairing Random (remote) */ - u8 pcnf[16]; /* SMP Pairing Confirm */ - u8 tk[16]; /* SMP Temporary Key */ - u8 enc_key_size; - unsigned long smp_flags; - struct crypto_blkcipher *tfm; - struct work_struct confirm; - struct work_struct random; - -}; - -/* SMP Commands */ -int smp_conn_security(struct hci_conn *hcon, __u8 sec_level); -int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb); -int smp_distribute_keys(struct l2cap_conn *conn, __u8 force); -int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey); - -void smp_chan_destroy(struct l2cap_conn *conn); - -#endif /* __SMP_H */ diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 8141c8d83139..139587159200 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -28,8 +28,8 @@ #include #include -#include +#include "smp.h" #include "a2mp.h" struct sco_param { diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 947e18691e92..a7d10c3596e3 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -36,8 +36,8 @@ #include #include #include -#include +#include "smp.h" #include "a2mp.h" #include "amp.h" diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 1daa4c579eb2..69e42db8a707 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -32,7 +32,8 @@ #include #include #include -#include + +#include "smp.h" static struct bt_sock_list l2cap_sk_list = { .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 9a069b532bde..143dd7319981 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -30,7 +30,8 @@ #include #include #include -#include + +#include "smp.h" #define MGMT_VERSION 1 #define MGMT_REVISION 4 diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 884b2081a262..9272094bd429 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -28,7 +28,8 @@ #include #include #include -#include + +#include "smp.h" #define SMP_TIMEOUT msecs_to_jiffies(30000) diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h new file mode 100644 index 000000000000..f8ba07f3e5fa --- /dev/null +++ b/net/bluetooth/smp.h @@ -0,0 +1,146 @@ +/* + BlueZ - Bluetooth protocol stack for Linux + Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License version 2 as + published by the Free Software Foundation; + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. + IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) AND AUTHOR(S) BE LIABLE FOR ANY + CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PATENTS, + COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS, RELATING TO USE OF THIS + SOFTWARE IS DISCLAIMED. +*/ + +#ifndef __SMP_H +#define __SMP_H + +struct smp_command_hdr { + __u8 code; +} __packed; + +#define SMP_CMD_PAIRING_REQ 0x01 +#define SMP_CMD_PAIRING_RSP 0x02 +struct smp_cmd_pairing { + __u8 io_capability; + __u8 oob_flag; + __u8 auth_req; + __u8 max_key_size; + __u8 init_key_dist; + __u8 resp_key_dist; +} __packed; + +#define SMP_IO_DISPLAY_ONLY 0x00 +#define SMP_IO_DISPLAY_YESNO 0x01 +#define SMP_IO_KEYBOARD_ONLY 0x02 +#define SMP_IO_NO_INPUT_OUTPUT 0x03 +#define SMP_IO_KEYBOARD_DISPLAY 0x04 + +#define SMP_OOB_NOT_PRESENT 0x00 +#define SMP_OOB_PRESENT 0x01 + +#define SMP_DIST_ENC_KEY 0x01 +#define SMP_DIST_ID_KEY 0x02 +#define SMP_DIST_SIGN 0x04 + +#define SMP_AUTH_NONE 0x00 +#define SMP_AUTH_BONDING 0x01 +#define SMP_AUTH_MITM 0x04 + +#define SMP_CMD_PAIRING_CONFIRM 0x03 +struct smp_cmd_pairing_confirm { + __u8 confirm_val[16]; +} __packed; + +#define SMP_CMD_PAIRING_RANDOM 0x04 +struct smp_cmd_pairing_random { + __u8 rand_val[16]; +} __packed; + +#define SMP_CMD_PAIRING_FAIL 0x05 +struct smp_cmd_pairing_fail { + __u8 reason; +} __packed; + +#define SMP_CMD_ENCRYPT_INFO 0x06 +struct smp_cmd_encrypt_info { + __u8 ltk[16]; +} __packed; + +#define SMP_CMD_MASTER_IDENT 0x07 +struct smp_cmd_master_ident { + __le16 ediv; + __u8 rand[8]; +} __packed; + +#define SMP_CMD_IDENT_INFO 0x08 +struct smp_cmd_ident_info { + __u8 irk[16]; +} __packed; + +#define SMP_CMD_IDENT_ADDR_INFO 0x09 +struct smp_cmd_ident_addr_info { + __u8 addr_type; + bdaddr_t bdaddr; +} __packed; + +#define SMP_CMD_SIGN_INFO 0x0a +struct smp_cmd_sign_info { + __u8 csrk[16]; +} __packed; + +#define SMP_CMD_SECURITY_REQ 0x0b +struct smp_cmd_security_req { + __u8 auth_req; +} __packed; + +#define SMP_PASSKEY_ENTRY_FAILED 0x01 +#define SMP_OOB_NOT_AVAIL 0x02 +#define SMP_AUTH_REQUIREMENTS 0x03 +#define SMP_CONFIRM_FAILED 0x04 +#define SMP_PAIRING_NOTSUPP 0x05 +#define SMP_ENC_KEY_SIZE 0x06 +#define SMP_CMD_NOTSUPP 0x07 +#define SMP_UNSPECIFIED 0x08 +#define SMP_REPEATED_ATTEMPTS 0x09 + +#define SMP_MIN_ENC_KEY_SIZE 7 +#define SMP_MAX_ENC_KEY_SIZE 16 + +#define SMP_FLAG_TK_VALID 1 +#define SMP_FLAG_CFM_PENDING 2 +#define SMP_FLAG_MITM_AUTH 3 + +struct smp_chan { + struct l2cap_conn *conn; + u8 preq[7]; /* SMP Pairing Request */ + u8 prsp[7]; /* SMP Pairing Response */ + u8 prnd[16]; /* SMP Pairing Random (local) */ + u8 rrnd[16]; /* SMP Pairing Random (remote) */ + u8 pcnf[16]; /* SMP Pairing Confirm */ + u8 tk[16]; /* SMP Temporary Key */ + u8 enc_key_size; + unsigned long smp_flags; + struct crypto_blkcipher *tfm; + struct work_struct confirm; + struct work_struct random; + +}; + +/* SMP Commands */ +int smp_conn_security(struct hci_conn *hcon, __u8 sec_level); +int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb); +int smp_distribute_keys(struct l2cap_conn *conn, __u8 force); +int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey); + +void smp_chan_destroy(struct l2cap_conn *conn); + +#endif /* __SMP_H */ -- cgit v1.2.3-73-gaa49b From 57d17d70dfa4345fbe3e0d049504aa20626ed0e1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Oct 2013 14:54:17 -0700 Subject: Bluetooth: Move skb->dev assignment for hdev->send into central place The assignement of skb->dev is done all over the place. So it makes it hard to eventually get rid of it. Move it all in one central place so it gets assigned right before calling hdev->send driver callback. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 25 ++++++++++--------------- net/bluetooth/hci_sock.c | 2 -- 2 files changed, 10 insertions(+), 17 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 593b4efb1d7f..925bd47c4a3c 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2697,10 +2697,8 @@ int hci_unregister_cb(struct hci_cb *cb) } EXPORT_SYMBOL(hci_unregister_cb); -static int hci_send_frame(struct sk_buff *skb) +static int hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_dev *hdev = (struct hci_dev *) skb->dev; - if (!hdev) { kfree_skb(skb); return -ENODEV; @@ -2722,6 +2720,8 @@ static int hci_send_frame(struct sk_buff *skb) /* Get rid of skb owner, prior to sending to the driver. */ skb_orphan(skb); + skb->dev = (void *) hdev; + return hdev->send(skb); } @@ -2785,7 +2785,6 @@ static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, BT_DBG("skb len %d", skb->len); bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; - skb->dev = (void *) hdev; return skb; } @@ -2929,7 +2928,6 @@ static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue, do { skb = list; list = list->next; - skb->dev = (void *) hdev; bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; hci_add_acl_hdr(skb, conn->handle, flags); @@ -2948,8 +2946,6 @@ void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags) BT_DBG("%s chan %p flags 0x%4.4x", hdev->name, chan, flags); - skb->dev = (void *) hdev; - hci_queue_acl(chan, &chan->data_q, skb, flags); queue_work(hdev->workqueue, &hdev->tx_work); @@ -2970,7 +2966,6 @@ void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb) skb_reset_transport_header(skb); memcpy(skb_transport_header(skb), &hdr, HCI_SCO_HDR_SIZE); - skb->dev = (void *) hdev; bt_cb(skb)->pkt_type = HCI_SCODATA_PKT; skb_queue_tail(&conn->data_q, skb); @@ -3235,7 +3230,7 @@ static void hci_sched_acl_pkt(struct hci_dev *hdev) hci_conn_enter_active_mode(chan->conn, bt_cb(skb)->force_active); - hci_send_frame(skb); + hci_send_frame(hdev, skb); hdev->acl_last_tx = jiffies; hdev->acl_cnt--; @@ -3287,7 +3282,7 @@ static void hci_sched_acl_blk(struct hci_dev *hdev) hci_conn_enter_active_mode(chan->conn, bt_cb(skb)->force_active); - hci_send_frame(skb); + hci_send_frame(hdev, skb); hdev->acl_last_tx = jiffies; hdev->block_cnt -= blocks; @@ -3340,7 +3335,7 @@ static void hci_sched_sco(struct hci_dev *hdev) while (hdev->sco_cnt && (conn = hci_low_sent(hdev, SCO_LINK, "e))) { while (quote-- && (skb = skb_dequeue(&conn->data_q))) { BT_DBG("skb %p len %d", skb, skb->len); - hci_send_frame(skb); + hci_send_frame(hdev, skb); conn->sent++; if (conn->sent == ~0) @@ -3364,7 +3359,7 @@ static void hci_sched_esco(struct hci_dev *hdev) "e))) { while (quote-- && (skb = skb_dequeue(&conn->data_q))) { BT_DBG("skb %p len %d", skb, skb->len); - hci_send_frame(skb); + hci_send_frame(hdev, skb); conn->sent++; if (conn->sent == ~0) @@ -3406,7 +3401,7 @@ static void hci_sched_le(struct hci_dev *hdev) skb = skb_dequeue(&chan->data_q); - hci_send_frame(skb); + hci_send_frame(hdev, skb); hdev->le_last_tx = jiffies; cnt--; @@ -3442,7 +3437,7 @@ static void hci_tx_work(struct work_struct *work) /* Send next queued raw (unknown type) packet */ while ((skb = skb_dequeue(&hdev->raw_q))) - hci_send_frame(skb); + hci_send_frame(hdev, skb); } /* ----- HCI RX task (incoming data processing) ----- */ @@ -3688,7 +3683,7 @@ static void hci_cmd_work(struct work_struct *work) hdev->sent_cmd = skb_clone(skb, GFP_KERNEL); if (hdev->sent_cmd) { atomic_dec(&hdev->cmd_cnt); - hci_send_frame(skb); + hci_send_frame(hdev, skb); if (test_bit(HCI_RESET, &hdev->flags)) del_timer(&hdev->cmd_timer); else diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 3beaa0594009..97f96ebdd56d 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -387,7 +387,6 @@ static void hci_si_event(struct hci_dev *hdev, int type, int dlen, void *data) __net_timestamp(skb); bt_cb(skb)->pkt_type = HCI_EVENT_PKT; - skb->dev = (void *) hdev; hci_send_to_sock(hdev, skb); kfree_skb(skb); } @@ -942,7 +941,6 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, bt_cb(skb)->pkt_type = *((unsigned char *) skb->data); skb_pull(skb, 1); - skb->dev = (void *) hdev; if (hci_pi(sk)->channel == HCI_CHANNEL_RAW && bt_cb(skb)->pkt_type == HCI_COMMAND_PKT) { -- cgit v1.2.3-73-gaa49b From 3d386acea090e7af3346de59d9e322f92128a4b1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Oct 2013 14:54:18 -0700 Subject: Bluetooth: Remove pointless check of hci_send_frame parameter The hdev parameter of hci_send_frame must be always valid. If the hdev is not valid, it would not even make it to this stage. The callers will have already accessed hdev at that point many times. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 925bd47c4a3c..47cf3a95dac0 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2699,11 +2699,6 @@ EXPORT_SYMBOL(hci_unregister_cb); static int hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { - if (!hdev) { - kfree_skb(skb); - return -ENODEV; - } - BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); /* Time stamp */ -- cgit v1.2.3-73-gaa49b From 5108699194dfccd8cc324ec6691b2bc810a317ab Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Oct 2013 14:54:19 -0700 Subject: Bluetooth: Remove return value from hci_send_frame() function The return value of hci_send_frame() is never checked. So just make this function void and print an error when the hdev->send driver callback returns a negative value. Having the error printed is actually an improvement over the current situation where any driver error just gets ignored. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 47cf3a95dac0..6cc2f86499f8 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2697,7 +2697,7 @@ int hci_unregister_cb(struct hci_cb *cb) } EXPORT_SYMBOL(hci_unregister_cb); -static int hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) +static void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); @@ -2717,7 +2717,8 @@ static int hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) skb->dev = (void *) hdev; - return hdev->send(skb); + if (hdev->send(skb) < 0) + BT_ERR("%s sending frame failed", hdev->name); } void hci_req_init(struct hci_request *req, struct hci_dev *hdev) -- cgit v1.2.3-73-gaa49b From e1a26170692dc1e5fbe0ccd98ef86cc9fcd31a64 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Oct 2013 16:52:43 -0700 Subject: Bluetooth: Provide hdev parameter to hci_recv_frame() driver callback To avoid casting skb->dev into hdev, just let the drivers provide the hdev directly when calling hci_recv_frame() function. This patch also fixes up all drivers to provide the hdev. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/bfusb.c | 3 +-- drivers/bluetooth/bluecard_cs.c | 3 +-- drivers/bluetooth/bpa10x.c | 4 +--- drivers/bluetooth/bt3c_cs.c | 3 +-- drivers/bluetooth/btmrvl_sdio.c | 8 +++----- drivers/bluetooth/btsdio.c | 3 +-- drivers/bluetooth/btuart_cs.c | 3 +-- drivers/bluetooth/btwilink.c | 4 +--- drivers/bluetooth/dtl1_cs.c | 3 +-- drivers/bluetooth/hci_bcsp.c | 5 ++--- drivers/bluetooth/hci_h5.c | 2 +- drivers/bluetooth/hci_ll.c | 13 ++++++------- drivers/bluetooth/hci_vhci.c | 3 +-- include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/hci_core.c | 6 ++---- 15 files changed, 24 insertions(+), 41 deletions(-) (limited to 'net/bluetooth') diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index 66faad0c6237..b7b5bb879f08 100644 --- a/drivers/bluetooth/bfusb.c +++ b/drivers/bluetooth/bfusb.c @@ -318,7 +318,6 @@ static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned ch return -ENOMEM; } - skb->dev = (void *) data->hdev; bt_cb(skb)->pkt_type = pkt_type; data->reassembly = skb; @@ -333,7 +332,7 @@ static inline int bfusb_recv_block(struct bfusb_data *data, int hdr, unsigned ch memcpy(skb_put(data->reassembly, len), buf, len); if (hdr & 0x08) { - hci_recv_frame(data->reassembly); + hci_recv_frame(data->hdev, data->reassembly); data->reassembly = NULL; } diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index aa872c9b3fc2..395acde99d78 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -399,7 +399,6 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset) if (info->rx_state == RECV_WAIT_PACKET_TYPE) { - info->rx_skb->dev = (void *) info->hdev; bt_cb(info->rx_skb)->pkt_type = buf[i]; switch (bt_cb(info->rx_skb)->pkt_type) { @@ -477,7 +476,7 @@ static void bluecard_receive(bluecard_info_t *info, unsigned int offset) break; case RECV_WAIT_DATA: - hci_recv_frame(info->rx_skb); + hci_recv_frame(info->hdev, info->rx_skb); info->rx_skb = NULL; break; diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 2fe4a8031348..3188fb48bf4b 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -129,8 +129,6 @@ static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count) return -ENOMEM; } - skb->dev = (void *) hdev; - data->rx_skb[queue] = skb; scb = (void *) skb->cb; @@ -155,7 +153,7 @@ static int bpa10x_recv(struct hci_dev *hdev, int queue, void *buf, int count) data->rx_skb[queue] = NULL; bt_cb(skb)->pkt_type = scb->type; - hci_recv_frame(skb); + hci_recv_frame(hdev, skb); } count -= len; buf += len; diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 673455cbde4c..d8e4b0d7926e 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -247,7 +247,6 @@ static void bt3c_receive(bt3c_info_t *info) if (info->rx_state == RECV_WAIT_PACKET_TYPE) { - info->rx_skb->dev = (void *) info->hdev; bt_cb(info->rx_skb)->pkt_type = inb(iobase + DATA_L); inb(iobase + DATA_H); //printk("bt3c: PACKET_TYPE=%02x\n", bt_cb(info->rx_skb)->pkt_type); @@ -318,7 +317,7 @@ static void bt3c_receive(bt3c_info_t *info) break; case RECV_WAIT_DATA: - hci_recv_frame(info->rx_skb); + hci_recv_frame(info->hdev, info->rx_skb); info->rx_skb = NULL; break; diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c index 332475e400cf..fabcf5bb48af 100644 --- a/drivers/bluetooth/btmrvl_sdio.c +++ b/drivers/bluetooth/btmrvl_sdio.c @@ -600,15 +600,14 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) case HCI_SCODATA_PKT: case HCI_EVENT_PKT: bt_cb(skb)->pkt_type = type; - skb->dev = (void *)hdev; skb_put(skb, buf_len); skb_pull(skb, SDIO_HEADER_LEN); if (type == HCI_EVENT_PKT) { if (btmrvl_check_evtpkt(priv, skb)) - hci_recv_frame(skb); + hci_recv_frame(hdev, skb); } else { - hci_recv_frame(skb); + hci_recv_frame(hdev, skb); } hdev->stat.byte_rx += buf_len; @@ -616,12 +615,11 @@ static int btmrvl_sdio_card_to_host(struct btmrvl_private *priv) case MRVL_VENDOR_PKT: bt_cb(skb)->pkt_type = HCI_VENDOR_PKT; - skb->dev = (void *)hdev; skb_put(skb, buf_len); skb_pull(skb, SDIO_HEADER_LEN); if (btmrvl_process_event(priv, skb)) - hci_recv_frame(skb); + hci_recv_frame(hdev, skb); hdev->stat.byte_rx += buf_len; break; diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index 4a9909713874..72fe49e60359 100644 --- a/drivers/bluetooth/btsdio.c +++ b/drivers/bluetooth/btsdio.c @@ -157,10 +157,9 @@ static int btsdio_rx_packet(struct btsdio_data *data) data->hdev->stat.byte_rx += len; - skb->dev = (void *) data->hdev; bt_cb(skb)->pkt_type = hdr[3]; - err = hci_recv_frame(skb); + err = hci_recv_frame(data->hdev, skb); if (err < 0) return err; diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index 970e2d3dd3c2..d0b89ecf1c59 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -198,7 +198,6 @@ static void btuart_receive(btuart_info_t *info) if (info->rx_state == RECV_WAIT_PACKET_TYPE) { - info->rx_skb->dev = (void *) info->hdev; bt_cb(info->rx_skb)->pkt_type = inb(iobase + UART_RX); switch (bt_cb(info->rx_skb)->pkt_type) { @@ -265,7 +264,7 @@ static void btuart_receive(btuart_info_t *info) break; case RECV_WAIT_DATA: - hci_recv_frame(info->rx_skb); + hci_recv_frame(info->hdev, info->rx_skb); info->rx_skb = NULL; break; diff --git a/drivers/bluetooth/btwilink.c b/drivers/bluetooth/btwilink.c index 60abf596f60e..5e10fb0a7e05 100644 --- a/drivers/bluetooth/btwilink.c +++ b/drivers/bluetooth/btwilink.c @@ -108,10 +108,8 @@ static long st_receive(void *priv_data, struct sk_buff *skb) return -EFAULT; } - skb->dev = (void *) lhst->hdev; - /* Forward skb to HCI core layer */ - err = hci_recv_frame(skb); + err = hci_recv_frame(lhst->hdev, skb); if (err < 0) { BT_ERR("Unable to push skb to HCI core(%d)", err); return err; diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index c43aff8ec995..29451413bc04 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -256,9 +256,8 @@ static void dtl1_receive(dtl1_info_t *info) case 0x83: case 0x84: /* send frame to the HCI layer */ - info->rx_skb->dev = (void *) info->hdev; bt_cb(info->rx_skb)->pkt_type &= 0x0f; - hci_recv_frame(info->rx_skb); + hci_recv_frame(info->hdev, info->rx_skb); break; default: /* unknown packet */ diff --git a/drivers/bluetooth/hci_bcsp.c b/drivers/bluetooth/hci_bcsp.c index 57e502e06080..0bc87f7abd95 100644 --- a/drivers/bluetooth/hci_bcsp.c +++ b/drivers/bluetooth/hci_bcsp.c @@ -522,7 +522,7 @@ static void bcsp_complete_rx_pkt(struct hci_uart *hu) memcpy(skb_push(bcsp->rx_skb, HCI_EVENT_HDR_SIZE), &hdr, HCI_EVENT_HDR_SIZE); bt_cb(bcsp->rx_skb)->pkt_type = HCI_EVENT_PKT; - hci_recv_frame(bcsp->rx_skb); + hci_recv_frame(hu->hdev, bcsp->rx_skb); } else { BT_ERR ("Packet for unknown channel (%u %s)", bcsp->rx_skb->data[1] & 0x0f, @@ -536,7 +536,7 @@ static void bcsp_complete_rx_pkt(struct hci_uart *hu) /* Pull out BCSP hdr */ skb_pull(bcsp->rx_skb, 4); - hci_recv_frame(bcsp->rx_skb); + hci_recv_frame(hu->hdev, bcsp->rx_skb); } bcsp->rx_state = BCSP_W4_PKT_DELIMITER; @@ -655,7 +655,6 @@ static int bcsp_recv(struct hci_uart *hu, void *data, int count) bcsp->rx_count = 0; return 0; } - bcsp->rx_skb->dev = (void *) hu->hdev; break; } break; diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c index b6154d5a07a5..f6f497450560 100644 --- a/drivers/bluetooth/hci_h5.c +++ b/drivers/bluetooth/hci_h5.c @@ -340,7 +340,7 @@ static void h5_complete_rx_pkt(struct hci_uart *hu) /* Remove Three-wire header */ skb_pull(h5->rx_skb, 4); - hci_recv_frame(h5->rx_skb); + hci_recv_frame(hu->hdev, h5->rx_skb); h5->rx_skb = NULL; break; diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index cfc767938589..58a9541feba6 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -346,14 +346,14 @@ static int ll_enqueue(struct hci_uart *hu, struct sk_buff *skb) return 0; } -static inline int ll_check_data_len(struct ll_struct *ll, int len) +static inline int ll_check_data_len(struct hci_dev *hdev, struct ll_struct *ll, int len) { int room = skb_tailroom(ll->rx_skb); BT_DBG("len %d room %d", len, room); if (!len) { - hci_recv_frame(ll->rx_skb); + hci_recv_frame(hdev, ll->rx_skb); } else if (len > room) { BT_ERR("Data length is too large"); kfree_skb(ll->rx_skb); @@ -395,7 +395,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) switch (ll->rx_state) { case HCILL_W4_DATA: BT_DBG("Complete data"); - hci_recv_frame(ll->rx_skb); + hci_recv_frame(hu->hdev, ll->rx_skb); ll->rx_state = HCILL_W4_PACKET_TYPE; ll->rx_skb = NULL; @@ -406,7 +406,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) BT_DBG("Event header: evt 0x%2.2x plen %d", eh->evt, eh->plen); - ll_check_data_len(ll, eh->plen); + ll_check_data_len(hu->hdev, ll, eh->plen); continue; case HCILL_W4_ACL_HDR: @@ -415,7 +415,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) BT_DBG("ACL header: dlen %d", dlen); - ll_check_data_len(ll, dlen); + ll_check_data_len(hu->hdev, ll, dlen); continue; case HCILL_W4_SCO_HDR: @@ -423,7 +423,7 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) BT_DBG("SCO header: dlen %d", sh->dlen); - ll_check_data_len(ll, sh->dlen); + ll_check_data_len(hu->hdev, ll, sh->dlen); continue; } } @@ -494,7 +494,6 @@ static int ll_recv(struct hci_uart *hu, void *data, int count) return -ENOMEM; } - ll->rx_skb->dev = (void *) hu->hdev; bt_cb(ll->rx_skb)->pkt_type = type; } diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index c04a3e6fb37c..0fd522e85a71 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -179,10 +179,9 @@ static inline ssize_t vhci_get_user(struct vhci_data *data, return -ENODEV; } - skb->dev = (void *) data->hdev; bt_cb(skb)->pkt_type = pkt_type; - ret = hci_recv_frame(skb); + ret = hci_recv_frame(data->hdev, skb); break; case HCI_VENDOR_PKT: diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 237bf8c03fb4..29b81476424c 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -755,7 +755,7 @@ 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 sk_buff *skb); +int hci_recv_frame(struct hci_dev *hdev, 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); diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 6cc2f86499f8..4f0d4b443171 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2485,9 +2485,8 @@ int hci_resume_dev(struct hci_dev *hdev) EXPORT_SYMBOL(hci_resume_dev); /* Receive frame from HCI drivers */ -int hci_recv_frame(struct sk_buff *skb) +int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_dev *hdev = (struct hci_dev *) skb->dev; if (!hdev || (!test_bit(HCI_UP, &hdev->flags) && !test_bit(HCI_INIT, &hdev->flags))) { kfree_skb(skb); @@ -2546,7 +2545,6 @@ static int hci_reassembly(struct hci_dev *hdev, int type, void *data, scb->expect = hlen; scb->pkt_type = type; - skb->dev = (void *) hdev; hdev->reassembly[index] = skb; } @@ -2606,7 +2604,7 @@ static int hci_reassembly(struct hci_dev *hdev, int type, void *data, /* Complete frame */ bt_cb(skb)->pkt_type = type; - hci_recv_frame(skb); + hci_recv_frame(hdev, skb); hdev->reassembly[index] = NULL; return remain; -- cgit v1.2.3-73-gaa49b From 7bd8f09f69f8a190f9b8334a07bb0a9237612314 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 11 Oct 2013 06:19:18 -0700 Subject: Bluetooth: Add hdev parameter to hdev->send driver callback Instead of masking hdev inside the skb->dev parameter, hand it directly to the driver as a parameter to hdev->send. This makes the driver interface more clear and simpler. This patch fixes all drivers to accept and handle the new parameter of hdev->send callback. Special care has been taken for bpa10x and btusb drivers that require having skb->dev set to hdev for the URB transmit complete handlers. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- drivers/bluetooth/bfusb.c | 3 +-- drivers/bluetooth/bluecard_cs.c | 3 +-- drivers/bluetooth/bpa10x.c | 5 +++-- drivers/bluetooth/bt3c_cs.c | 3 +-- drivers/bluetooth/btmrvl_main.c | 4 +--- drivers/bluetooth/btsdio.c | 3 +-- drivers/bluetooth/btuart_cs.c | 3 +-- drivers/bluetooth/btusb.c | 5 +++-- drivers/bluetooth/btwilink.c | 5 +---- drivers/bluetooth/dtl1_cs.c | 3 +-- drivers/bluetooth/hci_ldisc.c | 3 +-- drivers/bluetooth/hci_ll.c | 1 - drivers/bluetooth/hci_vhci.c | 3 +-- include/net/bluetooth/hci_core.h | 2 +- net/bluetooth/hci_core.c | 4 +--- 15 files changed, 18 insertions(+), 32 deletions(-) (limited to 'net/bluetooth') diff --git a/drivers/bluetooth/bfusb.c b/drivers/bluetooth/bfusb.c index b7b5bb879f08..a6758490fa61 100644 --- a/drivers/bluetooth/bfusb.c +++ b/drivers/bluetooth/bfusb.c @@ -464,9 +464,8 @@ static int bfusb_close(struct hci_dev *hdev) return 0; } -static int bfusb_send_frame(struct sk_buff *skb) +static int bfusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_dev *hdev = (struct hci_dev *) skb->dev; struct bfusb_data *data; struct sk_buff *nskb; unsigned char buf[3]; diff --git a/drivers/bluetooth/bluecard_cs.c b/drivers/bluetooth/bluecard_cs.c index 395acde99d78..9194a1ba897f 100644 --- a/drivers/bluetooth/bluecard_cs.c +++ b/drivers/bluetooth/bluecard_cs.c @@ -658,10 +658,9 @@ static int bluecard_hci_close(struct hci_dev *hdev) } -static int bluecard_hci_send_frame(struct sk_buff *skb) +static int bluecard_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { bluecard_info_t *info; - struct hci_dev *hdev = (struct hci_dev *)(skb->dev); if (!hdev) { BT_ERR("Frame for unknown HCI device (hdev=NULL)"); diff --git a/drivers/bluetooth/bpa10x.c b/drivers/bluetooth/bpa10x.c index 3188fb48bf4b..b9e4e621fb10 100644 --- a/drivers/bluetooth/bpa10x.c +++ b/drivers/bluetooth/bpa10x.c @@ -350,9 +350,8 @@ static int bpa10x_flush(struct hci_dev *hdev) return 0; } -static int bpa10x_send_frame(struct sk_buff *skb) +static int bpa10x_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_dev *hdev = (struct hci_dev *) skb->dev; struct bpa10x_data *data = hci_get_drvdata(hdev); struct usb_ctrlrequest *dr; struct urb *urb; @@ -364,6 +363,8 @@ static int bpa10x_send_frame(struct sk_buff *skb) if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; + skb->dev = (void *) hdev; + urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index d8e4b0d7926e..fcd5fe993ad0 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -415,10 +415,9 @@ static int bt3c_hci_close(struct hci_dev *hdev) } -static int bt3c_hci_send_frame(struct sk_buff *skb) +static int bt3c_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { bt3c_info_t *info; - struct hci_dev *hdev = (struct hci_dev *)(skb->dev); unsigned long flags; if (!hdev) { diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c index 8ac4d938d89c..547a447149d3 100644 --- a/drivers/bluetooth/btmrvl_main.c +++ b/drivers/bluetooth/btmrvl_main.c @@ -187,7 +187,6 @@ static int btmrvl_send_sync_cmd(struct btmrvl_private *priv, u16 cmd_no, bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT; - skb->dev = (void *) priv->btmrvl_dev.hcidev; skb_queue_head(&priv->adapter->tx_queue, skb); priv->btmrvl_dev.sendcmdflag = true; @@ -356,9 +355,8 @@ static void btmrvl_free_adapter(struct btmrvl_private *priv) priv->adapter = NULL; } -static int btmrvl_send_frame(struct sk_buff *skb) +static int btmrvl_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_dev *hdev = (struct hci_dev *) skb->dev; struct btmrvl_private *priv = NULL; BT_DBG("type=%d, len=%d", skb->pkt_type, skb->len); diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c index 72fe49e60359..b61440aaee65 100644 --- a/drivers/bluetooth/btsdio.c +++ b/drivers/bluetooth/btsdio.c @@ -254,9 +254,8 @@ static int btsdio_flush(struct hci_dev *hdev) return 0; } -static int btsdio_send_frame(struct sk_buff *skb) +static int btsdio_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_dev *hdev = (struct hci_dev *) skb->dev; struct btsdio_data *data = hci_get_drvdata(hdev); BT_DBG("%s", hdev->name); diff --git a/drivers/bluetooth/btuart_cs.c b/drivers/bluetooth/btuart_cs.c index d0b89ecf1c59..f567cd8424c3 100644 --- a/drivers/bluetooth/btuart_cs.c +++ b/drivers/bluetooth/btuart_cs.c @@ -423,10 +423,9 @@ static int btuart_hci_close(struct hci_dev *hdev) } -static int btuart_hci_send_frame(struct sk_buff *skb) +static int btuart_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { btuart_info_t *info; - struct hci_dev *hdev = (struct hci_dev *)(skb->dev); if (!hdev) { BT_ERR("Frame for unknown HCI device (hdev=NULL)"); diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index faa429f7d8a1..621069cb3053 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -716,9 +716,8 @@ static int btusb_flush(struct hci_dev *hdev) return 0; } -static int btusb_send_frame(struct sk_buff *skb) +static int btusb_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_dev *hdev = (struct hci_dev *) skb->dev; struct btusb_data *data = hci_get_drvdata(hdev); struct usb_ctrlrequest *dr; struct urb *urb; @@ -730,6 +729,8 @@ static int btusb_send_frame(struct sk_buff *skb) if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; + skb->dev = (void *) hdev; + switch (bt_cb(skb)->pkt_type) { case HCI_COMMAND_PKT: urb = usb_alloc_urb(0, GFP_ATOMIC); diff --git a/drivers/bluetooth/btwilink.c b/drivers/bluetooth/btwilink.c index 5e10fb0a7e05..f038dba19e36 100644 --- a/drivers/bluetooth/btwilink.c +++ b/drivers/bluetooth/btwilink.c @@ -251,14 +251,11 @@ static int ti_st_close(struct hci_dev *hdev) return err; } -static int ti_st_send_frame(struct sk_buff *skb) +static int ti_st_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_dev *hdev; struct ti_st *hst; long len; - hdev = (struct hci_dev *)skb->dev; - if (!test_bit(HCI_RUNNING, &hdev->flags)) return -EBUSY; diff --git a/drivers/bluetooth/dtl1_cs.c b/drivers/bluetooth/dtl1_cs.c index 29451413bc04..ad1a2f9dc772 100644 --- a/drivers/bluetooth/dtl1_cs.c +++ b/drivers/bluetooth/dtl1_cs.c @@ -382,10 +382,9 @@ static int dtl1_hci_close(struct hci_dev *hdev) } -static int dtl1_hci_send_frame(struct sk_buff *skb) +static int dtl1_hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { dtl1_info_t *info; - struct hci_dev *hdev = (struct hci_dev *)(skb->dev); struct sk_buff *s; nsh_t nsh; diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index bc68a440d432..b04054675c48 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -234,9 +234,8 @@ static int hci_uart_close(struct hci_dev *hdev) } /* Send frames from HCI layer */ -static int hci_uart_send_frame(struct sk_buff *skb) +static int hci_uart_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_dev* hdev = (struct hci_dev *) skb->dev; struct hci_uart *hu; if (!hdev) { diff --git a/drivers/bluetooth/hci_ll.c b/drivers/bluetooth/hci_ll.c index 58a9541feba6..69a90b1b5ff5 100644 --- a/drivers/bluetooth/hci_ll.c +++ b/drivers/bluetooth/hci_ll.c @@ -110,7 +110,6 @@ static int send_hcill_cmd(u8 cmd, struct hci_uart *hu) /* prepare packet */ hcill_packet = (struct hcill_cmd *) skb_put(skb, 1); hcill_packet->cmd = cmd; - skb->dev = (void *) hu->hdev; /* send packet */ skb_queue_tail(&ll->txq, skb); diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index 0fd522e85a71..e6f591969d95 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -81,9 +81,8 @@ static int vhci_flush(struct hci_dev *hdev) return 0; } -static int vhci_send_frame(struct sk_buff *skb) +static int vhci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) { - struct hci_dev* hdev = (struct hci_dev *) skb->dev; struct vhci_data *data; if (!hdev) { diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 29b81476424c..0e01dc257880 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -285,7 +285,7 @@ struct hci_dev { int (*close)(struct hci_dev *hdev); int (*flush)(struct hci_dev *hdev); int (*setup)(struct hci_dev *hdev); - int (*send)(struct sk_buff *skb); + int (*send)(struct hci_dev *hdev, struct sk_buff *skb); void (*notify)(struct hci_dev *hdev, unsigned int evt); }; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 4f0d4b443171..a097a623912a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2713,9 +2713,7 @@ static void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) /* Get rid of skb owner, prior to sending to the driver. */ skb_orphan(skb); - skb->dev = (void *) hdev; - - if (hdev->send(skb) < 0) + if (hdev->send(hdev, skb) < 0) BT_ERR("%s sending frame failed", hdev->name); } -- cgit v1.2.3-73-gaa49b From bef64738e3fb87eabc6fbeededad0c44ea173384 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 11 Oct 2013 08:23:19 -0700 Subject: Bluetooth: Make LE scan interval and window a controller option The scan interval and window for LE passive scanning and connection establishment should be configurable on a per controller basis. So introduce a setting that later on will allow modifying it. This setting does not affect LE active scanning during device discovery phase. As long as that phase uses interleaved discovery, it will continuously scan. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 2 ++ net/bluetooth/hci_conn.c | 4 ++-- net/bluetooth/hci_core.c | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 0e01dc257880..690045498420 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -164,6 +164,8 @@ struct hci_dev { __u16 page_scan_interval; __u16 page_scan_window; __u8 page_scan_type; + __u16 le_scan_interval; + __u16 le_scan_window; __u16 devid_source; __u16 devid_vendor; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 139587159200..c52bfb7e44fd 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -562,8 +562,8 @@ static int hci_create_le_conn(struct hci_conn *conn) hci_req_init(&req, hdev); memset(&cp, 0, sizeof(cp)); - cp.scan_interval = __constant_cpu_to_le16(0x0060); - cp.scan_window = __constant_cpu_to_le16(0x0030); + cp.scan_interval = cpu_to_le16(hdev->le_scan_interval); + cp.scan_window = cpu_to_le16(hdev->le_scan_window); bacpy(&cp.peer_addr, &conn->dst); cp.peer_addr_type = conn->dst_type; if (bacmp(&hdev->bdaddr, BDADDR_ANY)) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index a097a623912a..1910dc2d33cf 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2273,6 +2273,9 @@ struct hci_dev *hci_alloc_dev(void) hdev->sniff_max_interval = 800; hdev->sniff_min_interval = 80; + hdev->le_scan_interval = 0x0060; + hdev->le_scan_window = 0x0030; + mutex_init(&hdev->lock); mutex_init(&hdev->req_lock); -- cgit v1.2.3-73-gaa49b From 14b49b9a49f0d80ef9a3ce7991b373f93016f5e4 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 11 Oct 2013 08:23:20 -0700 Subject: Bluetooth: Add management command for setting LE scan parameters The scan interval and window parameters are used for LE passive background scanning and connection establishment. This allows userspace to change the values. These two values should be kept in sync with whatever is used for the scan parameters service on remote devices. And it puts the controlling daemon (for example bluetoothd) in charge of setting the values. Main use case would be to switch between two sets of values. One for foreground applications and one for background applications. At this moment, the values are only used for manual connection establishment, but soon that should be extended to background scanning and automatic connection establishment. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/mgmt.h | 7 +++++++ net/bluetooth/mgmt.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h index 2ad433bb9a2e..518c5c84e39a 100644 --- a/include/net/bluetooth/mgmt.h +++ b/include/net/bluetooth/mgmt.h @@ -362,6 +362,13 @@ struct mgmt_cp_set_static_address { } __packed; #define MGMT_SET_STATIC_ADDRESS_SIZE 6 +#define MGMT_OP_SET_SCAN_PARAMS 0x002C +struct mgmt_cp_set_scan_params { + __le16 interval; + __le16 window; +} __packed; +#define MGMT_SET_SCAN_PARAMS_SIZE 4 + #define MGMT_EV_CMD_COMPLETE 0x0001 struct mgmt_ev_cmd_complete { __le16 opcode; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 143dd7319981..f57ec19547af 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3374,6 +3374,43 @@ static int set_static_address(struct sock *sk, struct hci_dev *hdev, return err; } +static int set_scan_params(struct sock *sk, struct hci_dev *hdev, + void *data, u16 len) +{ + struct mgmt_cp_set_scan_params *cp = data; + __u16 interval, window; + int err; + + BT_DBG("%s", hdev->name); + + if (!lmp_le_capable(hdev)) + return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, + MGMT_STATUS_NOT_SUPPORTED); + + interval = __le16_to_cpu(cp->interval); + + if (interval < 0x0004 || interval > 0x4000) + return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, + MGMT_STATUS_INVALID_PARAMS); + + window = __le16_to_cpu(cp->window); + + if (window < 0x0004 || window > 0x4000) + return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, + MGMT_STATUS_INVALID_PARAMS); + + hci_dev_lock(hdev); + + hdev->le_scan_interval = interval; + hdev->le_scan_window = window; + + err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0); + + hci_dev_unlock(hdev); + + return err; +} + static void fast_connectable_complete(struct hci_dev *hdev, u8 status) { struct pending_cmd *cmd; @@ -3710,6 +3747,7 @@ static const struct mgmt_handler { { set_advertising, false, MGMT_SETTING_SIZE }, { set_bredr, false, MGMT_SETTING_SIZE }, { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE }, + { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE }, }; -- cgit v1.2.3-73-gaa49b From 3a6afbd2171a1e92c22d1a9eb54adf1474d938f1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 11 Oct 2013 09:44:12 -0700 Subject: Bluetooth: Fix endless loop with HCI_QUIRK_RESET_ON_CLOSE Really early versions of the Bluetooth specification were unclear with the behavior of HCI Reset for USB devices. They assumed that also an USB reset needs to be issued. Later Bluetooth specifications cleared this out and it is safe to call HCI Reset without affecting the transport. For old devices that misbehave, the HCI_QUIRK_RESET_ON_CLOSE quirk was introduced to postpone the HCI Reset until the device was no longer in use. One of these devices is the Digianswer BPA-105 Bluetooth Protocol Analyzer. The only problem now is that with the quirk set, the HCI Reset is also executed at the end of the setup phase. So the controller gets configured and then it disconnects from the USB bus, connects again, gets configured and of course disconnects again. This game goes on forever. For devices that need HCI_QUIRK_RESET_ON_CLOSE it is important that the HCI Reset is not executed after the setup phase. In specific when HCI_AUTO_OFF is set, do not call HCI Reset when closing the device. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 1910dc2d33cf..8f70a35b4d0e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1378,6 +1378,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) skb_queue_purge(&hdev->cmd_q); atomic_set(&hdev->cmd_cnt, 1); if (!test_bit(HCI_RAW, &hdev->flags) && + !test_bit(HCI_AUTO_OFF, &hdev->dev_flags) && test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) { set_bit(HCI_INIT, &hdev->flags); __hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT); -- cgit v1.2.3-73-gaa49b From a82974c9f4ed07b89715d0695ff41379116fd622 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 11 Oct 2013 09:48:47 -0700 Subject: Bluetooth: Don't advertise high speed support without SSP It is not allowed to enable high speed support when Secure Simple Pairing is not available or disabled. However the support for high speed gets advertised on a controller that does not even support Secure Simple Pairing. Since there is no way to enable high speed support on such a controller, do not even advertise its support. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index f57ec19547af..aa59490044aa 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -363,9 +363,6 @@ static u32 get_supported_settings(struct hci_dev *hdev) settings |= MGMT_SETTING_POWERED; settings |= MGMT_SETTING_PAIRABLE; - if (lmp_ssp_capable(hdev)) - settings |= MGMT_SETTING_SSP; - if (lmp_bredr_capable(hdev)) { settings |= MGMT_SETTING_CONNECTABLE; if (hdev->hci_ver >= BLUETOOTH_VER_1_2) @@ -373,7 +370,11 @@ static u32 get_supported_settings(struct hci_dev *hdev) settings |= MGMT_SETTING_DISCOVERABLE; settings |= MGMT_SETTING_BREDR; settings |= MGMT_SETTING_LINK_SECURITY; - settings |= MGMT_SETTING_HS; + + if (lmp_ssp_capable(hdev)) { + settings |= MGMT_SETTING_SSP; + settings |= MGMT_SETTING_HS; + } } if (lmp_le_capable(hdev)) { -- cgit v1.2.3-73-gaa49b From 7f72134e08bb15511ffcb880cdd01ca77ea54cb7 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 11 Oct 2013 14:44:58 -0700 Subject: Bluetooth: Add MGMT_OP_SET_SCAN_PARAMS to supported commands list When adding support for MGMT_OP_SET_SCAN_PARAMS command the addition to the supported commands list has been forgotten. This is needed for userspace to detect if the command is supported or not. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index aa59490044aa..338878c13571 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -78,6 +78,7 @@ static const u16 mgmt_commands[] = { MGMT_OP_SET_ADVERTISING, MGMT_OP_SET_BREDR, MGMT_OP_SET_STATIC_ADDRESS, + MGMT_OP_SET_SCAN_PARAMS, }; static const u16 mgmt_events[] = { -- cgit v1.2.3-73-gaa49b From 4ca048e3a38e9691eb3e390c5eea3acd9b51cd17 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 11 Oct 2013 16:42:07 -0700 Subject: Bluetooth: Fix HCI init for 1st generation BlueFRITZ! devices The 1st generation of BlueFRITZ! devices from AVM Berlin pretend to be HCI version 1.2 controllers, but they are not. They are simple Bluetooth 1.1 devices. Since this company never created any newer controllers, it is safe to use the manufacturer ID instead of an USB quirk. < HCI Command: Read Page Scan Activity (0x03|0x001b) plen 0 > HCI Event: Command Complete (0x0e) plen 8 Read Page Scan Activity (0x03|0x001b) ncmd 1 Status: Success (0x00) Interval: 1280.000 msec (0x0800) Window: 21.250 msec (0x0022) < HCI Command: Read Page Scan Type (0x03|0x0046) plen 0 > HCI Event: Command Status (0x0f) plen 4 Read Page Scan Type (0x03|0x0046) ncmd 1 Status: Unknown HCI Command (0x01) Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_core.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 8f70a35b4d0e..082f3966f894 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -353,6 +353,8 @@ static void hci_init1_req(struct hci_request *req, unsigned long opt) static void bredr_setup(struct hci_request *req) { + struct hci_dev *hdev = req->hdev; + __le16 param; __u8 flt_type; @@ -376,8 +378,10 @@ static void bredr_setup(struct hci_request *req) param = __constant_cpu_to_le16(0x7d00); hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); - /* Read page scan parameters */ - if (req->hdev->hci_ver > BLUETOOTH_VER_1_1) { + /* AVM Berlin (31), aka "BlueFRITZ!", reports version 1.2, + * but it does not support page scan related HCI commands. + */ + if (hdev->manufacturer != 31 && hdev->hci_ver > BLUETOOTH_VER_1_1) { hci_req_add(req, HCI_OP_READ_PAGE_SCAN_ACTIVITY, 0, NULL); hci_req_add(req, HCI_OP_READ_PAGE_SCAN_TYPE, 0, NULL); } -- cgit v1.2.3-73-gaa49b From 43b1b8dfb4fa326d89aa5930f88b943cc410cbfa Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 12 Oct 2013 06:01:26 -0700 Subject: Bluetooth: Fix PSM value for L2CAP connectionless data packets The put_unaligned() for setting the PSM is missing the (__le16 *) cast. Without this, the PSM information transmitted over the air are bogus. In addition, print the used PSM value in the debug message so this becomes easier to debug in the future. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/l2cap_core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a7d10c3596e3..ab976a1c6466 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -2283,7 +2283,8 @@ static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; struct l2cap_hdr *lh; - BT_DBG("chan %p len %zu priority %u", chan, len, priority); + BT_DBG("chan %p psm 0x%2.2x len %zu priority %u", chan, + __le16_to_cpu(chan->psm), len, priority); count = min_t(unsigned int, (conn->mtu - hlen), len); @@ -2298,7 +2299,7 @@ static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); lh->cid = cpu_to_le16(chan->dcid); lh->len = cpu_to_le16(len + L2CAP_PSMLEN_SIZE); - put_unaligned(chan->psm, skb_put(skb, L2CAP_PSMLEN_SIZE)); + put_unaligned(chan->psm, (__le16 *) skb_put(skb, L2CAP_PSMLEN_SIZE)); err = l2cap_skbuff_fromiovec(chan, msg, len, count, skb); if (unlikely(err < 0)) { -- cgit v1.2.3-73-gaa49b From 6a974b50a1b0909803faac3c3228f7c1339d9971 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 12 Oct 2013 07:19:31 -0700 Subject: Bluetooth: Limit security mode 4 level 0 to connection oriented channels The exception for certain PSM channels when it comes to security mode 4 level 0 should only be checked when actually a connection oriented channel is established. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/l2cap_core.c | 24 +++++++++++++++--------- net/bluetooth/l2cap_sock.c | 10 +++++++--- 2 files changed, 22 insertions(+), 12 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index ab976a1c6466..cc51cb860c40 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -677,7 +677,8 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) { - if (chan->chan_type == L2CAP_CHAN_RAW) { + switch (chan->chan_type) { + case L2CAP_CHAN_RAW: switch (chan->sec_level) { case BT_SECURITY_HIGH: return HCI_AT_DEDICATED_BONDING_MITM; @@ -686,15 +687,19 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) default: return HCI_AT_NO_BONDING; } - } else if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { - if (chan->sec_level == BT_SECURITY_LOW) - chan->sec_level = BT_SECURITY_SDP; + break; + case L2CAP_CHAN_CONN_ORIENTED: + if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { + if (chan->sec_level == BT_SECURITY_LOW) + chan->sec_level = BT_SECURITY_SDP; - if (chan->sec_level == BT_SECURITY_HIGH) - return HCI_AT_NO_BONDING_MITM; - else - return HCI_AT_NO_BONDING; - } else { + if (chan->sec_level == BT_SECURITY_HIGH) + return HCI_AT_NO_BONDING_MITM; + else + return HCI_AT_NO_BONDING; + } + /* fall through */ + default: switch (chan->sec_level) { case BT_SECURITY_HIGH: return HCI_AT_GENERAL_BONDING_MITM; @@ -703,6 +708,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) default: return HCI_AT_NO_BONDING; } + break; } } diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 69e42db8a707..bee98ebfae4d 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -100,9 +100,13 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) if (err < 0) goto done; - if (__le16_to_cpu(la.l2_psm) == L2CAP_PSM_SDP || - __le16_to_cpu(la.l2_psm) == L2CAP_PSM_RFCOMM) - chan->sec_level = BT_SECURITY_SDP; + switch (chan->chan_type) { + case L2CAP_CHAN_CONN_ORIENTED: + if (__le16_to_cpu(la.l2_psm) == L2CAP_PSM_SDP || + __le16_to_cpu(la.l2_psm) == L2CAP_PSM_RFCOMM) + chan->sec_level = BT_SECURITY_SDP; + break; + } bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); -- cgit v1.2.3-73-gaa49b From 3124b84309a0699c98bdc0ef1fc8cd5e058ad5fa Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 12 Oct 2013 07:19:32 -0700 Subject: Bluetooth: Allow 3D profile to use security mode 4 level 0 The PSM 0x0021 is dedicated to the 3D profile and has permission to use security mode 4 level 0 for L2CAP connectionless unicast data transfers. When establishing a L2CAP connectionless channel on PSM 0x0021, it will no longer force Secure Simple Pairing. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/l2cap.h | 1 + net/bluetooth/l2cap_core.c | 10 ++++++++++ net/bluetooth/l2cap_sock.c | 4 ++++ 3 files changed, 15 insertions(+) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index f141b5f6e4f1..12523c79eb3b 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -237,6 +237,7 @@ struct l2cap_conn_rsp { /* protocol/service multiplexer (PSM) */ #define L2CAP_PSM_SDP 0x0001 #define L2CAP_PSM_RFCOMM 0x0003 +#define L2CAP_PSM_3DSP 0x0021 /* channel indentifier */ #define L2CAP_CID_SIGNALING 0x0001 diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index cc51cb860c40..e932ffda5445 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -688,6 +688,16 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) return HCI_AT_NO_BONDING; } break; + case L2CAP_CHAN_CONN_LESS: + if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) { + if (chan->sec_level == BT_SECURITY_LOW) + chan->sec_level = BT_SECURITY_SDP; + } + if (chan->sec_level == BT_SECURITY_HIGH) + return HCI_AT_NO_BONDING_MITM; + else + return HCI_AT_NO_BONDING; + break; case L2CAP_CHAN_CONN_ORIENTED: if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { if (chan->sec_level == BT_SECURITY_LOW) diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index bee98ebfae4d..bd6fe7fd2737 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -101,6 +101,10 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) goto done; switch (chan->chan_type) { + case L2CAP_CHAN_CONN_LESS: + if (__le16_to_cpu(la.l2_psm) == L2CAP_PSM_3DSP) + chan->sec_level = BT_SECURITY_SDP; + break; case L2CAP_CHAN_CONN_ORIENTED: if (__le16_to_cpu(la.l2_psm) == L2CAP_PSM_SDP || __le16_to_cpu(la.l2_psm) == L2CAP_PSM_RFCOMM) -- cgit v1.2.3-73-gaa49b From d40bffbc4e9afce9c0be6ea399b4103f72e50ec2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 12 Oct 2013 08:18:18 -0700 Subject: Bluetooth: The L2CAP fixed channel connectionless data is supported The implementation actually supports the L2CAP connectionless data channel. So set it as supported in the fixed channels bitmask. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/l2cap.h | 1 + net/bluetooth/l2cap_core.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 12523c79eb3b..56f540e7a8fc 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -131,6 +131,7 @@ struct l2cap_conninfo { /* L2CAP fixed channels */ #define L2CAP_FC_L2CAP 0x02 +#define L2CAP_FC_CONNLESS 0x04 #define L2CAP_FC_A2MP 0x08 /* L2CAP Control Field bit masks */ diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index e932ffda5445..8b5437c44c7b 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -44,7 +44,7 @@ bool disable_ertm; static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; -static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP, }; +static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_CONNLESS, }; static LIST_HEAD(chan_list); static DEFINE_RWLOCK(chan_list_lock); -- cgit v1.2.3-73-gaa49b From 547d103280690b8febd2354320e164ae508d912e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 12 Oct 2013 08:18:19 -0700 Subject: Bluetooth: Unicast connectionless data reception is supported The unicast connectionless data reception feature is actually support and has been supported all along. Mark it as supported in the L2CAP features bitmask. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/l2cap_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 8b5437c44c7b..13bb9da2c93a 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -43,7 +43,7 @@ bool disable_ertm; -static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; +static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_CONNLESS, }; static LIST_HEAD(chan_list); -- cgit v1.2.3-73-gaa49b From bdc8ead27c71b4d3f3e883b0bf3f279a18a6f590 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 02:23:38 -0700 Subject: Bluetooth: Remove l2cap_conn->dst usage from AMP manager The l2cap_conn->dst address is just a pointer into the hci_conn->dst structure. Use hci_conn->dst directly instead. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/a2mp.c | 3 ++- net/bluetooth/amp.c | 5 +++-- 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 7e25be3e8a79..60ca52819247 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c @@ -537,7 +537,8 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb, goto send_rsp; } - hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, mgr->l2cap_conn->dst); + hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, + &mgr->l2cap_conn->hcon->dst); if (!hcon) { BT_ERR("No phys link exist"); rsp.status = A2MP_STATUS_NO_PHYSICAL_LINK_EXISTS; diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c index 5497ed3f2e3d..bb39509b3f06 100644 --- a/net/bluetooth/amp.c +++ b/net/bluetooth/amp.c @@ -111,7 +111,7 @@ static u8 __next_handle(struct amp_mgr *mgr) struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, u8 remote_id, bool out) { - bdaddr_t *dst = mgr->l2cap_conn->dst; + bdaddr_t *dst = &mgr->l2cap_conn->hcon->dst; struct hci_conn *hcon; hcon = hci_conn_add(hdev, AMP_LINK, dst); @@ -410,7 +410,8 @@ void amp_create_logical_link(struct l2cap_chan *chan) struct hci_cp_create_accept_logical_link cp; struct hci_dev *hdev; - BT_DBG("chan %p hs_hcon %p dst %pMR", chan, hs_hcon, chan->conn->dst); + BT_DBG("chan %p hs_hcon %p dst %pMR", chan, hs_hcon, + &chan->conn->hcon->dst); if (!hs_hcon) return; -- cgit v1.2.3-73-gaa49b From ce39fb4e45a4315fcdf75ef25d61281e946ebb07 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 02:23:39 -0700 Subject: Bluetooth: Remove l2cap_conn->src and l2cap_conn->dst usage from SMP The l2cap_conn->src and l2cap_conn->dst addresses are just a pointer to hci_conn->hdev->bdaddr and hci_conn->dst structures. Use the data provided by hci_conn directly. This is done for hci_conn->dst_type already anyway and with this change it makes it a lot clearer were the address information comes from. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/smp.c | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 9272094bd429..06a082ea903e 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -266,13 +266,13 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), &reason); - clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->hcon->flags); - mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type, - hcon->dst_type, HCI_ERROR_AUTH_FAILURE); + clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags); + mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type, + HCI_ERROR_AUTH_FAILURE); cancel_delayed_work_sync(&conn->security_timer); - if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) + if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) smp_chan_destroy(conn); } @@ -355,10 +355,10 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, hci_dev_lock(hcon->hdev); if (method == REQ_PASSKEY) - ret = mgmt_user_passkey_request(hcon->hdev, conn->dst, + ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type); else - ret = mgmt_user_confirm_request(hcon->hdev, conn->dst, + ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type, cpu_to_le32(passkey), 0); @@ -388,11 +388,12 @@ static void confirm_work(struct work_struct *work) if (conn->hcon->out) ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0, - conn->src, conn->hcon->dst_type, conn->dst, res); + &conn->hcon->hdev->bdaddr, conn->hcon->dst_type, + &conn->hcon->dst, res); else ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, - conn->hcon->dst_type, conn->dst, 0, conn->src, - res); + conn->hcon->dst_type, &conn->hcon->dst, 0, + &conn->hcon->hdev->bdaddr, res); if (ret) { reason = SMP_UNSPECIFIED; goto error; @@ -427,10 +428,12 @@ static void random_work(struct work_struct *work) if (hcon->out) ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0, - conn->src, hcon->dst_type, conn->dst, res); + &hcon->hdev->bdaddr, hcon->dst_type, &hcon->dst, + res); else ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, - hcon->dst_type, conn->dst, 0, conn->src, res); + hcon->dst_type, &hcon->dst, 0, &hcon->hdev->bdaddr, + res); if (ret) { reason = SMP_UNSPECIFIED; goto error; @@ -480,7 +483,7 @@ static void random_work(struct work_struct *work) memset(stk + smp->enc_key_size, 0, SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); - hci_add_ltk(hcon->hdev, conn->dst, hcon->dst_type, + hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size, ediv, rand); } @@ -715,7 +718,7 @@ static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) struct smp_ltk *key; struct hci_conn *hcon = conn->hcon; - key = hci_find_ltk_by_addr(hcon->hdev, conn->dst, hcon->dst_type); + key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type); if (!key) return 0; @@ -836,9 +839,9 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) skb_pull(skb, sizeof(*rp)); hci_dev_lock(hdev); - authenticated = (conn->hcon->sec_level == BT_SECURITY_HIGH); - hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type, - HCI_SMP_LTK, 1, authenticated, smp->tk, smp->enc_key_size, + authenticated = (hcon->sec_level == BT_SECURITY_HIGH); + hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, 1, + authenticated, smp->tk, smp->enc_key_size, rp->ediv, rp->rand); smp_distribute_keys(conn, 1); hci_dev_unlock(hdev); @@ -986,7 +989,7 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); authenticated = hcon->sec_level == BT_SECURITY_HIGH; - hci_add_ltk(conn->hcon->hdev, conn->dst, hcon->dst_type, + hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK_SLAVE, 1, authenticated, enc.ltk, smp->enc_key_size, ediv, ident.rand); @@ -1008,7 +1011,7 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) /* Just public address */ memset(&addrinfo, 0, sizeof(addrinfo)); - bacpy(&addrinfo.bdaddr, conn->src); + bacpy(&addrinfo.bdaddr, &conn->hcon->hdev->bdaddr); smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo), &addrinfo); -- cgit v1.2.3-73-gaa49b From 98e0f7ea4a5b4774805c62be104f19abba6187ac Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 02:23:40 -0700 Subject: Bluetooth: Remove l2cap_conn->src and l2cap_conn->dst usage from L2CAP The l2cap_conn->src and l2cap_conn->dst addresses are just a pointers to hci_conn structure. Use hci_conn->hdev->bdaddr and hci_conn->dst directly instead. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/l2cap_core.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 13bb9da2c93a..41e2efe67f7f 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1381,7 +1381,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) /* Check if we have socket listening on cid */ pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, - conn->src, conn->dst); + &conn->hcon->hdev->bdaddr, + &conn->hcon->dst); if (!pchan) return; @@ -1399,8 +1400,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) chan->dcid = L2CAP_CID_ATT; - bacpy(&bt_sk(chan->sk)->src, conn->src); - bacpy(&bt_sk(chan->sk)->dst, conn->dst); + bacpy(&bt_sk(chan->sk)->src, &conn->hcon->hdev->bdaddr); + bacpy(&bt_sk(chan->sk)->dst, &conn->hcon->dst); __l2cap_chan_add(conn, chan); @@ -1665,9 +1666,6 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) break; } - conn->src = &hcon->hdev->bdaddr; - conn->dst = &hcon->dst; - conn->feat_mask = 0; if (hcon->type == ACL_LINK) @@ -1861,7 +1859,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, } /* Update source addr of the socket */ - bacpy(src, conn->src); + bacpy(src, &hdev->bdaddr); l2cap_chan_unlock(chan); l2cap_chan_add(conn, chan); @@ -3761,7 +3759,9 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); /* Check if we have socket listening on psm */ - pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, conn->src, conn->dst); + pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, + &conn->hcon->hdev->bdaddr, + &conn->hcon->dst); if (!pchan) { result = L2CAP_CR_BAD_PSM; goto sendresp; @@ -3799,8 +3799,8 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, */ conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; - bacpy(&bt_sk(sk)->src, conn->src); - bacpy(&bt_sk(sk)->dst, conn->dst); + bacpy(&bt_sk(sk)->src, &conn->hcon->hdev->bdaddr); + bacpy(&bt_sk(sk)->dst, &conn->hcon->dst); chan->psm = psm; chan->dcid = scid; chan->local_amp_id = amp_id; @@ -4479,7 +4479,8 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn, struct amp_mgr *mgr = conn->hcon->amp_mgr; struct hci_conn *hs_hcon; - hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, conn->dst); + hs_hcon = hci_conn_hash_lookup_ba(hdev, AMP_LINK, + &conn->hcon->dst); if (!hs_hcon) { hci_dev_put(hdev); return -EBADSLT; @@ -4922,7 +4923,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn, */ if ((__chan_is_moving(chan) || chan->move_role != L2CAP_MOVE_ROLE_NONE) && - bacmp(conn->src, conn->dst) > 0) { + bacmp(&conn->hcon->hdev->bdaddr, &conn->hcon->dst) > 0) { result = L2CAP_MR_COLLISION; goto send_move_response; } @@ -6437,7 +6438,8 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, if (hcon->type != ACL_LINK) goto drop; - chan = l2cap_global_chan_by_psm(0, psm, conn->src, conn->dst); + chan = l2cap_global_chan_by_psm(0, psm, &conn->hcon->hdev->bdaddr, + &conn->hcon->dst); if (!chan) goto drop; @@ -6466,7 +6468,8 @@ static void l2cap_att_channel(struct l2cap_conn *conn, goto drop; chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT, - conn->src, conn->dst); + &conn->hcon->hdev->bdaddr, + &conn->hcon->dst); if (!chan) goto drop; -- cgit v1.2.3-73-gaa49b From 79d95a19a445f5758571b3342064f2c1e40b6c5f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 03:57:38 -0700 Subject: Bluetooth: Remove pointless bdaddr_to_le() helper function The bdaddr_to_le() function tries to convert the internal address type to one that matches the HCI address type for LE. It does not handle any address types not used by LE and in the end just make the code a lot harder to read. So instead of just hiding behind a magic function, just convert the internal address type where it needs to be converted. And it turns out that these are only two cases anyway. One when creating new LE connections and the other when loading the long term keys. In both cases this makes it more clear on what it going on. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 2 -- net/bluetooth/hci_conn.c | 5 ++++- net/bluetooth/hci_core.c | 12 ------------ net/bluetooth/mgmt.c | 10 +++++++--- 4 files changed, 11 insertions(+), 18 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 690045498420..7889495da843 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1187,8 +1187,6 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, 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 diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index c52bfb7e44fd..bb32f48b88f9 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -622,7 +622,10 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, if (!conn) return ERR_PTR(-ENOMEM); - conn->dst_type = bdaddr_to_le(dst_type); + if (dst_type == BDADDR_LE_PUBLIC) + conn->dst_type = ADDR_LE_DEV_PUBLIC; + else + conn->dst_type = ADDR_LE_DEV_RANDOM; conn->state = BT_CONNECT; conn->out = true; conn->link_mode |= HCI_LM_MASTER; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 082f3966f894..0e05edee0962 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -3695,15 +3695,3 @@ static void hci_cmd_work(struct work_struct *work) } } } - -u8 bdaddr_to_le(u8 bdaddr_type) -{ - switch (bdaddr_type) { - case BDADDR_LE_PUBLIC: - return ADDR_LE_DEV_PUBLIC; - - default: - /* Fallback to LE Random address type */ - return ADDR_LE_DEV_RANDOM; - } -} diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 338878c13571..020f95b84b09 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3678,15 +3678,19 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, for (i = 0; i < key_count; i++) { struct mgmt_ltk_info *key = &cp->keys[i]; - u8 type; + u8 type, addr_type; + + if (key->addr.type == BDADDR_LE_PUBLIC) + addr_type = ADDR_LE_DEV_PUBLIC; + else + addr_type = ADDR_LE_DEV_RANDOM; if (key->master) type = HCI_SMP_LTK; else type = HCI_SMP_LTK_SLAVE; - hci_add_ltk(hdev, &key->addr.bdaddr, - bdaddr_to_le(key->addr.type), + hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type, 0, key->authenticated, key->val, key->enc_size, key->ediv, key->rand); } -- cgit v1.2.3-73-gaa49b From e7c4096e16f0e362c6cf902baab0de37ebfc1266 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 03:57:39 -0700 Subject: Bluetooth: Store the source address type of LE connections When establishing LE connections, it is possible to use a public address (if available) or a random address. The type of address is only known when creating connections, so make sure it is stored in hci_conn structure. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 1 + net/bluetooth/hci_conn.c | 11 +++++++---- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 7889495da843..714da9ea465e 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -300,6 +300,7 @@ struct hci_conn { bdaddr_t dst; __u8 dst_type; + __u8 src_type; __u16 handle; __u16 state; __u8 mode; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index bb32f48b88f9..d9f7f93b813e 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -566,10 +566,7 @@ static int hci_create_le_conn(struct hci_conn *conn) cp.scan_window = cpu_to_le16(hdev->le_scan_window); bacpy(&cp.peer_addr, &conn->dst); cp.peer_addr_type = conn->dst_type; - if (bacmp(&hdev->bdaddr, BDADDR_ANY)) - cp.own_address_type = ADDR_LE_DEV_PUBLIC; - else - cp.own_address_type = ADDR_LE_DEV_RANDOM; + cp.own_address_type = conn->src_type; cp.conn_interval_min = __constant_cpu_to_le16(0x0028); cp.conn_interval_max = __constant_cpu_to_le16(0x0038); cp.supervision_timeout = __constant_cpu_to_le16(0x002a); @@ -626,6 +623,12 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, conn->dst_type = ADDR_LE_DEV_PUBLIC; else conn->dst_type = ADDR_LE_DEV_RANDOM; + + if (bacmp(&hdev->bdaddr, BDADDR_ANY)) + conn->src_type = ADDR_LE_DEV_PUBLIC; + else + conn->src_type = ADDR_LE_DEV_RANDOM; + conn->state = BT_CONNECT; conn->out = true; conn->link_mode |= HCI_LM_MASTER; -- cgit v1.2.3-73-gaa49b From 662e8820f38dcc458e0d4769194db5ed3469224f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 05:23:59 -0700 Subject: Bluetooth: Store source address of HCI connections The source addressed was based on the public address of the HCI device, but with LE connections this not always the case. For example single mode LE-only controllers would use a static random address. And this address is configured by userspace. To not complicate the lookup of what kind of address is in use, store the correct source address for each HCI connection. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/hci_core.h | 1 + net/bluetooth/hci_conn.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 714da9ea465e..0326b160b89a 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -300,6 +300,7 @@ struct hci_conn { bdaddr_t dst; __u8 dst_type; + bdaddr_t src; __u8 src_type; __u16 handle; __u16 state; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index d9f7f93b813e..ff04b051792d 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -381,6 +381,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) return NULL; bacpy(&conn->dst, dst); + bacpy(&conn->src, &hdev->bdaddr); conn->hdev = hdev; conn->type = type; conn->mode = HCI_CM_ACTIVE; @@ -624,10 +625,12 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, else conn->dst_type = ADDR_LE_DEV_RANDOM; - if (bacmp(&hdev->bdaddr, BDADDR_ANY)) + if (bacmp(&conn->src, BDADDR_ANY)) { conn->src_type = ADDR_LE_DEV_PUBLIC; - else + } else { + bacpy(&conn->src, &hdev->static_addr); conn->src_type = ADDR_LE_DEV_RANDOM; + } conn->state = BT_CONNECT; conn->out = true; -- cgit v1.2.3-73-gaa49b From 880be4e8d0db86a635b87f75fee7daa4f6006f45 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 07:25:18 -0700 Subject: Bluetooth: Update source address and type for incoming LE connections The incoming LE connections do not have a proper source address and address type set. The connection needs to be set with the same values as used for advertising parameters. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hci_event.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index bbe2d292c4a9..aa6fed3a553b 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3477,6 +3477,17 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) conn->dst_type = ev->bdaddr_type; + /* The advertising parameters for own address type + * define which source address and source address + * type this connections has. + */ + if (bacmp(&conn->src, BDADDR_ANY)) { + conn->src_type = ADDR_LE_DEV_PUBLIC; + } else { + bacpy(&conn->src, &hdev->static_addr); + conn->src_type = ADDR_LE_DEV_RANDOM; + } + if (ev->role == LE_CONN_ROLE_MASTER) { conn->out = true; conn->link_mode |= HCI_LM_MASTER; -- cgit v1.2.3-73-gaa49b From 2b36a5620acb5ee0c101ec32a20793da4426fd33 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 05:24:00 -0700 Subject: Bluetooth: Use hci_conn->src address for SMP functions The source address is now stored in hci_conn->src and so use that one for SMP functions. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/smp.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 06a082ea903e..f57b20908ed5 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -388,12 +388,12 @@ static void confirm_work(struct work_struct *work) if (conn->hcon->out) ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0, - &conn->hcon->hdev->bdaddr, conn->hcon->dst_type, + &conn->hcon->src, conn->hcon->dst_type, &conn->hcon->dst, res); else ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, conn->hcon->dst_type, &conn->hcon->dst, 0, - &conn->hcon->hdev->bdaddr, res); + &conn->hcon->src, res); if (ret) { reason = SMP_UNSPECIFIED; goto error; @@ -428,12 +428,10 @@ static void random_work(struct work_struct *work) if (hcon->out) ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0, - &hcon->hdev->bdaddr, hcon->dst_type, &hcon->dst, - res); + &hcon->src, hcon->dst_type, &hcon->dst, res); else ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, - hcon->dst_type, &hcon->dst, 0, &hcon->hdev->bdaddr, - res); + hcon->dst_type, &hcon->dst, 0, &hcon->src, res); if (ret) { reason = SMP_UNSPECIFIED; goto error; @@ -1011,7 +1009,7 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) /* Just public address */ memset(&addrinfo, 0, sizeof(addrinfo)); - bacpy(&addrinfo.bdaddr, &conn->hcon->hdev->bdaddr); + bacpy(&addrinfo.bdaddr, &conn->hcon->src); smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo), &addrinfo); -- cgit v1.2.3-73-gaa49b From 6f59b904ae57df92915d7ade750853647620db2c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 05:24:01 -0700 Subject: Bluetooth: Use hci_conn->src address for L2CAP functions The source address is now stored in hci_conn->src and so use that one for L2CAP functions. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/l2cap_core.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 41e2efe67f7f..3ed9a2bf3d7c 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1381,8 +1381,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) /* Check if we have socket listening on cid */ pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, - &conn->hcon->hdev->bdaddr, - &conn->hcon->dst); + &conn->hcon->src, &conn->hcon->dst); if (!pchan) return; @@ -1400,7 +1399,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) chan->dcid = L2CAP_CID_ATT; - bacpy(&bt_sk(chan->sk)->src, &conn->hcon->hdev->bdaddr); + bacpy(&bt_sk(chan->sk)->src, &conn->hcon->src); bacpy(&bt_sk(chan->sk)->dst, &conn->hcon->dst); __l2cap_chan_add(conn, chan); @@ -3759,8 +3758,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, BT_DBG("psm 0x%2.2x scid 0x%4.4x", __le16_to_cpu(psm), scid); /* Check if we have socket listening on psm */ - pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, - &conn->hcon->hdev->bdaddr, + pchan = l2cap_global_chan_by_psm(BT_LISTEN, psm, &conn->hcon->src, &conn->hcon->dst); if (!pchan) { result = L2CAP_CR_BAD_PSM; @@ -3799,7 +3797,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, */ conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; - bacpy(&bt_sk(sk)->src, &conn->hcon->hdev->bdaddr); + bacpy(&bt_sk(sk)->src, &conn->hcon->src); bacpy(&bt_sk(sk)->dst, &conn->hcon->dst); chan->psm = psm; chan->dcid = scid; @@ -4923,7 +4921,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn, */ if ((__chan_is_moving(chan) || chan->move_role != L2CAP_MOVE_ROLE_NONE) && - bacmp(&conn->hcon->hdev->bdaddr, &conn->hcon->dst) > 0) { + bacmp(&conn->hcon->src, &conn->hcon->dst) > 0) { result = L2CAP_MR_COLLISION; goto send_move_response; } @@ -6438,7 +6436,7 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, if (hcon->type != ACL_LINK) goto drop; - chan = l2cap_global_chan_by_psm(0, psm, &conn->hcon->hdev->bdaddr, + chan = l2cap_global_chan_by_psm(0, psm, &conn->hcon->src, &conn->hcon->dst); if (!chan) goto drop; @@ -6468,8 +6466,7 @@ static void l2cap_att_channel(struct l2cap_conn *conn, goto drop; chan = l2cap_global_chan_by_scid(BT_CONNECTED, L2CAP_CID_ATT, - &conn->hcon->hdev->bdaddr, - &conn->hcon->dst); + &conn->hcon->src, &conn->hcon->dst); if (!chan) goto drop; -- cgit v1.2.3-73-gaa49b From c8462ca65f39d9402c52ef0c5f338a466bb34b43 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 05:24:02 -0700 Subject: Bluetooth: Fix input address type for SMP C1 function The smp_c1() so far always assumed public addresses as input for its operation. However it should provide actually the source address type of the actual connection. Finally the source address type is tracked in hci_conn->src_type and so use that one as input. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/smp.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index f57b20908ed5..112e58153f92 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -387,13 +387,13 @@ static void confirm_work(struct work_struct *work) smp->tfm = tfm; if (conn->hcon->out) - ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, 0, - &conn->hcon->src, conn->hcon->dst_type, - &conn->hcon->dst, res); + ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, + conn->hcon->src_type, &conn->hcon->src, + conn->hcon->dst_type, &conn->hcon->dst, res); else ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, - conn->hcon->dst_type, &conn->hcon->dst, 0, - &conn->hcon->src, res); + conn->hcon->dst_type, &conn->hcon->dst, + conn->hcon->src_type, &conn->hcon->src, res); if (ret) { reason = SMP_UNSPECIFIED; goto error; @@ -427,11 +427,13 @@ static void random_work(struct work_struct *work) BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); if (hcon->out) - ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, 0, - &hcon->src, hcon->dst_type, &hcon->dst, res); + ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, + hcon->src_type, &hcon->src, + hcon->dst_type, &hcon->dst, res); else ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, - hcon->dst_type, &hcon->dst, 0, &hcon->src, res); + hcon->dst_type, &hcon->dst, + hcon->src_type, &hcon->src, res); if (ret) { reason = SMP_UNSPECIFIED; goto error; -- cgit v1.2.3-73-gaa49b From f1560463ebb7d883be2f5e55e71f7e8b78c0ca1a Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 05:43:25 -0700 Subject: Bluetooth: Fix coding style violations in SMP handling The SMP source code has a few coding style violations. Fix them up all at once. No actual code has changed. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/smp.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 112e58153f92..463e50c58716 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -86,8 +86,8 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) } static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], - u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, - u8 _rat, bdaddr_t *ra, u8 res[16]) + u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, + u8 _rat, bdaddr_t *ra, u8 res[16]) { u8 p1[16], p2[16]; int err; @@ -127,8 +127,8 @@ static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], return err; } -static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], - u8 r1[16], u8 r2[16], u8 _r[16]) +static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16], + u8 r2[16], u8 _r[16]) { int err; @@ -151,7 +151,7 @@ static int smp_rand(u8 *buf) } static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code, - u16 dlen, void *data) + u16 dlen, void *data) { struct sk_buff *skb; struct l2cap_hdr *lh; @@ -214,9 +214,8 @@ static __u8 seclevel_to_authreq(__u8 sec_level) } static void build_pairing_cmd(struct l2cap_conn *conn, - struct smp_cmd_pairing *req, - struct smp_cmd_pairing *rsp, - __u8 authreq) + struct smp_cmd_pairing *req, + struct smp_cmd_pairing *rsp, __u8 authreq) { u8 dist_keys = 0; @@ -250,7 +249,7 @@ static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) struct smp_chan *smp = conn->smp_chan; if ((max_key_size > SMP_MAX_ENC_KEY_SIZE) || - (max_key_size < SMP_MIN_ENC_KEY_SIZE)) + (max_key_size < SMP_MIN_ENC_KEY_SIZE)) return SMP_ENC_KEY_SIZE; smp->enc_key_size = max_key_size; @@ -264,7 +263,7 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send) if (send) smp_send_cmd(conn, SMP_CMD_PAIRING_FAIL, sizeof(reason), - &reason); + &reason); clear_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags); mgmt_auth_failed(hcon->hdev, &hcon->dst, hcon->type, hcon->dst_type, @@ -310,8 +309,8 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, /* If either side has unknown io_caps, use JUST WORKS */ /* Otherwise, look up method from the table */ if (!(auth & SMP_AUTH_MITM) || - local_io > SMP_IO_KEYBOARD_DISPLAY || - remote_io > SMP_IO_KEYBOARD_DISPLAY) + local_io > SMP_IO_KEYBOARD_DISPLAY || + remote_io > SMP_IO_KEYBOARD_DISPLAY) method = JUST_WORKS; else method = gen_method[remote_io][local_io]; @@ -481,7 +480,7 @@ static void random_work(struct work_struct *work) swap128(key, stk); memset(stk + smp->enc_key_size, 0, - SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); + SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size, @@ -498,7 +497,7 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) { struct smp_chan *smp; - smp = kzalloc(sizeof(struct smp_chan), GFP_ATOMIC); + smp = kzalloc(sizeof(*smp), GFP_ATOMIC); if (!smp) return NULL; @@ -653,7 +652,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); if ((req->auth_req & SMP_AUTH_BONDING) && - (rsp->auth_req & SMP_AUTH_BONDING)) + (rsp->auth_req & SMP_AUTH_BONDING)) auth = SMP_AUTH_BONDING; auth |= (req->auth_req | rsp->auth_req) & SMP_AUTH_MITM; @@ -688,7 +687,7 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) swap128(smp->prnd, random); smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), - random); + random); } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) { queue_work(hdev->workqueue, &smp->confirm); } else { @@ -732,8 +731,8 @@ static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) hcon->enc_key_size = key->enc_size; return 1; - } + static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) { struct smp_cmd_security_req *rp = (void *) skb->data; @@ -1014,7 +1013,7 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) bacpy(&addrinfo.bdaddr, &conn->hcon->src); smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo), - &addrinfo); + &addrinfo); *keydist &= ~SMP_DIST_ID_KEY; } -- cgit v1.2.3-73-gaa49b From 4637f7c0d0e95361f25f456b34cc2138fdfe95f8 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 05:56:37 -0700 Subject: Bluetooth: Update L2CAP socket source address from HCI connection When having LE connections, the source address is not always the public address of the controller. So update the socket address based on the actual used source address of the HCI connection. This also remove the pointless source address pointer and adds a proper lock around the socket structure. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/l2cap_core.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 3ed9a2bf3d7c..062e28e4722b 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1756,17 +1756,16 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, bdaddr_t *dst, u8 dst_type) { struct sock *sk = chan->sk; - bdaddr_t *src = &bt_sk(sk)->src; struct l2cap_conn *conn; struct hci_conn *hcon; struct hci_dev *hdev; __u8 auth_type; int err; - BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", src, dst, + BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &bt_sk(sk)->src, dst, dst_type, __le16_to_cpu(psm)); - hdev = hci_get_route(dst, src); + hdev = hci_get_route(dst, &bt_sk(sk)->src); if (!hdev) return -EHOSTUNREACH; @@ -1858,7 +1857,9 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, } /* Update source addr of the socket */ - bacpy(src, &hdev->bdaddr); + lock_sock(sk); + bacpy(&bt_sk(sk)->src, &hcon->src); + release_sock(sk); l2cap_chan_unlock(chan); l2cap_chan_add(conn, chan); -- cgit v1.2.3-73-gaa49b From 7eafc59e2f547fce3a31b3e2d03c14d57e9162b2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 08:12:47 -0700 Subject: Bluetooth: Store address information in L2CAP channel structure With the effort of abstracting the L2CAP socket from the underlying L2CAP channel it is important to store the source and destination address information directly in the L2CAP channel structure. Direct access to the HCI connection address information is not possible since they might not be avaiable at L2CAP channel creation time. The address information will be updated when the underlying BR/EDR or LE connection status changes. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/l2cap.h | 2 ++ net/bluetooth/l2cap_core.c | 61 +++++++++++++++++-------------------------- net/bluetooth/l2cap_sock.c | 6 ++--- 3 files changed, 29 insertions(+), 40 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 1a929afe4f16..26b5066e74e2 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -444,6 +444,8 @@ struct l2cap_chan { __u8 state; + bdaddr_t dst; + bdaddr_t src; __le16 psm; __u16 dcid; __u16 scid; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 062e28e4722b..be3e0f8c6f8b 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -149,7 +149,7 @@ static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src) struct l2cap_chan *c; list_for_each_entry(c, &chan_list, global_l) { - if (c->sport == psm && !bacmp(&bt_sk(c->sk)->src, src)) + if (c->sport == psm && !bacmp(&c->src, src)) return c; } return NULL; @@ -621,10 +621,8 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) void l2cap_chan_close(struct l2cap_chan *chan, int reason) { struct l2cap_conn *conn = chan->conn; - struct sock *sk = chan->sk; - BT_DBG("chan %p state %s sk %p", chan, state_to_string(chan->state), - sk); + BT_DBG("chan %p state %s", chan, state_to_string(chan->state)); switch (chan->state) { case BT_LISTEN: @@ -635,6 +633,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) case BT_CONFIG: if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && conn->hcon->type == ACL_LINK) { + struct sock *sk = chan->sk; __set_chan_timer(chan, sk->sk_sndtimeo); l2cap_send_disconn_req(chan, reason); } else @@ -644,6 +643,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) case BT_CONNECT2: if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && conn->hcon->type == ACL_LINK) { + struct sock *sk = chan->sk; struct l2cap_conn_rsp rsp; __u16 result; @@ -1257,8 +1257,6 @@ static void l2cap_conn_start(struct l2cap_conn *conn) mutex_lock(&conn->chan_lock); list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { - struct sock *sk = chan->sk; - l2cap_chan_lock(chan); if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { @@ -1284,6 +1282,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) l2cap_start_connection(chan); } else if (chan->state == BT_CONNECT2) { + struct sock *sk = chan->sk; struct l2cap_conn_rsp rsp; char buf[128]; rsp.scid = cpu_to_le16(chan->dcid); @@ -1341,8 +1340,6 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, read_lock(&chan_list_lock); list_for_each_entry(c, &chan_list, global_l) { - struct sock *sk = c->sk; - if (state && c->state != state) continue; @@ -1351,16 +1348,16 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, int src_any, dst_any; /* Exact match. */ - src_match = !bacmp(&bt_sk(sk)->src, src); - dst_match = !bacmp(&bt_sk(sk)->dst, dst); + src_match = !bacmp(&c->src, src); + dst_match = !bacmp(&c->dst, dst); if (src_match && dst_match) { read_unlock(&chan_list_lock); return c; } /* Closest match */ - src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); - dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); + src_any = !bacmp(&c->src, BDADDR_ANY); + dst_any = !bacmp(&c->dst, BDADDR_ANY); if ((src_match && dst_any) || (src_any && dst_match) || (src_any && dst_any)) c1 = c; @@ -1399,8 +1396,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) chan->dcid = L2CAP_CID_ATT; - bacpy(&bt_sk(chan->sk)->src, &conn->hcon->src); - bacpy(&bt_sk(chan->sk)->dst, &conn->hcon->dst); + bacpy(&chan->src, &conn->hcon->src); + bacpy(&chan->dst, &conn->hcon->dst); __l2cap_chan_add(conn, chan); @@ -1721,8 +1718,6 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, read_lock(&chan_list_lock); list_for_each_entry(c, &chan_list, global_l) { - struct sock *sk = c->sk; - if (state && c->state != state) continue; @@ -1731,16 +1726,16 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, int src_any, dst_any; /* Exact match. */ - src_match = !bacmp(&bt_sk(sk)->src, src); - dst_match = !bacmp(&bt_sk(sk)->dst, dst); + src_match = !bacmp(&c->src, src); + dst_match = !bacmp(&c->dst, dst); if (src_match && dst_match) { read_unlock(&chan_list_lock); return c; } /* Closest match */ - src_any = !bacmp(&bt_sk(sk)->src, BDADDR_ANY); - dst_any = !bacmp(&bt_sk(sk)->dst, BDADDR_ANY); + src_any = !bacmp(&c->src, BDADDR_ANY); + dst_any = !bacmp(&c->dst, BDADDR_ANY); if ((src_match && dst_any) || (src_any && dst_match) || (src_any && dst_any)) c1 = c; @@ -1762,10 +1757,10 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, __u8 auth_type; int err; - BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &bt_sk(sk)->src, dst, + BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst, dst_type, __le16_to_cpu(psm)); - hdev = hci_get_route(dst, &bt_sk(sk)->src); + hdev = hci_get_route(dst, &chan->src); if (!hdev) return -EHOSTUNREACH; @@ -1822,9 +1817,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, } /* Set destination address and psm */ - lock_sock(sk); - bacpy(&bt_sk(sk)->dst, dst); - release_sock(sk); + bacpy(&chan->dst, dst); chan->psm = psm; chan->dcid = cid; @@ -1857,9 +1850,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, } /* Update source addr of the socket */ - lock_sock(sk); - bacpy(&bt_sk(sk)->src, &hcon->src); - release_sock(sk); + bacpy(&chan->src, &hcon->src); l2cap_chan_unlock(chan); l2cap_chan_add(conn, chan); @@ -3798,8 +3789,8 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, */ conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; - bacpy(&bt_sk(sk)->src, &conn->hcon->src); - bacpy(&bt_sk(sk)->dst, &conn->hcon->dst); + bacpy(&chan->src, &conn->hcon->src); + bacpy(&chan->dst, &conn->hcon->dst); chan->psm = psm; chan->dcid = scid; chan->local_amp_id = amp_id; @@ -6542,17 +6533,15 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) /* Find listening sockets and check their link_mode */ read_lock(&chan_list_lock); list_for_each_entry(c, &chan_list, global_l) { - struct sock *sk = c->sk; - if (c->state != BT_LISTEN) continue; - if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr)) { + if (!bacmp(&c->src, &hdev->bdaddr)) { lm1 |= HCI_LM_ACCEPT; if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) lm1 |= HCI_LM_MASTER; exact++; - } else if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { + } else if (!bacmp(&c->src, BDADDR_ANY)) { lm2 |= HCI_LM_ACCEPT; if (test_bit(FLAG_ROLE_SWITCH, &c->flags)) lm2 |= HCI_LM_MASTER; @@ -6840,10 +6829,8 @@ static int l2cap_debugfs_show(struct seq_file *f, void *p) read_lock(&chan_list_lock); list_for_each_entry(c, &chan_list, global_l) { - struct sock *sk = c->sk; - seq_printf(f, "%pMR %pMR %d %d 0x%4.4x 0x%4.4x %d %d %d %d\n", - &bt_sk(sk)->src, &bt_sk(sk)->dst, + &c->src, &c->dst, c->state, __le16_to_cpu(c->psm), c->scid, c->dcid, c->imtu, c->omtu, c->sec_level, c->mode); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index bd6fe7fd2737..9fe80d228c19 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -112,7 +112,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) break; } - bacpy(&bt_sk(sk)->src, &la.l2_bdaddr); + bacpy(&chan->src, &la.l2_bdaddr); chan->state = BT_BOUND; sk->sk_state = BT_BOUND; @@ -274,11 +274,11 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, if (peer) { la->l2_psm = chan->psm; - bacpy(&la->l2_bdaddr, &bt_sk(sk)->dst); + bacpy(&la->l2_bdaddr, &chan->dst); la->l2_cid = cpu_to_le16(chan->dcid); } else { la->l2_psm = chan->sport; - bacpy(&la->l2_bdaddr, &bt_sk(sk)->src); + bacpy(&la->l2_bdaddr, &chan->src); la->l2_cid = cpu_to_le16(chan->scid); } -- cgit v1.2.3-73-gaa49b From 4f1654e08464abad06487e173661cb73721d27a7 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 08:50:41 -0700 Subject: Bluetooth: Return the correct address type for L2CAP sockets The L2CAP sockets can use BR/EDR public, LE public and LE random addresses for various combinations of source and destination devices. So make sure that getsockname(), getpeername() and accept() return the correct address type. For this the address type of the source and destination is stored with the L2CAP channel information. The stored address type is not the one specific for the HCI protocol. It is the address type used for the L2CAP sockets and the management interface. The underlying HCI connections store the HCI address type. If needed, it gets converted to the socket address type. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/l2cap.h | 5 +++-- net/bluetooth/l2cap_core.c | 18 ++++++++++++++++++ net/bluetooth/l2cap_sock.c | 3 +++ 3 files changed, 24 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 26b5066e74e2..a27d51dc39a4 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -445,8 +445,11 @@ struct l2cap_chan { __u8 state; bdaddr_t dst; + __u8 dst_type; bdaddr_t src; + __u8 src_type; __le16 psm; + __le16 sport; __u16 dcid; __u16 scid; @@ -457,8 +460,6 @@ struct l2cap_chan { __u8 chan_type; __u8 chan_policy; - __le16 sport; - __u8 sec_level; __u8 ident; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index be3e0f8c6f8b..769c379b3eeb 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -59,6 +59,18 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err); static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, struct sk_buff_head *skbs, u8 event); +static inline __u8 bdaddr_type(struct hci_conn *hcon, __u8 type) +{ + if (hcon->type == LE_LINK) { + if (type == ADDR_LE_DEV_PUBLIC) + return BDADDR_LE_PUBLIC; + else + return BDADDR_LE_RANDOM; + } + + return BDADDR_BREDR; +} + /* ---- L2CAP channels ---- */ static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, @@ -1398,6 +1410,8 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) bacpy(&chan->src, &conn->hcon->src); bacpy(&chan->dst, &conn->hcon->dst); + chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); + chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); __l2cap_chan_add(conn, chan); @@ -1818,6 +1832,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, /* Set destination address and psm */ bacpy(&chan->dst, dst); + chan->dst_type = dst_type; chan->psm = psm; chan->dcid = cid; @@ -1851,6 +1866,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, /* Update source addr of the socket */ bacpy(&chan->src, &hcon->src); + chan->src_type = bdaddr_type(hcon, hcon->src_type); l2cap_chan_unlock(chan); l2cap_chan_add(conn, chan); @@ -3791,6 +3807,8 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, bacpy(&chan->src, &conn->hcon->src); bacpy(&chan->dst, &conn->hcon->dst); + chan->src_type = bdaddr_type(conn->hcon, conn->hcon->src_type); + chan->dst_type = bdaddr_type(conn->hcon, conn->hcon->dst_type); chan->psm = psm; chan->dcid = scid; chan->local_amp_id = amp_id; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 9fe80d228c19..6262e23b71a4 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -113,6 +113,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) } bacpy(&chan->src, &la.l2_bdaddr); + chan->src_type = la.l2_bdaddr_type; chan->state = BT_BOUND; sk->sk_state = BT_BOUND; @@ -276,10 +277,12 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, la->l2_psm = chan->psm; bacpy(&la->l2_bdaddr, &chan->dst); la->l2_cid = cpu_to_le16(chan->dcid); + la->l2_bdaddr_type = chan->dst_type; } else { la->l2_psm = chan->sport; bacpy(&la->l2_bdaddr, &chan->src); la->l2_cid = cpu_to_le16(chan->scid); + la->l2_bdaddr_type = chan->src_type; } return 0; -- cgit v1.2.3-73-gaa49b From 24bc10cad3a76a4fc0f96a7220d4fe02379826d2 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 09:49:54 -0700 Subject: Bluetooth: Access RFCOMM session addresses through L2CAP channel The L2CAP socket structure does not contain the address information anymore. They need to be accessed through the L2CAP channel. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/rfcomm/core.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index ca957d34b0c8..27e936a7ddd9 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -641,13 +641,13 @@ static struct rfcomm_session *rfcomm_session_get(bdaddr_t *src, bdaddr_t *dst) { struct rfcomm_session *s; struct list_head *p, *n; - struct bt_sock *sk; + struct l2cap_chan *chan; list_for_each_safe(p, n, &session_list) { s = list_entry(p, struct rfcomm_session, list); - sk = bt_sk(s->sock->sk); + chan = l2cap_pi(s->sock->sk)->chan; - if ((!bacmp(src, BDADDR_ANY) || !bacmp(&sk->src, src)) && - !bacmp(&sk->dst, dst)) + if ((!bacmp(src, BDADDR_ANY) || !bacmp(&chan->src, src)) && + !bacmp(&chan->dst, dst)) return s; } return NULL; @@ -732,11 +732,11 @@ failed: void rfcomm_session_getaddr(struct rfcomm_session *s, bdaddr_t *src, bdaddr_t *dst) { - struct sock *sk = s->sock->sk; + struct l2cap_chan *chan = l2cap_pi(s->sock->sk)->chan; if (src) - bacpy(src, &bt_sk(sk)->src); + bacpy(src, &chan->src); if (dst) - bacpy(dst, &bt_sk(sk)->dst); + bacpy(dst, &chan->dst); } /* ---- RFCOMM frame sending ---- */ @@ -2112,12 +2112,11 @@ static int rfcomm_dlc_debugfs_show(struct seq_file *f, void *x) rfcomm_lock(); list_for_each_entry(s, &session_list, list) { + struct l2cap_chan *chan = l2cap_pi(s->sock->sk)->chan; struct rfcomm_dlc *d; list_for_each_entry(d, &s->dlcs, list) { - struct sock *sk = s->sock->sk; - seq_printf(f, "%pMR %pMR %ld %d %d %d %d\n", - &bt_sk(sk)->src, &bt_sk(sk)->dst, + &chan->src, &chan->dst, d->state, d->dlci, d->mtu, d->rx_credits, d->tx_credits); } -- cgit v1.2.3-73-gaa49b From 88f1fd27080013c8216bc6ed26e3c9a184a78588 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 09:49:55 -0700 Subject: Bluetooth: Access CMTP session addresses through L2CAP channel The L2CAP socket structure does not contain the address information anymore. They need to be accessed through the L2CAP channel. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/cmtp/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index e0a6ebf2baa6..67fe5e84e68f 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c @@ -340,20 +340,20 @@ int cmtp_add_connection(struct cmtp_connadd_req *req, struct socket *sock) down_write(&cmtp_session_sem); - s = __cmtp_get_session(&bt_sk(sock->sk)->dst); + s = __cmtp_get_session(&l2cap_pi(sock->sk)->chan->dst); if (s && s->state == BT_CONNECTED) { err = -EEXIST; goto failed; } - bacpy(&session->bdaddr, &bt_sk(sock->sk)->dst); + bacpy(&session->bdaddr, &l2cap_pi(sock->sk)->chan->dst); session->mtu = min_t(uint, l2cap_pi(sock->sk)->chan->omtu, l2cap_pi(sock->sk)->chan->imtu); BT_DBG("mtu %d", session->mtu); - sprintf(session->name, "%pMR", &bt_sk(sock->sk)->dst); + sprintf(session->name, "%pMR", &session->bdaddr); session->sock = sock; session->state = BT_CONFIG; -- cgit v1.2.3-73-gaa49b From 755b82aa2fdb62a61990f6c132df150abd9e9206 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 09:49:56 -0700 Subject: Bluetooth: Access HIDP session addresses through L2CAP channel The L2CAP socket structure does not contain the address information anymore. They need to be accessed through the L2CAP channel. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/hidp/core.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index bdc35a7a7fee..292e619db896 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c @@ -767,10 +767,10 @@ static int hidp_setup_hid(struct hidp_session *session, strncpy(hid->name, req->name, sizeof(req->name) - 1); snprintf(hid->phys, sizeof(hid->phys), "%pMR", - &bt_sk(session->ctrl_sock->sk)->src); + &l2cap_pi(session->ctrl_sock->sk)->chan->src); snprintf(hid->uniq, sizeof(hid->uniq), "%pMR", - &bt_sk(session->ctrl_sock->sk)->dst); + &l2cap_pi(session->ctrl_sock->sk)->chan->dst); hid->dev.parent = &session->conn->hcon->dev; hid->ll_driver = &hidp_hid_driver; @@ -1283,23 +1283,29 @@ static int hidp_session_thread(void *arg) static int hidp_verify_sockets(struct socket *ctrl_sock, struct socket *intr_sock) { + struct l2cap_chan *ctrl_chan, *intr_chan; struct bt_sock *ctrl, *intr; struct hidp_session *session; if (!l2cap_is_socket(ctrl_sock) || !l2cap_is_socket(intr_sock)) return -EINVAL; + ctrl_chan = l2cap_pi(ctrl_sock->sk)->chan; + intr_chan = l2cap_pi(intr_sock->sk)->chan; + + if (bacmp(&ctrl_chan->src, &intr_chan->src) || + bacmp(&ctrl_chan->dst, &intr_chan->dst)) + return -ENOTUNIQ; + ctrl = bt_sk(ctrl_sock->sk); intr = bt_sk(intr_sock->sk); - if (bacmp(&ctrl->src, &intr->src) || bacmp(&ctrl->dst, &intr->dst)) - return -ENOTUNIQ; if (ctrl->sk.sk_state != BT_CONNECTED || intr->sk.sk_state != BT_CONNECTED) return -EBADFD; /* early session check, we check again during session registration */ - session = hidp_session_find(&ctrl->dst); + session = hidp_session_find(&ctrl_chan->dst); if (session) { hidp_session_put(session); return -EEXIST; @@ -1332,7 +1338,7 @@ int hidp_connection_add(struct hidp_connadd_req *req, if (!conn) return -EBADFD; - ret = hidp_session_new(&session, &bt_sk(ctrl_sock->sk)->dst, ctrl_sock, + ret = hidp_session_new(&session, &chan->dst, ctrl_sock, intr_sock, req, conn); if (ret) goto out_conn; -- cgit v1.2.3-73-gaa49b From 65f53e9802dbfae0e5758a91793c3f5f8bece49b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 09:49:57 -0700 Subject: Bluetooth: Access BNEP session addresses through L2CAP channel The L2CAP socket structure does not contain the address information anymore. They need to be accessed through the L2CAP channel. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/bnep/core.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index e430b1abcd2f..a841d3e776c5 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -32,6 +32,7 @@ #include #include +#include #include #include "bnep.h" @@ -510,20 +511,13 @@ static int bnep_session(void *arg) static struct device *bnep_get_device(struct bnep_session *session) { - bdaddr_t *src = &bt_sk(session->sock->sk)->src; - bdaddr_t *dst = &bt_sk(session->sock->sk)->dst; - struct hci_dev *hdev; struct hci_conn *conn; - hdev = hci_get_route(dst, src); - if (!hdev) + conn = l2cap_pi(session->sock->sk)->chan->conn->hcon; + if (!conn) return NULL; - conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); - - hci_dev_put(hdev); - - return conn ? &conn->dev : NULL; + return &conn->dev; } static struct device_type bnep_type = { @@ -539,8 +533,8 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) BT_DBG(""); - baswap((void *) dst, &bt_sk(sock->sk)->dst); - baswap((void *) src, &bt_sk(sock->sk)->src); + baswap((void *) dst, &l2cap_pi(sock->sk)->chan->dst); + baswap((void *) src, &l2cap_pi(sock->sk)->chan->src); /* session struct allocated as private part of net_device */ dev = alloc_netdev(sizeof(struct bnep_session), -- cgit v1.2.3-73-gaa49b From 041987cff6fb7d2e7acd5897390ad0eef575ed39 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 10:15:22 -0700 Subject: Bluetooth: Use SCO addresses from HCI connection directly Instead of storing a pointer to the addresses for the HCI device and HCI connection, use them directly. With the recent changes to address tracking of HCI connections, this becomes simple. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/sco.h | 3 --- net/bluetooth/sco.c | 20 ++++++++------------ 2 files changed, 8 insertions(+), 15 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/sco.h b/include/net/bluetooth/sco.h index e252a31ee6b6..94703a25d1c2 100644 --- a/include/net/bluetooth/sco.h +++ b/include/net/bluetooth/sco.h @@ -55,9 +55,6 @@ struct sco_conninfo { struct sco_conn { struct hci_conn *hcon; - bdaddr_t *dst; - bdaddr_t *src; - spinlock_t lock; struct sock *sk; diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 96bd388d93a4..2cc8f425613a 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -92,9 +92,6 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon) hcon->sco_data = conn; conn->hcon = hcon; - conn->src = &hdev->bdaddr; - conn->dst = &hcon->dst; - if (hdev->sco_mtu > 0) conn->mtu = hdev->sco_mtu; else @@ -156,16 +153,14 @@ static int sco_chan_add(struct sco_conn *conn, struct sock *sk, static int sco_connect(struct sock *sk) { - bdaddr_t *src = &bt_sk(sk)->src; - bdaddr_t *dst = &bt_sk(sk)->dst; struct sco_conn *conn; struct hci_conn *hcon; struct hci_dev *hdev; int err, type; - BT_DBG("%pMR -> %pMR", src, dst); + BT_DBG("%pMR -> %pMR", &bt_sk(sk)->src, &bt_sk(sk)->dst); - hdev = hci_get_route(dst, src); + hdev = hci_get_route(&bt_sk(sk)->dst, &bt_sk(sk)->src); if (!hdev) return -EHOSTUNREACH; @@ -182,7 +177,8 @@ static int sco_connect(struct sock *sk) goto done; } - hcon = hci_connect_sco(hdev, type, dst, sco_pi(sk)->setting); + hcon = hci_connect_sco(hdev, type, &bt_sk(sk)->dst, + sco_pi(sk)->setting); if (IS_ERR(hcon)) { err = PTR_ERR(hcon); goto done; @@ -196,7 +192,7 @@ static int sco_connect(struct sock *sk) } /* Update source addr of the socket */ - bacpy(src, conn->src); + bacpy(&bt_sk(sk)->src, &hcon->src); err = sco_chan_add(conn, sk, NULL); if (err) @@ -999,7 +995,7 @@ static void sco_conn_ready(struct sco_conn *conn) } else { sco_conn_lock(conn); - parent = sco_get_sock_listen(conn->src); + parent = sco_get_sock_listen(&conn->hcon->src); if (!parent) { sco_conn_unlock(conn); return; @@ -1017,8 +1013,8 @@ static void sco_conn_ready(struct sco_conn *conn) sco_sock_init(sk, parent); - bacpy(&bt_sk(sk)->src, conn->src); - bacpy(&bt_sk(sk)->dst, conn->dst); + bacpy(&bt_sk(sk)->src, &conn->hcon->src); + bacpy(&bt_sk(sk)->dst, &conn->hcon->dst); hci_conn_hold(conn->hcon); __sco_chan_add(conn, sk, parent); -- cgit v1.2.3-73-gaa49b From eea963641bf548bda164b92aa20ccda56c5cf349 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 10:34:01 -0700 Subject: Bluetooth: Store SCO address information in its own socket structure The address information of SCO sockets should be stored in its own socket structure. Trying to generalize them is not helpful since different transports have different address types. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/sco.h | 2 ++ net/bluetooth/sco.c | 36 ++++++++++++++++++------------------ 2 files changed, 20 insertions(+), 18 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/sco.h b/include/net/bluetooth/sco.h index 94703a25d1c2..2019d1a0996a 100644 --- a/include/net/bluetooth/sco.h +++ b/include/net/bluetooth/sco.h @@ -69,6 +69,8 @@ struct sco_conn { struct sco_pinfo { struct bt_sock bt; + bdaddr_t src; + bdaddr_t dst; __u32 flags; __u16 setting; struct sco_conn *conn; diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 2cc8f425613a..a92aebac56ca 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -158,9 +158,9 @@ static int sco_connect(struct sock *sk) struct hci_dev *hdev; int err, type; - BT_DBG("%pMR -> %pMR", &bt_sk(sk)->src, &bt_sk(sk)->dst); + BT_DBG("%pMR -> %pMR", &sco_pi(sk)->src, &sco_pi(sk)->dst); - hdev = hci_get_route(&bt_sk(sk)->dst, &bt_sk(sk)->src); + hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src); if (!hdev) return -EHOSTUNREACH; @@ -177,7 +177,7 @@ static int sco_connect(struct sock *sk) goto done; } - hcon = hci_connect_sco(hdev, type, &bt_sk(sk)->dst, + hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst, sco_pi(sk)->setting); if (IS_ERR(hcon)) { err = PTR_ERR(hcon); @@ -192,7 +192,7 @@ static int sco_connect(struct sock *sk) } /* Update source addr of the socket */ - bacpy(&bt_sk(sk)->src, &hcon->src); + bacpy(&sco_pi(sk)->src, &hcon->src); err = sco_chan_add(conn, sk, NULL); if (err) @@ -266,7 +266,7 @@ static struct sock *__sco_get_sock_listen_by_addr(bdaddr_t *ba) if (sk->sk_state != BT_LISTEN) continue; - if (!bacmp(&bt_sk(sk)->src, ba)) + if (!bacmp(&sco_pi(sk)->src, ba)) return sk; } @@ -287,11 +287,11 @@ static struct sock *sco_get_sock_listen(bdaddr_t *src) continue; /* Exact match. */ - if (!bacmp(&bt_sk(sk)->src, src)) + if (!bacmp(&sco_pi(sk)->src, src)) break; /* Closest match */ - if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) + if (!bacmp(&sco_pi(sk)->src, BDADDR_ANY)) sk1 = sk; } @@ -471,7 +471,7 @@ static int sco_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le goto done; } - bacpy(&bt_sk(sk)->src, &sa->sco_bdaddr); + bacpy(&sco_pi(sk)->src, &sa->sco_bdaddr); sk->sk_state = BT_BOUND; @@ -501,7 +501,7 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen lock_sock(sk); /* Set destination address and psm */ - bacpy(&bt_sk(sk)->dst, &sa->sco_bdaddr); + bacpy(&sco_pi(sk)->dst, &sa->sco_bdaddr); err = sco_connect(sk); if (err) @@ -518,7 +518,7 @@ done: static int sco_sock_listen(struct socket *sock, int backlog) { struct sock *sk = sock->sk; - bdaddr_t *src = &bt_sk(sk)->src; + bdaddr_t *src = &sco_pi(sk)->src; int err = 0; BT_DBG("sk %p backlog %d", sk, backlog); @@ -622,9 +622,9 @@ static int sco_sock_getname(struct socket *sock, struct sockaddr *addr, int *len *len = sizeof(struct sockaddr_sco); if (peer) - bacpy(&sa->sco_bdaddr, &bt_sk(sk)->dst); + bacpy(&sa->sco_bdaddr, &sco_pi(sk)->dst); else - bacpy(&sa->sco_bdaddr, &bt_sk(sk)->src); + bacpy(&sa->sco_bdaddr, &sco_pi(sk)->src); return 0; } @@ -1013,8 +1013,8 @@ static void sco_conn_ready(struct sco_conn *conn) sco_sock_init(sk, parent); - bacpy(&bt_sk(sk)->src, &conn->hcon->src); - bacpy(&bt_sk(sk)->dst, &conn->hcon->dst); + bacpy(&sco_pi(sk)->src, &conn->hcon->src); + bacpy(&sco_pi(sk)->dst, &conn->hcon->dst); hci_conn_hold(conn->hcon); __sco_chan_add(conn, sk, parent); @@ -1047,8 +1047,8 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) if (sk->sk_state != BT_LISTEN) continue; - if (!bacmp(&bt_sk(sk)->src, &hdev->bdaddr) || - !bacmp(&bt_sk(sk)->src, BDADDR_ANY)) { + if (!bacmp(&sco_pi(sk)->src, &hdev->bdaddr) || + !bacmp(&sco_pi(sk)->src, BDADDR_ANY)) { lm |= HCI_LM_ACCEPT; if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) @@ -1107,8 +1107,8 @@ static int sco_debugfs_show(struct seq_file *f, void *p) read_lock(&sco_sk_list.lock); sk_for_each(sk, &sco_sk_list.head) { - seq_printf(f, "%pMR %pMR %d\n", &bt_sk(sk)->src, - &bt_sk(sk)->dst, sk->sk_state); + seq_printf(f, "%pMR %pMR %d\n", &sco_pi(sk)->src, + &sco_pi(sk)->dst, sk->sk_state); } read_unlock(&sco_sk_list.lock); -- cgit v1.2.3-73-gaa49b From 94a86df01082557e2de45865e538d7fb6c46231c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 10:34:02 -0700 Subject: Bluetooth: Store RFCOMM address information in its own socket structure The address information of RFCOMM sockets should be stored in its own socket structure. Trying to generalize them is not helpful since different transports have different address types. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/rfcomm.h | 2 ++ net/bluetooth/rfcomm/sock.c | 28 +++++++++++++++------------- 2 files changed, 17 insertions(+), 13 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h index 7afd4199d6b6..3588f48bfd35 100644 --- a/include/net/bluetooth/rfcomm.h +++ b/include/net/bluetooth/rfcomm.h @@ -300,6 +300,8 @@ struct rfcomm_conninfo { struct rfcomm_pinfo { struct bt_sock bt; + bdaddr_t src; + bdaddr_t dst; struct rfcomm_dlc *dlc; u8 channel; u8 sec_level; diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 072938dc527d..df17276eb32b 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -87,7 +87,8 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err) parent->sk_data_ready(parent, 0); } else { if (d->state == BT_CONNECTED) - rfcomm_session_getaddr(d->session, &bt_sk(sk)->src, NULL); + rfcomm_session_getaddr(d->session, + &rfcomm_pi(sk)->src, NULL); sk->sk_state_change(sk); } @@ -110,7 +111,7 @@ static struct sock *__rfcomm_get_sock_by_addr(u8 channel, bdaddr_t *src) sk_for_each(sk, &rfcomm_sk_list.head) { if (rfcomm_pi(sk)->channel == channel && - !bacmp(&bt_sk(sk)->src, src)) + !bacmp(&rfcomm_pi(sk)->src, src)) break; } @@ -132,11 +133,11 @@ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t * if (rfcomm_pi(sk)->channel == channel) { /* Exact match. */ - if (!bacmp(&bt_sk(sk)->src, src)) + if (!bacmp(&rfcomm_pi(sk)->src, src)) break; /* Closest match */ - if (!bacmp(&bt_sk(sk)->src, BDADDR_ANY)) + if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY)) sk1 = sk; } } @@ -355,7 +356,7 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr err = -EADDRINUSE; } else { /* Save source address */ - bacpy(&bt_sk(sk)->src, &sa->rc_bdaddr); + bacpy(&rfcomm_pi(sk)->src, &sa->rc_bdaddr); rfcomm_pi(sk)->channel = sa->rc_channel; sk->sk_state = BT_BOUND; } @@ -393,13 +394,14 @@ static int rfcomm_sock_connect(struct socket *sock, struct sockaddr *addr, int a } sk->sk_state = BT_CONNECT; - bacpy(&bt_sk(sk)->dst, &sa->rc_bdaddr); + bacpy(&rfcomm_pi(sk)->dst, &sa->rc_bdaddr); rfcomm_pi(sk)->channel = sa->rc_channel; d->sec_level = rfcomm_pi(sk)->sec_level; d->role_switch = rfcomm_pi(sk)->role_switch; - err = rfcomm_dlc_open(d, &bt_sk(sk)->src, &sa->rc_bdaddr, sa->rc_channel); + err = rfcomm_dlc_open(d, &rfcomm_pi(sk)->src, &sa->rc_bdaddr, + sa->rc_channel); if (!err) err = bt_sock_wait_state(sk, BT_CONNECTED, sock_sndtimeo(sk, flags & O_NONBLOCK)); @@ -429,7 +431,7 @@ static int rfcomm_sock_listen(struct socket *sock, int backlog) } if (!rfcomm_pi(sk)->channel) { - bdaddr_t *src = &bt_sk(sk)->src; + bdaddr_t *src = &rfcomm_pi(sk)->src; u8 channel; err = -EINVAL; @@ -530,9 +532,9 @@ static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int * sa->rc_family = AF_BLUETOOTH; sa->rc_channel = rfcomm_pi(sk)->channel; if (peer) - bacpy(&sa->rc_bdaddr, &bt_sk(sk)->dst); + bacpy(&sa->rc_bdaddr, &rfcomm_pi(sk)->dst); else - bacpy(&sa->rc_bdaddr, &bt_sk(sk)->src); + bacpy(&sa->rc_bdaddr, &rfcomm_pi(sk)->src); *len = sizeof(struct sockaddr_rc); return 0; @@ -951,8 +953,8 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc * bt_sock_reclassify_lock(sk, BTPROTO_RFCOMM); rfcomm_sock_init(sk, parent); - bacpy(&bt_sk(sk)->src, &src); - bacpy(&bt_sk(sk)->dst, &dst); + bacpy(&rfcomm_pi(sk)->src, &src); + bacpy(&rfcomm_pi(sk)->dst, &dst); rfcomm_pi(sk)->channel = channel; sk->sk_state = BT_CONFIG; @@ -979,7 +981,7 @@ static int rfcomm_sock_debugfs_show(struct seq_file *f, void *p) sk_for_each(sk, &rfcomm_sk_list.head) { seq_printf(f, "%pMR %pMR %d %d\n", - &bt_sk(sk)->src, &bt_sk(sk)->dst, + &rfcomm_pi(sk)->src, &rfcomm_pi(sk)->dst, sk->sk_state, rfcomm_pi(sk)->channel); } -- cgit v1.2.3-73-gaa49b From 5f6cd79f477743cab98fd49feb03a39e0138b32f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 10:34:03 -0700 Subject: Bluetooth: Remove src and dst fields from bt_sock structure Every socket protocol now stores its own address information. So just remove the generic src and dst fields since they are no longer needed. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/bluetooth.h | 2 -- net/bluetooth/af_bluetooth.c | 4 +--- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 5fd510675cfa..1d6e484e08ef 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -218,8 +218,6 @@ void baswap(bdaddr_t *dst, bdaddr_t *src); struct bt_sock { struct sock sk; - bdaddr_t src; - bdaddr_t dst; struct list_head accept_q; struct sock *parent; unsigned long flags; diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index e6e1278dca89..9c7e4edc6504 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -617,15 +617,13 @@ static int bt_seq_show(struct seq_file *seq, void *v) struct bt_sock *bt = bt_sk(sk); seq_printf(seq, - "%pK %-6d %-6u %-6u %-6u %-6lu %pMR %pMR %-6lu", + "%pK %-6d %-6u %-6u %-6u %-6lu %-6lu", sk, atomic_read(&sk->sk_refcnt), sk_rmem_alloc_get(sk), sk_wmem_alloc_get(sk), from_kuid(seq_user_ns(seq), sock_i_uid(sk)), sock_i_ino(sk), - &bt->src, - &bt->dst, bt->parent? sock_i_ino(bt->parent): 0LU); if (l->custom_seq_show) { -- cgit v1.2.3-73-gaa49b From 84b34d9867f826caecaab4444c86438935b7eb2b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 11:36:07 -0700 Subject: Bluetooth: Use l2cap_pi(sk) directly where possible There are few places where it makes sense to use l2cap_pi(sk) directly instead of assigning it to temporary structure. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/l2cap_sock.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 6262e23b71a4..8fe9f497c645 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -976,13 +976,12 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan) static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) { - int err; struct sock *sk = chan->data; - struct l2cap_pinfo *pi = l2cap_pi(sk); + int err; lock_sock(sk); - if (pi->rx_busy_skb) { + if (l2cap_pi(sk)->rx_busy_skb) { err = -ENOMEM; goto done; } @@ -998,9 +997,9 @@ static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) * acked and reassembled until there is buffer space * available. */ - if (err < 0 && pi->chan->mode == L2CAP_MODE_ERTM) { - pi->rx_busy_skb = skb; - l2cap_chan_busy(pi->chan, 1); + if (err < 0 && chan->mode == L2CAP_MODE_ERTM) { + l2cap_pi(sk)->rx_busy_skb = skb; + l2cap_chan_busy(chan, 1); err = 0; } @@ -1128,6 +1127,7 @@ static void l2cap_sock_destruct(struct sock *sk) if (l2cap_pi(sk)->chan) l2cap_chan_put(l2cap_pi(sk)->chan); + if (l2cap_pi(sk)->rx_busy_skb) { kfree_skb(l2cap_pi(sk)->rx_busy_skb); l2cap_pi(sk)->rx_busy_skb = NULL; @@ -1139,8 +1139,7 @@ static void l2cap_sock_destruct(struct sock *sk) static void l2cap_sock_init(struct sock *sk, struct sock *parent) { - struct l2cap_pinfo *pi = l2cap_pi(sk); - struct l2cap_chan *chan = pi->chan; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; BT_DBG("sk %p", sk); -- cgit v1.2.3-73-gaa49b From d97636980f6ba7344c8aa6fa349b9059c60ee478 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 12:55:28 -0700 Subject: Bluetooth: Add support for per socket msg_name callback This allows to add a per socket msg_name callback that can be used for updating the msg_name information for recvmsg() system calls. This feature is used by another patch to support address information on L2CAP connectionless channels. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/bluetooth.h | 1 + net/bluetooth/af_bluetooth.c | 15 +++++++++++---- 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 1d6e484e08ef..896aad80bc4d 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -221,6 +221,7 @@ struct bt_sock { struct list_head accept_q; struct sock *parent; unsigned long flags; + void (*skb_msg_name)(struct sk_buff *, void *, int *); }; enum { diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 9c7e4edc6504..f0aadeac4455 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -221,12 +221,12 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, if (flags & (MSG_OOB)) return -EOPNOTSUPP; - msg->msg_namelen = 0; - skb = skb_recv_datagram(sk, flags, noblock, &err); if (!skb) { - if (sk->sk_shutdown & RCV_SHUTDOWN) + if (sk->sk_shutdown & RCV_SHUTDOWN) { + msg->msg_namelen = 0; return 0; + } return err; } @@ -238,9 +238,16 @@ int bt_sock_recvmsg(struct kiocb *iocb, struct socket *sock, skb_reset_transport_header(skb); err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); - if (err == 0) + if (err == 0) { sock_recv_ts_and_drops(msg, sk, skb); + if (bt_sk(sk)->skb_msg_name) + bt_sk(sk)->skb_msg_name(skb, msg->msg_name, + &msg->msg_namelen); + else + msg->msg_namelen = 0; + } + skb_free_datagram(sk, skb); return err ? : copied; -- cgit v1.2.3-73-gaa49b From 2edf870d198adeb43d5a2a5ddfa7e3cea4fc999b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 12:55:29 -0700 Subject: Bluetooth: Provide msg_name callback for L2CAP connectionless channels The L2CAP connectionless channels use SOCK_DGRAM and recvmsg() and need to receive the remote BD_ADDR and PSM information via msg_name from the recvmsg() system call. So in case the L2CAP socket is for connectionless channels, provide a msg_name callback that can update the data. Also store the remote BD_ADDR and PSM in the skb so it can be extracted later on. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/bluetooth.h | 2 ++ net/bluetooth/l2cap_core.c | 4 ++++ net/bluetooth/l2cap_sock.c | 15 ++++++++++++++- 3 files changed, 20 insertions(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index 896aad80bc4d..bf2ddffdae2d 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -284,6 +284,8 @@ struct bt_skb_cb { __u8 force_active; struct l2cap_ctrl control; struct hci_req_ctrl req; + bdaddr_t bdaddr; + __le16 psm; }; #define bt_cb(skb) ((struct bt_skb_cb *)((skb)->cb)) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 769c379b3eeb..f6b5f94cbf39 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -6459,6 +6459,10 @@ static void l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, if (chan->imtu < skb->len) goto drop; + /* Store remote BD_ADDR and PSM for msg_name */ + bacpy(&bt_cb(skb)->bdaddr, &conn->hcon->dst); + bt_cb(skb)->psm = psm; + if (!chan->ops->recv(chan, skb)) return; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 8fe9f497c645..f1b462faf649 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -1137,6 +1137,19 @@ static void l2cap_sock_destruct(struct sock *sk) skb_queue_purge(&sk->sk_write_queue); } +static void l2cap_skb_msg_name(struct sk_buff *skb, void *msg_name, + int *msg_namelen) +{ + struct sockaddr_l2 *la = (struct sockaddr_l2 *) msg_name; + + memset(la, 0, sizeof(struct sockaddr_l2)); + la->l2_family = AF_BLUETOOTH; + la->l2_psm = bt_cb(skb)->psm; + bacpy(&la->l2_bdaddr, &bt_cb(skb)->bdaddr); + + *msg_namelen = sizeof(struct sockaddr_l2); +} + static void l2cap_sock_init(struct sock *sk, struct sock *parent) { struct l2cap_chan *chan = l2cap_pi(sk)->chan; @@ -1163,13 +1176,13 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) security_sk_clone(parent, sk); } else { - switch (sk->sk_type) { case SOCK_RAW: chan->chan_type = L2CAP_CHAN_RAW; break; case SOCK_DGRAM: chan->chan_type = L2CAP_CHAN_CONN_LESS; + bt_sk(sk)->skb_msg_name = l2cap_skb_msg_name; break; case SOCK_SEQPACKET: case SOCK_STREAM: -- cgit v1.2.3-73-gaa49b From dcbc729eef18b93e689d853aa8ccc41549e7fd58 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sun, 13 Oct 2013 13:09:02 -0700 Subject: Bluetooth: Increase minor version of core module There have been a lot of changes in the core Bluetooth handling lately. So it is a good idea to increase the module version. The module version is not used anywhere, but it makes debugging a little bit simpler if versions can be distinguished. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/af_bluetooth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index f0aadeac4455..61501c9b34f6 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -30,7 +30,7 @@ #include #include -#define VERSION "2.16" +#define VERSION "2.17" /* Bluetooth sockets */ #define BT_MAX_PROTO 8 -- cgit v1.2.3-73-gaa49b From c56057557672b65c11e7f99c124670c2297743f0 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 14 Oct 2013 02:05:25 -0700 Subject: Bluetooth: Adjust header for proc socket information The exposed socket information do not contain source or destination addresses. So adjust the header accordingly. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/af_bluetooth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 61501c9b34f6..1f1a1118f489 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -611,7 +611,7 @@ static int bt_seq_show(struct seq_file *seq, void *v) struct bt_sock_list *l = s->l; if (v == SEQ_START_TOKEN) { - seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent"); + seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Parent"); if (l->custom_seq_show) { seq_putc(seq, ' '); -- cgit v1.2.3-73-gaa49b From bdc257830760a784370ae4ab2d682b252b983e77 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 14 Oct 2013 02:45:34 -0700 Subject: Bluetooth: Introduce L2CAP channel flag for defer setup The L2CAP core should not look into the socket flags to figure out the setting of defer setup. So introduce a L2CAP channel flag that mirrors the socket flag. Since the defer setup option is only set in one place this becomes a really easy thing to do. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/l2cap.h | 1 + net/bluetooth/l2cap_core.c | 15 +++++++-------- net/bluetooth/l2cap_sock.c | 7 +++++-- 3 files changed, 13 insertions(+), 10 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index a27d51dc39a4..1a38edee38e4 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -652,6 +652,7 @@ enum { FLAG_FLUSHABLE, FLAG_EXT_CTRL, FLAG_EFS_ENABLE, + FLAG_DEFER_SETUP, }; enum { diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index f6b5f94cbf39..e5819cb67372 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -655,14 +655,14 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) case BT_CONNECT2: if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && conn->hcon->type == ACL_LINK) { - struct sock *sk = chan->sk; struct l2cap_conn_rsp rsp; __u16 result; - if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) + if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) result = L2CAP_CR_SEC_BLOCK; else result = L2CAP_CR_BAD_PSM; + l2cap_state_change(chan, BT_DISCONN); rsp.scid = cpu_to_le16(chan->dcid); @@ -1294,16 +1294,16 @@ static void l2cap_conn_start(struct l2cap_conn *conn) l2cap_start_connection(chan); } else if (chan->state == BT_CONNECT2) { - struct sock *sk = chan->sk; struct l2cap_conn_rsp rsp; char buf[128]; rsp.scid = cpu_to_le16(chan->dcid); rsp.dcid = cpu_to_le16(chan->scid); if (l2cap_chan_check_security(chan)) { + struct sock *sk = chan->sk; + lock_sock(sk); - if (test_bit(BT_SK_DEFER_SETUP, - &bt_sk(sk)->flags)) { + if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); chan->ops->defer(chan); @@ -3823,7 +3823,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { if (l2cap_chan_check_security(chan)) { - if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { + if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { __l2cap_state_change(chan, BT_CONNECT2); result = L2CAP_CR_PEND; status = L2CAP_CS_AUTHOR_PEND; @@ -6693,8 +6693,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) lock_sock(sk); if (!status) { - if (test_bit(BT_SK_DEFER_SETUP, - &bt_sk(sk)->flags)) { + if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { res = L2CAP_CR_PEND; stat = L2CAP_CS_AUTHOR_PEND; chan->ops->defer(chan); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index f1b462faf649..f5d957328545 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -672,10 +672,13 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, break; } - if (opt) + if (opt) { set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); - else + set_bit(FLAG_DEFER_SETUP, &chan->flags); + } else { clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); + clear_bit(FLAG_DEFER_SETUP, &chan->flags); + } break; case BT_FLUSHABLE: -- cgit v1.2.3-73-gaa49b From d97c899bde330cd1c76c3a162558177563a74362 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 14 Oct 2013 02:53:54 -0700 Subject: Bluetooth: Introduce L2CAP channel callback for resuming Clearing the BT_SK_SUSPEND socket flag from the L2CAP core is causing a dependency on the socket. So intead of doing that, use a channel callback into the socket handling to resume. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- include/net/bluetooth/l2cap.h | 1 + net/bluetooth/l2cap_core.c | 6 +----- net/bluetooth/l2cap_sock.c | 9 +++++++++ 3 files changed, 11 insertions(+), 5 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 1a38edee38e4..07757a2af942 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -554,6 +554,7 @@ struct l2cap_ops { int state); void (*ready) (struct l2cap_chan *chan); void (*defer) (struct l2cap_chan *chan); + void (*resume) (struct l2cap_chan *chan); struct sk_buff *(*alloc_skb) (struct l2cap_chan *chan, unsigned long len, int nb); }; diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index e5819cb67372..0c3446da1ec9 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -6669,11 +6669,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) if (!status && (chan->state == BT_CONNECTED || chan->state == BT_CONFIG)) { - struct sock *sk = chan->sk; - - clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); - sk->sk_state_change(sk); - + chan->ops->resume(chan); l2cap_check_encryption(chan, encrypt); l2cap_chan_unlock(chan); continue; diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index f5d957328545..fcf012a422fd 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -1112,6 +1112,14 @@ static void l2cap_sock_defer_cb(struct l2cap_chan *chan) parent->sk_data_ready(parent, 0); } +static void l2cap_sock_resume_cb(struct l2cap_chan *chan) +{ + struct sock *sk = chan->data; + + clear_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); + sk->sk_state_change(sk); +} + static struct l2cap_ops l2cap_chan_ops = { .name = "L2CAP Socket Interface", .new_connection = l2cap_sock_new_connection_cb, @@ -1121,6 +1129,7 @@ static struct l2cap_ops l2cap_chan_ops = { .state_change = l2cap_sock_state_change_cb, .ready = l2cap_sock_ready_cb, .defer = l2cap_sock_defer_cb, + .resume = l2cap_sock_resume_cb, .alloc_skb = l2cap_sock_alloc_skb_cb, }; -- cgit v1.2.3-73-gaa49b From 9b74246f3a074b6072fa81002805ceaefb87a013 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 14 Oct 2013 16:20:03 +0300 Subject: Bluetooth: Reorganize set_connectable HCI command sending This patch moves all the decisions of which HCI commands to send (or not to send) to the code between hci_req_init() and hci_req_run() this allows us to further extend the request with further commands but still keep the same logic of handling whether to return a direct mgmt response in the case that no HCI commands were sent. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 020f95b84b09..cfd8d448c25b 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1144,30 +1144,29 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, goto failed; } - if (!!cp->val == test_bit(HCI_PSCAN, &hdev->flags)) { - err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev); - goto failed; - } - cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len); if (!cmd) { err = -ENOMEM; goto failed; } - if (cp->val) { - scan = SCAN_PAGE; - } else { - scan = 0; + hci_req_init(&req, hdev); - if (test_bit(HCI_ISCAN, &hdev->flags) && - hdev->discov_timeout > 0) - cancel_delayed_work(&hdev->discov_off); - } + if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags) && + cp->val != test_bit(HCI_PSCAN, &hdev->flags)) { - hci_req_init(&req, hdev); + if (cp->val) { + scan = SCAN_PAGE; + } else { + scan = 0; - hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); + if (test_bit(HCI_ISCAN, &hdev->flags) && + hdev->discov_timeout > 0) + cancel_delayed_work(&hdev->discov_off); + } + + hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); + } /* If we're going from non-connectable to connectable or * vice-versa when fast connectable is enabled ensure that fast @@ -1179,8 +1178,13 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, write_fast_connectable(&req, false); err = hci_req_run(&req, set_connectable_complete); - if (err < 0) + if (err < 0) { mgmt_pending_remove(cmd); + if (err == -ENODATA) + err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, + hdev); + goto failed; + } failed: hci_dev_unlock(hdev); -- cgit v1.2.3-73-gaa49b From d7b856f9380d95a9d663180701da904123c035b8 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 14 Oct 2013 16:20:04 +0300 Subject: Bluetooth: Move more logic into set_connectable complete callback This patch moves the responsibility of setting/clearing the HCI_CONNECTABLE flag to the request completion callback of the Set Connectable command. This will allow us to cleanly add support for LE Advertising hooks in later patches. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index cfd8d448c25b..8dcea7726f8d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1075,6 +1075,8 @@ static void write_fast_connectable(struct hci_request *req, bool enable) static void set_connectable_complete(struct hci_dev *hdev, u8 status) { struct pending_cmd *cmd; + struct mgmt_mode *cp; + bool changed; BT_DBG("status 0x%02x", status); @@ -1084,8 +1086,17 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status) if (!cmd) goto unlock; + cp = cmd->param; + if (cp->val) + changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags); + else + changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags); + send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev); + if (changed) + new_settings(hdev, cmd->sk); + mgmt_pending_remove(cmd); unlock: @@ -4053,10 +4064,16 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) int mgmt_connectable(struct hci_dev *hdev, u8 connectable) { - struct pending_cmd *cmd; bool changed = false; int err = 0; + /* Nothing needed here if there's a pending command since that + * commands request completion callback takes care of everything + * necessary. + */ + if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) + return 0; + if (connectable) { if (!test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags)) changed = true; @@ -4065,10 +4082,8 @@ int mgmt_connectable(struct hci_dev *hdev, u8 connectable) changed = true; } - cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev); - if (changed) - err = new_settings(hdev, cmd ? cmd->sk : NULL); + err = new_settings(hdev, NULL); return err; } -- cgit v1.2.3-73-gaa49b From 37438c1f7f6d26e1532d6bfc588c958b7dfae668 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 14 Oct 2013 16:20:05 +0300 Subject: Bluetooth: Add missing error handling for Set Connectable If the HCI commands related to the Set Connectable command fail we will get a non-zero status in the request completion callback. In such a case we must respond with the appropriate command status message to user space. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 8dcea7726f8d..a5c015cadd55 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1086,6 +1086,12 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status) if (!cmd) goto unlock; + if (status) { + u8 mgmt_err = mgmt_status(status); + cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); + goto remove_cmd; + } + cp = cmd->param; if (cp->val) changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags); @@ -1097,6 +1103,7 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status) if (changed) new_settings(hdev, cmd->sk); +remove_cmd: mgmt_pending_remove(cmd); unlock: -- cgit v1.2.3-73-gaa49b From 95c66e75baf34024213a779dac08f95e6b5aa6a4 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 14 Oct 2013 16:20:06 +0300 Subject: Bluetooth: Move static advertising functions to avoid forward declarations These functions will soon be used by set_connectable() so move them to a location in mgmt.c that doesn't require forward declarations. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 56 ++++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a5c015cadd55..caa552cf21f3 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1072,6 +1072,34 @@ static void write_fast_connectable(struct hci_request *req, bool enable) hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); } +static void enable_advertising(struct hci_request *req) +{ + struct hci_dev *hdev = req->hdev; + struct hci_cp_le_set_adv_param cp; + u8 enable = 0x01; + + memset(&cp, 0, sizeof(cp)); + cp.min_interval = __constant_cpu_to_le16(0x0800); + cp.max_interval = __constant_cpu_to_le16(0x0800); + cp.type = LE_ADV_IND; + if (bacmp(&hdev->bdaddr, BDADDR_ANY)) + cp.own_address_type = ADDR_LE_DEV_PUBLIC; + else + cp.own_address_type = ADDR_LE_DEV_RANDOM; + cp.channel_map = 0x07; + + hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp); + + hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); +} + +static void disable_advertising(struct hci_request *req) +{ + u8 enable = 0x00; + + hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); +} + static void set_connectable_complete(struct hci_dev *hdev, u8 status) { struct pending_cmd *cmd; @@ -1440,34 +1468,6 @@ unlock: return err; } -static void enable_advertising(struct hci_request *req) -{ - struct hci_dev *hdev = req->hdev; - struct hci_cp_le_set_adv_param cp; - u8 enable = 0x01; - - memset(&cp, 0, sizeof(cp)); - cp.min_interval = __constant_cpu_to_le16(0x0800); - cp.max_interval = __constant_cpu_to_le16(0x0800); - cp.type = LE_ADV_IND; - if (bacmp(&hdev->bdaddr, BDADDR_ANY)) - cp.own_address_type = ADDR_LE_DEV_PUBLIC; - else - cp.own_address_type = ADDR_LE_DEV_RANDOM; - cp.channel_map = 0x07; - - hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp); - - hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); -} - -static void disable_advertising(struct hci_request *req) -{ - u8 enable = 0x00; - - hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); -} - static void le_enable_complete(struct hci_dev *hdev, u8 status) { struct cmd_lookup match = { NULL, hdev }; -- cgit v1.2.3-73-gaa49b From c6d887aaf8f772fbe07604390975921ad3350a58 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 14 Oct 2013 16:20:07 +0300 Subject: Bluetooth: Fix updating advertising data needlessly We need to ensure that the advertising data is up-to-date whenever advertising is enabled, but when disabling advertising we do not need to worry about it (since it will eventually get fixed as soon as advertising is enabled again). This patch fixes this in the command complete callback for set_adv_enable. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_event.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index aa6fed3a553b..da2bc3d3d289 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -924,7 +924,7 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) clear_bit(HCI_ADVERTISING, &hdev->dev_flags); } - if (!test_bit(HCI_INIT, &hdev->flags)) { + if (*sent && !test_bit(HCI_INIT, &hdev->flags)) { struct hci_request req; hci_req_init(&req, hdev); -- cgit v1.2.3-73-gaa49b From 1987fdc77f49282efeec76d14eee2ded3ee9b5d2 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 14 Oct 2013 21:15:24 +0300 Subject: Bluetooth: Make Set Connectable also update the LE advertising type This patch updates the Set Connectable Management command to also update the LE advertising type to either connectable or non-connectable advertising. An extra helper function is needed for getting the right advertising type since we can not only rely on the HCI_CONNECTABLE flag but must also check for a pending Set Connectable command (in which case the flag does not yet have its final value). Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 35 ++++++++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 5 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index caa552cf21f3..a07b08156dba 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1072,6 +1072,25 @@ static void write_fast_connectable(struct hci_request *req, bool enable) hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); } +static u8 get_adv_type(struct hci_dev *hdev) +{ + struct pending_cmd *cmd; + bool connectable; + + /* If there's a pending mgmt command the flag will not yet have + * it's final value, so check for this first. + */ + cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev); + if (cmd) { + struct mgmt_mode *cp = cmd->param; + connectable = !!cp->val; + } else { + connectable = test_bit(HCI_CONNECTABLE, &hdev->dev_flags); + } + + return connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND; +} + static void enable_advertising(struct hci_request *req) { struct hci_dev *hdev = req->hdev; @@ -1081,7 +1100,7 @@ static void enable_advertising(struct hci_request *req) memset(&cp, 0, sizeof(cp)); cp.min_interval = __constant_cpu_to_le16(0x0800); cp.max_interval = __constant_cpu_to_le16(0x0800); - cp.type = LE_ADV_IND; + cp.type = get_adv_type(hdev); if (bacmp(&hdev->bdaddr, BDADDR_ANY)) cp.own_address_type = ADDR_LE_DEV_PUBLIC; else @@ -1144,15 +1163,15 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, struct mgmt_mode *cp = data; struct pending_cmd *cmd; struct hci_request req; - u8 scan, status; + u8 scan; int err; BT_DBG("request for %s", hdev->name); - status = mgmt_bredr_support(hdev); - if (status) + if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags) && + !test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, - status); + MGMT_STATUS_REJECTED); if (cp->val != 0x00 && cp->val != 0x01) return cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE, @@ -1223,6 +1242,12 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) write_fast_connectable(&req, false); + if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) && + hci_conn_num(hdev, LE_LINK) == 0) { + disable_advertising(&req); + enable_advertising(&req); + } + err = hci_req_run(&req, set_connectable_complete); if (err < 0) { mgmt_pending_remove(cmd); -- cgit v1.2.3-73-gaa49b From 67e5a7a3d796d88da9662ab90aa23161c6a9f753 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 14 Oct 2013 21:15:25 +0300 Subject: Bluetooth: Move set_bredr_scan() to avoid forward declaration The set_bredr_scan() function will soon be needed by the set_bredr() function, so move it to a new location to avoid having to add a forward declaration. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a07b08156dba..48aa23977da3 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3558,6 +3558,26 @@ unlock: return err; } +static void set_bredr_scan(struct hci_request *req) +{ + struct hci_dev *hdev = req->hdev; + u8 scan = 0; + + /* Ensure that fast connectable is disabled. This function will + * not do anything if the page scan parameters are already what + * they should be. + */ + write_fast_connectable(req, false); + + if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) + scan |= SCAN_PAGE; + if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) + scan |= SCAN_INQUIRY; + + if (scan) + hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); +} + static void set_bredr_complete(struct hci_dev *hdev, u8 status) { struct pending_cmd *cmd; @@ -3917,26 +3937,6 @@ void mgmt_index_removed(struct hci_dev *hdev) mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); } -static void set_bredr_scan(struct hci_request *req) -{ - struct hci_dev *hdev = req->hdev; - u8 scan = 0; - - /* Ensure that fast connectable is disabled. This function will - * not do anything if the page scan parameters are already what - * they should be. - */ - write_fast_connectable(req, false); - - if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) - scan |= SCAN_PAGE; - if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) - scan |= SCAN_INQUIRY; - - if (scan) - hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); -} - static void powered_complete(struct hci_dev *hdev, u8 status) { struct cmd_lookup match = { NULL, hdev }; -- cgit v1.2.3-73-gaa49b From aa8af46e90869686e1a2707d0803ea9445a643a3 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 14 Oct 2013 21:15:26 +0300 Subject: Bluetooth: Fix updating scan mode in set_bredr() Now that the connectable setting is also applicable for the LE side it's possible that the HCI_CONNECTABLE flag is already set when changing the BR/EDR setting from false to true while the controller is powered. In this situation we need to update the BR/EDR scan mode to reflect the setting. Additionally, since HCI_CONNECTABLE also applies to LE we must not clear the HCI_CONNECTABLE flag when disabling bredr. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 48aa23977da3..0bad451e5a90 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3640,7 +3640,6 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) if (!hdev_is_powered(hdev)) { if (!cp->val) { - clear_bit(HCI_CONNECTABLE, &hdev->dev_flags); clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); clear_bit(HCI_SSP_ENABLED, &hdev->dev_flags); clear_bit(HCI_LINK_SECURITY, &hdev->dev_flags); @@ -3683,7 +3682,12 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); hci_req_init(&req, hdev); + + if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) + set_bredr_scan(&req); + hci_update_ad(&req); + err = hci_req_run(&req, set_bredr_complete); if (err < 0) mgmt_pending_remove(cmd); -- cgit v1.2.3-73-gaa49b From bfaf8c9ff17a256fe435d452e8ff5a515155ee3b Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 14 Oct 2013 21:15:27 +0300 Subject: Bluetooth: Convert Set Discoverable to use an asynchronous request This patch converts Set Discoverable to use an asynchronous request along with its own completion callback. This is necessary for splitting raw HCI socket use cases from mgmt, as well as for enabling the hooking up of Advertising parameters together with the HCI_DISCOVERABLE flag (coming in later patches). Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 63 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 9 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 0bad451e5a90..813012f5032e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -935,11 +935,52 @@ static u8 mgmt_le_support(struct hci_dev *hdev) return MGMT_STATUS_SUCCESS; } +static void set_discoverable_complete(struct hci_dev *hdev, u8 status) +{ + struct pending_cmd *cmd; + struct mgmt_mode *cp; + bool changed; + + BT_DBG("status 0x%02x", status); + + hci_dev_lock(hdev); + + cmd = mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev); + if (!cmd) + goto unlock; + + if (status) { + u8 mgmt_err = mgmt_status(status); + cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err); + goto remove_cmd; + } + + cp = cmd->param; + if (cp->val) + changed = !test_and_set_bit(HCI_DISCOVERABLE, + &hdev->dev_flags); + else + changed = test_and_clear_bit(HCI_DISCOVERABLE, + &hdev->dev_flags); + + send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev); + + if (changed) + new_settings(hdev, cmd->sk); + +remove_cmd: + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock(hdev); +} + static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) { struct mgmt_cp_set_discoverable *cp = data; struct pending_cmd *cmd; + struct hci_request req; u16 timeout; u8 scan, status; int err; @@ -1021,6 +1062,8 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, goto failed; } + hci_req_init(&req, hdev); + scan = SCAN_PAGE; if (cp->val) @@ -1028,7 +1071,9 @@ static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data, else cancel_delayed_work(&hdev->discov_off); - err = hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); + hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); + + err = hci_req_run(&req, set_discoverable_complete); if (err < 0) mgmt_pending_remove(cmd); @@ -4074,10 +4119,16 @@ void mgmt_set_powered_failed(struct hci_dev *hdev, int err) int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) { - struct cmd_lookup match = { NULL, hdev }; bool changed = false; int err = 0; + /* Nothing needed here if there's a pending command since that + * commands request completion callback takes care of everything + * necessary. + */ + if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev)) + return 0; + if (discoverable) { if (!test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) changed = true; @@ -4086,14 +4137,8 @@ int mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) changed = true; } - mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, settings_rsp, - &match); - if (changed) - err = new_settings(hdev, match.sk); - - if (match.sk) - sock_put(match.sk); + err = new_settings(hdev, NULL); return err; } -- cgit v1.2.3-73-gaa49b From 80c1a2e76dbb36588facb265ab364b1302f7ef8c Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 14 Oct 2013 21:17:52 +0300 Subject: Bluetooth: Reject invalid bdaddr types for sockets We need to verify that the bdaddr type passed to connect() and bind() is within the set of valid values. If it is not we need to cleanly fail with EINVAL. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/l2cap_sock.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index fcf012a422fd..3f21207d59e5 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -69,6 +69,9 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) if (la.l2_cid && la.l2_psm) return -EINVAL; + if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) + return -EINVAL; + lock_sock(sk); if (sk->sk_state != BT_OPEN) { @@ -144,6 +147,9 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, if (la.l2_cid && la.l2_psm) return -EINVAL; + if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) + return -EINVAL; + err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid), &la.l2_bdaddr, la.l2_bdaddr_type); if (err) -- cgit v1.2.3-73-gaa49b From 1f209383f2be94e15e179da3a4cbcfeabcc2efc2 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Mon, 14 Oct 2013 21:17:53 +0300 Subject: Bluetooth: Check that bind() bdaddr type matches connect() If a socket was bound to an address type other than BR/EDR (such as LE) we should reject trying to connect it to a BR/EDR address. The same applies for binding to BR/EDR and trying to connect to non-BR/EDR. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/l2cap_sock.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 3f21207d59e5..5ffd75e20bde 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -150,6 +150,12 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) return -EINVAL; + if (chan->src_type == BDADDR_BREDR && la.l2_bdaddr_type != BDADDR_BREDR) + return -EINVAL; + + if (chan->src_type != BDADDR_BREDR && la.l2_bdaddr_type == BDADDR_BREDR) + return -EINVAL; + err = l2cap_chan_connect(chan, la.l2_psm, __le16_to_cpu(la.l2_cid), &la.l2_bdaddr, la.l2_bdaddr_type); if (err) -- cgit v1.2.3-73-gaa49b From 899e107577a8de67b97a877ed90bbfbfefb1916e Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 14 Oct 2013 09:55:32 -0700 Subject: Bluetooth: Check that scan window is smaller or equal than scan interval The scan window parameter for connection establishment and passive scanning needs to be smaller or equal than the scan interval. Instead of waiting for a controller to reject these values later on, just reject them right away. Signed-off-by: Marcel Holtmann Signed-off-by: Johan Hedberg --- net/bluetooth/mgmt.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 813012f5032e..861e389f4b4c 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3493,6 +3493,10 @@ static int set_scan_params(struct sock *sk, struct hci_dev *hdev, return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, MGMT_STATUS_INVALID_PARAMS); + if (window > interval) + return cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, + MGMT_STATUS_INVALID_PARAMS); + hci_dev_lock(hdev); hdev->le_scan_interval = interval; -- cgit v1.2.3-73-gaa49b From b4cb9fb25e9eae749f456e9e94446650389e736b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 14 Oct 2013 13:56:16 -0700 Subject: Bluetooth: Read number of supported IAC on controller setup When initializing a controller make sure to read out the number of supported IAC and store its result. This value is needed to determine if limited discoverable for BR/EDR can be configured or not. Signed-off-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci.h | 6 ++++++ include/net/bluetooth/hci_core.h | 1 + net/bluetooth/hci_core.c | 6 +++++- net/bluetooth/hci_event.c | 19 +++++++++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index c8a91cb20173..8567f44aa618 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -815,6 +815,12 @@ struct hci_cp_host_buffer_size { __le16 sco_max_pkt; } __packed; +#define HCI_OP_READ_NUM_SUPPORTED_IAC 0x0c38 +struct hci_rp_read_num_supported_iac { + __u8 status; + __u8 num_iac; +} __packed; + #define HCI_OP_WRITE_INQUIRY_MODE 0x0c45 #define HCI_MAX_EIR_LENGTH 240 diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 0326b160b89a..4e208420d84c 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -159,6 +159,7 @@ 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; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 0e05edee0962..b5ef05e66a2d 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -370,6 +370,9 @@ static void bredr_setup(struct hci_request *req) /* Read Voice Setting */ hci_req_add(req, HCI_OP_READ_VOICE_SETTING, 0, NULL); + /* Read Number of Supported IAC */ + hci_req_add(req, HCI_OP_READ_NUM_SUPPORTED_IAC, 0, NULL); + /* Clear Event Filters */ flt_type = HCI_FLT_CLEAR_ALL; hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type); @@ -2271,7 +2274,8 @@ struct hci_dev *hci_alloc_dev(void) hdev->pkt_type = (HCI_DM1 | HCI_DH1 | HCI_HV1); hdev->esco_type = (ESCO_HV1); hdev->link_mode = (HCI_LM_ACCEPT); - hdev->io_capability = 0x03; /* No Input No Output */ + hdev->num_iac = 0x01; /* One IAC support is mandatory */ + hdev->io_capability = 0x03; /* No Input No Output */ hdev->inq_tx_power = HCI_TX_POWER_INVALID; hdev->adv_tx_power = HCI_TX_POWER_INVALID; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index da2bc3d3d289..5391469ff1a5 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -418,6 +418,21 @@ static void hci_cc_write_voice_setting(struct hci_dev *hdev, hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING); } +static void hci_cc_read_num_supported_iac(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_rp_read_num_supported_iac *rp = (void *) skb->data; + + BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); + + if (rp->status) + return; + + hdev->num_iac = rp->num_iac; + + BT_DBG("%s num iac %d", hdev->name, hdev->num_iac); +} + static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) { __u8 status = *((__u8 *) skb->data); @@ -2135,6 +2150,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_cc_write_voice_setting(hdev, skb); break; + case HCI_OP_READ_NUM_SUPPORTED_IAC: + hci_cc_read_num_supported_iac(hdev, skb); + break; + case HCI_OP_WRITE_SSP_MODE: hci_cc_write_ssp_mode(hdev, skb); break; -- cgit v1.2.3-73-gaa49b From 4b836f393bd8ed111857a6ee1865e44627266ec6 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 14 Oct 2013 14:06:36 -0700 Subject: Bluetooth: Read current IAC LAP on controller setup Read the current IAC LAP values when initializing the controller. The values are not used, but it is good to have them in the trace files for debugging purposes. Signed-off-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- include/net/bluetooth/hci.h | 2 ++ net/bluetooth/hci_core.c | 3 +++ 2 files changed, 5 insertions(+) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 8567f44aa618..b096f5f73789 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -821,6 +821,8 @@ struct hci_rp_read_num_supported_iac { __u8 num_iac; } __packed; +#define HCI_OP_READ_CURRENT_IAC_LAP 0x0c39 + #define HCI_OP_WRITE_INQUIRY_MODE 0x0c45 #define HCI_MAX_EIR_LENGTH 240 diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index b5ef05e66a2d..7add9c96e32c 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -373,6 +373,9 @@ static void bredr_setup(struct hci_request *req) /* Read Number of Supported IAC */ hci_req_add(req, HCI_OP_READ_NUM_SUPPORTED_IAC, 0, NULL); + /* Read Current IAC LAP */ + hci_req_add(req, HCI_OP_READ_CURRENT_IAC_LAP, 0, NULL); + /* Clear Event Filters */ flt_type = HCI_FLT_CLEAR_ALL; hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type); -- cgit v1.2.3-73-gaa49b