From 57f5d0d1d9f8e59819cb0ab4b707364c54b5b2d1 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 27 Jul 2012 19:32:54 -0300 Subject: Bluetooth: Remove some functions from being exported Some connection related functions are only used inside hci_conn.c so no need to have them exported. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 5ad7da21747..724eea98081 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -59,7 +59,7 @@ static void hci_le_connect_cancel(struct hci_conn *conn) hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL); } -void hci_acl_connect(struct hci_conn *conn) +static void hci_acl_connect(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; struct inquiry_entry *ie; @@ -129,7 +129,7 @@ void hci_acl_disconn(struct hci_conn *conn, __u8 reason) hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp); } -void hci_add_sco(struct hci_conn *conn, __u16 handle) +static void hci_add_sco(struct hci_conn *conn, __u16 handle) { struct hci_dev *hdev = conn->hdev; struct hci_cp_add_sco cp; -- cgit v1.2.3 From 1aef866968223ddfd7268457b642a9233f0b8006 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 27 Jul 2012 19:32:55 -0300 Subject: Bluetooth: Rename LE and ACL connection functions These names were causing much confusion, so we rename these functions that send HCI commands to be more similar in naming to the actual HCI commands that will be sent. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 724eea98081..c30c507345f 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -30,7 +30,7 @@ #include #include -static void hci_le_connect(struct hci_conn *conn) +static void hci_le_create_connection(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; struct hci_cp_le_create_conn cp; @@ -54,12 +54,12 @@ static void hci_le_connect(struct hci_conn *conn) hci_send_cmd(hdev, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); } -static void hci_le_connect_cancel(struct hci_conn *conn) +static void hci_le_create_connection_cancel(struct hci_conn *conn) { hci_send_cmd(conn->hdev, HCI_OP_LE_CREATE_CONN_CANCEL, 0, NULL); } -static void hci_acl_connect(struct hci_conn *conn) +static void hci_acl_create_connection(struct hci_conn *conn) { struct hci_dev *hdev = conn->hdev; struct inquiry_entry *ie; @@ -103,7 +103,7 @@ static void hci_acl_connect(struct hci_conn *conn) hci_send_cmd(hdev, HCI_OP_CREATE_CONN, sizeof(cp), &cp); } -static void hci_acl_connect_cancel(struct hci_conn *conn) +static void hci_acl_create_connection_cancel(struct hci_conn *conn) { struct hci_cp_create_conn_cancel cp; @@ -245,9 +245,9 @@ static void hci_conn_timeout(struct work_struct *work) case BT_CONNECT2: if (conn->out) { if (conn->type == ACL_LINK) - hci_acl_connect_cancel(conn); + hci_acl_create_connection_cancel(conn); else if (conn->type == LE_LINK) - hci_le_connect_cancel(conn); + hci_le_create_connection_cancel(conn); } break; case BT_CONFIG: @@ -494,7 +494,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, return ERR_PTR(-ENOMEM); le->dst_type = bdaddr_to_le(dst_type); - hci_le_connect(le); + hci_le_create_connection(le); } le->pending_sec_level = sec_level; @@ -518,7 +518,7 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, acl->sec_level = BT_SECURITY_LOW; acl->pending_sec_level = sec_level; acl->auth_type = auth_type; - hci_acl_connect(acl); + hci_acl_create_connection(acl); } if (type == ACL_LINK) @@ -771,7 +771,7 @@ void hci_conn_check_pending(struct hci_dev *hdev) conn = hci_conn_hash_lookup_state(hdev, ACL_LINK, BT_CONNECT2); if (conn) - hci_acl_connect(conn); + hci_acl_create_connection(conn); hci_dev_unlock(hdev); } -- cgit v1.2.3 From d04aef4cccf203fdfd1716e9ba458060cbab0928 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 27 Jul 2012 19:32:56 -0300 Subject: Bluetooth: Refactor LE connection into its own function The code that handles LE connection is already quite separated from the rest of the connection procedure, so we can easily put it into its own. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 53 ++++++++++++++++++++++++++---------------------- 1 file changed, 29 insertions(+), 24 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index c30c507345f..0a74399dde5 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -470,6 +470,33 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) } 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; + + 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) + return ERR_PTR(-EBUSY); + + le = hci_conn_add(hdev, LE_LINK, dst); + if (!le) + return ERR_PTR(-ENOMEM); + + le->dst_type = bdaddr_to_le(dst_type); + hci_le_create_connection(le); + } + + le->pending_sec_level = sec_level; + le->auth_type = auth_type; + + hci_conn_hold(le); + + return le; +} + /* Create SCO, ACL or LE connection. * Device _must_ be locked */ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, @@ -477,33 +504,11 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, { struct hci_conn *acl; struct hci_conn *sco; - struct hci_conn *le; BT_DBG("%s dst %s", hdev->name, batostr(dst)); - if (type == LE_LINK) { - 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) - return ERR_PTR(-EBUSY); - - le = hci_conn_add(hdev, LE_LINK, dst); - if (!le) - return ERR_PTR(-ENOMEM); - - le->dst_type = bdaddr_to_le(dst_type); - hci_le_create_connection(le); - } - - le->pending_sec_level = sec_level; - le->auth_type = auth_type; - - hci_conn_hold(le); - - return le; - } + if (type == LE_LINK) + return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); if (!acl) { -- cgit v1.2.3 From db4742756ae2a836618cd5acf599522573589149 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Sat, 28 Jul 2012 22:35:59 -0300 Subject: Bluetooth: Refactor ACL connection into its own function The hci_connect() function was starting to get too complicated to be quickly understood. We can separate the creation of a new ACL connection into its own function. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 0a74399dde5..1d70e9fc7a4 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -497,18 +497,10 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, return le; } -/* Create SCO, ACL or LE connection. - * Device _must_ be locked */ -struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, - __u8 dst_type, __u8 sec_level, __u8 auth_type) +static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, + u8 sec_level, u8 auth_type) { struct hci_conn *acl; - struct hci_conn *sco; - - BT_DBG("%s dst %s", hdev->name, batostr(dst)); - - if (type == LE_LINK) - return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); if (!acl) { @@ -526,6 +518,26 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, hci_acl_create_connection(acl); } + return acl; +} + +/* Create SCO, ACL or LE connection. + * Device _must_ be locked */ +struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, + __u8 dst_type, __u8 sec_level, __u8 auth_type) +{ + struct hci_conn *acl; + struct hci_conn *sco; + + BT_DBG("%s dst %s", hdev->name, batostr(dst)); + + if (type == LE_LINK) + return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); + + acl = hci_connect_acl(hdev, dst, sec_level, auth_type); + if (IS_ERR(acl)) + return acl; + if (type == ACL_LINK) return acl; -- cgit v1.2.3 From b7d839bfff78a01705f3d7b0acd5257dc7b067c9 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 27 Jul 2012 19:32:58 -0300 Subject: Bluetooth: Refactor SCO connection into its own function We can do the same that we did for the other link types, for SCO connections. The only thing that's worth noting is that as SCO links need an ACL link, this functions uses the function that adds an ACL link. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 1d70e9fc7a4..de7df88a396 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -521,29 +521,19 @@ static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, return acl; } -/* Create SCO, ACL or LE connection. - * Device _must_ be locked */ -struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, - __u8 dst_type, __u8 sec_level, __u8 auth_type) +static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, bdaddr_t *dst, + u8 sec_level, u8 auth_type) { struct hci_conn *acl; struct hci_conn *sco; - BT_DBG("%s dst %s", hdev->name, batostr(dst)); - - if (type == LE_LINK) - return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); - acl = hci_connect_acl(hdev, dst, sec_level, auth_type); if (IS_ERR(acl)) return acl; - if (type == ACL_LINK) - return acl; - - sco = hci_conn_hash_lookup_ba(hdev, type, dst); + sco = hci_conn_hash_lookup_ba(hdev, SCO_LINK, dst); if (!sco) { - sco = hci_conn_add(hdev, type, dst); + sco = hci_conn_add(hdev, SCO_LINK, dst); if (!sco) { hci_conn_put(acl); return ERR_PTR(-ENOMEM); @@ -572,6 +562,21 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, return sco; } +/* Create SCO, ACL or LE connection. */ +struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, + __u8 dst_type, __u8 sec_level, __u8 auth_type) +{ + BT_DBG("%s dst %s", hdev->name, batostr(dst)); + + if (type == LE_LINK) + return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); + + if (type == ACL_LINK) + return hci_connect_acl(hdev, dst, sec_level, auth_type); + + return hci_connect_sco(hdev, dst, sec_level, auth_type); +} + /* Check link security requirement */ int hci_conn_check_link_mode(struct hci_conn *conn) { -- cgit v1.2.3 From 4cd2d98340b4f03d5532c30fdaeb451b035429cb Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 27 Jul 2012 19:32:59 -0300 Subject: Bluetooth: Simplify a the connection type handling Now that we have separate ways of doing connections for each link type, we can do better than an "if" statement to handle each link type. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index de7df88a396..2e7b7765e0e 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -568,13 +568,16 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, { BT_DBG("%s dst %s", hdev->name, batostr(dst)); - if (type == LE_LINK) + switch (type) { + case LE_LINK: return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); - - if (type == ACL_LINK) + case ACL_LINK: return hci_connect_acl(hdev, dst, sec_level, auth_type); + case SCO_LINK: + return hci_connect_sco(hdev, dst, sec_level, auth_type); + } - return hci_connect_sco(hdev, dst, sec_level, auth_type); + return ERR_PTR(-EINVAL); } /* Check link security requirement */ -- cgit v1.2.3 From e6dd548b9a3c7b3fcdd2fd97880abf7597e8334b Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 27 Jul 2012 19:33:00 -0300 Subject: Bluetooth: Add type information to the hci_connect() debug statement Now that we have a "connect" function for each link type, we should be able to indentify which function is going to be called. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 2e7b7765e0e..98670b1df17 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -566,7 +566,7 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, bdaddr_t *dst, struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 dst_type, __u8 sec_level, __u8 auth_type) { - BT_DBG("%s dst %s", hdev->name, batostr(dst)); + BT_DBG("%s dst %s type 0x%x", hdev->name, batostr(dst), type); switch (type) { case LE_LINK: -- cgit v1.2.3 From 09d5d4aa647367eeb42352a2bc9d438b9c703670 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Tue, 7 Aug 2012 18:05:04 +0300 Subject: Bluetooth: trivial: Shorten variable scope Make code more clear by moving sk and bt vars to the place where they are actually used. Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/af_bluetooth.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 58f9762b339..1b88fe41f4b 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -567,8 +567,6 @@ static void bt_seq_stop(struct seq_file *seq, void *v) static int bt_seq_show(struct seq_file *seq, void *v) { - struct sock *sk; - struct bt_sock *bt; struct bt_seq_state *s = seq->private; struct bt_sock_list *l = s->l; bdaddr_t src_baswapped, dst_baswapped; @@ -583,8 +581,8 @@ static int bt_seq_show(struct seq_file *seq, void *v) seq_putc(seq, '\n'); } else { - sk = sk_entry(v); - bt = bt_sk(sk); + struct sock *sk = sk_entry(v); + struct bt_sock *bt = bt_sk(sk); baswap(&src_baswapped, &bt->src); baswap(&dst_baswapped, &bt->dst); -- cgit v1.2.3 From 31f470738bf9fefc9399a45710c74322121119ac Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Tue, 7 Aug 2012 18:05:06 +0300 Subject: Bluetooth: trivial: Use preferred method for NULL check Use standard bluetooth way to check NULL pointer !var instead of var == NULL. Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/af_bluetooth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 1b88fe41f4b..9d49ee6d721 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c @@ -622,7 +622,7 @@ static int bt_seq_open(struct inode *inode, struct file *file) sk_list = PDE(inode)->data; s = __seq_open_private(file, &bt_seq_ops, sizeof(struct bt_seq_state)); - if (s == NULL) + if (!s) return -ENOMEM; s->l = sk_list; @@ -644,7 +644,7 @@ int bt_procfs_init(struct module* module, struct net *net, const char *name, sk_list->fops.release = seq_release_private; pde = proc_net_fops_create(net, name, 0, &sk_list->fops); - if (pde == NULL) + if (!pde) return -ENOMEM; pde->data = sk_list; -- cgit v1.2.3 From fa1bd91809d58b3c183611556219fafd93c08625 Mon Sep 17 00:00:00 2001 From: Mikel Astiz Date: Thu, 9 Aug 2012 09:52:29 +0200 Subject: Bluetooth: Fix minor coding style in hci_event.c Replace the status checks with the short form of the boolean expression. Signed-off-by: Mikel Astiz Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 32e21ad36a6..bfa9bcc0f5e 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -303,7 +303,7 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) hci_dev_lock(hdev); - if (status != 0) { + if (status) { mgmt_write_scan_failed(hdev, param, status); hdev->discov_timeout = 0; goto done; @@ -925,7 +925,7 @@ static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) if (test_bit(HCI_MGMT, &hdev->dev_flags)) mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status); - if (rp->status != 0) + if (rp->status) goto unlock; cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY); @@ -1893,7 +1893,7 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && (conn->type == ACL_LINK || conn->type == LE_LINK)) { - if (ev->status != 0) + if (ev->status) mgmt_disconnect_failed(hdev, &conn->dst, conn->type, conn->dst_type, ev->status); else @@ -3262,7 +3262,7 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev, * initiated the authentication. A traditional auth_complete * event gets always produced as initiator and is also mapped to * the mgmt_auth_failed event */ - if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status != 0) + if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && ev->status) mgmt_auth_failed(hdev, &conn->dst, conn->type, conn->dst_type, ev->status); -- cgit v1.2.3 From f0d6a0ea330617454032d6e2ed48759858a44427 Mon Sep 17 00:00:00 2001 From: Mikel Astiz Date: Thu, 9 Aug 2012 09:52:30 +0200 Subject: Bluetooth: mgmt: Add device disconnect reason MGMT_EV_DEVICE_DISCONNECTED will now expose the disconnection reason to userland, distinguishing four possible values: 0x00 Reason not known or unspecified 0x01 Connection timeout 0x02 Connection terminated by local host 0x03 Connection terminated by remote host Note that the local/remote distinction just determines which side terminated the low-level connection, regardless of the disconnection of the higher-level profiles. This can sometimes be misleading and thus must be used with care. For example, some hardware combinations would report a locally initiated disconnection even if the user turned Bluetooth off in the remote side. Signed-off-by: Mikel Astiz Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 26 +++++++++++++++++++++++--- net/bluetooth/mgmt.c | 9 +++++---- 2 files changed, 28 insertions(+), 7 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index bfa9bcc0f5e..48d730228c2 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -29,6 +29,7 @@ #include #include +#include /* Handle HCI Event packets */ @@ -1875,6 +1876,22 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) } } +static u8 hci_to_mgmt_reason(u8 err) +{ + switch (err) { + case HCI_ERROR_CONNECTION_TIMEOUT: + return MGMT_DEV_DISCONN_TIMEOUT; + case HCI_ERROR_REMOTE_USER_TERM: + case HCI_ERROR_REMOTE_LOW_RESOURCES: + case HCI_ERROR_REMOTE_POWER_OFF: + return MGMT_DEV_DISCONN_REMOTE; + case HCI_ERROR_LOCAL_HOST_TERM: + return MGMT_DEV_DISCONN_LOCAL_HOST; + default: + return MGMT_DEV_DISCONN_UNKNOWN; + } +} + static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_disconn_complete *ev = (void *) skb->data; @@ -1893,12 +1910,15 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags) && (conn->type == ACL_LINK || conn->type == LE_LINK)) { - if (ev->status) + if (ev->status) { mgmt_disconnect_failed(hdev, &conn->dst, conn->type, conn->dst_type, ev->status); - else + } else { + u8 reason = hci_to_mgmt_reason(ev->reason); + mgmt_device_disconnected(hdev, &conn->dst, conn->type, - conn->dst_type); + conn->dst_type, reason); + } } if (ev->status == 0) { diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a3329cbd3e4..05d4b83a018 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -3077,16 +3077,17 @@ static void unpair_device_rsp(struct pending_cmd *cmd, void *data) } int mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, - u8 link_type, u8 addr_type) + u8 link_type, u8 addr_type, u8 reason) { - struct mgmt_addr_info ev; + struct mgmt_ev_device_disconnected ev; struct sock *sk = NULL; int err; mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk); - bacpy(&ev.bdaddr, bdaddr); - ev.type = link_to_bdaddr(link_type, addr_type); + bacpy(&ev.addr.bdaddr, 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); -- cgit v1.2.3 From ab19516a50b375c11b9fa442954a43454a730950 Mon Sep 17 00:00:00 2001 From: Syam Sidhardhan Date: Fri, 27 Jul 2012 23:51:22 +0530 Subject: Bluetooth: debug: Correct the PSM printing Earlier we were printing chan->psm before assigning any value. Signed-off-by: Syam Sidhardhan Acked-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- 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 9f8b29ef5b6..dae895e3ca7 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1446,7 +1446,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, int err; BT_DBG("%s -> %s (type %u) psm 0x%2.2x", batostr(src), batostr(dst), - dst_type, __le16_to_cpu(chan->psm)); + dst_type, __le16_to_cpu(psm)); hdev = hci_get_route(dst, src); if (!hdev) -- cgit v1.2.3 From 144ad33020a0af66fbb188ef3f13ca91c5326a69 Mon Sep 17 00:00:00 2001 From: Syam Sidhardhan Date: Fri, 27 Jul 2012 23:51:21 +0530 Subject: Bluetooth: Use kref for l2cap channel reference counting This patch changes the struct l2cap_chan and associated code to use kref api for object refcounting and freeing. Suggested-by: Andrei Emeltchenko Signed-off-by: Jaganath Kanakkassery Signed-off-by: Syam Sidhardhan Signed-off-by: Gustavo Padovan --- net/bluetooth/l2cap_core.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index dae895e3ca7..9732f03cfbe 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -406,7 +406,7 @@ struct l2cap_chan *l2cap_chan_create(void) chan->state = BT_OPEN; - atomic_set(&chan->refcnt, 1); + kref_init(&chan->kref); /* This flag is cleared in l2cap_chan_ready() */ set_bit(CONF_NOT_COMPLETE, &chan->conf_state); @@ -416,8 +416,10 @@ struct l2cap_chan *l2cap_chan_create(void) return chan; } -static void l2cap_chan_destroy(struct l2cap_chan *chan) +static void l2cap_chan_destroy(struct kref *kref) { + struct l2cap_chan *chan = container_of(kref, struct l2cap_chan, kref); + BT_DBG("chan %p", chan); write_lock(&chan_list_lock); @@ -429,17 +431,16 @@ static void l2cap_chan_destroy(struct l2cap_chan *chan) void l2cap_chan_hold(struct l2cap_chan *c) { - BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); + BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); - atomic_inc(&c->refcnt); + kref_get(&c->kref); } void l2cap_chan_put(struct l2cap_chan *c) { - BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); + BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->kref.refcount)); - if (atomic_dec_and_test(&c->refcnt)) - l2cap_chan_destroy(c); + kref_put(&c->kref, l2cap_chan_destroy); } void l2cap_chan_set_defaults(struct l2cap_chan *chan) -- cgit v1.2.3 From f91c8468df97d0ac18132eb38283524a74317901 Mon Sep 17 00:00:00 2001 From: Vinicius Costa Gomes Date: Fri, 17 Aug 2012 21:37:59 -0300 Subject: Bluetooth: Fix establishing ESCO links Commit 4cd2d98340b4f03d5532c30fdaeb451b035429cb "Bluetooth: Simplify the connection type handling" broke the creation of ESCO links. This patch adds a type parameter to hci_connect_sco() so it creates the connection of the right kind. Signed-off-by: Vinicius Costa Gomes Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 98670b1df17..3e65c021df5 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -521,8 +521,8 @@ static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, return acl; } -static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, bdaddr_t *dst, - u8 sec_level, u8 auth_type) +static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, + bdaddr_t *dst, u8 sec_level, u8 auth_type) { struct hci_conn *acl; struct hci_conn *sco; @@ -531,9 +531,9 @@ static struct hci_conn *hci_connect_sco(struct hci_dev *hdev, bdaddr_t *dst, if (IS_ERR(acl)) return acl; - sco = hci_conn_hash_lookup_ba(hdev, SCO_LINK, dst); + sco = hci_conn_hash_lookup_ba(hdev, type, dst); if (!sco) { - sco = hci_conn_add(hdev, SCO_LINK, dst); + sco = hci_conn_add(hdev, type, dst); if (!sco) { hci_conn_put(acl); return ERR_PTR(-ENOMEM); @@ -574,7 +574,8 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, case ACL_LINK: return hci_connect_acl(hdev, dst, sec_level, auth_type); case SCO_LINK: - return hci_connect_sco(hdev, dst, sec_level, auth_type); + case ESCO_LINK: + return hci_connect_sco(hdev, type, dst, sec_level, auth_type); } return ERR_PTR(-EINVAL); -- cgit v1.2.3 From 6b536b5e5e1da32f3ba1e3f42c7bf2f80d37dc6b Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Fri, 31 Aug 2012 16:39:28 +0300 Subject: Bluetooth: Remove unneeded zero init hdev is allocated with kzalloc so zero initialization is not needed. Signed-off-by: Andrei Emeltchenko Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- 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 fa974a19d36..86abe721f48 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1652,6 +1652,7 @@ struct hci_dev *hci_alloc_dev(void) INIT_LIST_HEAD(&hdev->link_keys); INIT_LIST_HEAD(&hdev->long_term_keys); INIT_LIST_HEAD(&hdev->remote_oob_data); + INIT_LIST_HEAD(&hdev->conn_hash.list); INIT_WORK(&hdev->rx_work, hci_rx_work); INIT_WORK(&hdev->cmd_work, hci_cmd_work); @@ -1674,7 +1675,6 @@ struct hci_dev *hci_alloc_dev(void) hci_init_sysfs(hdev); discovery_init(hdev); - hci_conn_hash_init(hdev); return hdev; } -- cgit v1.2.3 From 9472007c62ecc8f21daa2e1e252bf73b67e535fc Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 6 Sep 2012 15:05:43 +0300 Subject: Bluetooth: trivial: Make hci_chan_del return void Return code is not needed in hci_chan_del Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_conn.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 3e65c021df5..59f0344406c 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -935,7 +935,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn) return chan; } -int hci_chan_del(struct hci_chan *chan) +void hci_chan_del(struct hci_chan *chan) { struct hci_conn *conn = chan->conn; struct hci_dev *hdev = conn->hdev; @@ -948,8 +948,6 @@ int hci_chan_del(struct hci_chan *chan) skb_queue_purge(&chan->data_q); kfree(chan); - - return 0; } void hci_chan_list_flush(struct hci_conn *conn) -- cgit v1.2.3 From 93f71941c6d3ead73ca74d447b4007c6908f6eb5 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 6 Sep 2012 15:05:44 +0300 Subject: Bluetooth: trivial: Remove empty line Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_core.c | 1 - 1 file changed, 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 86abe721f48..9e6574a8e6e 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -268,7 +268,6 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) BT_ERR("Unknown device type %d", hdev->dev_type); break; } - } static void hci_le_init_req(struct hci_dev *hdev, unsigned long opt) -- cgit v1.2.3 From e71dfabab03129182a955663cbd53406714d96c0 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 6 Sep 2012 15:05:46 +0300 Subject: Bluetooth: AMP: Add Read Data Block Size to amp_init Add Read Data Block Size HCI cmd to AMP initialization, then it makes possible to send data. Signed-off-by: Andrei Emeltchenko Signed-off-by: Gustavo Padovan --- 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 9e6574a8e6e..e4070517ff3 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -231,6 +231,9 @@ static void amp_init(struct hci_dev *hdev) /* Read Local AMP Info */ hci_send_cmd(hdev, HCI_OP_READ_LOCAL_AMP_INFO, 0, NULL); + + /* Read Data Blk size */ + hci_send_cmd(hdev, HCI_OP_READ_DATA_BLOCK_SIZE, 0, NULL); } static void hci_init_req(struct hci_dev *hdev, unsigned long opt) -- cgit v1.2.3 From 92a25256f142d55e25f9959441cea6ddeabae57e Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 6 Sep 2012 18:39:26 +0300 Subject: Bluetooth: mgmt: Implement support for passkey notification This patch adds support for Secure Simple Pairing with devices that have KeyboardOnly as their IO capability. Such devices will cause a passkey notification on our side and optionally also keypress notifications. Without this patch some keyboards cannot be paired using the mgmt interface. Signed-off-by: Johan Hedberg Cc: stable@vger.kernel.org Acked-by: Marcel Holtmann Signed-off-by: Gustavo Padovan --- net/bluetooth/hci_event.c | 67 +++++++++++++++++++++++++++++++++++++++++++++++ net/bluetooth/mgmt.c | 17 ++++++++++++ 2 files changed, 84 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 48d730228c2..ccca88fc619 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3263,6 +3263,65 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev, mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); } +static void hci_user_passkey_notify_evt(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_ev_user_passkey_notify *ev = (void *) skb->data; + struct hci_conn *conn; + + BT_DBG("%s", hdev->name); + + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); + if (!conn) + return; + + conn->passkey_notify = __le32_to_cpu(ev->passkey); + conn->passkey_entered = 0; + + if (test_bit(HCI_MGMT, &hdev->dev_flags)) + mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, + conn->dst_type, conn->passkey_notify, + conn->passkey_entered); +} + +static void hci_keypress_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_ev_keypress_notify *ev = (void *) skb->data; + struct hci_conn *conn; + + BT_DBG("%s", hdev->name); + + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); + if (!conn) + return; + + switch (ev->type) { + case HCI_KEYPRESS_STARTED: + conn->passkey_entered = 0; + return; + + case HCI_KEYPRESS_ENTERED: + conn->passkey_entered++; + break; + + case HCI_KEYPRESS_ERASED: + conn->passkey_entered--; + break; + + case HCI_KEYPRESS_CLEARED: + conn->passkey_entered = 0; + break; + + case HCI_KEYPRESS_COMPLETED: + return; + } + + if (test_bit(HCI_MGMT, &hdev->dev_flags)) + mgmt_user_passkey_notify(hdev, &conn->dst, conn->type, + conn->dst_type, conn->passkey_notify, + conn->passkey_entered); +} + static void hci_simple_pair_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) { @@ -3627,6 +3686,14 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) hci_user_passkey_request_evt(hdev, skb); break; + case HCI_EV_USER_PASSKEY_NOTIFY: + hci_user_passkey_notify_evt(hdev, skb); + break; + + case HCI_EV_KEYPRESS_NOTIFY: + hci_keypress_notify_evt(hdev, skb); + break; + case HCI_EV_SIMPLE_PAIR_COMPLETE: hci_simple_pair_complete_evt(hdev, skb); break; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 05d4b83a018..8e1ab59a9ce 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -99,6 +99,7 @@ static const u16 mgmt_events[] = { MGMT_EV_DEVICE_BLOCKED, MGMT_EV_DEVICE_UNBLOCKED, MGMT_EV_DEVICE_UNPAIRED, + MGMT_EV_PASSKEY_NOTIFY, }; /* @@ -3276,6 +3277,22 @@ int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, MGMT_OP_USER_PASSKEY_NEG_REPLY); } +int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr, + u8 link_type, u8 addr_type, u32 passkey, + u8 entered) +{ + struct mgmt_ev_passkey_notify ev; + + BT_DBG("%s", hdev->name); + + bacpy(&ev.addr.bdaddr, bdaddr); + ev.addr.type = link_to_bdaddr(link_type, addr_type); + ev.passkey = __cpu_to_le32(passkey); + ev.entered = entered; + + return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL); +} + int mgmt_auth_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 status) { -- cgit v1.2.3 From 23b3b1330abc643e1fbb7cfffcb6947e2583cff2 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 6 Sep 2012 18:39:27 +0300 Subject: Bluetooth: Update management interface revision For each kernel release where commands or events are added to the management interface, the revision field should be increment by one. The increment should only happen once per kernel release and not for every command/event that gets added. The revision value is for informational purposes only, but this simple policy would make any future debugging a lot simple. Signed-off-by: Johan Hedberg Cc: stable@vger.kernel.org Signed-off-by: Gustavo Padovan --- net/bluetooth/mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 8e1ab59a9ce..8934343be0e 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -35,7 +35,7 @@ bool enable_hs; #define MGMT_VERSION 1 -#define MGMT_REVISION 1 +#define MGMT_REVISION 2 static const u16 mgmt_commands[] = { MGMT_OP_READ_INDEX_LIST, -- cgit v1.2.3