2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-02 18:33:55 +08:00
linux-next/net/bluetooth/hci_event.c

6956 lines
176 KiB
C
Raw Normal View History

/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
Written 2000,2001 by Maxim Krasnyansky <maxk@qualcomm.com>
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.
*/
/* Bluetooth HCI event handling. */
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/mgmt.h>
#include "hci_request.h"
#include "hci_debugfs.h"
#include "a2mp.h"
#include "amp.h"
#include "smp.h"
#include "msft.h"
#include "eir.h"
#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
"\x00\x00\x00\x00\x00\x00\x00\x00"
#define secs_to_jiffies(_secs) msecs_to_jiffies((_secs) * 1000)
/* Handle HCI Event packets */
static void *hci_ev_skb_pull(struct hci_dev *hdev, struct sk_buff *skb,
u8 ev, size_t len)
{
void *data;
data = skb_pull_data(skb, len);
if (!data)
bt_dev_err(hdev, "Malformed Event: 0x%2.2x", ev);
return data;
}
static void *hci_cc_skb_pull(struct hci_dev *hdev, struct sk_buff *skb,
u16 op, size_t len)
{
void *data;
data = skb_pull_data(skb, len);
if (!data)
bt_dev_err(hdev, "Malformed Command Complete: 0x%4.4x", op);
return data;
}
static void *hci_le_ev_skb_pull(struct hci_dev *hdev, struct sk_buff *skb,
u8 ev, size_t len)
{
void *data;
data = skb_pull_data(skb, len);
if (!data)
bt_dev_err(hdev, "Malformed LE Event: 0x%2.2x", ev);
return data;
}
static u8 hci_cc_inquiry_cancel(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
/* It is possible that we receive Inquiry Complete event right
* before we receive Inquiry Cancel Command Complete event, in
* which case the latter event should have status of Command
* Disallowed (0x0c). This should not be treated as error, since
* we actually achieve what Inquiry Cancel wants to achieve,
* which is to end the last Inquiry session.
*/
if (rp->status == 0x0c && !test_bit(HCI_INQUIRY, &hdev->flags)) {
bt_dev_warn(hdev, "Ignoring error of Inquiry Cancel command");
rp->status = 0x00;
}
if (rp->status)
return rp->status;
clear_bit(HCI_INQUIRY, &hdev->flags);
smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */
wake_up_bit(&hdev->flags, HCI_INQUIRY);
hci_dev_lock(hdev);
/* Set discovery state to stopped if we're not doing LE active
* scanning.
*/
if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
hdev->le_scan_type != LE_SCAN_ACTIVE)
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
hci_dev_unlock(hdev);
hci_conn_check_pending(hdev);
return rp->status;
}
static u8 hci_cc_periodic_inq(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hci_dev_set_flag(hdev, HCI_PERIODIC_INQ);
return rp->status;
}
static u8 hci_cc_exit_periodic_inq(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ);
hci_conn_check_pending(hdev);
return rp->status;
}
static u8 hci_cc_remote_name_req_cancel(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
return rp->status;
}
static u8 hci_cc_role_discovery(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_role_discovery *rp = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
if (conn)
conn->role = rp->role;
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_read_link_policy(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_link_policy *rp = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
if (conn)
conn->link_policy = __le16_to_cpu(rp->policy);
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_write_link_policy(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_write_link_policy *rp = data;
struct hci_conn *conn;
void *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LINK_POLICY);
if (!sent)
return rp->status;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
if (conn)
conn->link_policy = get_unaligned_le16(sent + 2);
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_read_def_link_policy(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_def_link_policy *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hdev->link_policy = __le16_to_cpu(rp->policy);
return rp->status;
}
static u8 hci_cc_write_def_link_policy(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
void *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY);
if (!sent)
return rp->status;
hdev->link_policy = get_unaligned_le16(sent);
return rp->status;
}
static u8 hci_cc_reset(struct hci_dev *hdev, void *data, struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
clear_bit(HCI_RESET, &hdev->flags);
if (rp->status)
return rp->status;
/* Reset all non-persistent flags */
hci_dev_clear_volatile_flags(hdev);
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
hdev->inq_tx_power = HCI_TX_POWER_INVALID;
hdev->adv_tx_power = HCI_TX_POWER_INVALID;
memset(hdev->adv_data, 0, sizeof(hdev->adv_data));
hdev->adv_data_len = 0;
memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data));
hdev->scan_rsp_data_len = 0;
hdev->le_scan_type = LE_SCAN_PASSIVE;
hdev->ssp_debug_mode = 0;
hci_bdaddr_list_clear(&hdev->le_accept_list);
Bluetooth: Store Resolv list size When the controller supports the Read LE Resolv List size feature, the maximum list size are read and now stored. Before patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 17.979791 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 17.980629 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 17.980786 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 17.981627 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #59 [hci0] 17.981786 > HCI Event: Command Complete (0x0e) plen 12 #60 [hci0] 17.982636 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 After patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 13.338168 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 13.338842 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 13.339029 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 13.339939 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Resolving L.. (0x08|0x002a) plen 0 #59 [hci0] 13.340152 > HCI Event: Command Complete (0x0e) plen 5 #60 [hci0] 13.340952 LE Read Resolving List Size (0x08|0x002a) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #61 [hci0] 13.341180 > HCI Event: Command Complete (0x0e) plen 12 #62 [hci0] 13.341898 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 Signed-off-by: Ankit Navik <ankit.p.navik@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-06-29 14:42:50 +08:00
hci_bdaddr_list_clear(&hdev->le_resolv_list);
return rp->status;
}
static u8 hci_cc_read_stored_link_key(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_stored_link_key *rp = data;
struct hci_cp_read_stored_link_key *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
sent = hci_sent_cmd_data(hdev, HCI_OP_READ_STORED_LINK_KEY);
if (!sent)
return rp->status;
if (!rp->status && sent->read_all == 0x01) {
hdev->stored_max_keys = le16_to_cpu(rp->max_keys);
hdev->stored_num_keys = le16_to_cpu(rp->num_keys);
}
return rp->status;
}
static u8 hci_cc_delete_stored_link_key(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_delete_stored_link_key *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
if (rp->num_keys <= hdev->stored_num_keys)
hdev->stored_num_keys -= le16_to_cpu(rp->num_keys);
else
hdev->stored_num_keys = 0;
return rp->status;
}
static u8 hci_cc_write_local_name(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
void *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LOCAL_NAME);
if (!sent)
return rp->status;
hci_dev_lock(hdev);
if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_set_local_name_complete(hdev, sent, rp->status);
else if (!rp->status)
memcpy(hdev->dev_name, sent, HCI_MAX_NAME_LENGTH);
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_read_local_name(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_local_name *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
if (hci_dev_test_flag(hdev, HCI_SETUP) ||
hci_dev_test_flag(hdev, HCI_CONFIG))
memcpy(hdev->dev_name, rp->name, HCI_MAX_NAME_LENGTH);
return rp->status;
}
static u8 hci_cc_write_auth_enable(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
void *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_ENABLE);
if (!sent)
return rp->status;
hci_dev_lock(hdev);
if (!rp->status) {
__u8 param = *((__u8 *) sent);
if (param == AUTH_ENABLED)
set_bit(HCI_AUTH, &hdev->flags);
else
clear_bit(HCI_AUTH, &hdev->flags);
}
if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_auth_enable_complete(hdev, rp->status);
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_write_encrypt_mode(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
__u8 param;
void *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE);
if (!sent)
return rp->status;
param = *((__u8 *) sent);
if (param)
set_bit(HCI_ENCRYPT, &hdev->flags);
else
clear_bit(HCI_ENCRYPT, &hdev->flags);
return rp->status;
}
static u8 hci_cc_write_scan_enable(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
__u8 param;
void *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SCAN_ENABLE);
if (!sent)
return rp->status;
param = *((__u8 *) sent);
hci_dev_lock(hdev);
if (rp->status) {
hdev->discov_timeout = 0;
goto done;
}
if (param & SCAN_INQUIRY)
set_bit(HCI_ISCAN, &hdev->flags);
else
clear_bit(HCI_ISCAN, &hdev->flags);
if (param & SCAN_PAGE)
set_bit(HCI_PSCAN, &hdev->flags);
else
clear_bit(HCI_PSCAN, &hdev->flags);
done:
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_set_event_filter(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
struct hci_cp_set_event_filter *cp;
void *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_SET_EVENT_FLT);
if (!sent)
return rp->status;
cp = (struct hci_cp_set_event_filter *)sent;
if (cp->flt_type == HCI_FLT_CLEAR_ALL)
hci_dev_clear_flag(hdev, HCI_EVENT_FILTER_CONFIGURED);
else
hci_dev_set_flag(hdev, HCI_EVENT_FILTER_CONFIGURED);
return rp->status;
}
static u8 hci_cc_read_class_of_dev(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_class_of_dev *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
memcpy(hdev->dev_class, rp->dev_class, 3);
bt_dev_dbg(hdev, "class 0x%.2x%.2x%.2x", hdev->dev_class[2],
hdev->dev_class[1], hdev->dev_class[0]);
return rp->status;
}
static u8 hci_cc_write_class_of_dev(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
void *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_CLASS_OF_DEV);
if (!sent)
return rp->status;
hci_dev_lock(hdev);
if (!rp->status)
memcpy(hdev->dev_class, sent, 3);
if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_set_class_of_dev_complete(hdev, sent, rp->status);
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_read_voice_setting(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_voice_setting *rp = data;
__u16 setting;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
setting = __le16_to_cpu(rp->voice_setting);
if (hdev->voice_setting == setting)
return rp->status;
hdev->voice_setting = setting;
bt_dev_dbg(hdev, "voice setting 0x%4.4x", setting);
if (hdev->notify)
hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
return rp->status;
}
static u8 hci_cc_write_voice_setting(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
__u16 setting;
void *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_VOICE_SETTING);
if (!sent)
return rp->status;
setting = get_unaligned_le16(sent);
if (hdev->voice_setting == setting)
return rp->status;
hdev->voice_setting = setting;
bt_dev_dbg(hdev, "voice setting 0x%4.4x", setting);
if (hdev->notify)
hdev->notify(hdev, HCI_NOTIFY_VOICE_SETTING);
return rp->status;
}
static u8 hci_cc_read_num_supported_iac(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_num_supported_iac *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hdev->num_iac = rp->num_iac;
bt_dev_dbg(hdev, "num iac %d", hdev->num_iac);
return rp->status;
}
static u8 hci_cc_write_ssp_mode(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
struct hci_cp_write_ssp_mode *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_MODE);
if (!sent)
return rp->status;
hci_dev_lock(hdev);
if (!rp->status) {
if (sent->mode)
hdev->features[1][0] |= LMP_HOST_SSP;
else
hdev->features[1][0] &= ~LMP_HOST_SSP;
}
if (!rp->status) {
if (sent->mode)
hci_dev_set_flag(hdev, HCI_SSP_ENABLED);
else
hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
}
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_write_sc_support(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
struct hci_cp_write_sc_support *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT);
if (!sent)
return rp->status;
hci_dev_lock(hdev);
if (!rp->status) {
if (sent->support)
hdev->features[1][0] |= LMP_HOST_SC;
else
hdev->features[1][0] &= ~LMP_HOST_SC;
}
if (!hci_dev_test_flag(hdev, HCI_MGMT) && !rp->status) {
if (sent->support)
hci_dev_set_flag(hdev, HCI_SC_ENABLED);
else
hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
}
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_read_local_version(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_local_version *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
if (hci_dev_test_flag(hdev, HCI_SETUP) ||
hci_dev_test_flag(hdev, HCI_CONFIG)) {
hdev->hci_ver = rp->hci_ver;
hdev->hci_rev = __le16_to_cpu(rp->hci_rev);
hdev->lmp_ver = rp->lmp_ver;
hdev->manufacturer = __le16_to_cpu(rp->manufacturer);
hdev->lmp_subver = __le16_to_cpu(rp->lmp_subver);
}
return rp->status;
}
static u8 hci_cc_read_local_commands(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_local_commands *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
if (hci_dev_test_flag(hdev, HCI_SETUP) ||
hci_dev_test_flag(hdev, HCI_CONFIG))
memcpy(hdev->commands, rp->commands, sizeof(hdev->commands));
return rp->status;
}
static u8 hci_cc_read_auth_payload_timeout(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_auth_payload_to *rp = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
if (conn)
conn->auth_payload_timeout = __le16_to_cpu(rp->timeout);
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_write_auth_payload_timeout(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_write_auth_payload_to *rp = data;
struct hci_conn *conn;
void *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_AUTH_PAYLOAD_TO);
if (!sent)
return rp->status;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
if (conn)
conn->auth_payload_timeout = get_unaligned_le16(sent + 2);
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_read_local_features(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_local_features *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
memcpy(hdev->features, rp->features, 8);
/* Adjust default settings according to features
* supported by device. */
if (hdev->features[0][0] & LMP_3SLOT)
hdev->pkt_type |= (HCI_DM3 | HCI_DH3);
if (hdev->features[0][0] & LMP_5SLOT)
hdev->pkt_type |= (HCI_DM5 | HCI_DH5);
if (hdev->features[0][1] & LMP_HV2) {
hdev->pkt_type |= (HCI_HV2);
hdev->esco_type |= (ESCO_HV2);
}
if (hdev->features[0][1] & LMP_HV3) {
hdev->pkt_type |= (HCI_HV3);
hdev->esco_type |= (ESCO_HV3);
}
if (lmp_esco_capable(hdev))
hdev->esco_type |= (ESCO_EV3);
if (hdev->features[0][4] & LMP_EV4)
hdev->esco_type |= (ESCO_EV4);
if (hdev->features[0][4] & LMP_EV5)
hdev->esco_type |= (ESCO_EV5);
if (hdev->features[0][5] & LMP_EDR_ESCO_2M)
hdev->esco_type |= (ESCO_2EV3);
if (hdev->features[0][5] & LMP_EDR_ESCO_3M)
hdev->esco_type |= (ESCO_3EV3);
if (hdev->features[0][5] & LMP_EDR_3S_ESCO)
hdev->esco_type |= (ESCO_2EV5 | ESCO_3EV5);
return rp->status;
}
static u8 hci_cc_read_local_ext_features(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_local_ext_features *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
if (hdev->max_page < rp->max_page)
hdev->max_page = rp->max_page;
if (rp->page < HCI_MAX_PAGES)
memcpy(hdev->features[rp->page], rp->features, 8);
return rp->status;
}
static u8 hci_cc_read_flow_control_mode(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_flow_control_mode *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hdev->flow_ctl_mode = rp->mode;
return rp->status;
}
static u8 hci_cc_read_buffer_size(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_buffer_size *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hdev->acl_mtu = __le16_to_cpu(rp->acl_mtu);
hdev->sco_mtu = rp->sco_mtu;
hdev->acl_pkts = __le16_to_cpu(rp->acl_max_pkt);
hdev->sco_pkts = __le16_to_cpu(rp->sco_max_pkt);
if (test_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks)) {
hdev->sco_mtu = 64;
hdev->sco_pkts = 8;
}
hdev->acl_cnt = hdev->acl_pkts;
hdev->sco_cnt = hdev->sco_pkts;
BT_DBG("%s acl mtu %d:%d sco mtu %d:%d", hdev->name, hdev->acl_mtu,
hdev->acl_pkts, hdev->sco_mtu, hdev->sco_pkts);
return rp->status;
}
static u8 hci_cc_read_bd_addr(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_bd_addr *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
if (test_bit(HCI_INIT, &hdev->flags))
bacpy(&hdev->bdaddr, &rp->bdaddr);
if (hci_dev_test_flag(hdev, HCI_SETUP))
bacpy(&hdev->setup_addr, &rp->bdaddr);
return rp->status;
}
static u8 hci_cc_read_local_pairing_opts(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_local_pairing_opts *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
if (hci_dev_test_flag(hdev, HCI_SETUP) ||
hci_dev_test_flag(hdev, HCI_CONFIG)) {
hdev->pairing_opts = rp->pairing_opts;
hdev->max_enc_key_size = rp->max_key_size;
}
return rp->status;
}
static u8 hci_cc_read_page_scan_activity(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_page_scan_activity *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
if (test_bit(HCI_INIT, &hdev->flags)) {
hdev->page_scan_interval = __le16_to_cpu(rp->interval);
hdev->page_scan_window = __le16_to_cpu(rp->window);
}
return rp->status;
}
static u8 hci_cc_write_page_scan_activity(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
struct hci_cp_write_page_scan_activity *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY);
if (!sent)
return rp->status;
hdev->page_scan_interval = __le16_to_cpu(sent->interval);
hdev->page_scan_window = __le16_to_cpu(sent->window);
return rp->status;
}
static u8 hci_cc_read_page_scan_type(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_page_scan_type *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
if (test_bit(HCI_INIT, &hdev->flags))
hdev->page_scan_type = rp->type;
return rp->status;
}
static u8 hci_cc_write_page_scan_type(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
u8 *type;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
type = hci_sent_cmd_data(hdev, HCI_OP_WRITE_PAGE_SCAN_TYPE);
if (type)
hdev->page_scan_type = *type;
return rp->status;
}
static u8 hci_cc_read_data_block_size(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_data_block_size *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hdev->block_mtu = __le16_to_cpu(rp->max_acl_len);
hdev->block_len = __le16_to_cpu(rp->block_len);
hdev->num_blocks = __le16_to_cpu(rp->num_blocks);
hdev->block_cnt = hdev->num_blocks;
BT_DBG("%s blk mtu %d cnt %d len %d", hdev->name, hdev->block_mtu,
hdev->block_cnt, hdev->block_len);
return rp->status;
}
static u8 hci_cc_read_clock(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_clock *rp = data;
struct hci_cp_read_clock *cp;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hci_dev_lock(hdev);
cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK);
if (!cp)
goto unlock;
if (cp->which == 0x00) {
hdev->clock = le32_to_cpu(rp->clock);
goto unlock;
}
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
if (conn) {
conn->clock = le32_to_cpu(rp->clock);
conn->clock_accuracy = le16_to_cpu(rp->accuracy);
}
unlock:
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_read_local_amp_info(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_local_amp_info *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hdev->amp_status = rp->amp_status;
hdev->amp_total_bw = __le32_to_cpu(rp->total_bw);
hdev->amp_max_bw = __le32_to_cpu(rp->max_bw);
hdev->amp_min_latency = __le32_to_cpu(rp->min_latency);
hdev->amp_max_pdu = __le32_to_cpu(rp->max_pdu);
hdev->amp_type = rp->amp_type;
hdev->amp_pal_cap = __le16_to_cpu(rp->pal_cap);
hdev->amp_assoc_size = __le16_to_cpu(rp->max_assoc_size);
hdev->amp_be_flush_to = __le32_to_cpu(rp->be_flush_to);
hdev->amp_max_flush_to = __le32_to_cpu(rp->max_flush_to);
return rp->status;
}
static u8 hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_inq_rsp_tx_power *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hdev->inq_tx_power = rp->tx_power;
return rp->status;
}
static u8 hci_cc_read_def_err_data_reporting(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_def_err_data_reporting *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hdev->err_data_reporting = rp->err_data_reporting;
return rp->status;
}
static u8 hci_cc_write_def_err_data_reporting(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
struct hci_cp_write_def_err_data_reporting *cp;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
cp = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_ERR_DATA_REPORTING);
if (!cp)
return rp->status;
hdev->err_data_reporting = cp->err_data_reporting;
return rp->status;
}
static u8 hci_cc_pin_code_reply(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_pin_code_reply *rp = data;
struct hci_cp_pin_code_reply *cp;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
hci_dev_lock(hdev);
if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_pin_code_reply_complete(hdev, &rp->bdaddr, rp->status);
if (rp->status)
goto unlock;
cp = hci_sent_cmd_data(hdev, HCI_OP_PIN_CODE_REPLY);
if (!cp)
goto unlock;
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
if (conn)
conn->pin_length = cp->pin_len;
unlock:
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_pin_code_neg_reply(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_pin_code_neg_reply *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
hci_dev_lock(hdev);
if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_pin_code_neg_reply_complete(hdev, &rp->bdaddr,
rp->status);
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_le_read_buffer_size(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_le_read_buffer_size *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hdev->le_mtu = __le16_to_cpu(rp->le_mtu);
hdev->le_pkts = rp->le_max_pkt;
hdev->le_cnt = hdev->le_pkts;
BT_DBG("%s le mtu %d:%d", hdev->name, hdev->le_mtu, hdev->le_pkts);
return rp->status;
}
static u8 hci_cc_le_read_local_features(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_le_read_local_features *rp = data;
BT_DBG("%s status 0x%2.2x", hdev->name, rp->status);
if (rp->status)
return rp->status;
memcpy(hdev->le_features, rp->features, 8);
return rp->status;
}
static u8 hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_le_read_adv_tx_power *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hdev->adv_tx_power = rp->tx_power;
return rp->status;
}
static u8 hci_cc_user_confirm_reply(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_user_confirm_reply *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
hci_dev_lock(hdev);
if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_user_confirm_reply_complete(hdev, &rp->bdaddr, ACL_LINK, 0,
rp->status);
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_user_confirm_neg_reply(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_user_confirm_reply *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
hci_dev_lock(hdev);
if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_user_confirm_neg_reply_complete(hdev, &rp->bdaddr,
ACL_LINK, 0, rp->status);
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_user_passkey_reply(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_user_confirm_reply *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
hci_dev_lock(hdev);
if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_user_passkey_reply_complete(hdev, &rp->bdaddr, ACL_LINK,
0, rp->status);
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_user_confirm_reply *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
hci_dev_lock(hdev);
if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_user_passkey_neg_reply_complete(hdev, &rp->bdaddr,
ACL_LINK, 0, rp->status);
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_read_local_oob_data(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_local_oob_data *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
return rp->status;
Bluetooth: Add support for local OOB data with Secure Connections For Secure Connections support and the usage of out-of-band pairing, it is needed to read the P-256 hash and randomizer or P-192 hash and randomizer. This change will read P-192 data when Secure Connections is disabled and P-192 and P-256 data when it is enabled. The difference is between using HCI Read Local OOB Data and using the new HCI Read Local OOB Extended Data command. The first one has been introduced with Bluetooth 2.1 and returns only the P-192 data. < HCI Command: Read Local OOB Data (0x03|0x0057) plen 0 > HCI Event: Command Complete (0x0e) plen 36 Read Local OOB Data (0x03|0x0057) ncmd 1 Status: Success (0x00) Hash C from P-192: 975a59baa1c4eee391477cb410b23e6d Randomizer R with P-192: 9ee63b7dec411d3b467c5ae446df7f7d The second command has been introduced with Bluetooth 4.1 and will return P-192 and P-256 data. < HCI Command: Read Local OOB Extended Data (0x03|0x007d) plen 0 > HCI Event: Command Complete (0x0e) plen 68 Read Local OOB Extended Data (0x03|0x007d) ncmd 1 Status: Success (0x00) Hash C from P-192: 6489731804b156fa6355efb8124a1389 Randomizer R with P-192: 4781d5352fb215b2958222b3937b6026 Hash C from P-256: 69ef8a928b9d07fc149e630e74ecb991 Randomizer R with P-256: 4781d5352fb215b2958222b3937b6026 The change for the management interface is transparent and no change is required for existing userspace. The Secure Connections feature needs to be manually enabled. When it is disabled, then userspace only gets the P-192 returned and with Secure Connections enabled, userspace gets P-192 and P-256 in an extended structure. It is also acceptable to just ignore the P-256 data since it is not required to support them. The pairing with out-of-band credentials will still succeed. However then of course no Secure Connection will b established. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2014-01-10 18:07:26 +08:00
}
static u8 hci_cc_read_local_oob_ext_data(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
Bluetooth: Add support for local OOB data with Secure Connections For Secure Connections support and the usage of out-of-band pairing, it is needed to read the P-256 hash and randomizer or P-192 hash and randomizer. This change will read P-192 data when Secure Connections is disabled and P-192 and P-256 data when it is enabled. The difference is between using HCI Read Local OOB Data and using the new HCI Read Local OOB Extended Data command. The first one has been introduced with Bluetooth 2.1 and returns only the P-192 data. < HCI Command: Read Local OOB Data (0x03|0x0057) plen 0 > HCI Event: Command Complete (0x0e) plen 36 Read Local OOB Data (0x03|0x0057) ncmd 1 Status: Success (0x00) Hash C from P-192: 975a59baa1c4eee391477cb410b23e6d Randomizer R with P-192: 9ee63b7dec411d3b467c5ae446df7f7d The second command has been introduced with Bluetooth 4.1 and will return P-192 and P-256 data. < HCI Command: Read Local OOB Extended Data (0x03|0x007d) plen 0 > HCI Event: Command Complete (0x0e) plen 68 Read Local OOB Extended Data (0x03|0x007d) ncmd 1 Status: Success (0x00) Hash C from P-192: 6489731804b156fa6355efb8124a1389 Randomizer R with P-192: 4781d5352fb215b2958222b3937b6026 Hash C from P-256: 69ef8a928b9d07fc149e630e74ecb991 Randomizer R with P-256: 4781d5352fb215b2958222b3937b6026 The change for the management interface is transparent and no change is required for existing userspace. The Secure Connections feature needs to be manually enabled. When it is disabled, then userspace only gets the P-192 returned and with Secure Connections enabled, userspace gets P-192 and P-256 in an extended structure. It is also acceptable to just ignore the P-256 data since it is not required to support them. The pairing with out-of-band credentials will still succeed. However then of course no Secure Connection will b established. Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2014-01-10 18:07:26 +08:00
{
struct hci_rp_read_local_oob_ext_data *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
return rp->status;
}
static u8 hci_cc_le_set_random_addr(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
bdaddr_t *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR);
if (!sent)
return rp->status;
hci_dev_lock(hdev);
bacpy(&hdev->random_addr, sent);
if (!bacmp(&hdev->rpa, sent)) {
hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
queue_delayed_work(hdev->workqueue, &hdev->rpa_expired,
secs_to_jiffies(hdev->rpa_timeout));
}
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_le_set_default_phy(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
struct hci_cp_le_set_default_phy *cp;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_DEFAULT_PHY);
if (!cp)
return rp->status;
hci_dev_lock(hdev);
hdev->le_tx_def_phys = cp->tx_phys;
hdev->le_rx_def_phys = cp->rx_phys;
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_le_set_adv_set_random_addr(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
struct hci_cp_le_set_adv_set_rand_addr *cp;
struct adv_info *adv;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_SET_RAND_ADDR);
/* Update only in case the adv instance since handle 0x00 shall be using
* HCI_OP_LE_SET_RANDOM_ADDR since that allows both extended and
* non-extended adverting.
*/
if (!cp || !cp->handle)
return rp->status;
hci_dev_lock(hdev);
adv = hci_find_adv_instance(hdev, cp->handle);
if (adv) {
bacpy(&adv->random_addr, &cp->bdaddr);
if (!bacmp(&hdev->rpa, &cp->bdaddr)) {
adv->rpa_expired = false;
queue_delayed_work(hdev->workqueue,
&adv->rpa_expired_cb,
secs_to_jiffies(hdev->rpa_timeout));
}
}
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_le_remove_adv_set(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2 This make use of hci_cmd_sync_queue for the following MGMT commands: Add Advertising Remove Advertising Add Extended Advertising Parameters Add Extended Advertising Data mgmt-tester -s "Add Advertising" Test Summary ------------ Add Advertising - Failure: LE off Passed Add Advertising - Invalid Params 1 (AD too long) Passed Add Advertising - Invalid Params 2 (Malformed len) Passed Add Advertising - Invalid Params 3 (Malformed len) Passed Add Advertising - Invalid Params 4 (Malformed len) Passed Add Advertising - Invalid Params 5 (AD too long) Passed Add Advertising - Invalid Params 6 (ScRsp too long) Passed Add Advertising - Invalid Params 7 (Malformed len) Passed Add Advertising - Invalid Params 8 (Malformed len) Passed Add Advertising - Invalid Params 9 (Malformed len) Passed Add Advertising - Invalid Params 10 (ScRsp too long) Passed Add Advertising - Rejected (Timeout, !Powered) Passed Add Advertising - Success 1 (Powered, Add Adv Inst) Passed Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed Add Advertising - Success 3 (!Powered, Adv Enable) Passed Add Advertising - Success 4 (Set Adv on override) Passed Add Advertising - Success 5 (Set Adv off override) Passed Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed Add Advertising - Success 8 (Connectable Flag) Passed Add Advertising - Success 9 (General Discov Flag) Passed Add Advertising - Success 10 (Limited Discov Flag) Passed Add Advertising - Success 11 (Managed Flags) Passed Add Advertising - Success 12 (TX Power Flag) Passed Add Advertising - Success 13 (ADV_SCAN_IND) Passed Add Advertising - Success 14 (ADV_NONCONN_IND) Passed Add Advertising - Success 15 (ADV_IND) Passed Add Advertising - Success 16 (Connectable -> on) Passed Add Advertising - Success 17 (Connectable -> off) Passed Add Advertising - Success 18 (Power -> off, Remove) Passed Add Advertising - Success 19 (Power -> off, Keep) Passed Add Advertising - Success 20 (Add Adv override) Passed Add Advertising - Success 21 (Timeout expires) Passed Add Advertising - Success 22 (LE -> off, Remove) Passed Add Advertising - Success (Empty ScRsp) Passed Add Advertising - Success (ScRsp only) Passed Add Advertising - Invalid Params (ScRsp too long) Passed Add Advertising - Success (ScRsp appear) Passed Add Advertising - Invalid Params (ScRsp appear long) Passed Add Advertising - Success (Appear is null) Passed Add Advertising - Success (Name is null) Passed Add Advertising - Success (Complete name) Passed Add Advertising - Success (Shortened name) Passed Add Advertising - Success (Short name) Passed Add Advertising - Success (Name + data) Passed Add Advertising - Invalid Params (Name + data) Passed Add Advertising - Success (Name+data+appear) Passed Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 2.17 seconds mgmt-tester -s "Remove Advertising" Test Summary ------------ Remove Advertising - Invalid Params 1 Passed Remove Advertising - Success 1 Passed Remove Advertising - Success 2 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0585 seconds mgmt-tester -s "Ext Adv MGMT Params" Test Summary: ------------ Ext Adv MGMT Params - Unpowered Passed Ext Adv MGMT Params - Invalid parameters Passed Ext Adv MGMT Params - Success Passed Ext Adv MGMT Params - (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0746 seconds mgmt-tester -s "Ext Adv MGMT -" Test Summary ------------ Ext Adv MGMT - Data set without Params Passed Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed Ext Adv MGMT - AD Data (5.0) Success Passed Ext Adv MGMT - AD Scan Response (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0805 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 07:58:40 +08:00
{
struct hci_ev_status *rp = data;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2 This make use of hci_cmd_sync_queue for the following MGMT commands: Add Advertising Remove Advertising Add Extended Advertising Parameters Add Extended Advertising Data mgmt-tester -s "Add Advertising" Test Summary ------------ Add Advertising - Failure: LE off Passed Add Advertising - Invalid Params 1 (AD too long) Passed Add Advertising - Invalid Params 2 (Malformed len) Passed Add Advertising - Invalid Params 3 (Malformed len) Passed Add Advertising - Invalid Params 4 (Malformed len) Passed Add Advertising - Invalid Params 5 (AD too long) Passed Add Advertising - Invalid Params 6 (ScRsp too long) Passed Add Advertising - Invalid Params 7 (Malformed len) Passed Add Advertising - Invalid Params 8 (Malformed len) Passed Add Advertising - Invalid Params 9 (Malformed len) Passed Add Advertising - Invalid Params 10 (ScRsp too long) Passed Add Advertising - Rejected (Timeout, !Powered) Passed Add Advertising - Success 1 (Powered, Add Adv Inst) Passed Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed Add Advertising - Success 3 (!Powered, Adv Enable) Passed Add Advertising - Success 4 (Set Adv on override) Passed Add Advertising - Success 5 (Set Adv off override) Passed Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed Add Advertising - Success 8 (Connectable Flag) Passed Add Advertising - Success 9 (General Discov Flag) Passed Add Advertising - Success 10 (Limited Discov Flag) Passed Add Advertising - Success 11 (Managed Flags) Passed Add Advertising - Success 12 (TX Power Flag) Passed Add Advertising - Success 13 (ADV_SCAN_IND) Passed Add Advertising - Success 14 (ADV_NONCONN_IND) Passed Add Advertising - Success 15 (ADV_IND) Passed Add Advertising - Success 16 (Connectable -> on) Passed Add Advertising - Success 17 (Connectable -> off) Passed Add Advertising - Success 18 (Power -> off, Remove) Passed Add Advertising - Success 19 (Power -> off, Keep) Passed Add Advertising - Success 20 (Add Adv override) Passed Add Advertising - Success 21 (Timeout expires) Passed Add Advertising - Success 22 (LE -> off, Remove) Passed Add Advertising - Success (Empty ScRsp) Passed Add Advertising - Success (ScRsp only) Passed Add Advertising - Invalid Params (ScRsp too long) Passed Add Advertising - Success (ScRsp appear) Passed Add Advertising - Invalid Params (ScRsp appear long) Passed Add Advertising - Success (Appear is null) Passed Add Advertising - Success (Name is null) Passed Add Advertising - Success (Complete name) Passed Add Advertising - Success (Shortened name) Passed Add Advertising - Success (Short name) Passed Add Advertising - Success (Name + data) Passed Add Advertising - Invalid Params (Name + data) Passed Add Advertising - Success (Name+data+appear) Passed Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 2.17 seconds mgmt-tester -s "Remove Advertising" Test Summary ------------ Remove Advertising - Invalid Params 1 Passed Remove Advertising - Success 1 Passed Remove Advertising - Success 2 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0585 seconds mgmt-tester -s "Ext Adv MGMT Params" Test Summary: ------------ Ext Adv MGMT Params - Unpowered Passed Ext Adv MGMT Params - Invalid parameters Passed Ext Adv MGMT Params - Success Passed Ext Adv MGMT Params - (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0746 seconds mgmt-tester -s "Ext Adv MGMT -" Test Summary ------------ Ext Adv MGMT - Data set without Params Passed Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed Ext Adv MGMT - AD Data (5.0) Success Passed Ext Adv MGMT - AD Scan Response (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0805 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 07:58:40 +08:00
u8 *instance;
int err;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2 This make use of hci_cmd_sync_queue for the following MGMT commands: Add Advertising Remove Advertising Add Extended Advertising Parameters Add Extended Advertising Data mgmt-tester -s "Add Advertising" Test Summary ------------ Add Advertising - Failure: LE off Passed Add Advertising - Invalid Params 1 (AD too long) Passed Add Advertising - Invalid Params 2 (Malformed len) Passed Add Advertising - Invalid Params 3 (Malformed len) Passed Add Advertising - Invalid Params 4 (Malformed len) Passed Add Advertising - Invalid Params 5 (AD too long) Passed Add Advertising - Invalid Params 6 (ScRsp too long) Passed Add Advertising - Invalid Params 7 (Malformed len) Passed Add Advertising - Invalid Params 8 (Malformed len) Passed Add Advertising - Invalid Params 9 (Malformed len) Passed Add Advertising - Invalid Params 10 (ScRsp too long) Passed Add Advertising - Rejected (Timeout, !Powered) Passed Add Advertising - Success 1 (Powered, Add Adv Inst) Passed Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed Add Advertising - Success 3 (!Powered, Adv Enable) Passed Add Advertising - Success 4 (Set Adv on override) Passed Add Advertising - Success 5 (Set Adv off override) Passed Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed Add Advertising - Success 8 (Connectable Flag) Passed Add Advertising - Success 9 (General Discov Flag) Passed Add Advertising - Success 10 (Limited Discov Flag) Passed Add Advertising - Success 11 (Managed Flags) Passed Add Advertising - Success 12 (TX Power Flag) Passed Add Advertising - Success 13 (ADV_SCAN_IND) Passed Add Advertising - Success 14 (ADV_NONCONN_IND) Passed Add Advertising - Success 15 (ADV_IND) Passed Add Advertising - Success 16 (Connectable -> on) Passed Add Advertising - Success 17 (Connectable -> off) Passed Add Advertising - Success 18 (Power -> off, Remove) Passed Add Advertising - Success 19 (Power -> off, Keep) Passed Add Advertising - Success 20 (Add Adv override) Passed Add Advertising - Success 21 (Timeout expires) Passed Add Advertising - Success 22 (LE -> off, Remove) Passed Add Advertising - Success (Empty ScRsp) Passed Add Advertising - Success (ScRsp only) Passed Add Advertising - Invalid Params (ScRsp too long) Passed Add Advertising - Success (ScRsp appear) Passed Add Advertising - Invalid Params (ScRsp appear long) Passed Add Advertising - Success (Appear is null) Passed Add Advertising - Success (Name is null) Passed Add Advertising - Success (Complete name) Passed Add Advertising - Success (Shortened name) Passed Add Advertising - Success (Short name) Passed Add Advertising - Success (Name + data) Passed Add Advertising - Invalid Params (Name + data) Passed Add Advertising - Success (Name+data+appear) Passed Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 2.17 seconds mgmt-tester -s "Remove Advertising" Test Summary ------------ Remove Advertising - Invalid Params 1 Passed Remove Advertising - Success 1 Passed Remove Advertising - Success 2 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0585 seconds mgmt-tester -s "Ext Adv MGMT Params" Test Summary: ------------ Ext Adv MGMT Params - Unpowered Passed Ext Adv MGMT Params - Invalid parameters Passed Ext Adv MGMT Params - Success Passed Ext Adv MGMT Params - (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0746 seconds mgmt-tester -s "Ext Adv MGMT -" Test Summary ------------ Ext Adv MGMT - Data set without Params Passed Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed Ext Adv MGMT - AD Data (5.0) Success Passed Ext Adv MGMT - AD Scan Response (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0805 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 07:58:40 +08:00
instance = hci_sent_cmd_data(hdev, HCI_OP_LE_REMOVE_ADV_SET);
if (!instance)
return rp->status;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2 This make use of hci_cmd_sync_queue for the following MGMT commands: Add Advertising Remove Advertising Add Extended Advertising Parameters Add Extended Advertising Data mgmt-tester -s "Add Advertising" Test Summary ------------ Add Advertising - Failure: LE off Passed Add Advertising - Invalid Params 1 (AD too long) Passed Add Advertising - Invalid Params 2 (Malformed len) Passed Add Advertising - Invalid Params 3 (Malformed len) Passed Add Advertising - Invalid Params 4 (Malformed len) Passed Add Advertising - Invalid Params 5 (AD too long) Passed Add Advertising - Invalid Params 6 (ScRsp too long) Passed Add Advertising - Invalid Params 7 (Malformed len) Passed Add Advertising - Invalid Params 8 (Malformed len) Passed Add Advertising - Invalid Params 9 (Malformed len) Passed Add Advertising - Invalid Params 10 (ScRsp too long) Passed Add Advertising - Rejected (Timeout, !Powered) Passed Add Advertising - Success 1 (Powered, Add Adv Inst) Passed Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed Add Advertising - Success 3 (!Powered, Adv Enable) Passed Add Advertising - Success 4 (Set Adv on override) Passed Add Advertising - Success 5 (Set Adv off override) Passed Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed Add Advertising - Success 8 (Connectable Flag) Passed Add Advertising - Success 9 (General Discov Flag) Passed Add Advertising - Success 10 (Limited Discov Flag) Passed Add Advertising - Success 11 (Managed Flags) Passed Add Advertising - Success 12 (TX Power Flag) Passed Add Advertising - Success 13 (ADV_SCAN_IND) Passed Add Advertising - Success 14 (ADV_NONCONN_IND) Passed Add Advertising - Success 15 (ADV_IND) Passed Add Advertising - Success 16 (Connectable -> on) Passed Add Advertising - Success 17 (Connectable -> off) Passed Add Advertising - Success 18 (Power -> off, Remove) Passed Add Advertising - Success 19 (Power -> off, Keep) Passed Add Advertising - Success 20 (Add Adv override) Passed Add Advertising - Success 21 (Timeout expires) Passed Add Advertising - Success 22 (LE -> off, Remove) Passed Add Advertising - Success (Empty ScRsp) Passed Add Advertising - Success (ScRsp only) Passed Add Advertising - Invalid Params (ScRsp too long) Passed Add Advertising - Success (ScRsp appear) Passed Add Advertising - Invalid Params (ScRsp appear long) Passed Add Advertising - Success (Appear is null) Passed Add Advertising - Success (Name is null) Passed Add Advertising - Success (Complete name) Passed Add Advertising - Success (Shortened name) Passed Add Advertising - Success (Short name) Passed Add Advertising - Success (Name + data) Passed Add Advertising - Invalid Params (Name + data) Passed Add Advertising - Success (Name+data+appear) Passed Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 2.17 seconds mgmt-tester -s "Remove Advertising" Test Summary ------------ Remove Advertising - Invalid Params 1 Passed Remove Advertising - Success 1 Passed Remove Advertising - Success 2 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0585 seconds mgmt-tester -s "Ext Adv MGMT Params" Test Summary: ------------ Ext Adv MGMT Params - Unpowered Passed Ext Adv MGMT Params - Invalid parameters Passed Ext Adv MGMT Params - Success Passed Ext Adv MGMT Params - (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0746 seconds mgmt-tester -s "Ext Adv MGMT -" Test Summary ------------ Ext Adv MGMT - Data set without Params Passed Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed Ext Adv MGMT - AD Data (5.0) Success Passed Ext Adv MGMT - AD Scan Response (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0805 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 07:58:40 +08:00
hci_dev_lock(hdev);
err = hci_remove_adv_instance(hdev, *instance);
if (!err)
mgmt_advertising_removed(hci_skb_sk(hdev->sent_cmd), hdev,
*instance);
hci_dev_unlock(hdev);
return rp->status;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2 This make use of hci_cmd_sync_queue for the following MGMT commands: Add Advertising Remove Advertising Add Extended Advertising Parameters Add Extended Advertising Data mgmt-tester -s "Add Advertising" Test Summary ------------ Add Advertising - Failure: LE off Passed Add Advertising - Invalid Params 1 (AD too long) Passed Add Advertising - Invalid Params 2 (Malformed len) Passed Add Advertising - Invalid Params 3 (Malformed len) Passed Add Advertising - Invalid Params 4 (Malformed len) Passed Add Advertising - Invalid Params 5 (AD too long) Passed Add Advertising - Invalid Params 6 (ScRsp too long) Passed Add Advertising - Invalid Params 7 (Malformed len) Passed Add Advertising - Invalid Params 8 (Malformed len) Passed Add Advertising - Invalid Params 9 (Malformed len) Passed Add Advertising - Invalid Params 10 (ScRsp too long) Passed Add Advertising - Rejected (Timeout, !Powered) Passed Add Advertising - Success 1 (Powered, Add Adv Inst) Passed Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed Add Advertising - Success 3 (!Powered, Adv Enable) Passed Add Advertising - Success 4 (Set Adv on override) Passed Add Advertising - Success 5 (Set Adv off override) Passed Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed Add Advertising - Success 8 (Connectable Flag) Passed Add Advertising - Success 9 (General Discov Flag) Passed Add Advertising - Success 10 (Limited Discov Flag) Passed Add Advertising - Success 11 (Managed Flags) Passed Add Advertising - Success 12 (TX Power Flag) Passed Add Advertising - Success 13 (ADV_SCAN_IND) Passed Add Advertising - Success 14 (ADV_NONCONN_IND) Passed Add Advertising - Success 15 (ADV_IND) Passed Add Advertising - Success 16 (Connectable -> on) Passed Add Advertising - Success 17 (Connectable -> off) Passed Add Advertising - Success 18 (Power -> off, Remove) Passed Add Advertising - Success 19 (Power -> off, Keep) Passed Add Advertising - Success 20 (Add Adv override) Passed Add Advertising - Success 21 (Timeout expires) Passed Add Advertising - Success 22 (LE -> off, Remove) Passed Add Advertising - Success (Empty ScRsp) Passed Add Advertising - Success (ScRsp only) Passed Add Advertising - Invalid Params (ScRsp too long) Passed Add Advertising - Success (ScRsp appear) Passed Add Advertising - Invalid Params (ScRsp appear long) Passed Add Advertising - Success (Appear is null) Passed Add Advertising - Success (Name is null) Passed Add Advertising - Success (Complete name) Passed Add Advertising - Success (Shortened name) Passed Add Advertising - Success (Short name) Passed Add Advertising - Success (Name + data) Passed Add Advertising - Invalid Params (Name + data) Passed Add Advertising - Success (Name+data+appear) Passed Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 2.17 seconds mgmt-tester -s "Remove Advertising" Test Summary ------------ Remove Advertising - Invalid Params 1 Passed Remove Advertising - Success 1 Passed Remove Advertising - Success 2 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0585 seconds mgmt-tester -s "Ext Adv MGMT Params" Test Summary: ------------ Ext Adv MGMT Params - Unpowered Passed Ext Adv MGMT Params - Invalid parameters Passed Ext Adv MGMT Params - Success Passed Ext Adv MGMT Params - (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0746 seconds mgmt-tester -s "Ext Adv MGMT -" Test Summary ------------ Ext Adv MGMT - Data set without Params Passed Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed Ext Adv MGMT - AD Data (5.0) Success Passed Ext Adv MGMT - AD Scan Response (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0805 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 07:58:40 +08:00
}
static u8 hci_cc_le_clear_adv_sets(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2 This make use of hci_cmd_sync_queue for the following MGMT commands: Add Advertising Remove Advertising Add Extended Advertising Parameters Add Extended Advertising Data mgmt-tester -s "Add Advertising" Test Summary ------------ Add Advertising - Failure: LE off Passed Add Advertising - Invalid Params 1 (AD too long) Passed Add Advertising - Invalid Params 2 (Malformed len) Passed Add Advertising - Invalid Params 3 (Malformed len) Passed Add Advertising - Invalid Params 4 (Malformed len) Passed Add Advertising - Invalid Params 5 (AD too long) Passed Add Advertising - Invalid Params 6 (ScRsp too long) Passed Add Advertising - Invalid Params 7 (Malformed len) Passed Add Advertising - Invalid Params 8 (Malformed len) Passed Add Advertising - Invalid Params 9 (Malformed len) Passed Add Advertising - Invalid Params 10 (ScRsp too long) Passed Add Advertising - Rejected (Timeout, !Powered) Passed Add Advertising - Success 1 (Powered, Add Adv Inst) Passed Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed Add Advertising - Success 3 (!Powered, Adv Enable) Passed Add Advertising - Success 4 (Set Adv on override) Passed Add Advertising - Success 5 (Set Adv off override) Passed Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed Add Advertising - Success 8 (Connectable Flag) Passed Add Advertising - Success 9 (General Discov Flag) Passed Add Advertising - Success 10 (Limited Discov Flag) Passed Add Advertising - Success 11 (Managed Flags) Passed Add Advertising - Success 12 (TX Power Flag) Passed Add Advertising - Success 13 (ADV_SCAN_IND) Passed Add Advertising - Success 14 (ADV_NONCONN_IND) Passed Add Advertising - Success 15 (ADV_IND) Passed Add Advertising - Success 16 (Connectable -> on) Passed Add Advertising - Success 17 (Connectable -> off) Passed Add Advertising - Success 18 (Power -> off, Remove) Passed Add Advertising - Success 19 (Power -> off, Keep) Passed Add Advertising - Success 20 (Add Adv override) Passed Add Advertising - Success 21 (Timeout expires) Passed Add Advertising - Success 22 (LE -> off, Remove) Passed Add Advertising - Success (Empty ScRsp) Passed Add Advertising - Success (ScRsp only) Passed Add Advertising - Invalid Params (ScRsp too long) Passed Add Advertising - Success (ScRsp appear) Passed Add Advertising - Invalid Params (ScRsp appear long) Passed Add Advertising - Success (Appear is null) Passed Add Advertising - Success (Name is null) Passed Add Advertising - Success (Complete name) Passed Add Advertising - Success (Shortened name) Passed Add Advertising - Success (Short name) Passed Add Advertising - Success (Name + data) Passed Add Advertising - Invalid Params (Name + data) Passed Add Advertising - Success (Name+data+appear) Passed Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 2.17 seconds mgmt-tester -s "Remove Advertising" Test Summary ------------ Remove Advertising - Invalid Params 1 Passed Remove Advertising - Success 1 Passed Remove Advertising - Success 2 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0585 seconds mgmt-tester -s "Ext Adv MGMT Params" Test Summary: ------------ Ext Adv MGMT Params - Unpowered Passed Ext Adv MGMT Params - Invalid parameters Passed Ext Adv MGMT Params - Success Passed Ext Adv MGMT Params - (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0746 seconds mgmt-tester -s "Ext Adv MGMT -" Test Summary ------------ Ext Adv MGMT - Data set without Params Passed Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed Ext Adv MGMT - AD Data (5.0) Success Passed Ext Adv MGMT - AD Scan Response (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0805 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 07:58:40 +08:00
{
struct hci_ev_status *rp = data;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2 This make use of hci_cmd_sync_queue for the following MGMT commands: Add Advertising Remove Advertising Add Extended Advertising Parameters Add Extended Advertising Data mgmt-tester -s "Add Advertising" Test Summary ------------ Add Advertising - Failure: LE off Passed Add Advertising - Invalid Params 1 (AD too long) Passed Add Advertising - Invalid Params 2 (Malformed len) Passed Add Advertising - Invalid Params 3 (Malformed len) Passed Add Advertising - Invalid Params 4 (Malformed len) Passed Add Advertising - Invalid Params 5 (AD too long) Passed Add Advertising - Invalid Params 6 (ScRsp too long) Passed Add Advertising - Invalid Params 7 (Malformed len) Passed Add Advertising - Invalid Params 8 (Malformed len) Passed Add Advertising - Invalid Params 9 (Malformed len) Passed Add Advertising - Invalid Params 10 (ScRsp too long) Passed Add Advertising - Rejected (Timeout, !Powered) Passed Add Advertising - Success 1 (Powered, Add Adv Inst) Passed Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed Add Advertising - Success 3 (!Powered, Adv Enable) Passed Add Advertising - Success 4 (Set Adv on override) Passed Add Advertising - Success 5 (Set Adv off override) Passed Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed Add Advertising - Success 8 (Connectable Flag) Passed Add Advertising - Success 9 (General Discov Flag) Passed Add Advertising - Success 10 (Limited Discov Flag) Passed Add Advertising - Success 11 (Managed Flags) Passed Add Advertising - Success 12 (TX Power Flag) Passed Add Advertising - Success 13 (ADV_SCAN_IND) Passed Add Advertising - Success 14 (ADV_NONCONN_IND) Passed Add Advertising - Success 15 (ADV_IND) Passed Add Advertising - Success 16 (Connectable -> on) Passed Add Advertising - Success 17 (Connectable -> off) Passed Add Advertising - Success 18 (Power -> off, Remove) Passed Add Advertising - Success 19 (Power -> off, Keep) Passed Add Advertising - Success 20 (Add Adv override) Passed Add Advertising - Success 21 (Timeout expires) Passed Add Advertising - Success 22 (LE -> off, Remove) Passed Add Advertising - Success (Empty ScRsp) Passed Add Advertising - Success (ScRsp only) Passed Add Advertising - Invalid Params (ScRsp too long) Passed Add Advertising - Success (ScRsp appear) Passed Add Advertising - Invalid Params (ScRsp appear long) Passed Add Advertising - Success (Appear is null) Passed Add Advertising - Success (Name is null) Passed Add Advertising - Success (Complete name) Passed Add Advertising - Success (Shortened name) Passed Add Advertising - Success (Short name) Passed Add Advertising - Success (Name + data) Passed Add Advertising - Invalid Params (Name + data) Passed Add Advertising - Success (Name+data+appear) Passed Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 2.17 seconds mgmt-tester -s "Remove Advertising" Test Summary ------------ Remove Advertising - Invalid Params 1 Passed Remove Advertising - Success 1 Passed Remove Advertising - Success 2 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0585 seconds mgmt-tester -s "Ext Adv MGMT Params" Test Summary: ------------ Ext Adv MGMT Params - Unpowered Passed Ext Adv MGMT Params - Invalid parameters Passed Ext Adv MGMT Params - Success Passed Ext Adv MGMT Params - (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0746 seconds mgmt-tester -s "Ext Adv MGMT -" Test Summary ------------ Ext Adv MGMT - Data set without Params Passed Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed Ext Adv MGMT - AD Data (5.0) Success Passed Ext Adv MGMT - AD Scan Response (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0805 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 07:58:40 +08:00
struct adv_info *adv, *n;
int err;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2 This make use of hci_cmd_sync_queue for the following MGMT commands: Add Advertising Remove Advertising Add Extended Advertising Parameters Add Extended Advertising Data mgmt-tester -s "Add Advertising" Test Summary ------------ Add Advertising - Failure: LE off Passed Add Advertising - Invalid Params 1 (AD too long) Passed Add Advertising - Invalid Params 2 (Malformed len) Passed Add Advertising - Invalid Params 3 (Malformed len) Passed Add Advertising - Invalid Params 4 (Malformed len) Passed Add Advertising - Invalid Params 5 (AD too long) Passed Add Advertising - Invalid Params 6 (ScRsp too long) Passed Add Advertising - Invalid Params 7 (Malformed len) Passed Add Advertising - Invalid Params 8 (Malformed len) Passed Add Advertising - Invalid Params 9 (Malformed len) Passed Add Advertising - Invalid Params 10 (ScRsp too long) Passed Add Advertising - Rejected (Timeout, !Powered) Passed Add Advertising - Success 1 (Powered, Add Adv Inst) Passed Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed Add Advertising - Success 3 (!Powered, Adv Enable) Passed Add Advertising - Success 4 (Set Adv on override) Passed Add Advertising - Success 5 (Set Adv off override) Passed Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed Add Advertising - Success 8 (Connectable Flag) Passed Add Advertising - Success 9 (General Discov Flag) Passed Add Advertising - Success 10 (Limited Discov Flag) Passed Add Advertising - Success 11 (Managed Flags) Passed Add Advertising - Success 12 (TX Power Flag) Passed Add Advertising - Success 13 (ADV_SCAN_IND) Passed Add Advertising - Success 14 (ADV_NONCONN_IND) Passed Add Advertising - Success 15 (ADV_IND) Passed Add Advertising - Success 16 (Connectable -> on) Passed Add Advertising - Success 17 (Connectable -> off) Passed Add Advertising - Success 18 (Power -> off, Remove) Passed Add Advertising - Success 19 (Power -> off, Keep) Passed Add Advertising - Success 20 (Add Adv override) Passed Add Advertising - Success 21 (Timeout expires) Passed Add Advertising - Success 22 (LE -> off, Remove) Passed Add Advertising - Success (Empty ScRsp) Passed Add Advertising - Success (ScRsp only) Passed Add Advertising - Invalid Params (ScRsp too long) Passed Add Advertising - Success (ScRsp appear) Passed Add Advertising - Invalid Params (ScRsp appear long) Passed Add Advertising - Success (Appear is null) Passed Add Advertising - Success (Name is null) Passed Add Advertising - Success (Complete name) Passed Add Advertising - Success (Shortened name) Passed Add Advertising - Success (Short name) Passed Add Advertising - Success (Name + data) Passed Add Advertising - Invalid Params (Name + data) Passed Add Advertising - Success (Name+data+appear) Passed Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 2.17 seconds mgmt-tester -s "Remove Advertising" Test Summary ------------ Remove Advertising - Invalid Params 1 Passed Remove Advertising - Success 1 Passed Remove Advertising - Success 2 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0585 seconds mgmt-tester -s "Ext Adv MGMT Params" Test Summary: ------------ Ext Adv MGMT Params - Unpowered Passed Ext Adv MGMT Params - Invalid parameters Passed Ext Adv MGMT Params - Success Passed Ext Adv MGMT Params - (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0746 seconds mgmt-tester -s "Ext Adv MGMT -" Test Summary ------------ Ext Adv MGMT - Data set without Params Passed Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed Ext Adv MGMT - AD Data (5.0) Success Passed Ext Adv MGMT - AD Scan Response (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0805 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 07:58:40 +08:00
if (!hci_sent_cmd_data(hdev, HCI_OP_LE_CLEAR_ADV_SETS))
return rp->status;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2 This make use of hci_cmd_sync_queue for the following MGMT commands: Add Advertising Remove Advertising Add Extended Advertising Parameters Add Extended Advertising Data mgmt-tester -s "Add Advertising" Test Summary ------------ Add Advertising - Failure: LE off Passed Add Advertising - Invalid Params 1 (AD too long) Passed Add Advertising - Invalid Params 2 (Malformed len) Passed Add Advertising - Invalid Params 3 (Malformed len) Passed Add Advertising - Invalid Params 4 (Malformed len) Passed Add Advertising - Invalid Params 5 (AD too long) Passed Add Advertising - Invalid Params 6 (ScRsp too long) Passed Add Advertising - Invalid Params 7 (Malformed len) Passed Add Advertising - Invalid Params 8 (Malformed len) Passed Add Advertising - Invalid Params 9 (Malformed len) Passed Add Advertising - Invalid Params 10 (ScRsp too long) Passed Add Advertising - Rejected (Timeout, !Powered) Passed Add Advertising - Success 1 (Powered, Add Adv Inst) Passed Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed Add Advertising - Success 3 (!Powered, Adv Enable) Passed Add Advertising - Success 4 (Set Adv on override) Passed Add Advertising - Success 5 (Set Adv off override) Passed Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed Add Advertising - Success 8 (Connectable Flag) Passed Add Advertising - Success 9 (General Discov Flag) Passed Add Advertising - Success 10 (Limited Discov Flag) Passed Add Advertising - Success 11 (Managed Flags) Passed Add Advertising - Success 12 (TX Power Flag) Passed Add Advertising - Success 13 (ADV_SCAN_IND) Passed Add Advertising - Success 14 (ADV_NONCONN_IND) Passed Add Advertising - Success 15 (ADV_IND) Passed Add Advertising - Success 16 (Connectable -> on) Passed Add Advertising - Success 17 (Connectable -> off) Passed Add Advertising - Success 18 (Power -> off, Remove) Passed Add Advertising - Success 19 (Power -> off, Keep) Passed Add Advertising - Success 20 (Add Adv override) Passed Add Advertising - Success 21 (Timeout expires) Passed Add Advertising - Success 22 (LE -> off, Remove) Passed Add Advertising - Success (Empty ScRsp) Passed Add Advertising - Success (ScRsp only) Passed Add Advertising - Invalid Params (ScRsp too long) Passed Add Advertising - Success (ScRsp appear) Passed Add Advertising - Invalid Params (ScRsp appear long) Passed Add Advertising - Success (Appear is null) Passed Add Advertising - Success (Name is null) Passed Add Advertising - Success (Complete name) Passed Add Advertising - Success (Shortened name) Passed Add Advertising - Success (Short name) Passed Add Advertising - Success (Name + data) Passed Add Advertising - Invalid Params (Name + data) Passed Add Advertising - Success (Name+data+appear) Passed Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 2.17 seconds mgmt-tester -s "Remove Advertising" Test Summary ------------ Remove Advertising - Invalid Params 1 Passed Remove Advertising - Success 1 Passed Remove Advertising - Success 2 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0585 seconds mgmt-tester -s "Ext Adv MGMT Params" Test Summary: ------------ Ext Adv MGMT Params - Unpowered Passed Ext Adv MGMT Params - Invalid parameters Passed Ext Adv MGMT Params - Success Passed Ext Adv MGMT Params - (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0746 seconds mgmt-tester -s "Ext Adv MGMT -" Test Summary ------------ Ext Adv MGMT - Data set without Params Passed Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed Ext Adv MGMT - AD Data (5.0) Success Passed Ext Adv MGMT - AD Scan Response (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0805 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 07:58:40 +08:00
hci_dev_lock(hdev);
list_for_each_entry_safe(adv, n, &hdev->adv_instances, list) {
u8 instance = adv->instance;
err = hci_remove_adv_instance(hdev, instance);
if (!err)
mgmt_advertising_removed(hci_skb_sk(hdev->sent_cmd),
hdev, instance);
}
hci_dev_unlock(hdev);
return rp->status;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2 This make use of hci_cmd_sync_queue for the following MGMT commands: Add Advertising Remove Advertising Add Extended Advertising Parameters Add Extended Advertising Data mgmt-tester -s "Add Advertising" Test Summary ------------ Add Advertising - Failure: LE off Passed Add Advertising - Invalid Params 1 (AD too long) Passed Add Advertising - Invalid Params 2 (Malformed len) Passed Add Advertising - Invalid Params 3 (Malformed len) Passed Add Advertising - Invalid Params 4 (Malformed len) Passed Add Advertising - Invalid Params 5 (AD too long) Passed Add Advertising - Invalid Params 6 (ScRsp too long) Passed Add Advertising - Invalid Params 7 (Malformed len) Passed Add Advertising - Invalid Params 8 (Malformed len) Passed Add Advertising - Invalid Params 9 (Malformed len) Passed Add Advertising - Invalid Params 10 (ScRsp too long) Passed Add Advertising - Rejected (Timeout, !Powered) Passed Add Advertising - Success 1 (Powered, Add Adv Inst) Passed Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed Add Advertising - Success 3 (!Powered, Adv Enable) Passed Add Advertising - Success 4 (Set Adv on override) Passed Add Advertising - Success 5 (Set Adv off override) Passed Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed Add Advertising - Success 8 (Connectable Flag) Passed Add Advertising - Success 9 (General Discov Flag) Passed Add Advertising - Success 10 (Limited Discov Flag) Passed Add Advertising - Success 11 (Managed Flags) Passed Add Advertising - Success 12 (TX Power Flag) Passed Add Advertising - Success 13 (ADV_SCAN_IND) Passed Add Advertising - Success 14 (ADV_NONCONN_IND) Passed Add Advertising - Success 15 (ADV_IND) Passed Add Advertising - Success 16 (Connectable -> on) Passed Add Advertising - Success 17 (Connectable -> off) Passed Add Advertising - Success 18 (Power -> off, Remove) Passed Add Advertising - Success 19 (Power -> off, Keep) Passed Add Advertising - Success 20 (Add Adv override) Passed Add Advertising - Success 21 (Timeout expires) Passed Add Advertising - Success 22 (LE -> off, Remove) Passed Add Advertising - Success (Empty ScRsp) Passed Add Advertising - Success (ScRsp only) Passed Add Advertising - Invalid Params (ScRsp too long) Passed Add Advertising - Success (ScRsp appear) Passed Add Advertising - Invalid Params (ScRsp appear long) Passed Add Advertising - Success (Appear is null) Passed Add Advertising - Success (Name is null) Passed Add Advertising - Success (Complete name) Passed Add Advertising - Success (Shortened name) Passed Add Advertising - Success (Short name) Passed Add Advertising - Success (Name + data) Passed Add Advertising - Invalid Params (Name + data) Passed Add Advertising - Success (Name+data+appear) Passed Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 2.17 seconds mgmt-tester -s "Remove Advertising" Test Summary ------------ Remove Advertising - Invalid Params 1 Passed Remove Advertising - Success 1 Passed Remove Advertising - Success 2 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0585 seconds mgmt-tester -s "Ext Adv MGMT Params" Test Summary: ------------ Ext Adv MGMT Params - Unpowered Passed Ext Adv MGMT Params - Invalid parameters Passed Ext Adv MGMT Params - Success Passed Ext Adv MGMT Params - (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0746 seconds mgmt-tester -s "Ext Adv MGMT -" Test Summary ------------ Ext Adv MGMT - Data set without Params Passed Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed Ext Adv MGMT - AD Data (5.0) Success Passed Ext Adv MGMT - AD Scan Response (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0805 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 07:58:40 +08:00
}
static u8 hci_cc_le_read_transmit_power(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_le_read_transmit_power *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hdev->min_le_tx_power = rp->min_le_tx_power;
hdev->max_le_tx_power = rp->max_le_tx_power;
return rp->status;
}
static u8 hci_cc_le_set_privacy_mode(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
struct hci_cp_le_set_privacy_mode *cp;
struct hci_conn_params *params;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_PRIVACY_MODE);
if (!cp)
return rp->status;
hci_dev_lock(hdev);
params = hci_conn_params_lookup(hdev, &cp->bdaddr, cp->bdaddr_type);
if (params)
params->privacy_mode = cp->mode;
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_le_set_adv_enable(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
__u8 *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE);
if (!sent)
return rp->status;
hci_dev_lock(hdev);
/* If we're doing connection initiation as peripheral. Set a
* timeout in case something goes wrong.
*/
if (*sent) {
struct hci_conn *conn;
hci_dev_set_flag(hdev, HCI_LE_ADV);
conn = hci_lookup_le_connect(hdev);
if (conn)
queue_delayed_work(hdev->workqueue,
&conn->le_conn_timeout,
conn->conn_timeout);
} else {
hci_dev_clear_flag(hdev, HCI_LE_ADV);
}
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
{
struct hci_cp_le_set_ext_adv_enable *cp;
struct hci_cp_ext_adv_set *set;
struct adv_info *adv = NULL, *n;
struct hci_ev_status *rp = data;
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE);
if (!cp)
return rp->status;
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
set = (void *)cp->data;
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
hci_dev_lock(hdev);
if (cp->num_of_sets)
adv = hci_find_adv_instance(hdev, set->handle);
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
if (cp->enable) {
struct hci_conn *conn;
hci_dev_set_flag(hdev, HCI_LE_ADV);
if (adv)
adv->enabled = true;
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
conn = hci_lookup_le_connect(hdev);
if (conn)
queue_delayed_work(hdev->workqueue,
&conn->le_conn_timeout,
conn->conn_timeout);
} else {
if (cp->num_of_sets) {
if (adv)
adv->enabled = false;
/* If just one instance was disabled check if there are
* any other instance enabled before clearing HCI_LE_ADV
*/
list_for_each_entry_safe(adv, n, &hdev->adv_instances,
list) {
if (adv->enabled)
goto unlock;
}
} else {
/* All instances shall be considered disabled */
list_for_each_entry_safe(adv, n, &hdev->adv_instances,
list)
adv->enabled = false;
}
hci_dev_clear_flag(hdev, HCI_LE_ADV);
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
}
unlock:
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
hci_dev_unlock(hdev);
return rp->status;
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
}
static u8 hci_cc_le_set_scan_param(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_cp_le_set_scan_param *cp;
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM);
if (!cp)
return rp->status;
hci_dev_lock(hdev);
hdev->le_scan_type = cp->type;
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_le_set_ext_scan_param(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_cp_le_set_ext_scan_params *cp;
struct hci_ev_status *rp = data;
struct hci_cp_le_scan_phy_params *phy_param;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_PARAMS);
if (!cp)
return rp->status;
phy_param = (void *)cp->data;
hci_dev_lock(hdev);
hdev->le_scan_type = phy_param->type;
hci_dev_unlock(hdev);
return rp->status;
}
static bool has_pending_adv_report(struct hci_dev *hdev)
{
struct discovery_state *d = &hdev->discovery;
return bacmp(&d->last_adv_addr, BDADDR_ANY);
}
static void clear_pending_adv_report(struct hci_dev *hdev)
{
struct discovery_state *d = &hdev->discovery;
bacpy(&d->last_adv_addr, BDADDR_ANY);
d->last_adv_data_len = 0;
}
static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 bdaddr_type, s8 rssi, u32 flags,
u8 *data, u8 len)
{
struct discovery_state *d = &hdev->discovery;
Bluetooth: fix kernel oops in store_pending_adv_report Fix kernel oops observed when an ext adv data is larger than 31 bytes. This can be reproduced by setting up an advertiser with advertisement larger than 31 bytes. The issue is not sensitive to the advertisement content. In particular, this was reproduced with an advertisement of 229 bytes filled with 'A'. See stack trace below. This is fixed by not catching ext_adv as legacy adv are only cached to be able to concatenate a scanable adv with its scan response before sending it up through mgmt. With ext_adv, this is no longer necessary. general protection fault: 0000 [#1] SMP PTI CPU: 6 PID: 205 Comm: kworker/u17:0 Not tainted 5.4.0-37-generic #41-Ubuntu Hardware name: Dell Inc. XPS 15 7590/0CF6RR, BIOS 1.7.0 05/11/2020 Workqueue: hci0 hci_rx_work [bluetooth] RIP: 0010:hci_bdaddr_list_lookup+0x1e/0x40 [bluetooth] Code: ff ff e9 26 ff ff ff 0f 1f 44 00 00 0f 1f 44 00 00 55 48 8b 07 48 89 e5 48 39 c7 75 0a eb 24 48 8b 00 48 39 f8 74 1c 44 8b 06 <44> 39 40 10 75 ef 44 0f b7 4e 04 66 44 39 48 14 75 e3 38 50 16 75 RSP: 0018:ffffbc6a40493c70 EFLAGS: 00010286 RAX: 4141414141414141 RBX: 000000000000001b RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff9903e76c100f RDI: ffff9904289d4b28 RBP: ffffbc6a40493c70 R08: 0000000093570362 R09: 0000000000000000 R10: 0000000000000000 R11: ffff9904344eae38 R12: ffff9904289d4000 R13: 0000000000000000 R14: 00000000ffffffa3 R15: ffff9903e76c100f FS: 0000000000000000(0000) GS:ffff990434580000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007feed125a000 CR3: 00000001b860a003 CR4: 00000000003606e0 Call Trace: process_adv_report+0x12e/0x560 [bluetooth] hci_le_meta_evt+0x7b2/0xba0 [bluetooth] hci_event_packet+0x1c29/0x2a90 [bluetooth] hci_rx_work+0x19b/0x360 [bluetooth] process_one_work+0x1eb/0x3b0 worker_thread+0x4d/0x400 kthread+0x104/0x140 Fixes: c215e9397b00 ("Bluetooth: Process extended ADV report event") Reported-by: Andy Nguyen <theflow@google.com> Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Reported-by: Balakrishna Godavarthi <bgodavar@codeaurora.org> Signed-off-by: Alain Michaud <alainm@chromium.org> Tested-by: Sonny Sasaka <sonnysasaka@chromium.org> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2020-07-28 04:48:55 +08:00
if (len > HCI_MAX_AD_LENGTH)
return;
bacpy(&d->last_adv_addr, bdaddr);
d->last_adv_addr_type = bdaddr_type;
d->last_adv_rssi = rssi;
d->last_adv_flags = flags;
memcpy(d->last_adv_data, data, len);
d->last_adv_data_len = len;
}
static void le_set_scan_enable_complete(struct hci_dev *hdev, u8 enable)
{
hci_dev_lock(hdev);
switch (enable) {
case LE_SCAN_ENABLE:
hci_dev_set_flag(hdev, HCI_LE_SCAN);
if (hdev->le_scan_type == LE_SCAN_ACTIVE)
clear_pending_adv_report(hdev);
break;
case LE_SCAN_DISABLE:
/* We do this here instead of when setting DISCOVERY_STOPPED
* since the latter would potentially require waiting for
* inquiry to stop too.
*/
if (has_pending_adv_report(hdev)) {
struct discovery_state *d = &hdev->discovery;
mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
d->last_adv_addr_type, NULL,
d->last_adv_rssi, d->last_adv_flags,
d->last_adv_data,
d->last_adv_data_len, NULL, 0);
}
/* Cancel this timer so that we don't try to disable scanning
* when it's already disabled.
*/
cancel_delayed_work(&hdev->le_scan_disable);
hci_dev_clear_flag(hdev, HCI_LE_SCAN);
/* The HCI_LE_SCAN_INTERRUPTED flag indicates that we
* interrupted scanning due to a connect request. Mark
Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY This make use of hci_cmd_sync_queue for MGMT_OP_START_DISCOVERY, MGMT_OP_START_SERVICE_DISCOVERY and MGMT_OP_STOP_DISCOVERY to use hci_cmd_sync_queue so they no longer depend on hdev->discov_update work to send any commands. Tested with: tools/mgmt-tester -s "Start Discovery" Test Summary ------------ Start Discovery - Not powered 1 Passed Start Discovery - Invalid parameters 1 Passed Start Discovery - Not supported 1 Passed Start Discovery - Success 1 Passed Start Discovery - Success 2 Passed Start Discovery - Power Off 1 Passed Start Discovery BREDR LE - (Ext Scan Enable) Passed Start Discovery LE - (Ext Scan Enable) Passed Start Discovery LE - (Ext Scan Param) Passed Start Discovery - (2m, Scan Param) Passed Start Discovery - (coded, Scan Param) Passed Start Discovery - (1m, 2m, coded, Scan Param) Passed LL Privacy - Start Discovery 1 (Disable RL) Passed LL Privacy - Start Discovery 2 (Disable RL) Passed Total: 14, Passed: 14 (100.0%), Failed: 0, Not Run: 0 tools/mgmt-tester -s "Start Service" Test Summary ------------ Start Service Discovery - Not powered 1 Passed Start Service Discovery - Invalid parameters 1 Passed Start Service Discovery - Not supported 1 Passed Start Service Discovery - Success 1 Passed Start Service Discovery - Success 2 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 tools/mgmt-tester -s "Stop Discovery" Test Summary ------------ Stop Discovery - Success 1 Passed Stop Discovery - BR/EDR (Inquiry) Success 1 Passed Stop Discovery - Rejected 1 Passed Stop Discovery - Invalid parameters 1 Passed Stop Discovery - (Ext Scan Disable) Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 07:58:45 +08:00
* therefore discovery as stopped.
*/
if (hci_dev_test_and_clear_flag(hdev, HCI_LE_SCAN_INTERRUPTED))
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
break;
default:
bt_dev_err(hdev, "use of reserved LE_Scan_Enable param %d",
enable);
break;
}
hci_dev_unlock(hdev);
}
static u8 hci_cc_le_set_scan_enable(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_cp_le_set_scan_enable *cp;
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE);
if (!cp)
return rp->status;
le_set_scan_enable_complete(hdev, cp->enable);
return rp->status;
}
static u8 hci_cc_le_set_ext_scan_enable(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_cp_le_set_ext_scan_enable *cp;
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_SCAN_ENABLE);
if (!cp)
return rp->status;
le_set_scan_enable_complete(hdev, cp->enable);
return rp->status;
}
static u8 hci_cc_le_read_num_adv_sets(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_le_read_num_supported_adv_sets *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x No of Adv sets %u", rp->status,
rp->num_of_sets);
if (rp->status)
return rp->status;
hdev->le_num_of_adv_sets = rp->num_of_sets;
return rp->status;
}
static u8 hci_cc_le_read_accept_list_size(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_le_read_accept_list_size *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x size %u", rp->status, rp->size);
if (rp->status)
return rp->status;
hdev->le_accept_list_size = rp->size;
return rp->status;
}
static u8 hci_cc_le_clear_accept_list(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hci_bdaddr_list_clear(&hdev->le_accept_list);
return rp->status;
}
static u8 hci_cc_le_add_to_accept_list(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_cp_le_add_to_accept_list *sent;
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_ACCEPT_LIST);
if (!sent)
return rp->status;
hci_bdaddr_list_add(&hdev->le_accept_list, &sent->bdaddr,
sent->bdaddr_type);
return rp->status;
}
static u8 hci_cc_le_del_from_accept_list(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_cp_le_del_from_accept_list *sent;
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_ACCEPT_LIST);
if (!sent)
return rp->status;
hci_bdaddr_list_del(&hdev->le_accept_list, &sent->bdaddr,
sent->bdaddr_type);
return rp->status;
}
static u8 hci_cc_le_read_supported_states(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_le_read_supported_states *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
memcpy(hdev->le_states, rp->le_states, 8);
return rp->status;
}
static u8 hci_cc_le_read_def_data_len(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_le_read_def_data_len *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hdev->le_def_tx_len = le16_to_cpu(rp->tx_len);
hdev->le_def_tx_time = le16_to_cpu(rp->tx_time);
return rp->status;
}
static u8 hci_cc_le_write_def_data_len(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_cp_le_write_def_data_len *sent;
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_LE_WRITE_DEF_DATA_LEN);
if (!sent)
return rp->status;
hdev->le_def_tx_len = le16_to_cpu(sent->tx_len);
hdev->le_def_tx_time = le16_to_cpu(sent->tx_time);
return rp->status;
}
static u8 hci_cc_le_add_to_resolv_list(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_cp_le_add_to_resolv_list *sent;
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_RESOLV_LIST);
if (!sent)
return rp->status;
hci_bdaddr_list_add_with_irk(&hdev->le_resolv_list, &sent->bdaddr,
sent->bdaddr_type, sent->peer_irk,
sent->local_irk);
return rp->status;
}
static u8 hci_cc_le_del_from_resolv_list(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_cp_le_del_from_resolv_list *sent;
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_RESOLV_LIST);
if (!sent)
return rp->status;
hci_bdaddr_list_del_with_irk(&hdev->le_resolv_list, &sent->bdaddr,
sent->bdaddr_type);
return rp->status;
}
static u8 hci_cc_le_clear_resolv_list(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
Bluetooth: Add HCI command for clear Resolv list Check for Resolv list supported by controller. So check the supported commmand first before issuing this command i.e.,HCI_OP_LE_CLEAR_RESOLV_LIST Before patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 13.338168 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 13.338842 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 13.339029 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 13.339939 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Resolving L.. (0x08|0x002a) plen 0 #59 [hci0] 13.340152 > HCI Event: Command Complete (0x0e) plen 5 #60 [hci0] 13.340952 LE Read Resolving List Size (0x08|0x002a) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #61 [hci0] 13.341180 > HCI Event: Command Complete (0x0e) plen 12 #62 [hci0] 13.341898 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 After patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 28.919131 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 28.920016 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 28.920164 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 28.920873 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Resolving L.. (0x08|0x002a) plen 0 #59 [hci0] 28.921109 > HCI Event: Command Complete (0x0e) plen 5 #60 [hci0] 28.922016 LE Read Resolving List Size (0x08|0x002a) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear Resolving... (0x08|0x0029) plen 0 #61 [hci0] 28.922166 > HCI Event: Command Complete (0x0e) plen 4 #62 [hci0] 28.922872 LE Clear Resolving List (0x08|0x0029) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #63 [hci0] 28.923117 > HCI Event: Command Complete (0x0e) plen 12 #64 [hci0] 28.924030 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 Signed-off-by: Ankit Navik <ankit.p.navik@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-06-29 14:43:20 +08:00
{
struct hci_ev_status *rp = data;
Bluetooth: Add HCI command for clear Resolv list Check for Resolv list supported by controller. So check the supported commmand first before issuing this command i.e.,HCI_OP_LE_CLEAR_RESOLV_LIST Before patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 13.338168 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 13.338842 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 13.339029 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 13.339939 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Resolving L.. (0x08|0x002a) plen 0 #59 [hci0] 13.340152 > HCI Event: Command Complete (0x0e) plen 5 #60 [hci0] 13.340952 LE Read Resolving List Size (0x08|0x002a) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #61 [hci0] 13.341180 > HCI Event: Command Complete (0x0e) plen 12 #62 [hci0] 13.341898 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 After patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 28.919131 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 28.920016 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 28.920164 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 28.920873 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Resolving L.. (0x08|0x002a) plen 0 #59 [hci0] 28.921109 > HCI Event: Command Complete (0x0e) plen 5 #60 [hci0] 28.922016 LE Read Resolving List Size (0x08|0x002a) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear Resolving... (0x08|0x0029) plen 0 #61 [hci0] 28.922166 > HCI Event: Command Complete (0x0e) plen 4 #62 [hci0] 28.922872 LE Clear Resolving List (0x08|0x0029) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #63 [hci0] 28.923117 > HCI Event: Command Complete (0x0e) plen 12 #64 [hci0] 28.924030 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 Signed-off-by: Ankit Navik <ankit.p.navik@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-06-29 14:43:20 +08:00
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
Bluetooth: Add HCI command for clear Resolv list Check for Resolv list supported by controller. So check the supported commmand first before issuing this command i.e.,HCI_OP_LE_CLEAR_RESOLV_LIST Before patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 13.338168 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 13.338842 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 13.339029 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 13.339939 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Resolving L.. (0x08|0x002a) plen 0 #59 [hci0] 13.340152 > HCI Event: Command Complete (0x0e) plen 5 #60 [hci0] 13.340952 LE Read Resolving List Size (0x08|0x002a) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #61 [hci0] 13.341180 > HCI Event: Command Complete (0x0e) plen 12 #62 [hci0] 13.341898 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 After patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 28.919131 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 28.920016 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 28.920164 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 28.920873 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Resolving L.. (0x08|0x002a) plen 0 #59 [hci0] 28.921109 > HCI Event: Command Complete (0x0e) plen 5 #60 [hci0] 28.922016 LE Read Resolving List Size (0x08|0x002a) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear Resolving... (0x08|0x0029) plen 0 #61 [hci0] 28.922166 > HCI Event: Command Complete (0x0e) plen 4 #62 [hci0] 28.922872 LE Clear Resolving List (0x08|0x0029) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #63 [hci0] 28.923117 > HCI Event: Command Complete (0x0e) plen 12 #64 [hci0] 28.924030 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 Signed-off-by: Ankit Navik <ankit.p.navik@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-06-29 14:43:20 +08:00
hci_bdaddr_list_clear(&hdev->le_resolv_list);
return rp->status;
Bluetooth: Add HCI command for clear Resolv list Check for Resolv list supported by controller. So check the supported commmand first before issuing this command i.e.,HCI_OP_LE_CLEAR_RESOLV_LIST Before patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 13.338168 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 13.338842 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 13.339029 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 13.339939 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Resolving L.. (0x08|0x002a) plen 0 #59 [hci0] 13.340152 > HCI Event: Command Complete (0x0e) plen 5 #60 [hci0] 13.340952 LE Read Resolving List Size (0x08|0x002a) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #61 [hci0] 13.341180 > HCI Event: Command Complete (0x0e) plen 12 #62 [hci0] 13.341898 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 After patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 28.919131 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 28.920016 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 28.920164 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 28.920873 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Resolving L.. (0x08|0x002a) plen 0 #59 [hci0] 28.921109 > HCI Event: Command Complete (0x0e) plen 5 #60 [hci0] 28.922016 LE Read Resolving List Size (0x08|0x002a) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear Resolving... (0x08|0x0029) plen 0 #61 [hci0] 28.922166 > HCI Event: Command Complete (0x0e) plen 4 #62 [hci0] 28.922872 LE Clear Resolving List (0x08|0x0029) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #63 [hci0] 28.923117 > HCI Event: Command Complete (0x0e) plen 12 #64 [hci0] 28.924030 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 Signed-off-by: Ankit Navik <ankit.p.navik@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-06-29 14:43:20 +08:00
}
static u8 hci_cc_le_read_resolv_list_size(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
Bluetooth: Store Resolv list size When the controller supports the Read LE Resolv List size feature, the maximum list size are read and now stored. Before patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 17.979791 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 17.980629 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 17.980786 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 17.981627 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #59 [hci0] 17.981786 > HCI Event: Command Complete (0x0e) plen 12 #60 [hci0] 17.982636 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 After patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 13.338168 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 13.338842 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 13.339029 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 13.339939 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Resolving L.. (0x08|0x002a) plen 0 #59 [hci0] 13.340152 > HCI Event: Command Complete (0x0e) plen 5 #60 [hci0] 13.340952 LE Read Resolving List Size (0x08|0x002a) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #61 [hci0] 13.341180 > HCI Event: Command Complete (0x0e) plen 12 #62 [hci0] 13.341898 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 Signed-off-by: Ankit Navik <ankit.p.navik@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-06-29 14:42:50 +08:00
{
struct hci_rp_le_read_resolv_list_size *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x size %u", rp->status, rp->size);
Bluetooth: Store Resolv list size When the controller supports the Read LE Resolv List size feature, the maximum list size are read and now stored. Before patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 17.979791 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 17.980629 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 17.980786 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 17.981627 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #59 [hci0] 17.981786 > HCI Event: Command Complete (0x0e) plen 12 #60 [hci0] 17.982636 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 After patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 13.338168 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 13.338842 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 13.339029 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 13.339939 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Resolving L.. (0x08|0x002a) plen 0 #59 [hci0] 13.340152 > HCI Event: Command Complete (0x0e) plen 5 #60 [hci0] 13.340952 LE Read Resolving List Size (0x08|0x002a) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #61 [hci0] 13.341180 > HCI Event: Command Complete (0x0e) plen 12 #62 [hci0] 13.341898 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 Signed-off-by: Ankit Navik <ankit.p.navik@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-06-29 14:42:50 +08:00
if (rp->status)
return rp->status;
Bluetooth: Store Resolv list size When the controller supports the Read LE Resolv List size feature, the maximum list size are read and now stored. Before patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 17.979791 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 17.980629 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 17.980786 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 17.981627 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #59 [hci0] 17.981786 > HCI Event: Command Complete (0x0e) plen 12 #60 [hci0] 17.982636 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 After patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 13.338168 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 13.338842 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 13.339029 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 13.339939 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Resolving L.. (0x08|0x002a) plen 0 #59 [hci0] 13.340152 > HCI Event: Command Complete (0x0e) plen 5 #60 [hci0] 13.340952 LE Read Resolving List Size (0x08|0x002a) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #61 [hci0] 13.341180 > HCI Event: Command Complete (0x0e) plen 12 #62 [hci0] 13.341898 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 Signed-off-by: Ankit Navik <ankit.p.navik@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-06-29 14:42:50 +08:00
hdev->le_resolv_list_size = rp->size;
return rp->status;
Bluetooth: Store Resolv list size When the controller supports the Read LE Resolv List size feature, the maximum list size are read and now stored. Before patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 17.979791 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 17.980629 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 17.980786 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 17.981627 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #59 [hci0] 17.981786 > HCI Event: Command Complete (0x0e) plen 12 #60 [hci0] 17.982636 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 After patch: < HCI Command: LE Read White List... (0x08|0x000f) plen 0 #55 [hci0] 13.338168 > HCI Event: Command Complete (0x0e) plen 5 #56 [hci0] 13.338842 LE Read White List Size (0x08|0x000f) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Clear White List (0x08|0x0010) plen 0 #57 [hci0] 13.339029 > HCI Event: Command Complete (0x0e) plen 4 #58 [hci0] 13.339939 LE Clear White List (0x08|0x0010) ncmd 1 Status: Success (0x00) < HCI Command: LE Read Resolving L.. (0x08|0x002a) plen 0 #59 [hci0] 13.340152 > HCI Event: Command Complete (0x0e) plen 5 #60 [hci0] 13.340952 LE Read Resolving List Size (0x08|0x002a) ncmd 1 Status: Success (0x00) Size: 25 < HCI Command: LE Read Maximum Dat.. (0x08|0x002f) plen 0 #61 [hci0] 13.341180 > HCI Event: Command Complete (0x0e) plen 12 #62 [hci0] 13.341898 LE Read Maximum Data Length (0x08|0x002f) ncmd 1 Status: Success (0x00) Max TX octets: 251 Max TX time: 17040 Max RX octets: 251 Max RX time: 17040 Signed-off-by: Ankit Navik <ankit.p.navik@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-06-29 14:42:50 +08:00
}
static u8 hci_cc_le_set_addr_resolution_enable(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
__u8 *sent;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADDR_RESOLV_ENABLE);
if (!sent)
return rp->status;
hci_dev_lock(hdev);
if (*sent)
hci_dev_set_flag(hdev, HCI_LL_RPA_RESOLUTION);
else
hci_dev_clear_flag(hdev, HCI_LL_RPA_RESOLUTION);
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_le_read_max_data_len(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_le_read_max_data_len *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hdev->le_max_tx_len = le16_to_cpu(rp->tx_len);
hdev->le_max_tx_time = le16_to_cpu(rp->tx_time);
hdev->le_max_rx_len = le16_to_cpu(rp->rx_len);
hdev->le_max_rx_time = le16_to_cpu(rp->rx_time);
return rp->status;
}
static u8 hci_cc_write_le_host_supported(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_cp_write_le_host_supported *sent;
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED);
if (!sent)
return rp->status;
hci_dev_lock(hdev);
if (sent->le) {
hdev->features[1][0] |= LMP_HOST_LE;
hci_dev_set_flag(hdev, HCI_LE_ENABLED);
} else {
hdev->features[1][0] &= ~LMP_HOST_LE;
hci_dev_clear_flag(hdev, HCI_LE_ENABLED);
hci_dev_clear_flag(hdev, HCI_ADVERTISING);
}
if (sent->simul)
hdev->features[1][0] |= LMP_HOST_LE_BREDR;
else
hdev->features[1][0] &= ~LMP_HOST_LE_BREDR;
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_set_adv_param(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_cp_le_set_adv_param *cp;
struct hci_ev_status *rp = data;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM);
if (!cp)
return rp->status;
hci_dev_lock(hdev);
hdev->adv_addr_type = cp->own_address_type;
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_set_ext_adv_param(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
{
struct hci_rp_le_set_ext_adv_params *rp = data;
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
struct hci_cp_le_set_ext_adv_params *cp;
struct adv_info *adv_instance;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
if (rp->status)
return rp->status;
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_EXT_ADV_PARAMS);
if (!cp)
return rp->status;
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
hci_dev_lock(hdev);
hdev->adv_addr_type = cp->own_addr_type;
if (!cp->handle) {
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
/* Store in hdev for instance 0 */
hdev->adv_tx_power = rp->tx_power;
} else {
adv_instance = hci_find_adv_instance(hdev, cp->handle);
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
if (adv_instance)
adv_instance->tx_power = rp->tx_power;
}
/* Update adv data as tx power is known now */
hci_req_update_adv_data(hdev, cp->handle);
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
hci_dev_unlock(hdev);
return rp->status;
Bluetooth: Impmlement extended adv enable This patch basically replaces legacy adv with extended adv based on the controller support. Currently there is no design change. ie only one adv set will be enabled at a time. This also adds tx_power in instance and store whatever returns from Set_ext_parameter, use the same in adv data as well. For instance 0 tx_power is stored in hdev only. < HCI Command: LE Set Extended Advertising Parameters (0x08|0x0036) plen 25 Handle: 0x00 Properties: 0x0010 Use legacy advertising PDUs: ADV_NONCONN_IND Min advertising interval: 1280.000 msec (0x0800) Max advertising interval: 1280.000 msec (0x0800) Channel map: 37, 38, 39 (0x07) Own address type: Random (0x01) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Filter policy: Allow Scan Request from Any, Allow Connect Request from Any (0x00) TX power: 127 dbm (0x7f) Primary PHY: LE 1M (0x01) Secondary max skip: 0x00 Secondary PHY: LE 1M (0x01) SID: 0x00 Scan request notifications: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 5 LE Set Extended Advertising Parameters (0x08|0x0036) ncmd 1 Status: Success (0x00) TX power (selected): 7 dbm (0x07) < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Enabled (0x01) Number of sets: 1 (0x01) Entry 0 Handle: 0x00 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-19 19:39:41 +08:00
}
static u8 hci_cc_read_rssi(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_rp_read_rssi *rp = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
if (conn)
conn->rssi = rp->rssi;
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_read_tx_power(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_cp_read_tx_power *sent;
struct hci_rp_read_tx_power *rp = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
sent = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
if (!sent)
return rp->status;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle));
if (!conn)
goto unlock;
switch (sent->type) {
case 0x00:
conn->tx_power = rp->tx_power;
break;
case 0x01:
conn->max_tx_power = rp->tx_power;
break;
}
unlock:
hci_dev_unlock(hdev);
return rp->status;
}
static u8 hci_cc_write_ssp_debug_mode(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *rp = data;
u8 *mode;
bt_dev_dbg(hdev, "status 0x%2.2x", rp->status);
if (rp->status)
return rp->status;
mode = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE);
if (mode)
hdev->ssp_debug_mode = *mode;
return rp->status;
}
static void hci_cs_inquiry(struct hci_dev *hdev, __u8 status)
{
bt_dev_dbg(hdev, "status 0x%2.2x", status);
if (status) {
hci_conn_check_pending(hdev);
return;
}
set_bit(HCI_INQUIRY, &hdev->flags);
}
static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_create_conn *cp;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
cp = hci_sent_cmd_data(hdev, HCI_OP_CREATE_CONN);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
bt_dev_dbg(hdev, "bdaddr %pMR hcon %p", &cp->bdaddr, conn);
if (status) {
if (conn && conn->state == BT_CONNECT) {
if (status != 0x0c || conn->attempt > 2) {
conn->state = BT_CLOSED;
hci_connect_cfm(conn, status);
hci_conn_del(conn);
} else
conn->state = BT_CONNECT2;
}
} else {
if (!conn) {
conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr,
HCI_ROLE_MASTER);
if (!conn)
bt_dev_err(hdev, "no memory for new connection");
}
}
hci_dev_unlock(hdev);
}
static void hci_cs_add_sco(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_add_sco *cp;
struct hci_conn *acl, *sco;
__u16 handle;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_ADD_SCO);
if (!cp)
return;
handle = __le16_to_cpu(cp->handle);
bt_dev_dbg(hdev, "handle 0x%4.4x", handle);
hci_dev_lock(hdev);
acl = hci_conn_hash_lookup_handle(hdev, handle);
if (acl) {
sco = acl->link;
if (sco) {
sco->state = BT_CLOSED;
hci_connect_cfm(sco, status);
hci_conn_del(sco);
}
}
hci_dev_unlock(hdev);
}
static void hci_cs_auth_requested(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_auth_requested *cp;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_AUTH_REQUESTED);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
if (conn->state == BT_CONFIG) {
hci_connect_cfm(conn, status);
hci_conn_drop(conn);
}
}
hci_dev_unlock(hdev);
}
static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_set_conn_encrypt *cp;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_SET_CONN_ENCRYPT);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
if (conn->state == BT_CONFIG) {
hci_connect_cfm(conn, status);
hci_conn_drop(conn);
}
}
hci_dev_unlock(hdev);
}
static int hci_outgoing_auth_needed(struct hci_dev *hdev,
struct hci_conn *conn)
{
if (conn->state != BT_CONFIG || !conn->out)
return 0;
if (conn->pending_sec_level == BT_SECURITY_SDP)
return 0;
/* Only request authentication for SSP connections or non-SSP
* devices with sec_level MEDIUM or HIGH or if MITM protection
* is requested.
*/
if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) &&
conn->pending_sec_level != BT_SECURITY_FIPS &&
conn->pending_sec_level != BT_SECURITY_HIGH &&
conn->pending_sec_level != BT_SECURITY_MEDIUM)
return 0;
return 1;
}
static int hci_resolve_name(struct hci_dev *hdev,
struct inquiry_entry *e)
{
struct hci_cp_remote_name_req cp;
memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, &e->data.bdaddr);
cp.pscan_rep_mode = e->data.pscan_rep_mode;
cp.pscan_mode = e->data.pscan_mode;
cp.clock_offset = e->data.clock_offset;
return hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
}
static bool hci_resolve_next_name(struct hci_dev *hdev)
{
struct discovery_state *discov = &hdev->discovery;
struct inquiry_entry *e;
if (list_empty(&discov->resolve))
return false;
/* We should stop if we already spent too much time resolving names. */
if (time_after(jiffies, discov->name_resolve_timeout)) {
bt_dev_warn_ratelimited(hdev, "Name resolve takes too long.");
return false;
}
e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
if (!e)
return false;
if (hci_resolve_name(hdev, e) == 0) {
e->name_state = NAME_PENDING;
return true;
}
return false;
}
static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn,
bdaddr_t *bdaddr, u8 *name, u8 name_len)
{
struct discovery_state *discov = &hdev->discovery;
struct inquiry_entry *e;
/* Update the mgmt connected state if necessary. Be careful with
* conn objects that exist but are not (yet) connected however.
* Only those in BT_CONFIG or BT_CONNECTED states can be
* considered connected.
*/
if (conn &&
(conn->state == BT_CONFIG || conn->state == BT_CONNECTED) &&
Bluetooth: Send mgmt_connected only if state is BT_CONFIG If a remote name request is initiated while acl connection is going on, and if it fails then mgmt_connected will be sent. Evetually after acl connection, authentication will not be initiated and userspace will never get pairing reply. < HCI Command: Create Connection (0x01|0x0005) plen 13 bdaddr AA:BB:CC:DD:EE:FF ptype 0xcc18 rswitch 0x01 clkoffset 0x2306 (valid) Packet type: DM1 DM3 DM5 DH1 DH3 DH5 > HCI Event: Command Status (0x0f) plen 4 Create Connection (0x01|0x0005) status 0x00 ncmd 1 > HCI Event: Inquiry Complete (0x01) plen 1 status 0x00 < HCI Command: Remote Name Request (0x01|0x0019) plen 10 bdaddr AA:BB:CC:DD:EE:FF mode 1 clkoffset 0x2306 > HCI Event: Command Status (0x0f) plen 4 Remote Name Request (0x01|0x0019) status 0x0c ncmd 1 Error: Command Disallowed > HCI Event: Connect Complete (0x03) plen 11 status 0x00 handle 50 bdaddr 00:0D:FD:47:53:B2 type ACL encrypt 0x00 < HCI Command: Read Remote Supported Features (0x01|0x001b) plen 2 handle 50 > HCI Event: Command Status (0x0f) plen 4 Read Remote Supported Features (0x01|0x001b) status 0x00 ncmd 1 > HCI Event: Max Slots Change (0x1b) plen 3 handle 50 slots 5 > HCI Event: Read Remote Supported Features (0x0b) plen 11 status 0x00 handle 50 Features: 0xff 0xff 0x8f 0xfe 0x9b 0xff 0x59 0x83 < HCI Command: Read Remote Extended Features (0x01|0x001c) plen 3 handle 50 page 1 > HCI Event: Command Status (0x0f) plen 4 Read Remote Extended Features (0x01|0x001c) status 0x00 ncmd 1 > HCI Event: Read Remote Extended Features (0x23) plen 13 status 0x00 handle 50 page 1 max 1 Features: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 This patch sends mgmt_connected in remote name command status only if conn->state is BT_CONFIG Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2014-11-07 19:09:09 +08:00
!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
mgmt_device_connected(hdev, conn, name, name_len);
if (discov->state == DISCOVERY_STOPPED)
return;
if (discov->state == DISCOVERY_STOPPING)
goto discov_complete;
if (discov->state != DISCOVERY_RESOLVING)
return;
e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING);
/* If the device was not found in a list of found devices names of which
* are pending. there is no need to continue resolving a next name as it
* will be done upon receiving another Remote Name Request Complete
* Event */
if (!e)
return;
list_del(&e->list);
e->name_state = name ? NAME_KNOWN : NAME_NOT_KNOWN;
mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, e->data.rssi,
name, name_len);
if (hci_resolve_next_name(hdev))
return;
discov_complete:
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
}
static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_remote_name_req *cp;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
/* If successful wait for the name req complete event before
* checking for the need to do authentication */
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
if (hci_dev_test_flag(hdev, HCI_MGMT))
hci_check_pending_name(hdev, conn, &cp->bdaddr, NULL, 0);
if (!conn)
goto unlock;
if (!hci_outgoing_auth_needed(hdev, conn))
goto unlock;
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
struct hci_cp_auth_requested auth_cp;
set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
auth_cp.handle = __cpu_to_le16(conn->handle);
hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED,
sizeof(auth_cp), &auth_cp);
}
unlock:
hci_dev_unlock(hdev);
}
static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_read_remote_features *cp;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_FEATURES);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
if (conn->state == BT_CONFIG) {
hci_connect_cfm(conn, status);
hci_conn_drop(conn);
}
}
hci_dev_unlock(hdev);
}
static void hci_cs_read_remote_ext_features(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_read_remote_ext_features *cp;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
if (conn->state == BT_CONFIG) {
hci_connect_cfm(conn, status);
hci_conn_drop(conn);
}
}
hci_dev_unlock(hdev);
}
static void hci_cs_setup_sync_conn(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_setup_sync_conn *cp;
struct hci_conn *acl, *sco;
__u16 handle;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_SETUP_SYNC_CONN);
if (!cp)
return;
handle = __le16_to_cpu(cp->handle);
bt_dev_dbg(hdev, "handle 0x%4.4x", handle);
hci_dev_lock(hdev);
acl = hci_conn_hash_lookup_handle(hdev, handle);
if (acl) {
sco = acl->link;
if (sco) {
sco->state = BT_CLOSED;
hci_connect_cfm(sco, status);
hci_conn_del(sco);
}
}
hci_dev_unlock(hdev);
}
static void hci_cs_enhanced_setup_sync_conn(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_enhanced_setup_sync_conn *cp;
struct hci_conn *acl, *sco;
__u16 handle;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_ENHANCED_SETUP_SYNC_CONN);
if (!cp)
return;
handle = __le16_to_cpu(cp->handle);
bt_dev_dbg(hdev, "handle 0x%4.4x", handle);
hci_dev_lock(hdev);
acl = hci_conn_hash_lookup_handle(hdev, handle);
if (acl) {
sco = acl->link;
if (sco) {
sco->state = BT_CLOSED;
hci_connect_cfm(sco, status);
hci_conn_del(sco);
}
}
hci_dev_unlock(hdev);
}
static void hci_cs_sniff_mode(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_sniff_mode *cp;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_SNIFF_MODE);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
hci_sco_setup(conn, status);
}
hci_dev_unlock(hdev);
}
static void hci_cs_exit_sniff_mode(struct hci_dev *hdev, __u8 status)
{
struct hci_cp_exit_sniff_mode *cp;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_EXIT_SNIFF_MODE);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags);
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
hci_sco_setup(conn, status);
}
hci_dev_unlock(hdev);
}
static void hci_cs_disconnect(struct hci_dev *hdev, u8 status)
{
struct hci_cp_disconnect *cp;
struct hci_conn_params *params;
struct hci_conn *conn;
bool mgmt_conn;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
/* Wait for HCI_EV_DISCONN_COMPLETE if status 0x00 and not suspended
* otherwise cleanup the connection immediately.
*/
if (!status && !hdev->suspended)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_DISCONNECT);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (!conn)
goto unlock;
if (status) {
mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
conn->dst_type, status);
if (conn->type == LE_LINK && conn->role == HCI_ROLE_SLAVE) {
hdev->cur_adv_instance = conn->adv_instance;
Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY This make use of hci_cmd_sync_queue for MGMT_OP_START_DISCOVERY, MGMT_OP_START_SERVICE_DISCOVERY and MGMT_OP_STOP_DISCOVERY to use hci_cmd_sync_queue so they no longer depend on hdev->discov_update work to send any commands. Tested with: tools/mgmt-tester -s "Start Discovery" Test Summary ------------ Start Discovery - Not powered 1 Passed Start Discovery - Invalid parameters 1 Passed Start Discovery - Not supported 1 Passed Start Discovery - Success 1 Passed Start Discovery - Success 2 Passed Start Discovery - Power Off 1 Passed Start Discovery BREDR LE - (Ext Scan Enable) Passed Start Discovery LE - (Ext Scan Enable) Passed Start Discovery LE - (Ext Scan Param) Passed Start Discovery - (2m, Scan Param) Passed Start Discovery - (coded, Scan Param) Passed Start Discovery - (1m, 2m, coded, Scan Param) Passed LL Privacy - Start Discovery 1 (Disable RL) Passed LL Privacy - Start Discovery 2 (Disable RL) Passed Total: 14, Passed: 14 (100.0%), Failed: 0, Not Run: 0 tools/mgmt-tester -s "Start Service" Test Summary ------------ Start Service Discovery - Not powered 1 Passed Start Service Discovery - Invalid parameters 1 Passed Start Service Discovery - Not supported 1 Passed Start Service Discovery - Success 1 Passed Start Service Discovery - Success 2 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 tools/mgmt-tester -s "Stop Discovery" Test Summary ------------ Stop Discovery - Success 1 Passed Stop Discovery - BR/EDR (Inquiry) Success 1 Passed Stop Discovery - Rejected 1 Passed Stop Discovery - Invalid parameters 1 Passed Stop Discovery - (Ext Scan Disable) Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 07:58:45 +08:00
hci_enable_advertising(hdev);
}
goto done;
Bluetooth: clean up connection in hci_cs_disconnect In bluetooth core specification 4.2, Vol 2, Part E, 7.8.9 LE Set Advertise Enable Command, it says The Controller shall continue advertising until ... or until a connection is created or ... In these cases, advertising is then disabled. Hence, advertising would be disabled before a connection is established. In current kernel implementation, advertising would be re-enabled when all connections are terminated. The correct disconnection flow looks like < HCI Command: Disconnect > HCI Event: Command Status Status: Success > HCI Event: Disconnect Complete Status: Success Specifically, the last Disconnect Complete Event would trigger a callback function hci_event.c:hci_disconn_complete_evt() to cleanup the connection and re-enable advertising when proper. However, sometimes, there might occur an exception in the controller when disconnection is being executed. The disconnection flow might then look like < HCI Command: Disconnect > HCI Event: Command Status Status: Unknown Connection Identifier Note that "> HCI Event: Disconnect Complete" is missing when such an exception occurs. This would result in advertising staying disabled forever since the connection in question is not cleaned up correctly. To fix the controller exception issue, we need to do some connection cleanup when the disconnect command status indicates an error. Signed-off-by: Joseph Hwang <josephsih@chromium.org> Signed-off-by: Manish Mandlik <mmandlik@google.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-03-12 10:20:14 +08:00
}
mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
if (conn->type == ACL_LINK) {
if (test_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
hci_remove_link_key(hdev, &conn->dst);
}
params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
if (params) {
switch (params->auto_connect) {
case HCI_AUTO_CONN_LINK_LOSS:
if (cp->reason != HCI_ERROR_CONNECTION_TIMEOUT)
break;
fallthrough;
case HCI_AUTO_CONN_DIRECT:
case HCI_AUTO_CONN_ALWAYS:
list_del_init(&params->action);
list_add(&params->action, &hdev->pend_le_conns);
break;
default:
break;
}
}
mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
cp->reason, mgmt_conn);
hci_disconn_cfm(conn, cp->reason);
done:
/* If the disconnection failed for any reason, the upper layer
* does not retry to disconnect in current implementation.
* Hence, we need to do some basic cleanup here and re-enable
* advertising if necessary.
*/
hci_conn_del(conn);
unlock:
hci_dev_unlock(hdev);
}
static u8 ev_bdaddr_type(struct hci_dev *hdev, u8 type, bool *resolved)
{
/* When using controller based address resolution, then the new
* address types 0x02 and 0x03 are used. These types need to be
* converted back into either public address or random address type
*/
switch (type) {
case ADDR_LE_DEV_PUBLIC_RESOLVED:
if (resolved)
*resolved = true;
return ADDR_LE_DEV_PUBLIC;
case ADDR_LE_DEV_RANDOM_RESOLVED:
if (resolved)
*resolved = true;
return ADDR_LE_DEV_RANDOM;
}
if (resolved)
*resolved = false;
return type;
}
static void cs_le_create_conn(struct hci_dev *hdev, bdaddr_t *peer_addr,
u8 peer_addr_type, u8 own_address_type,
u8 filter_policy)
{
struct hci_conn *conn;
conn = hci_conn_hash_lookup_le(hdev, peer_addr,
peer_addr_type);
if (!conn)
return;
own_address_type = ev_bdaddr_type(hdev, own_address_type, NULL);
/* Store the initiator and responder address information which
* is needed for SMP. These values will not change during the
* lifetime of the connection.
*/
conn->init_addr_type = own_address_type;
if (own_address_type == ADDR_LE_DEV_RANDOM)
bacpy(&conn->init_addr, &hdev->random_addr);
else
bacpy(&conn->init_addr, &hdev->bdaddr);
conn->resp_addr_type = peer_addr_type;
bacpy(&conn->resp_addr, peer_addr);
/* We don't want the connection attempt to stick around
* indefinitely since LE doesn't have a page timeout concept
* like BR/EDR. Set a timer for any connection that doesn't use
* the accept list for connecting.
*/
if (filter_policy == HCI_LE_USE_PEER_ADDR)
queue_delayed_work(conn->hdev->workqueue,
&conn->le_conn_timeout,
conn->conn_timeout);
}
static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status)
{
struct hci_cp_le_create_conn *cp;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
/* All connection failure handling is taken care of by the
* hci_le_conn_failed function which is triggered by the HCI
* request completion callbacks used for connecting.
*/
if (status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN);
if (!cp)
return;
hci_dev_lock(hdev);
cs_le_create_conn(hdev, &cp->peer_addr, cp->peer_addr_type,
cp->own_address_type, cp->filter_policy);
hci_dev_unlock(hdev);
}
Bluetooth: Use extended LE Connection if supported This implements extended LE craete connection and enhanced LE conn complete event if the controller supports. For now it is as good as legacy LE connection and event as no new features in the extended connection is handled. < HCI Command: LE Extended Create Connection (0x08|0x0043) plen 26 Filter policy: White list is not used (0x00) Own address type: Public (0x00) Peer address type: Random (0x01) Peer address: DB:7E:2E:1D:85:E8 (Static) Initiating PHYs: 0x01 Entry 0: LE 1M Scan interval: 60.000 msec (0x0060) Scan window: 60.000 msec (0x0060) Min connection interval: 50.00 msec (0x0028) Max connection interval: 70.00 msec (0x0038) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Min connection length: 0.000 msec (0x0000) Max connection length: 0.000 msec (0x0000) > HCI Event: Command Status (0x0f) plen 4 LE Extended Create Connection (0x08|0x0043) ncmd 2 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 31 LE Enhanced Connection Complete (0x0a) Status: Success (0x00) Handle: 3585 Role: Master (0x00) Peer address type: Random (0x01) Peer address: DB:7E:2E:1D:85:E8 (Static) Local resolvable private address: 00:00:00:00:00:00 (Non-Resolvable) Peer resolvable private address: 00:00:00:00:00:00 (Non-Resolvable) Connection interval: 67.50 msec (0x0036) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Master clock accuracy: 0x00 @ MGMT Event: Device Connected (0x000b) plen 40 LE Address: DB:7E:2E:1D:85:E8 (Static) Flags: 0x00000000 Data length: 27 Name (complete): Designer Mouse Appearance: Mouse (0x03c2) Flags: 0x05 LE Limited Discoverable Mode BR/EDR Not Supported 16-bit Service UUIDs (complete): 1 entry Human Interface Device (0x1812) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-07 04:50:32 +08:00
static void hci_cs_le_ext_create_conn(struct hci_dev *hdev, u8 status)
{
struct hci_cp_le_ext_create_conn *cp;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
Bluetooth: Use extended LE Connection if supported This implements extended LE craete connection and enhanced LE conn complete event if the controller supports. For now it is as good as legacy LE connection and event as no new features in the extended connection is handled. < HCI Command: LE Extended Create Connection (0x08|0x0043) plen 26 Filter policy: White list is not used (0x00) Own address type: Public (0x00) Peer address type: Random (0x01) Peer address: DB:7E:2E:1D:85:E8 (Static) Initiating PHYs: 0x01 Entry 0: LE 1M Scan interval: 60.000 msec (0x0060) Scan window: 60.000 msec (0x0060) Min connection interval: 50.00 msec (0x0028) Max connection interval: 70.00 msec (0x0038) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Min connection length: 0.000 msec (0x0000) Max connection length: 0.000 msec (0x0000) > HCI Event: Command Status (0x0f) plen 4 LE Extended Create Connection (0x08|0x0043) ncmd 2 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 31 LE Enhanced Connection Complete (0x0a) Status: Success (0x00) Handle: 3585 Role: Master (0x00) Peer address type: Random (0x01) Peer address: DB:7E:2E:1D:85:E8 (Static) Local resolvable private address: 00:00:00:00:00:00 (Non-Resolvable) Peer resolvable private address: 00:00:00:00:00:00 (Non-Resolvable) Connection interval: 67.50 msec (0x0036) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Master clock accuracy: 0x00 @ MGMT Event: Device Connected (0x000b) plen 40 LE Address: DB:7E:2E:1D:85:E8 (Static) Flags: 0x00000000 Data length: 27 Name (complete): Designer Mouse Appearance: Mouse (0x03c2) Flags: 0x05 LE Limited Discoverable Mode BR/EDR Not Supported 16-bit Service UUIDs (complete): 1 entry Human Interface Device (0x1812) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-07 04:50:32 +08:00
/* All connection failure handling is taken care of by the
* hci_le_conn_failed function which is triggered by the HCI
* request completion callbacks used for connecting.
*/
if (status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_EXT_CREATE_CONN);
if (!cp)
return;
hci_dev_lock(hdev);
cs_le_create_conn(hdev, &cp->peer_addr, cp->peer_addr_type,
cp->own_addr_type, cp->filter_policy);
hci_dev_unlock(hdev);
}
static void hci_cs_le_read_remote_features(struct hci_dev *hdev, u8 status)
{
struct hci_cp_le_read_remote_features *cp;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_READ_REMOTE_FEATURES);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (conn) {
if (conn->state == BT_CONFIG) {
hci_connect_cfm(conn, status);
hci_conn_drop(conn);
}
}
hci_dev_unlock(hdev);
}
static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status)
{
struct hci_cp_le_start_enc *cp;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", status);
if (!status)
return;
hci_dev_lock(hdev);
cp = hci_sent_cmd_data(hdev, HCI_OP_LE_START_ENC);
if (!cp)
goto unlock;
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle));
if (!conn)
goto unlock;
if (conn->state != BT_CONNECTED)
goto unlock;
hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
hci_conn_drop(conn);
unlock:
hci_dev_unlock(hdev);
}
static void hci_cs_switch_role(struct hci_dev *hdev, u8 status)
{
struct hci_cp_switch_role *cp;
struct hci_conn *conn;
BT_DBG("%s status 0x%2.2x", hdev->name, status);
if (!status)
return;
cp = hci_sent_cmd_data(hdev, HCI_OP_SWITCH_ROLE);
if (!cp)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
if (conn)
clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
hci_dev_unlock(hdev);
}
static void hci_inquiry_complete_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_status *ev = data;
struct discovery_state *discov = &hdev->discovery;
struct inquiry_entry *e;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
hci_conn_check_pending(hdev);
if (!test_and_clear_bit(HCI_INQUIRY, &hdev->flags))
return;
smp_mb__after_atomic(); /* wake_up_bit advises about this barrier */
wake_up_bit(&hdev->flags, HCI_INQUIRY);
if (!hci_dev_test_flag(hdev, HCI_MGMT))
return;
hci_dev_lock(hdev);
if (discov->state != DISCOVERY_FINDING)
goto unlock;
if (list_empty(&discov->resolve)) {
/* When BR/EDR inquiry is active and no LE scanning is in
* progress, then change discovery state to indicate completion.
*
* When running LE scanning and BR/EDR inquiry simultaneously
* and the LE scan already finished, then change the discovery
* state to indicate completion.
*/
if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
!test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
goto unlock;
}
e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED);
if (e && hci_resolve_name(hdev, e) == 0) {
e->name_state = NAME_PENDING;
hci_discovery_set_state(hdev, DISCOVERY_RESOLVING);
discov->name_resolve_timeout = jiffies + NAME_RESOLVE_DURATION;
} else {
/* When BR/EDR inquiry is active and no LE scanning is in
* progress, then change discovery state to indicate completion.
*
* When running LE scanning and BR/EDR inquiry simultaneously
* and the LE scan already finished, then change the discovery
* state to indicate completion.
*/
if (!hci_dev_test_flag(hdev, HCI_LE_SCAN) ||
!test_bit(HCI_QUIRK_SIMULTANEOUS_DISCOVERY, &hdev->quirks))
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
}
unlock:
hci_dev_unlock(hdev);
}
static void hci_inquiry_result_evt(struct hci_dev *hdev, void *edata,
struct sk_buff *skb)
{
struct hci_ev_inquiry_result *ev = edata;
struct inquiry_data data;
int i;
if (!hci_ev_skb_pull(hdev, skb, HCI_EV_INQUIRY_RESULT,
flex_array_size(ev, info, ev->num)))
return;
bt_dev_dbg(hdev, "num %d", ev->num);
if (!ev->num)
return;
if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
return;
hci_dev_lock(hdev);
for (i = 0; i < ev->num; i++) {
struct inquiry_info *info = &ev->info[i];
u32 flags;
bacpy(&data.bdaddr, &info->bdaddr);
data.pscan_rep_mode = info->pscan_rep_mode;
data.pscan_period_mode = info->pscan_period_mode;
data.pscan_mode = info->pscan_mode;
memcpy(data.dev_class, info->dev_class, 3);
data.clock_offset = info->clock_offset;
data.rssi = HCI_RSSI_INVALID;
data.ssp_mode = 0x00;
flags = hci_inquiry_cache_update(hdev, &data, false);
mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
info->dev_class, HCI_RSSI_INVALID,
flags, NULL, 0, NULL, 0);
}
hci_dev_unlock(hdev);
}
static void hci_conn_complete_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_conn_complete *ev = data;
struct hci_conn *conn;
if (__le16_to_cpu(ev->handle) > HCI_CONN_HANDLE_MAX) {
bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for invalid handle");
return;
}
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
if (!conn) {
/* Connection may not exist if auto-connected. Check the bredr
* allowlist to see if this device is allowed to auto connect.
* If link is an ACL type, create a connection class
* automatically.
*
* Auto-connect will only occur if the event filter is
* programmed with a given address. Right now, event filter is
* only used during suspend.
*/
if (ev->link_type == ACL_LINK &&
hci_bdaddr_list_lookup_with_flags(&hdev->accept_list,
&ev->bdaddr,
BDADDR_BREDR)) {
conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr,
HCI_ROLE_SLAVE);
if (!conn) {
bt_dev_err(hdev, "no memory for new conn");
goto unlock;
}
} else {
if (ev->link_type != SCO_LINK)
goto unlock;
conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK,
&ev->bdaddr);
if (!conn)
goto unlock;
conn->type = SCO_LINK;
}
}
/* The HCI_Connection_Complete event is only sent once per connection.
* Processing it more than once per connection can corrupt kernel memory.
*
* As the connection handle is set here for the first time, it indicates
* whether the connection is already set up.
*/
if (conn->handle != HCI_CONN_HANDLE_UNSET) {
bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for existing connection");
goto unlock;
}
if (!ev->status) {
conn->handle = __le16_to_cpu(ev->handle);
if (conn->type == ACL_LINK) {
conn->state = BT_CONFIG;
hci_conn_hold(conn);
Bluetooth: Fix legacy pairing with some devices Some devices e.g. some Android based phones don't do SDP search before pairing and cancel legacy pairing when ACL is disconnected. PIN Code Request event which changes ACL timeout to HCI_PAIRING_TIMEOUT is only received after remote user entered PIN. In that case no L2CAP is connected so default HCI_DISCONN_TIMEOUT (2 seconds) is being used to timeout ACL connection. This results in problems with legacy pairing as remote user has only few seconds to enter PIN before ACL is disconnected. Increase disconnect timeout for incomming connection to HCI_PAIRING_TIMEOUT if SSP is disabled and no linkey exists. To avoid keeping ACL alive for too long after SDP search set ACL timeout back to HCI_DISCONN_TIMEOUT when L2CAP is connected. 2012-07-19 13:24:43.413521 < HCI Command: Create Connection (0x01|0x0005) plen 13 bdaddr 00:02:72:D6:6A:3F ptype 0xcc18 rswitch 0x01 clkoffset 0x0000 Packet type: DM1 DM3 DM5 DH1 DH3 DH5 2012-07-19 13:24:43.425224 > HCI Event: Command Status (0x0f) plen 4 Create Connection (0x01|0x0005) status 0x00 ncmd 1 2012-07-19 13:24:43.885222 > HCI Event: Role Change (0x12) plen 8 status 0x00 bdaddr 00:02:72:D6:6A:3F role 0x01 Role: Slave 2012-07-19 13:24:44.054221 > HCI Event: Connect Complete (0x03) plen 11 status 0x00 handle 42 bdaddr 00:02:72:D6:6A:3F type ACL encrypt 0x00 2012-07-19 13:24:44.054313 < HCI Command: Read Remote Supported Features (0x01|0x001b) plen 2 handle 42 2012-07-19 13:24:44.055176 > HCI Event: Page Scan Repetition Mode Change (0x20) plen 7 bdaddr 00:02:72:D6:6A:3F mode 0 2012-07-19 13:24:44.056217 > HCI Event: Max Slots Change (0x1b) plen 3 handle 42 slots 5 2012-07-19 13:24:44.059218 > HCI Event: Command Status (0x0f) plen 4 Read Remote Supported Features (0x01|0x001b) status 0x00 ncmd 0 2012-07-19 13:24:44.062192 > HCI Event: Command Status (0x0f) plen 4 Unknown (0x00|0x0000) status 0x00 ncmd 1 2012-07-19 13:24:44.067219 > HCI Event: Read Remote Supported Features (0x0b) plen 11 status 0x00 handle 42 Features: 0xbf 0xfe 0xcf 0xfe 0xdb 0xff 0x7b 0x87 2012-07-19 13:24:44.067248 < HCI Command: Read Remote Extended Features (0x01|0x001c) plen 3 handle 42 page 1 2012-07-19 13:24:44.071217 > HCI Event: Command Status (0x0f) plen 4 Read Remote Extended Features (0x01|0x001c) status 0x00 ncmd 1 2012-07-19 13:24:44.076218 > HCI Event: Read Remote Extended Features (0x23) plen 13 status 0x00 handle 42 page 1 max 1 Features: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 2012-07-19 13:24:44.076249 < HCI Command: Remote Name Request (0x01|0x0019) plen 10 bdaddr 00:02:72:D6:6A:3F mode 2 clkoffset 0x0000 2012-07-19 13:24:44.081218 > HCI Event: Command Status (0x0f) plen 4 Remote Name Request (0x01|0x0019) status 0x00 ncmd 1 2012-07-19 13:24:44.105214 > HCI Event: Remote Name Req Complete (0x07) plen 255 status 0x00 bdaddr 00:02:72:D6:6A:3F name 'uw000951-0' 2012-07-19 13:24:44.105284 < HCI Command: Authentication Requested (0x01|0x0011) plen 2 handle 42 2012-07-19 13:24:44.111207 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) status 0x00 ncmd 1 2012-07-19 13:24:44.112220 > HCI Event: Link Key Request (0x17) plen 6 bdaddr 00:02:72:D6:6A:3F 2012-07-19 13:24:44.112249 < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 bdaddr 00:02:72:D6:6A:3F 2012-07-19 13:24:44.115215 > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 status 0x00 bdaddr 00:02:72:D6:6A:3F 2012-07-19 13:24:44.116215 > HCI Event: PIN Code Request (0x16) plen 6 bdaddr 00:02:72:D6:6A:3F 2012-07-19 13:24:48.099184 > HCI Event: Auth Complete (0x06) plen 3 status 0x13 handle 42 Error: Remote User Terminated Connection 2012-07-19 13:24:48.179182 > HCI Event: Disconn Complete (0x05) plen 4 status 0x00 handle 42 reason 0x13 Reason: Remote User Terminated Connection Cc: stable@vger.kernel.org Signed-off-by: Szymon Janc <szymon.janc@tieto.com> Acked-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
2012-07-19 20:46:08 +08:00
if (!conn->out && !hci_conn_ssp_enabled(conn) &&
!hci_find_link_key(hdev, &ev->bdaddr))
conn->disc_timeout = HCI_PAIRING_TIMEOUT;
else
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
} else
conn->state = BT_CONNECTED;
hci_debugfs_create_conn(conn);
hci_conn_add_sysfs(conn);
if (test_bit(HCI_AUTH, &hdev->flags))
set_bit(HCI_CONN_AUTH, &conn->flags);
if (test_bit(HCI_ENCRYPT, &hdev->flags))
set_bit(HCI_CONN_ENCRYPT, &conn->flags);
/* Get remote features */
if (conn->type == ACL_LINK) {
struct hci_cp_read_remote_features cp;
cp.handle = ev->handle;
hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
sizeof(cp), &cp);
hci_req_update_scan(hdev);
}
/* Set packet type for incoming connection */
if (!conn->out && hdev->hci_ver < BLUETOOTH_VER_2_0) {
struct hci_cp_change_conn_ptype cp;
cp.handle = ev->handle;
cp.pkt_type = cpu_to_le16(conn->pkt_type);
hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp),
&cp);
}
} else {
conn->state = BT_CLOSED;
if (conn->type == ACL_LINK)
mgmt_connect_failed(hdev, &conn->dst, conn->type,
conn->dst_type, ev->status);
}
if (conn->type == ACL_LINK)
hci_sco_setup(conn, ev->status);
if (ev->status) {
hci_connect_cfm(conn, ev->status);
hci_conn_del(conn);
} else if (ev->link_type == SCO_LINK) {
switch (conn->setting & SCO_AIRMODE_MASK) {
case SCO_AIRMODE_CVSD:
if (hdev->notify)
hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_CVSD);
break;
}
hci_connect_cfm(conn, ev->status);
}
unlock:
hci_dev_unlock(hdev);
hci_conn_check_pending(hdev);
}
static void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
struct hci_cp_reject_conn_req cp;
bacpy(&cp.bdaddr, bdaddr);
cp.reason = HCI_ERROR_REJ_BAD_ADDR;
hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp);
}
static void hci_conn_request_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_conn_request *ev = data;
int mask = hdev->link_mode;
struct inquiry_entry *ie;
struct hci_conn *conn;
__u8 flags = 0;
bt_dev_dbg(hdev, "bdaddr %pMR type 0x%x", &ev->bdaddr, ev->link_type);
mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type,
&flags);
if (!(mask & HCI_LM_ACCEPT)) {
hci_reject_conn(hdev, &ev->bdaddr);
return;
}
if (hci_bdaddr_list_lookup(&hdev->reject_list, &ev->bdaddr,
BDADDR_BREDR)) {
hci_reject_conn(hdev, &ev->bdaddr);
return;
}
/* Require HCI_CONNECTABLE or an accept list entry to accept the
* connection. These features are only touched through mgmt so
* only do the checks if HCI_MGMT is set.
*/
if (hci_dev_test_flag(hdev, HCI_MGMT) &&
!hci_dev_test_flag(hdev, HCI_CONNECTABLE) &&
!hci_bdaddr_list_lookup_with_flags(&hdev->accept_list, &ev->bdaddr,
BDADDR_BREDR)) {
hci_reject_conn(hdev, &ev->bdaddr);
return;
}
/* Connection accepted */
hci_dev_lock(hdev);
ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
if (ie)
memcpy(ie->data.dev_class, ev->dev_class, 3);
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type,
&ev->bdaddr);
if (!conn) {
conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr,
HCI_ROLE_SLAVE);
if (!conn) {
bt_dev_err(hdev, "no memory for new connection");
hci_dev_unlock(hdev);
return;
}
}
memcpy(conn->dev_class, ev->dev_class, 3);
hci_dev_unlock(hdev);
if (ev->link_type == ACL_LINK ||
(!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) {
struct hci_cp_accept_conn_req cp;
conn->state = BT_CONNECT;
bacpy(&cp.bdaddr, &ev->bdaddr);
if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER))
cp.role = 0x00; /* Become central */
else
cp.role = 0x01; /* Remain peripheral */
hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp);
} else if (!(flags & HCI_PROTO_DEFER)) {
struct hci_cp_accept_sync_conn_req cp;
conn->state = BT_CONNECT;
bacpy(&cp.bdaddr, &ev->bdaddr);
cp.pkt_type = cpu_to_le16(conn->pkt_type);
cp.tx_bandwidth = cpu_to_le32(0x00001f40);
cp.rx_bandwidth = cpu_to_le32(0x00001f40);
cp.max_latency = cpu_to_le16(0xffff);
cp.content_format = cpu_to_le16(hdev->voice_setting);
cp.retrans_effort = 0xff;
hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, sizeof(cp),
&cp);
} else {
conn->state = BT_CONNECT2;
hci_connect_cfm(conn, 0);
}
}
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, void *data,
struct sk_buff *skb)
{
struct hci_ev_disconn_complete *ev = data;
Bluetooth: Add Authentication Failed reason to Disconnected Mgmt event If link is disconnected due to Authentication Failure (PIN or Key Missing status) userspace will be notified about this with proper error code. Many LE profiles define "PIN or Key Missing" status as indication of remote lost bond so this allows userspace to take action on this. @ Device Connected: 88:63:DF:88:0E:83 (1) flags 0x0000 02 01 1a 05 03 0a 18 0d 18 0b 09 48 65 61 72 74 ...........Heart 20 52 61 74 65 Rate > HCI Event: Command Status (0x0f) plen 4 LE Read Remote Used Features (0x08|0x0016) ncmd 1 Status: Success (0x00) > ACL Data RX: Handle 3585 flags 0x02 dlen 11 ATT: Read By Group Type Request (0x10) len 6 Handle range: 0x0001-0xffff Attribute group type: Primary Service (0x2800) > HCI Event: LE Meta Event (0x3e) plen 12 LE Read Remote Used Features (0x04) Status: Success (0x00) Handle: 3585 Features: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 LE Encryption < HCI Command: LE Start Encryption (0x08|0x0019) plen 28 Handle: 3585 Random number: 0x0000000000000000 Encrypted diversifier: 0x0000 Long term key: 26201cd479a0921b6f949f0b1fa8dc82 > HCI Event: Command Status (0x0f) plen 4 LE Start Encryption (0x08|0x0019) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: PIN or Key Missing (0x06) Handle: 3585 Encryption: Disabled (0x00) < HCI Command: Disconnect (0x01|0x0006) plen 3 Handle: 3585 Reason: Authentication Failure (0x05) > HCI Event: Command Status (0x0f) plen 4 Disconnect (0x01|0x0006) ncmd 1 Status: Success (0x00) > HCI Event: Disconnect Complete (0x05) plen 4 Status: Success (0x00) Handle: 3585 Reason: Connection Terminated By Local Host (0x16) @ Device Disconnected: 88:63:DF:88:0E:83 (1) reason 4 @ Device Connected: C4:43:8F:A3:4D:83 (0) flags 0x0000 08 09 4e 65 78 75 73 20 35 ..Nexus 5 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: C4:43:8F:A3:4D:83 (LG Electronics) < HCI Command: Link Key Request Reply (0x01|0x000b) plen 22 Address: C4:43:8F:A3:4D:83 (LG Electronics) Link key: 080812e4aa97a863d11826f71f65a933 > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Reply (0x01|0x000b) ncmd 1 Status: Success (0x00) Address: C4:43:8F:A3:4D:83 (LG Electronics) > HCI Event: Auth Complete (0x06) plen 3 Status: PIN or Key Missing (0x06) Handle: 75 @ Authentication Failed: C4:43:8F:A3:4D:83 (0) status 0x05 < HCI Command: Disconnect (0x01|0x0006) plen 3 Handle: 75 Reason: Remote User Terminated Connection (0x13) > HCI Event: Command Status (0x0f) plen 4 Disconnect (0x01|0x0006) ncmd 1 Status: Success (0x00) > HCI Event: Disconnect Complete (0x05) plen 4 Status: Success (0x00) Handle: 75 Reason: Connection Terminated By Local Host (0x16) @ Device Disconnected: C4:43:8F:A3:4D:83 (0) reason 4 Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2016-07-12 08:12:16 +08:00
u8 reason;
struct hci_conn_params *params;
struct hci_conn *conn;
bool mgmt_connected;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (!conn)
goto unlock;
if (ev->status) {
mgmt_disconnect_failed(hdev, &conn->dst, conn->type,
conn->dst_type, ev->status);
goto unlock;
}
conn->state = BT_CLOSED;
mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags);
Bluetooth: Add Authentication Failed reason to Disconnected Mgmt event If link is disconnected due to Authentication Failure (PIN or Key Missing status) userspace will be notified about this with proper error code. Many LE profiles define "PIN or Key Missing" status as indication of remote lost bond so this allows userspace to take action on this. @ Device Connected: 88:63:DF:88:0E:83 (1) flags 0x0000 02 01 1a 05 03 0a 18 0d 18 0b 09 48 65 61 72 74 ...........Heart 20 52 61 74 65 Rate > HCI Event: Command Status (0x0f) plen 4 LE Read Remote Used Features (0x08|0x0016) ncmd 1 Status: Success (0x00) > ACL Data RX: Handle 3585 flags 0x02 dlen 11 ATT: Read By Group Type Request (0x10) len 6 Handle range: 0x0001-0xffff Attribute group type: Primary Service (0x2800) > HCI Event: LE Meta Event (0x3e) plen 12 LE Read Remote Used Features (0x04) Status: Success (0x00) Handle: 3585 Features: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 LE Encryption < HCI Command: LE Start Encryption (0x08|0x0019) plen 28 Handle: 3585 Random number: 0x0000000000000000 Encrypted diversifier: 0x0000 Long term key: 26201cd479a0921b6f949f0b1fa8dc82 > HCI Event: Command Status (0x0f) plen 4 LE Start Encryption (0x08|0x0019) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: PIN or Key Missing (0x06) Handle: 3585 Encryption: Disabled (0x00) < HCI Command: Disconnect (0x01|0x0006) plen 3 Handle: 3585 Reason: Authentication Failure (0x05) > HCI Event: Command Status (0x0f) plen 4 Disconnect (0x01|0x0006) ncmd 1 Status: Success (0x00) > HCI Event: Disconnect Complete (0x05) plen 4 Status: Success (0x00) Handle: 3585 Reason: Connection Terminated By Local Host (0x16) @ Device Disconnected: 88:63:DF:88:0E:83 (1) reason 4 @ Device Connected: C4:43:8F:A3:4D:83 (0) flags 0x0000 08 09 4e 65 78 75 73 20 35 ..Nexus 5 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: C4:43:8F:A3:4D:83 (LG Electronics) < HCI Command: Link Key Request Reply (0x01|0x000b) plen 22 Address: C4:43:8F:A3:4D:83 (LG Electronics) Link key: 080812e4aa97a863d11826f71f65a933 > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Reply (0x01|0x000b) ncmd 1 Status: Success (0x00) Address: C4:43:8F:A3:4D:83 (LG Electronics) > HCI Event: Auth Complete (0x06) plen 3 Status: PIN or Key Missing (0x06) Handle: 75 @ Authentication Failed: C4:43:8F:A3:4D:83 (0) status 0x05 < HCI Command: Disconnect (0x01|0x0006) plen 3 Handle: 75 Reason: Remote User Terminated Connection (0x13) > HCI Event: Command Status (0x0f) plen 4 Disconnect (0x01|0x0006) ncmd 1 Status: Success (0x00) > HCI Event: Disconnect Complete (0x05) plen 4 Status: Success (0x00) Handle: 75 Reason: Connection Terminated By Local Host (0x16) @ Device Disconnected: C4:43:8F:A3:4D:83 (0) reason 4 Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2016-07-12 08:12:16 +08:00
if (test_bit(HCI_CONN_AUTH_FAILURE, &conn->flags))
reason = MGMT_DEV_DISCONN_AUTH_FAILURE;
else
reason = hci_to_mgmt_reason(ev->reason);
mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
reason, mgmt_connected);
if (conn->type == ACL_LINK) {
if (test_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
hci_remove_link_key(hdev, &conn->dst);
hci_req_update_scan(hdev);
}
params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
if (params) {
switch (params->auto_connect) {
case HCI_AUTO_CONN_LINK_LOSS:
if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT)
break;
fallthrough;
case HCI_AUTO_CONN_DIRECT:
case HCI_AUTO_CONN_ALWAYS:
list_del_init(&params->action);
list_add(&params->action, &hdev->pend_le_conns);
hci_update_passive_scan(hdev);
break;
default:
break;
}
}
hci_disconn_cfm(conn, ev->reason);
/* 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 (conn->type == LE_LINK && conn->role == HCI_ROLE_SLAVE) {
hdev->cur_adv_instance = conn->adv_instance;
Bluetooth: hci_sync: Convert MGMT_OP_START_DISCOVERY This make use of hci_cmd_sync_queue for MGMT_OP_START_DISCOVERY, MGMT_OP_START_SERVICE_DISCOVERY and MGMT_OP_STOP_DISCOVERY to use hci_cmd_sync_queue so they no longer depend on hdev->discov_update work to send any commands. Tested with: tools/mgmt-tester -s "Start Discovery" Test Summary ------------ Start Discovery - Not powered 1 Passed Start Discovery - Invalid parameters 1 Passed Start Discovery - Not supported 1 Passed Start Discovery - Success 1 Passed Start Discovery - Success 2 Passed Start Discovery - Power Off 1 Passed Start Discovery BREDR LE - (Ext Scan Enable) Passed Start Discovery LE - (Ext Scan Enable) Passed Start Discovery LE - (Ext Scan Param) Passed Start Discovery - (2m, Scan Param) Passed Start Discovery - (coded, Scan Param) Passed Start Discovery - (1m, 2m, coded, Scan Param) Passed LL Privacy - Start Discovery 1 (Disable RL) Passed LL Privacy - Start Discovery 2 (Disable RL) Passed Total: 14, Passed: 14 (100.0%), Failed: 0, Not Run: 0 tools/mgmt-tester -s "Start Service" Test Summary ------------ Start Service Discovery - Not powered 1 Passed Start Service Discovery - Invalid parameters 1 Passed Start Service Discovery - Not supported 1 Passed Start Service Discovery - Success 1 Passed Start Service Discovery - Success 2 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 tools/mgmt-tester -s "Stop Discovery" Test Summary ------------ Stop Discovery - Success 1 Passed Stop Discovery - BR/EDR (Inquiry) Success 1 Passed Stop Discovery - Rejected 1 Passed Stop Discovery - Invalid parameters 1 Passed Stop Discovery - (Ext Scan Disable) Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 07:58:45 +08:00
hci_enable_advertising(hdev);
}
hci_conn_del(conn);
unlock:
hci_dev_unlock(hdev);
}
static void hci_auth_complete_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_auth_complete *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (!conn)
goto unlock;
if (!ev->status) {
Bluetooth: Add Authentication Failed reason to Disconnected Mgmt event If link is disconnected due to Authentication Failure (PIN or Key Missing status) userspace will be notified about this with proper error code. Many LE profiles define "PIN or Key Missing" status as indication of remote lost bond so this allows userspace to take action on this. @ Device Connected: 88:63:DF:88:0E:83 (1) flags 0x0000 02 01 1a 05 03 0a 18 0d 18 0b 09 48 65 61 72 74 ...........Heart 20 52 61 74 65 Rate > HCI Event: Command Status (0x0f) plen 4 LE Read Remote Used Features (0x08|0x0016) ncmd 1 Status: Success (0x00) > ACL Data RX: Handle 3585 flags 0x02 dlen 11 ATT: Read By Group Type Request (0x10) len 6 Handle range: 0x0001-0xffff Attribute group type: Primary Service (0x2800) > HCI Event: LE Meta Event (0x3e) plen 12 LE Read Remote Used Features (0x04) Status: Success (0x00) Handle: 3585 Features: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 LE Encryption < HCI Command: LE Start Encryption (0x08|0x0019) plen 28 Handle: 3585 Random number: 0x0000000000000000 Encrypted diversifier: 0x0000 Long term key: 26201cd479a0921b6f949f0b1fa8dc82 > HCI Event: Command Status (0x0f) plen 4 LE Start Encryption (0x08|0x0019) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: PIN or Key Missing (0x06) Handle: 3585 Encryption: Disabled (0x00) < HCI Command: Disconnect (0x01|0x0006) plen 3 Handle: 3585 Reason: Authentication Failure (0x05) > HCI Event: Command Status (0x0f) plen 4 Disconnect (0x01|0x0006) ncmd 1 Status: Success (0x00) > HCI Event: Disconnect Complete (0x05) plen 4 Status: Success (0x00) Handle: 3585 Reason: Connection Terminated By Local Host (0x16) @ Device Disconnected: 88:63:DF:88:0E:83 (1) reason 4 @ Device Connected: C4:43:8F:A3:4D:83 (0) flags 0x0000 08 09 4e 65 78 75 73 20 35 ..Nexus 5 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: C4:43:8F:A3:4D:83 (LG Electronics) < HCI Command: Link Key Request Reply (0x01|0x000b) plen 22 Address: C4:43:8F:A3:4D:83 (LG Electronics) Link key: 080812e4aa97a863d11826f71f65a933 > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Reply (0x01|0x000b) ncmd 1 Status: Success (0x00) Address: C4:43:8F:A3:4D:83 (LG Electronics) > HCI Event: Auth Complete (0x06) plen 3 Status: PIN or Key Missing (0x06) Handle: 75 @ Authentication Failed: C4:43:8F:A3:4D:83 (0) status 0x05 < HCI Command: Disconnect (0x01|0x0006) plen 3 Handle: 75 Reason: Remote User Terminated Connection (0x13) > HCI Event: Command Status (0x0f) plen 4 Disconnect (0x01|0x0006) ncmd 1 Status: Success (0x00) > HCI Event: Disconnect Complete (0x05) plen 4 Status: Success (0x00) Handle: 75 Reason: Connection Terminated By Local Host (0x16) @ Device Disconnected: C4:43:8F:A3:4D:83 (0) reason 4 Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2016-07-12 08:12:16 +08:00
clear_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
if (!hci_conn_ssp_enabled(conn) &&
test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) {
bt_dev_info(hdev, "re-auth of legacy device is not possible.");
} else {
set_bit(HCI_CONN_AUTH, &conn->flags);
conn->sec_level = conn->pending_sec_level;
}
} else {
Bluetooth: Add Authentication Failed reason to Disconnected Mgmt event If link is disconnected due to Authentication Failure (PIN or Key Missing status) userspace will be notified about this with proper error code. Many LE profiles define "PIN or Key Missing" status as indication of remote lost bond so this allows userspace to take action on this. @ Device Connected: 88:63:DF:88:0E:83 (1) flags 0x0000 02 01 1a 05 03 0a 18 0d 18 0b 09 48 65 61 72 74 ...........Heart 20 52 61 74 65 Rate > HCI Event: Command Status (0x0f) plen 4 LE Read Remote Used Features (0x08|0x0016) ncmd 1 Status: Success (0x00) > ACL Data RX: Handle 3585 flags 0x02 dlen 11 ATT: Read By Group Type Request (0x10) len 6 Handle range: 0x0001-0xffff Attribute group type: Primary Service (0x2800) > HCI Event: LE Meta Event (0x3e) plen 12 LE Read Remote Used Features (0x04) Status: Success (0x00) Handle: 3585 Features: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 LE Encryption < HCI Command: LE Start Encryption (0x08|0x0019) plen 28 Handle: 3585 Random number: 0x0000000000000000 Encrypted diversifier: 0x0000 Long term key: 26201cd479a0921b6f949f0b1fa8dc82 > HCI Event: Command Status (0x0f) plen 4 LE Start Encryption (0x08|0x0019) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: PIN or Key Missing (0x06) Handle: 3585 Encryption: Disabled (0x00) < HCI Command: Disconnect (0x01|0x0006) plen 3 Handle: 3585 Reason: Authentication Failure (0x05) > HCI Event: Command Status (0x0f) plen 4 Disconnect (0x01|0x0006) ncmd 1 Status: Success (0x00) > HCI Event: Disconnect Complete (0x05) plen 4 Status: Success (0x00) Handle: 3585 Reason: Connection Terminated By Local Host (0x16) @ Device Disconnected: 88:63:DF:88:0E:83 (1) reason 4 @ Device Connected: C4:43:8F:A3:4D:83 (0) flags 0x0000 08 09 4e 65 78 75 73 20 35 ..Nexus 5 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: C4:43:8F:A3:4D:83 (LG Electronics) < HCI Command: Link Key Request Reply (0x01|0x000b) plen 22 Address: C4:43:8F:A3:4D:83 (LG Electronics) Link key: 080812e4aa97a863d11826f71f65a933 > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Reply (0x01|0x000b) ncmd 1 Status: Success (0x00) Address: C4:43:8F:A3:4D:83 (LG Electronics) > HCI Event: Auth Complete (0x06) plen 3 Status: PIN or Key Missing (0x06) Handle: 75 @ Authentication Failed: C4:43:8F:A3:4D:83 (0) status 0x05 < HCI Command: Disconnect (0x01|0x0006) plen 3 Handle: 75 Reason: Remote User Terminated Connection (0x13) > HCI Event: Command Status (0x0f) plen 4 Disconnect (0x01|0x0006) ncmd 1 Status: Success (0x00) > HCI Event: Disconnect Complete (0x05) plen 4 Status: Success (0x00) Handle: 75 Reason: Connection Terminated By Local Host (0x16) @ Device Disconnected: C4:43:8F:A3:4D:83 (0) reason 4 Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2016-07-12 08:12:16 +08:00
if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING)
set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
mgmt_auth_failed(conn, ev->status);
}
clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
clear_bit(HCI_CONN_REAUTH_PEND, &conn->flags);
if (conn->state == BT_CONFIG) {
if (!ev->status && hci_conn_ssp_enabled(conn)) {
struct hci_cp_set_conn_encrypt cp;
cp.handle = ev->handle;
cp.encrypt = 0x01;
hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
&cp);
Bluetooth: Add different pairing timeout for Legacy Pairing The Bluetooth stack uses a reference counting for all established ACL links and if no user (L2CAP connection) is present, the link will be terminated to save power. The problem part is the dedicated pairing when using Legacy Pairing (Bluetooth 2.0 and before). At that point no user is present and pairing attempts will be disconnected within 10 seconds or less. In previous kernel version this was not a problem since the disconnect timeout wasn't triggered on incoming connections for the first time. However this caused issues with broken host stacks that kept the connections around after dedicated pairing. When the support for Simple Pairing got added, the link establishment procedure needed to be changed and now causes issues when using Legacy Pairing When using Simple Pairing it is possible to do a proper reference counting of ACL link users. With Legacy Pairing this is not possible since the specification is unclear in some areas and too many broken Bluetooth devices have already been deployed. So instead of trying to deal with all the broken devices, a special pairing timeout will be introduced that increases the timeout to 60 seconds when pairing is triggered. If a broken devices now puts the stack into an unforeseen state, the worst that happens is the disconnect timeout triggers after 120 seconds instead of 4 seconds. This allows successful pairings with legacy and broken devices now. Based on a report by Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2009-04-27 02:01:22 +08:00
} else {
conn->state = BT_CONNECTED;
hci_connect_cfm(conn, ev->status);
hci_conn_drop(conn);
Bluetooth: Add different pairing timeout for Legacy Pairing The Bluetooth stack uses a reference counting for all established ACL links and if no user (L2CAP connection) is present, the link will be terminated to save power. The problem part is the dedicated pairing when using Legacy Pairing (Bluetooth 2.0 and before). At that point no user is present and pairing attempts will be disconnected within 10 seconds or less. In previous kernel version this was not a problem since the disconnect timeout wasn't triggered on incoming connections for the first time. However this caused issues with broken host stacks that kept the connections around after dedicated pairing. When the support for Simple Pairing got added, the link establishment procedure needed to be changed and now causes issues when using Legacy Pairing When using Simple Pairing it is possible to do a proper reference counting of ACL link users. With Legacy Pairing this is not possible since the specification is unclear in some areas and too many broken Bluetooth devices have already been deployed. So instead of trying to deal with all the broken devices, a special pairing timeout will be introduced that increases the timeout to 60 seconds when pairing is triggered. If a broken devices now puts the stack into an unforeseen state, the worst that happens is the disconnect timeout triggers after 120 seconds instead of 4 seconds. This allows successful pairings with legacy and broken devices now. Based on a report by Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2009-04-27 02:01:22 +08:00
}
} else {
hci_auth_cfm(conn, ev->status);
Bluetooth: Add different pairing timeout for Legacy Pairing The Bluetooth stack uses a reference counting for all established ACL links and if no user (L2CAP connection) is present, the link will be terminated to save power. The problem part is the dedicated pairing when using Legacy Pairing (Bluetooth 2.0 and before). At that point no user is present and pairing attempts will be disconnected within 10 seconds or less. In previous kernel version this was not a problem since the disconnect timeout wasn't triggered on incoming connections for the first time. However this caused issues with broken host stacks that kept the connections around after dedicated pairing. When the support for Simple Pairing got added, the link establishment procedure needed to be changed and now causes issues when using Legacy Pairing When using Simple Pairing it is possible to do a proper reference counting of ACL link users. With Legacy Pairing this is not possible since the specification is unclear in some areas and too many broken Bluetooth devices have already been deployed. So instead of trying to deal with all the broken devices, a special pairing timeout will be introduced that increases the timeout to 60 seconds when pairing is triggered. If a broken devices now puts the stack into an unforeseen state, the worst that happens is the disconnect timeout triggers after 120 seconds instead of 4 seconds. This allows successful pairings with legacy and broken devices now. Based on a report by Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2009-04-27 02:01:22 +08:00
hci_conn_hold(conn);
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
hci_conn_drop(conn);
}
if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) {
if (!ev->status) {
struct hci_cp_set_conn_encrypt cp;
cp.handle = ev->handle;
cp.encrypt = 0x01;
hci_send_cmd(hdev, HCI_OP_SET_CONN_ENCRYPT, sizeof(cp),
&cp);
} else {
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
hci_encrypt_cfm(conn, ev->status);
}
}
unlock:
hci_dev_unlock(hdev);
}
static void hci_remote_name_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_remote_name *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
hci_conn_check_pending(hdev);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (!hci_dev_test_flag(hdev, HCI_MGMT))
goto check_auth;
if (ev->status == 0)
hci_check_pending_name(hdev, conn, &ev->bdaddr, ev->name,
strnlen(ev->name, HCI_MAX_NAME_LENGTH));
else
hci_check_pending_name(hdev, conn, &ev->bdaddr, NULL, 0);
check_auth:
if (!conn)
goto unlock;
if (!hci_outgoing_auth_needed(hdev, conn))
goto unlock;
if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) {
struct hci_cp_auth_requested cp;
set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags);
cp.handle = __cpu_to_le16(conn->handle);
hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp);
}
unlock:
hci_dev_unlock(hdev);
}
static void read_enc_key_size_complete(struct hci_dev *hdev, u8 status,
u16 opcode, struct sk_buff *skb)
{
const struct hci_rp_read_enc_key_size *rp;
struct hci_conn *conn;
u16 handle;
BT_DBG("%s status 0x%02x", hdev->name, status);
if (!skb || skb->len < sizeof(*rp)) {
bt_dev_err(hdev, "invalid read key size response");
return;
}
rp = (void *)skb->data;
handle = le16_to_cpu(rp->handle);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, handle);
if (!conn)
goto unlock;
/* While unexpected, the read_enc_key_size command may fail. The most
* secure approach is to then assume the key size is 0 to force a
* disconnection.
*/
if (rp->status) {
bt_dev_err(hdev, "failed to read key size for handle %u",
handle);
conn->enc_key_size = 0;
} else {
conn->enc_key_size = rp->key_size;
}
hci_encrypt_cfm(conn, 0);
unlock:
hci_dev_unlock(hdev);
}
static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_encrypt_change *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (!conn)
goto unlock;
if (!ev->status) {
if (ev->encrypt) {
/* Encryption implies authentication */
set_bit(HCI_CONN_AUTH, &conn->flags);
set_bit(HCI_CONN_ENCRYPT, &conn->flags);
conn->sec_level = conn->pending_sec_level;
/* P-256 authentication key implies FIPS */
if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256)
set_bit(HCI_CONN_FIPS, &conn->flags);
if ((conn->type == ACL_LINK && ev->encrypt == 0x02) ||
conn->type == LE_LINK)
set_bit(HCI_CONN_AES_CCM, &conn->flags);
} else {
clear_bit(HCI_CONN_ENCRYPT, &conn->flags);
clear_bit(HCI_CONN_AES_CCM, &conn->flags);
}
}
/* We should disregard the current RPA and generate a new one
* whenever the encryption procedure fails.
*/
if (ev->status && conn->type == LE_LINK) {
hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
hci_adv_instances_set_rpa_expired(hdev, true);
}
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
/* Check link security requirements are met */
if (!hci_conn_check_link_mode(conn))
ev->status = HCI_ERROR_AUTH_FAILURE;
if (ev->status && conn->state == BT_CONNECTED) {
Bluetooth: Add Authentication Failed reason to Disconnected Mgmt event If link is disconnected due to Authentication Failure (PIN or Key Missing status) userspace will be notified about this with proper error code. Many LE profiles define "PIN or Key Missing" status as indication of remote lost bond so this allows userspace to take action on this. @ Device Connected: 88:63:DF:88:0E:83 (1) flags 0x0000 02 01 1a 05 03 0a 18 0d 18 0b 09 48 65 61 72 74 ...........Heart 20 52 61 74 65 Rate > HCI Event: Command Status (0x0f) plen 4 LE Read Remote Used Features (0x08|0x0016) ncmd 1 Status: Success (0x00) > ACL Data RX: Handle 3585 flags 0x02 dlen 11 ATT: Read By Group Type Request (0x10) len 6 Handle range: 0x0001-0xffff Attribute group type: Primary Service (0x2800) > HCI Event: LE Meta Event (0x3e) plen 12 LE Read Remote Used Features (0x04) Status: Success (0x00) Handle: 3585 Features: 0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00 LE Encryption < HCI Command: LE Start Encryption (0x08|0x0019) plen 28 Handle: 3585 Random number: 0x0000000000000000 Encrypted diversifier: 0x0000 Long term key: 26201cd479a0921b6f949f0b1fa8dc82 > HCI Event: Command Status (0x0f) plen 4 LE Start Encryption (0x08|0x0019) ncmd 1 Status: Success (0x00) > HCI Event: Encryption Change (0x08) plen 4 Status: PIN or Key Missing (0x06) Handle: 3585 Encryption: Disabled (0x00) < HCI Command: Disconnect (0x01|0x0006) plen 3 Handle: 3585 Reason: Authentication Failure (0x05) > HCI Event: Command Status (0x0f) plen 4 Disconnect (0x01|0x0006) ncmd 1 Status: Success (0x00) > HCI Event: Disconnect Complete (0x05) plen 4 Status: Success (0x00) Handle: 3585 Reason: Connection Terminated By Local Host (0x16) @ Device Disconnected: 88:63:DF:88:0E:83 (1) reason 4 @ Device Connected: C4:43:8F:A3:4D:83 (0) flags 0x0000 08 09 4e 65 78 75 73 20 35 ..Nexus 5 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) ncmd 1 Status: Success (0x00) > HCI Event: Link Key Request (0x17) plen 6 Address: C4:43:8F:A3:4D:83 (LG Electronics) < HCI Command: Link Key Request Reply (0x01|0x000b) plen 22 Address: C4:43:8F:A3:4D:83 (LG Electronics) Link key: 080812e4aa97a863d11826f71f65a933 > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Reply (0x01|0x000b) ncmd 1 Status: Success (0x00) Address: C4:43:8F:A3:4D:83 (LG Electronics) > HCI Event: Auth Complete (0x06) plen 3 Status: PIN or Key Missing (0x06) Handle: 75 @ Authentication Failed: C4:43:8F:A3:4D:83 (0) status 0x05 < HCI Command: Disconnect (0x01|0x0006) plen 3 Handle: 75 Reason: Remote User Terminated Connection (0x13) > HCI Event: Command Status (0x0f) plen 4 Disconnect (0x01|0x0006) ncmd 1 Status: Success (0x00) > HCI Event: Disconnect Complete (0x05) plen 4 Status: Success (0x00) Handle: 75 Reason: Connection Terminated By Local Host (0x16) @ Device Disconnected: C4:43:8F:A3:4D:83 (0) reason 4 Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2016-07-12 08:12:16 +08:00
if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING)
set_bit(HCI_CONN_AUTH_FAILURE, &conn->flags);
/* Notify upper layers so they can cleanup before
* disconnecting.
*/
hci_encrypt_cfm(conn, ev->status);
hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
hci_conn_drop(conn);
goto unlock;
}
/* Try reading the encryption key size for encrypted ACL links */
if (!ev->status && ev->encrypt && conn->type == ACL_LINK) {
struct hci_cp_read_enc_key_size cp;
struct hci_request req;
/* Only send HCI_Read_Encryption_Key_Size if the
* controller really supports it. If it doesn't, assume
* the default size (16).
*/
if (!(hdev->commands[20] & 0x10)) {
conn->enc_key_size = HCI_LINK_KEY_SIZE;
goto notify;
}
hci_req_init(&req, hdev);
cp.handle = cpu_to_le16(conn->handle);
hci_req_add(&req, HCI_OP_READ_ENC_KEY_SIZE, sizeof(cp), &cp);
if (hci_req_run_skb(&req, read_enc_key_size_complete)) {
bt_dev_err(hdev, "sending read key size failed");
conn->enc_key_size = HCI_LINK_KEY_SIZE;
goto notify;
}
goto unlock;
}
/* Set the default Authenticated Payload Timeout after
* an LE Link is established. As per Core Spec v5.0, Vol 2, Part B
* Section 3.3, the HCI command WRITE_AUTH_PAYLOAD_TIMEOUT should be
* sent when the link is active and Encryption is enabled, the conn
* type can be either LE or ACL and controller must support LMP Ping.
* Ensure for AES-CCM encryption as well.
*/
if (test_bit(HCI_CONN_ENCRYPT, &conn->flags) &&
test_bit(HCI_CONN_AES_CCM, &conn->flags) &&
((conn->type == ACL_LINK && lmp_ping_capable(hdev)) ||
(conn->type == LE_LINK && (hdev->le_features[0] & HCI_LE_PING)))) {
struct hci_cp_write_auth_payload_to cp;
cp.handle = cpu_to_le16(conn->handle);
cp.timeout = cpu_to_le16(hdev->auth_payload_timeout);
hci_send_cmd(conn->hdev, HCI_OP_WRITE_AUTH_PAYLOAD_TO,
sizeof(cp), &cp);
}
notify:
hci_encrypt_cfm(conn, ev->status);
unlock:
hci_dev_unlock(hdev);
}
static void hci_change_link_key_complete_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_change_link_key_complete *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (conn) {
if (!ev->status)
set_bit(HCI_CONN_SECURE, &conn->flags);
clear_bit(HCI_CONN_AUTH_PEND, &conn->flags);
hci_key_change_cfm(conn, ev->status);
}
hci_dev_unlock(hdev);
}
static void hci_remote_features_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_remote_features *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (!conn)
goto unlock;
if (!ev->status)
memcpy(conn->features[0], ev->features, 8);
if (conn->state != BT_CONFIG)
goto unlock;
Bluetooth: Fix sending Read Remote Extended Features command This command should only be used if remote device reports that it supports extended features. Otherwise command will fail and connection will be dropped. Some devices support SSP but don't support extended features so current check for SSP support is not enought. Instead of checking for SSP support just check if both ends support Extended Feature. < HCI Command: Create Connection (0x01|0x0005) plen 13 Address: D0:9C:30:00:19:6F (Foster Electric Company, Limited) Packet type: 0xcc18 DM1 may be used DH1 may be used DM3 may be used DH3 may be used DM5 may be used DH5 may be used Page scan repetition mode: R1 (0x01) Page scan mode: Mandatory (0x00) Clock offset: 0x94c8 Role switch: Allow slave (0x01) > HCI Event: Command Status (0x0f) plen 4 Create Connection (0x01|0x0005) ncmd 1 Status: Success (0x00) > HCI Event: Connect Complete (0x03) plen 11 Status: Success (0x00) Handle: 5 Address: D0:9C:30:00:19:6F (Foster Electric Company, Limited) Link type: ACL (0x01) Encryption: Disabled (0x00) < HCI Command: Read Remote Supported Features (0x01|0x001b) plen 2 Handle: 5 > HCI Event: Command Status (0x0f) plen 4 Read Remote Supported Features (0x01|0x001b) ncmd 1 Status: Success (0x00) > HCI Event: Page Scan Repetition Mode Change (0x20) plen 7 Address: D0:9C:30:00:19:6F (Foster Electric Company, Limited) Page scan repetition mode: R1 (0x01) > HCI Event: Read Remote Supported Features (0x0b) plen 11 Status: Success (0x00) Handle: 5 Features: 0xff 0xff 0x8f 0xfe 0xdb 0xff 0x5b 0x07 3 slot packets 5 slot packets Encryption Slot offset Timing accuracy Role switch Hold mode Sniff mode Park state Power control requests Channel quality driven data rate (CQDDR) SCO link HV2 packets HV3 packets u-law log synchronous data A-law log synchronous data CVSD synchronous data Paging parameter negotiation Power control Transparent synchronous data Broadcast Encryption Enhanced Data Rate ACL 2 Mbps mode Enhanced Data Rate ACL 3 Mbps mode Enhanced inquiry scan Interlaced inquiry scan Interlaced page scan RSSI with inquiry results Extended SCO link (EV3 packets) EV4 packets EV5 packets AFH capable slave AFH classification slave LE Supported (Controller) 3-slot Enhanced Data Rate ACL packets 5-slot Enhanced Data Rate ACL packets Sniff subrating Pause encryption AFH capable master AFH classification master Enhanced Data Rate eSCO 2 Mbps mode Enhanced Data Rate eSCO 3 Mbps mode 3-slot Enhanced Data Rate eSCO packets Extended Inquiry Response Simultaneous LE and BR/EDR (Controller) Secure Simple Pairing Encapsulated PDU Non-flushable Packet Boundary Flag Link Supervision Timeout Changed Event Inquiry TX Power Level Enhanced Power Control < HCI Command: Read Remote Extended Features (0x01|0x001c) plen 3 Handle: 5 Page: 1 > HCI Event: Command Status (0x0f) plen 4 Read Remote Extended Features (0x01|0x001c) ncmd 1 Status: Command Disallowed (0x0c) < HCI Command: Read Clock Offset (0x01|0x001f) plen 2 Handle: 5 > HCI Event: Command Status (0x0f) plen 4 Read Clock Offset (0x01|0x001f) ncmd 1 Status: Success (0x00) < HCI Command: Disconnect (0x01|0x0006) plen 3 Handle: 5 Reason: Remote User Terminated Connection (0x13) Signed-off-by: Szymon Janc <szymon.janc@tieto.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2015-01-29 23:36:59 +08:00
if (!ev->status && lmp_ext_feat_capable(hdev) &&
lmp_ext_feat_capable(conn)) {
struct hci_cp_read_remote_ext_features cp;
cp.handle = ev->handle;
cp.page = 0x01;
hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES,
sizeof(cp), &cp);
goto unlock;
}
if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
struct hci_cp_remote_name_req cp;
memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, &conn->dst);
cp.pscan_rep_mode = 0x02;
hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
mgmt_device_connected(hdev, conn, NULL, 0);
if (!hci_outgoing_auth_needed(hdev, conn)) {
conn->state = BT_CONNECTED;
hci_connect_cfm(conn, ev->status);
hci_conn_drop(conn);
}
unlock:
hci_dev_unlock(hdev);
}
static inline void handle_cmd_cnt_and_timer(struct hci_dev *hdev, u8 ncmd)
{
cancel_delayed_work(&hdev->cmd_timer);
if (!test_bit(HCI_RESET, &hdev->flags)) {
if (ncmd) {
cancel_delayed_work(&hdev->ncmd_timer);
atomic_set(&hdev->cmd_cnt, 1);
} else {
schedule_delayed_work(&hdev->ncmd_timer,
HCI_NCMD_TIMEOUT);
}
}
}
#define HCI_CC_VL(_op, _func, _min, _max) \
{ \
.op = _op, \
.func = _func, \
.min_len = _min, \
.max_len = _max, \
}
#define HCI_CC(_op, _func, _len) \
HCI_CC_VL(_op, _func, _len, _len)
#define HCI_CC_STATUS(_op, _func) \
HCI_CC(_op, _func, sizeof(struct hci_ev_status))
static const struct hci_cc {
u16 op;
u8 (*func)(struct hci_dev *hdev, void *data, struct sk_buff *skb);
u16 min_len;
u16 max_len;
} hci_cc_table[] = {
HCI_CC_STATUS(HCI_OP_INQUIRY_CANCEL, hci_cc_inquiry_cancel),
HCI_CC_STATUS(HCI_OP_PERIODIC_INQ, hci_cc_periodic_inq),
HCI_CC_STATUS(HCI_OP_EXIT_PERIODIC_INQ, hci_cc_exit_periodic_inq),
HCI_CC_STATUS(HCI_OP_REMOTE_NAME_REQ_CANCEL,
hci_cc_remote_name_req_cancel),
HCI_CC(HCI_OP_ROLE_DISCOVERY, hci_cc_role_discovery,
sizeof(struct hci_rp_role_discovery)),
HCI_CC(HCI_OP_READ_LINK_POLICY, hci_cc_read_link_policy,
sizeof(struct hci_rp_read_link_policy)),
HCI_CC(HCI_OP_WRITE_LINK_POLICY, hci_cc_write_link_policy,
sizeof(struct hci_rp_write_link_policy)),
HCI_CC(HCI_OP_READ_DEF_LINK_POLICY, hci_cc_read_def_link_policy,
sizeof(struct hci_rp_read_def_link_policy)),
HCI_CC_STATUS(HCI_OP_WRITE_DEF_LINK_POLICY,
hci_cc_write_def_link_policy),
HCI_CC_STATUS(HCI_OP_RESET, hci_cc_reset),
HCI_CC(HCI_OP_READ_STORED_LINK_KEY, hci_cc_read_stored_link_key,
sizeof(struct hci_rp_read_stored_link_key)),
HCI_CC(HCI_OP_DELETE_STORED_LINK_KEY, hci_cc_delete_stored_link_key,
sizeof(struct hci_rp_delete_stored_link_key)),
HCI_CC_STATUS(HCI_OP_WRITE_LOCAL_NAME, hci_cc_write_local_name),
HCI_CC(HCI_OP_READ_LOCAL_NAME, hci_cc_read_local_name,
sizeof(struct hci_rp_read_local_name)),
HCI_CC_STATUS(HCI_OP_WRITE_AUTH_ENABLE, hci_cc_write_auth_enable),
HCI_CC_STATUS(HCI_OP_WRITE_ENCRYPT_MODE, hci_cc_write_encrypt_mode),
HCI_CC_STATUS(HCI_OP_WRITE_SCAN_ENABLE, hci_cc_write_scan_enable),
HCI_CC_STATUS(HCI_OP_SET_EVENT_FLT, hci_cc_set_event_filter),
HCI_CC(HCI_OP_READ_CLASS_OF_DEV, hci_cc_read_class_of_dev,
sizeof(struct hci_rp_read_class_of_dev)),
HCI_CC_STATUS(HCI_OP_WRITE_CLASS_OF_DEV, hci_cc_write_class_of_dev),
HCI_CC(HCI_OP_READ_VOICE_SETTING, hci_cc_read_voice_setting,
sizeof(struct hci_rp_read_voice_setting)),
HCI_CC_STATUS(HCI_OP_WRITE_VOICE_SETTING, hci_cc_write_voice_setting),
HCI_CC(HCI_OP_READ_NUM_SUPPORTED_IAC, hci_cc_read_num_supported_iac,
sizeof(struct hci_rp_read_num_supported_iac)),
HCI_CC_STATUS(HCI_OP_WRITE_SSP_MODE, hci_cc_write_ssp_mode),
HCI_CC_STATUS(HCI_OP_WRITE_SC_SUPPORT, hci_cc_write_sc_support),
HCI_CC(HCI_OP_READ_AUTH_PAYLOAD_TO, hci_cc_read_auth_payload_timeout,
sizeof(struct hci_rp_read_auth_payload_to)),
HCI_CC(HCI_OP_WRITE_AUTH_PAYLOAD_TO, hci_cc_write_auth_payload_timeout,
sizeof(struct hci_rp_write_auth_payload_to)),
HCI_CC(HCI_OP_READ_LOCAL_VERSION, hci_cc_read_local_version,
sizeof(struct hci_rp_read_local_version)),
HCI_CC(HCI_OP_READ_LOCAL_COMMANDS, hci_cc_read_local_commands,
sizeof(struct hci_rp_read_local_commands)),
HCI_CC(HCI_OP_READ_LOCAL_FEATURES, hci_cc_read_local_features,
sizeof(struct hci_rp_read_local_features)),
HCI_CC(HCI_OP_READ_LOCAL_EXT_FEATURES, hci_cc_read_local_ext_features,
sizeof(struct hci_rp_read_local_ext_features)),
HCI_CC(HCI_OP_READ_BUFFER_SIZE, hci_cc_read_buffer_size,
sizeof(struct hci_rp_read_buffer_size)),
HCI_CC(HCI_OP_READ_BD_ADDR, hci_cc_read_bd_addr,
sizeof(struct hci_rp_read_bd_addr)),
HCI_CC(HCI_OP_READ_LOCAL_PAIRING_OPTS, hci_cc_read_local_pairing_opts,
sizeof(struct hci_rp_read_local_pairing_opts)),
HCI_CC(HCI_OP_READ_PAGE_SCAN_ACTIVITY, hci_cc_read_page_scan_activity,
sizeof(struct hci_rp_read_page_scan_activity)),
HCI_CC_STATUS(HCI_OP_WRITE_PAGE_SCAN_ACTIVITY,
hci_cc_write_page_scan_activity),
HCI_CC(HCI_OP_READ_PAGE_SCAN_TYPE, hci_cc_read_page_scan_type,
sizeof(struct hci_rp_read_page_scan_type)),
HCI_CC_STATUS(HCI_OP_WRITE_PAGE_SCAN_TYPE, hci_cc_write_page_scan_type),
HCI_CC(HCI_OP_READ_DATA_BLOCK_SIZE, hci_cc_read_data_block_size,
sizeof(struct hci_rp_read_data_block_size)),
HCI_CC(HCI_OP_READ_FLOW_CONTROL_MODE, hci_cc_read_flow_control_mode,
sizeof(struct hci_rp_read_flow_control_mode)),
HCI_CC(HCI_OP_READ_LOCAL_AMP_INFO, hci_cc_read_local_amp_info,
sizeof(struct hci_rp_read_local_amp_info)),
HCI_CC(HCI_OP_READ_CLOCK, hci_cc_read_clock,
sizeof(struct hci_rp_read_clock)),
HCI_CC(HCI_OP_READ_INQ_RSP_TX_POWER, hci_cc_read_inq_rsp_tx_power,
sizeof(struct hci_rp_read_inq_rsp_tx_power)),
HCI_CC(HCI_OP_READ_DEF_ERR_DATA_REPORTING,
hci_cc_read_def_err_data_reporting,
sizeof(struct hci_rp_read_def_err_data_reporting)),
HCI_CC_STATUS(HCI_OP_WRITE_DEF_ERR_DATA_REPORTING,
hci_cc_write_def_err_data_reporting),
HCI_CC(HCI_OP_PIN_CODE_REPLY, hci_cc_pin_code_reply,
sizeof(struct hci_rp_pin_code_reply)),
HCI_CC(HCI_OP_PIN_CODE_NEG_REPLY, hci_cc_pin_code_neg_reply,
sizeof(struct hci_rp_pin_code_neg_reply)),
HCI_CC(HCI_OP_READ_LOCAL_OOB_DATA, hci_cc_read_local_oob_data,
sizeof(struct hci_rp_read_local_oob_data)),
HCI_CC(HCI_OP_READ_LOCAL_OOB_EXT_DATA, hci_cc_read_local_oob_ext_data,
sizeof(struct hci_rp_read_local_oob_ext_data)),
HCI_CC(HCI_OP_LE_READ_BUFFER_SIZE, hci_cc_le_read_buffer_size,
sizeof(struct hci_rp_le_read_buffer_size)),
HCI_CC(HCI_OP_LE_READ_LOCAL_FEATURES, hci_cc_le_read_local_features,
sizeof(struct hci_rp_le_read_local_features)),
HCI_CC(HCI_OP_LE_READ_ADV_TX_POWER, hci_cc_le_read_adv_tx_power,
sizeof(struct hci_rp_le_read_adv_tx_power)),
HCI_CC(HCI_OP_USER_CONFIRM_REPLY, hci_cc_user_confirm_reply,
sizeof(struct hci_rp_user_confirm_reply)),
HCI_CC(HCI_OP_USER_CONFIRM_NEG_REPLY, hci_cc_user_confirm_neg_reply,
sizeof(struct hci_rp_user_confirm_reply)),
HCI_CC(HCI_OP_USER_PASSKEY_REPLY, hci_cc_user_passkey_reply,
sizeof(struct hci_rp_user_confirm_reply)),
HCI_CC(HCI_OP_USER_PASSKEY_NEG_REPLY, hci_cc_user_passkey_neg_reply,
sizeof(struct hci_rp_user_confirm_reply)),
HCI_CC_STATUS(HCI_OP_LE_SET_RANDOM_ADDR, hci_cc_le_set_random_addr),
HCI_CC_STATUS(HCI_OP_LE_SET_ADV_ENABLE, hci_cc_le_set_adv_enable),
HCI_CC_STATUS(HCI_OP_LE_SET_SCAN_PARAM, hci_cc_le_set_scan_param),
HCI_CC_STATUS(HCI_OP_LE_SET_SCAN_ENABLE, hci_cc_le_set_scan_enable),
HCI_CC(HCI_OP_LE_READ_ACCEPT_LIST_SIZE,
hci_cc_le_read_accept_list_size,
sizeof(struct hci_rp_le_read_accept_list_size)),
HCI_CC_STATUS(HCI_OP_LE_CLEAR_ACCEPT_LIST, hci_cc_le_clear_accept_list),
HCI_CC_STATUS(HCI_OP_LE_ADD_TO_ACCEPT_LIST,
hci_cc_le_add_to_accept_list),
HCI_CC_STATUS(HCI_OP_LE_DEL_FROM_ACCEPT_LIST,
hci_cc_le_del_from_accept_list),
HCI_CC(HCI_OP_LE_READ_SUPPORTED_STATES, hci_cc_le_read_supported_states,
sizeof(struct hci_rp_le_read_supported_states)),
HCI_CC(HCI_OP_LE_READ_DEF_DATA_LEN, hci_cc_le_read_def_data_len,
sizeof(struct hci_rp_le_read_def_data_len)),
HCI_CC_STATUS(HCI_OP_LE_WRITE_DEF_DATA_LEN,
hci_cc_le_write_def_data_len),
HCI_CC_STATUS(HCI_OP_LE_ADD_TO_RESOLV_LIST,
hci_cc_le_add_to_resolv_list),
HCI_CC_STATUS(HCI_OP_LE_DEL_FROM_RESOLV_LIST,
hci_cc_le_del_from_resolv_list),
HCI_CC_STATUS(HCI_OP_LE_CLEAR_RESOLV_LIST,
hci_cc_le_clear_resolv_list),
HCI_CC(HCI_OP_LE_READ_RESOLV_LIST_SIZE, hci_cc_le_read_resolv_list_size,
sizeof(struct hci_rp_le_read_resolv_list_size)),
HCI_CC_STATUS(HCI_OP_LE_SET_ADDR_RESOLV_ENABLE,
hci_cc_le_set_addr_resolution_enable),
HCI_CC(HCI_OP_LE_READ_MAX_DATA_LEN, hci_cc_le_read_max_data_len,
sizeof(struct hci_rp_le_read_max_data_len)),
HCI_CC_STATUS(HCI_OP_WRITE_LE_HOST_SUPPORTED,
hci_cc_write_le_host_supported),
HCI_CC_STATUS(HCI_OP_LE_SET_ADV_PARAM, hci_cc_set_adv_param),
HCI_CC(HCI_OP_READ_RSSI, hci_cc_read_rssi,
sizeof(struct hci_rp_read_rssi)),
HCI_CC(HCI_OP_READ_TX_POWER, hci_cc_read_tx_power,
sizeof(struct hci_rp_read_tx_power)),
HCI_CC_STATUS(HCI_OP_WRITE_SSP_DEBUG_MODE, hci_cc_write_ssp_debug_mode),
HCI_CC_STATUS(HCI_OP_LE_SET_EXT_SCAN_PARAMS,
hci_cc_le_set_ext_scan_param),
HCI_CC_STATUS(HCI_OP_LE_SET_EXT_SCAN_ENABLE,
hci_cc_le_set_ext_scan_enable),
HCI_CC_STATUS(HCI_OP_LE_SET_DEFAULT_PHY, hci_cc_le_set_default_phy),
HCI_CC(HCI_OP_LE_READ_NUM_SUPPORTED_ADV_SETS,
hci_cc_le_read_num_adv_sets,
sizeof(struct hci_rp_le_read_num_supported_adv_sets)),
HCI_CC(HCI_OP_LE_SET_EXT_ADV_PARAMS, hci_cc_set_ext_adv_param,
sizeof(struct hci_rp_le_set_ext_adv_params)),
HCI_CC_STATUS(HCI_OP_LE_SET_EXT_ADV_ENABLE,
hci_cc_le_set_ext_adv_enable),
HCI_CC_STATUS(HCI_OP_LE_SET_ADV_SET_RAND_ADDR,
hci_cc_le_set_adv_set_random_addr),
HCI_CC_STATUS(HCI_OP_LE_REMOVE_ADV_SET, hci_cc_le_remove_adv_set),
HCI_CC_STATUS(HCI_OP_LE_CLEAR_ADV_SETS, hci_cc_le_clear_adv_sets),
HCI_CC(HCI_OP_LE_READ_TRANSMIT_POWER, hci_cc_le_read_transmit_power,
sizeof(struct hci_rp_le_read_transmit_power)),
HCI_CC_STATUS(HCI_OP_LE_SET_PRIVACY_MODE, hci_cc_le_set_privacy_mode)
};
static u8 hci_cc_func(struct hci_dev *hdev, const struct hci_cc *cc,
struct sk_buff *skb)
{
void *data;
if (skb->len < cc->min_len) {
bt_dev_err(hdev, "unexpected cc 0x%4.4x length: %u < %u",
cc->op, skb->len, cc->min_len);
return HCI_ERROR_UNSPECIFIED;
}
/* Just warn if the length is over max_len size it still be possible to
* partially parse the cc so leave to callback to decide if that is
* acceptable.
*/
if (skb->len > cc->max_len)
bt_dev_warn(hdev, "unexpected cc 0x%4.4x length: %u > %u",
cc->op, skb->len, cc->max_len);
data = hci_cc_skb_pull(hdev, skb, cc->op, cc->min_len);
if (!data)
return HCI_ERROR_UNSPECIFIED;
return cc->func(hdev, data, skb);
}
static void hci_cmd_complete_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb, u16 *opcode, u8 *status,
hci_req_complete_t *req_complete,
hci_req_complete_skb_t *req_complete_skb)
{
struct hci_ev_cmd_complete *ev = data;
int i;
*opcode = __le16_to_cpu(ev->opcode);
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2 This make use of hci_cmd_sync_queue for the following MGMT commands: Add Advertising Remove Advertising Add Extended Advertising Parameters Add Extended Advertising Data mgmt-tester -s "Add Advertising" Test Summary ------------ Add Advertising - Failure: LE off Passed Add Advertising - Invalid Params 1 (AD too long) Passed Add Advertising - Invalid Params 2 (Malformed len) Passed Add Advertising - Invalid Params 3 (Malformed len) Passed Add Advertising - Invalid Params 4 (Malformed len) Passed Add Advertising - Invalid Params 5 (AD too long) Passed Add Advertising - Invalid Params 6 (ScRsp too long) Passed Add Advertising - Invalid Params 7 (Malformed len) Passed Add Advertising - Invalid Params 8 (Malformed len) Passed Add Advertising - Invalid Params 9 (Malformed len) Passed Add Advertising - Invalid Params 10 (ScRsp too long) Passed Add Advertising - Rejected (Timeout, !Powered) Passed Add Advertising - Success 1 (Powered, Add Adv Inst) Passed Add Advertising - Success 2 (!Powered, Add Adv Inst) Passed Add Advertising - Success 3 (!Powered, Adv Enable) Passed Add Advertising - Success 4 (Set Adv on override) Passed Add Advertising - Success 5 (Set Adv off override) Passed Add Advertising - Success 6 (Scan Rsp Dta, Adv ok) Passed Add Advertising - Success 7 (Scan Rsp Dta, Scan ok) Passed Add Advertising - Success 8 (Connectable Flag) Passed Add Advertising - Success 9 (General Discov Flag) Passed Add Advertising - Success 10 (Limited Discov Flag) Passed Add Advertising - Success 11 (Managed Flags) Passed Add Advertising - Success 12 (TX Power Flag) Passed Add Advertising - Success 13 (ADV_SCAN_IND) Passed Add Advertising - Success 14 (ADV_NONCONN_IND) Passed Add Advertising - Success 15 (ADV_IND) Passed Add Advertising - Success 16 (Connectable -> on) Passed Add Advertising - Success 17 (Connectable -> off) Passed Add Advertising - Success 18 (Power -> off, Remove) Passed Add Advertising - Success 19 (Power -> off, Keep) Passed Add Advertising - Success 20 (Add Adv override) Passed Add Advertising - Success 21 (Timeout expires) Passed Add Advertising - Success 22 (LE -> off, Remove) Passed Add Advertising - Success (Empty ScRsp) Passed Add Advertising - Success (ScRsp only) Passed Add Advertising - Invalid Params (ScRsp too long) Passed Add Advertising - Success (ScRsp appear) Passed Add Advertising - Invalid Params (ScRsp appear long) Passed Add Advertising - Success (Appear is null) Passed Add Advertising - Success (Name is null) Passed Add Advertising - Success (Complete name) Passed Add Advertising - Success (Shortened name) Passed Add Advertising - Success (Short name) Passed Add Advertising - Success (Name + data) Passed Add Advertising - Invalid Params (Name + data) Passed Add Advertising - Success (Name+data+appear) Passed Total: 47, Passed: 47 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 2.17 seconds mgmt-tester -s "Remove Advertising" Test Summary ------------ Remove Advertising - Invalid Params 1 Passed Remove Advertising - Success 1 Passed Remove Advertising - Success 2 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0585 seconds mgmt-tester -s "Ext Adv MGMT Params" Test Summary: ------------ Ext Adv MGMT Params - Unpowered Passed Ext Adv MGMT Params - Invalid parameters Passed Ext Adv MGMT Params - Success Passed Ext Adv MGMT Params - (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0746 seconds mgmt-tester -s "Ext Adv MGMT -" Test Summary ------------ Ext Adv MGMT - Data set without Params Passed Ext Adv MGMT - AD Data (5.0) Invalid parameters Passed Ext Adv MGMT - AD Data (5.0) Success Passed Ext Adv MGMT - AD Scan Response (5.0) Success Passed Total: 4, Passed: 4 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0805 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-28 07:58:40 +08:00
bt_dev_dbg(hdev, "opcode 0x%4.4x", *opcode);
for (i = 0; i < ARRAY_SIZE(hci_cc_table); i++) {
if (hci_cc_table[i].op == *opcode) {
*status = hci_cc_func(hdev, &hci_cc_table[i], skb);
break;
}
}
handle_cmd_cnt_and_timer(hdev, ev->ncmd);
hci_req_cmd_complete(hdev, *opcode, *status, req_complete,
req_complete_skb);
Bluetooth: Ignore CC events not matching the last HCI command This commit makes the kernel not send the next queued HCI command until a command complete arrives for the last HCI command sent to the controller. This change avoids a problem with some buggy controllers (seen on two SKUs of QCA9377) that send an extra command complete event for the previous command after the kernel had already sent a new HCI command to the controller. The problem was reproduced when starting an active scanning procedure, where an extra command complete event arrives for the LE_SET_RANDOM_ADDR command. When this happends the kernel ends up not processing the command complete for the following commmand, LE_SET_SCAN_PARAM, and ultimately behaving as if a passive scanning procedure was being performed, when in fact controller is performing an active scanning procedure. This makes it impossible to discover BLE devices as no device found events are sent to userspace. This problem is reproducible on 100% of the attempts on the affected controllers. The extra command complete event can be seen at timestamp 27.420131 on the btmon logs bellow. Bluetooth monitor ver 5.50 = Note: Linux version 5.0.0+ (x86_64) 0.352340 = Note: Bluetooth subsystem version 2.22 0.352343 = New Index: 80:C5:F2:8F:87:84 (Primary,USB,hci0) [hci0] 0.352344 = Open Index: 80:C5:F2:8F:87:84 [hci0] 0.352345 = Index Info: 80:C5:F2:8F:87:84 (Qualcomm) [hci0] 0.352346 @ MGMT Open: bluetoothd (privileged) version 1.14 {0x0001} 0.352347 @ MGMT Open: btmon (privileged) version 1.14 {0x0002} 0.352366 @ MGMT Open: btmgmt (privileged) version 1.14 {0x0003} 27.302164 @ MGMT Command: Start Discovery (0x0023) plen 1 {0x0003} [hci0] 27.302310 Address type: 0x06 LE Public LE Random < HCI Command: LE Set Random Address (0x08|0x0005) plen 6 #1 [hci0] 27.302496 Address: 15:60:F2:91:B2:24 (Non-Resolvable) > HCI Event: Command Complete (0x0e) plen 4 #2 [hci0] 27.419117 LE Set Random Address (0x08|0x0005) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Scan Parameters (0x08|0x000b) plen 7 #3 [hci0] 27.419244 Type: Active (0x01) Interval: 11.250 msec (0x0012) Window: 11.250 msec (0x0012) Own address type: Random (0x01) Filter policy: Accept all advertisement (0x00) > HCI Event: Command Complete (0x0e) plen 4 #4 [hci0] 27.420131 LE Set Random Address (0x08|0x0005) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 #5 [hci0] 27.420259 Scanning: Enabled (0x01) Filter duplicates: Enabled (0x01) > HCI Event: Command Complete (0x0e) plen 4 #6 [hci0] 27.420969 LE Set Scan Parameters (0x08|0x000b) ncmd 1 Status: Success (0x00) > HCI Event: Command Complete (0x0e) plen 4 #7 [hci0] 27.421983 LE Set Scan Enable (0x08|0x000c) ncmd 1 Status: Success (0x00) @ MGMT Event: Command Complete (0x0001) plen 4 {0x0003} [hci0] 27.422059 Start Discovery (0x0023) plen 1 Status: Success (0x00) Address type: 0x06 LE Public LE Random @ MGMT Event: Discovering (0x0013) plen 2 {0x0003} [hci0] 27.422067 Address type: 0x06 LE Public LE Random Discovery: Enabled (0x01) @ MGMT Event: Discovering (0x0013) plen 2 {0x0002} [hci0] 27.422067 Address type: 0x06 LE Public LE Random Discovery: Enabled (0x01) @ MGMT Event: Discovering (0x0013) plen 2 {0x0001} [hci0] 27.422067 Address type: 0x06 LE Public LE Random Discovery: Enabled (0x01) Signed-off-by: João Paulo Rechi Vita <jprvita@endlessm.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2019-05-02 10:01:52 +08:00
if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
bt_dev_err(hdev,
"unexpected event for opcode 0x%4.4x", *opcode);
return;
}
if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
queue_work(hdev->workqueue, &hdev->cmd_work);
}
#define HCI_CS(_op, _func) \
{ \
.op = _op, \
.func = _func, \
}
static const struct hci_cs {
u16 op;
void (*func)(struct hci_dev *hdev, __u8 status);
} hci_cs_table[] = {
HCI_CS(HCI_OP_INQUIRY, hci_cs_inquiry),
HCI_CS(HCI_OP_CREATE_CONN, hci_cs_create_conn),
HCI_CS(HCI_OP_DISCONNECT, hci_cs_disconnect),
HCI_CS(HCI_OP_ADD_SCO, hci_cs_add_sco),
HCI_CS(HCI_OP_AUTH_REQUESTED, hci_cs_auth_requested),
HCI_CS(HCI_OP_SET_CONN_ENCRYPT, hci_cs_set_conn_encrypt),
HCI_CS(HCI_OP_REMOTE_NAME_REQ, hci_cs_remote_name_req),
HCI_CS(HCI_OP_READ_REMOTE_FEATURES, hci_cs_read_remote_features),
HCI_CS(HCI_OP_READ_REMOTE_EXT_FEATURES,
hci_cs_read_remote_ext_features),
HCI_CS(HCI_OP_SETUP_SYNC_CONN, hci_cs_setup_sync_conn),
HCI_CS(HCI_OP_ENHANCED_SETUP_SYNC_CONN,
hci_cs_enhanced_setup_sync_conn),
HCI_CS(HCI_OP_SNIFF_MODE, hci_cs_sniff_mode),
HCI_CS(HCI_OP_EXIT_SNIFF_MODE, hci_cs_exit_sniff_mode),
HCI_CS(HCI_OP_SWITCH_ROLE, hci_cs_switch_role),
HCI_CS(HCI_OP_LE_CREATE_CONN, hci_cs_le_create_conn),
HCI_CS(HCI_OP_LE_READ_REMOTE_FEATURES, hci_cs_le_read_remote_features),
HCI_CS(HCI_OP_LE_START_ENC, hci_cs_le_start_enc),
HCI_CS(HCI_OP_LE_EXT_CREATE_CONN, hci_cs_le_ext_create_conn)
};
static void hci_cmd_status_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb, u16 *opcode, u8 *status,
hci_req_complete_t *req_complete,
hci_req_complete_skb_t *req_complete_skb)
{
struct hci_ev_cmd_status *ev = data;
int i;
*opcode = __le16_to_cpu(ev->opcode);
*status = ev->status;
bt_dev_dbg(hdev, "opcode 0x%4.4x", *opcode);
Bluetooth: Use extended LE Connection if supported This implements extended LE craete connection and enhanced LE conn complete event if the controller supports. For now it is as good as legacy LE connection and event as no new features in the extended connection is handled. < HCI Command: LE Extended Create Connection (0x08|0x0043) plen 26 Filter policy: White list is not used (0x00) Own address type: Public (0x00) Peer address type: Random (0x01) Peer address: DB:7E:2E:1D:85:E8 (Static) Initiating PHYs: 0x01 Entry 0: LE 1M Scan interval: 60.000 msec (0x0060) Scan window: 60.000 msec (0x0060) Min connection interval: 50.00 msec (0x0028) Max connection interval: 70.00 msec (0x0038) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Min connection length: 0.000 msec (0x0000) Max connection length: 0.000 msec (0x0000) > HCI Event: Command Status (0x0f) plen 4 LE Extended Create Connection (0x08|0x0043) ncmd 2 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 31 LE Enhanced Connection Complete (0x0a) Status: Success (0x00) Handle: 3585 Role: Master (0x00) Peer address type: Random (0x01) Peer address: DB:7E:2E:1D:85:E8 (Static) Local resolvable private address: 00:00:00:00:00:00 (Non-Resolvable) Peer resolvable private address: 00:00:00:00:00:00 (Non-Resolvable) Connection interval: 67.50 msec (0x0036) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Master clock accuracy: 0x00 @ MGMT Event: Device Connected (0x000b) plen 40 LE Address: DB:7E:2E:1D:85:E8 (Static) Flags: 0x00000000 Data length: 27 Name (complete): Designer Mouse Appearance: Mouse (0x03c2) Flags: 0x05 LE Limited Discoverable Mode BR/EDR Not Supported 16-bit Service UUIDs (complete): 1 entry Human Interface Device (0x1812) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-07 04:50:32 +08:00
for (i = 0; i < ARRAY_SIZE(hci_cs_table); i++) {
if (hci_cs_table[i].op == *opcode) {
hci_cs_table[i].func(hdev, ev->status);
break;
}
}
handle_cmd_cnt_and_timer(hdev, ev->ncmd);
/* Indicate request completion if the command failed. Also, if
* we're not waiting for a special event and we get a success
* command status we should try to flag the request as completed
* (since for this kind of commands there will not be a command
* complete event).
*/
if (ev->status || (hdev->sent_cmd && !hci_skb_event(hdev->sent_cmd))) {
hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete,
req_complete_skb);
if (hci_dev_test_flag(hdev, HCI_CMD_PENDING)) {
bt_dev_err(hdev, "unexpected event for opcode 0x%4.4x",
*opcode);
return;
}
Bluetooth: Ignore CC events not matching the last HCI command This commit makes the kernel not send the next queued HCI command until a command complete arrives for the last HCI command sent to the controller. This change avoids a problem with some buggy controllers (seen on two SKUs of QCA9377) that send an extra command complete event for the previous command after the kernel had already sent a new HCI command to the controller. The problem was reproduced when starting an active scanning procedure, where an extra command complete event arrives for the LE_SET_RANDOM_ADDR command. When this happends the kernel ends up not processing the command complete for the following commmand, LE_SET_SCAN_PARAM, and ultimately behaving as if a passive scanning procedure was being performed, when in fact controller is performing an active scanning procedure. This makes it impossible to discover BLE devices as no device found events are sent to userspace. This problem is reproducible on 100% of the attempts on the affected controllers. The extra command complete event can be seen at timestamp 27.420131 on the btmon logs bellow. Bluetooth monitor ver 5.50 = Note: Linux version 5.0.0+ (x86_64) 0.352340 = Note: Bluetooth subsystem version 2.22 0.352343 = New Index: 80:C5:F2:8F:87:84 (Primary,USB,hci0) [hci0] 0.352344 = Open Index: 80:C5:F2:8F:87:84 [hci0] 0.352345 = Index Info: 80:C5:F2:8F:87:84 (Qualcomm) [hci0] 0.352346 @ MGMT Open: bluetoothd (privileged) version 1.14 {0x0001} 0.352347 @ MGMT Open: btmon (privileged) version 1.14 {0x0002} 0.352366 @ MGMT Open: btmgmt (privileged) version 1.14 {0x0003} 27.302164 @ MGMT Command: Start Discovery (0x0023) plen 1 {0x0003} [hci0] 27.302310 Address type: 0x06 LE Public LE Random < HCI Command: LE Set Random Address (0x08|0x0005) plen 6 #1 [hci0] 27.302496 Address: 15:60:F2:91:B2:24 (Non-Resolvable) > HCI Event: Command Complete (0x0e) plen 4 #2 [hci0] 27.419117 LE Set Random Address (0x08|0x0005) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Scan Parameters (0x08|0x000b) plen 7 #3 [hci0] 27.419244 Type: Active (0x01) Interval: 11.250 msec (0x0012) Window: 11.250 msec (0x0012) Own address type: Random (0x01) Filter policy: Accept all advertisement (0x00) > HCI Event: Command Complete (0x0e) plen 4 #4 [hci0] 27.420131 LE Set Random Address (0x08|0x0005) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 #5 [hci0] 27.420259 Scanning: Enabled (0x01) Filter duplicates: Enabled (0x01) > HCI Event: Command Complete (0x0e) plen 4 #6 [hci0] 27.420969 LE Set Scan Parameters (0x08|0x000b) ncmd 1 Status: Success (0x00) > HCI Event: Command Complete (0x0e) plen 4 #7 [hci0] 27.421983 LE Set Scan Enable (0x08|0x000c) ncmd 1 Status: Success (0x00) @ MGMT Event: Command Complete (0x0001) plen 4 {0x0003} [hci0] 27.422059 Start Discovery (0x0023) plen 1 Status: Success (0x00) Address type: 0x06 LE Public LE Random @ MGMT Event: Discovering (0x0013) plen 2 {0x0003} [hci0] 27.422067 Address type: 0x06 LE Public LE Random Discovery: Enabled (0x01) @ MGMT Event: Discovering (0x0013) plen 2 {0x0002} [hci0] 27.422067 Address type: 0x06 LE Public LE Random Discovery: Enabled (0x01) @ MGMT Event: Discovering (0x0013) plen 2 {0x0001} [hci0] 27.422067 Address type: 0x06 LE Public LE Random Discovery: Enabled (0x01) Signed-off-by: João Paulo Rechi Vita <jprvita@endlessm.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2019-05-02 10:01:52 +08:00
}
if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
queue_work(hdev->workqueue, &hdev->cmd_work);
}
static void hci_hardware_error_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_hardware_error *ev = data;
bt_dev_dbg(hdev, "code 0x%2.2x", ev->code);
hdev->hw_error_code = ev->code;
queue_work(hdev->req_workqueue, &hdev->error_reset);
}
static void hci_role_change_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_role_change *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (conn) {
if (!ev->status)
conn->role = ev->role;
clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags);
hci_role_switch_cfm(conn, ev->status, ev->role);
}
hci_dev_unlock(hdev);
}
static void hci_num_comp_pkts_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_num_comp_pkts *ev = data;
int i;
if (!hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_PKTS,
flex_array_size(ev, handles, ev->num)))
return;
if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_PACKET_BASED) {
bt_dev_err(hdev, "wrong event for mode %d", hdev->flow_ctl_mode);
return;
}
bt_dev_dbg(hdev, "num %d", ev->num);
for (i = 0; i < ev->num; i++) {
struct hci_comp_pkts_info *info = &ev->handles[i];
struct hci_conn *conn;
__u16 handle, count;
handle = __le16_to_cpu(info->handle);
count = __le16_to_cpu(info->count);
conn = hci_conn_hash_lookup_handle(hdev, handle);
if (!conn)
continue;
conn->sent -= count;
switch (conn->type) {
case ACL_LINK:
hdev->acl_cnt += count;
if (hdev->acl_cnt > hdev->acl_pkts)
hdev->acl_cnt = hdev->acl_pkts;
break;
case LE_LINK:
if (hdev->le_pkts) {
hdev->le_cnt += count;
if (hdev->le_cnt > hdev->le_pkts)
hdev->le_cnt = hdev->le_pkts;
} else {
hdev->acl_cnt += count;
if (hdev->acl_cnt > hdev->acl_pkts)
hdev->acl_cnt = hdev->acl_pkts;
}
break;
case SCO_LINK:
hdev->sco_cnt += count;
if (hdev->sco_cnt > hdev->sco_pkts)
hdev->sco_cnt = hdev->sco_pkts;
break;
default:
bt_dev_err(hdev, "unknown type %d conn %p",
conn->type, conn);
break;
}
}
queue_work(hdev->workqueue, &hdev->tx_work);
}
static struct hci_conn *__hci_conn_lookup_handle(struct hci_dev *hdev,
__u16 handle)
{
struct hci_chan *chan;
switch (hdev->dev_type) {
case HCI_PRIMARY:
return hci_conn_hash_lookup_handle(hdev, handle);
case HCI_AMP:
chan = hci_chan_lookup_handle(hdev, handle);
if (chan)
return chan->conn;
break;
default:
bt_dev_err(hdev, "unknown dev_type %d", hdev->dev_type);
break;
}
return NULL;
}
static void hci_num_comp_blocks_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_num_comp_blocks *ev = data;
int i;
if (!hci_ev_skb_pull(hdev, skb, HCI_EV_NUM_COMP_BLOCKS,
flex_array_size(ev, handles, ev->num_hndl)))
return;
if (hdev->flow_ctl_mode != HCI_FLOW_CTL_MODE_BLOCK_BASED) {
bt_dev_err(hdev, "wrong event for mode %d",
hdev->flow_ctl_mode);
return;
}
bt_dev_dbg(hdev, "num_blocks %d num_hndl %d", ev->num_blocks,
ev->num_hndl);
for (i = 0; i < ev->num_hndl; i++) {
struct hci_comp_blocks_info *info = &ev->handles[i];
struct hci_conn *conn = NULL;
__u16 handle, block_count;
handle = __le16_to_cpu(info->handle);
block_count = __le16_to_cpu(info->blocks);
conn = __hci_conn_lookup_handle(hdev, handle);
if (!conn)
continue;
conn->sent -= block_count;
switch (conn->type) {
case ACL_LINK:
case AMP_LINK:
hdev->block_cnt += block_count;
if (hdev->block_cnt > hdev->num_blocks)
hdev->block_cnt = hdev->num_blocks;
break;
default:
bt_dev_err(hdev, "unknown type %d conn %p",
conn->type, conn);
break;
}
}
queue_work(hdev->workqueue, &hdev->tx_work);
}
static void hci_mode_change_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_mode_change *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (conn) {
conn->mode = ev->mode;
if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND,
&conn->flags)) {
if (conn->mode == HCI_CM_ACTIVE)
set_bit(HCI_CONN_POWER_SAVE, &conn->flags);
else
clear_bit(HCI_CONN_POWER_SAVE, &conn->flags);
}
if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags))
hci_sco_setup(conn, ev->status);
}
hci_dev_unlock(hdev);
}
static void hci_pin_code_request_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_pin_code_req *ev = data;
Bluetooth: Add different pairing timeout for Legacy Pairing The Bluetooth stack uses a reference counting for all established ACL links and if no user (L2CAP connection) is present, the link will be terminated to save power. The problem part is the dedicated pairing when using Legacy Pairing (Bluetooth 2.0 and before). At that point no user is present and pairing attempts will be disconnected within 10 seconds or less. In previous kernel version this was not a problem since the disconnect timeout wasn't triggered on incoming connections for the first time. However this caused issues with broken host stacks that kept the connections around after dedicated pairing. When the support for Simple Pairing got added, the link establishment procedure needed to be changed and now causes issues when using Legacy Pairing When using Simple Pairing it is possible to do a proper reference counting of ACL link users. With Legacy Pairing this is not possible since the specification is unclear in some areas and too many broken Bluetooth devices have already been deployed. So instead of trying to deal with all the broken devices, a special pairing timeout will be introduced that increases the timeout to 60 seconds when pairing is triggered. If a broken devices now puts the stack into an unforeseen state, the worst that happens is the disconnect timeout triggers after 120 seconds instead of 4 seconds. This allows successful pairings with legacy and broken devices now. Based on a report by Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2009-04-27 02:01:22 +08:00
struct hci_conn *conn;
bt_dev_dbg(hdev, "");
Bluetooth: Add different pairing timeout for Legacy Pairing The Bluetooth stack uses a reference counting for all established ACL links and if no user (L2CAP connection) is present, the link will be terminated to save power. The problem part is the dedicated pairing when using Legacy Pairing (Bluetooth 2.0 and before). At that point no user is present and pairing attempts will be disconnected within 10 seconds or less. In previous kernel version this was not a problem since the disconnect timeout wasn't triggered on incoming connections for the first time. However this caused issues with broken host stacks that kept the connections around after dedicated pairing. When the support for Simple Pairing got added, the link establishment procedure needed to be changed and now causes issues when using Legacy Pairing When using Simple Pairing it is possible to do a proper reference counting of ACL link users. With Legacy Pairing this is not possible since the specification is unclear in some areas and too many broken Bluetooth devices have already been deployed. So instead of trying to deal with all the broken devices, a special pairing timeout will be introduced that increases the timeout to 60 seconds when pairing is triggered. If a broken devices now puts the stack into an unforeseen state, the worst that happens is the disconnect timeout triggers after 120 seconds instead of 4 seconds. This allows successful pairings with legacy and broken devices now. Based on a report by Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2009-04-27 02:01:22 +08:00
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (!conn)
goto unlock;
if (conn->state == BT_CONNECTED) {
Bluetooth: Add different pairing timeout for Legacy Pairing The Bluetooth stack uses a reference counting for all established ACL links and if no user (L2CAP connection) is present, the link will be terminated to save power. The problem part is the dedicated pairing when using Legacy Pairing (Bluetooth 2.0 and before). At that point no user is present and pairing attempts will be disconnected within 10 seconds or less. In previous kernel version this was not a problem since the disconnect timeout wasn't triggered on incoming connections for the first time. However this caused issues with broken host stacks that kept the connections around after dedicated pairing. When the support for Simple Pairing got added, the link establishment procedure needed to be changed and now causes issues when using Legacy Pairing When using Simple Pairing it is possible to do a proper reference counting of ACL link users. With Legacy Pairing this is not possible since the specification is unclear in some areas and too many broken Bluetooth devices have already been deployed. So instead of trying to deal with all the broken devices, a special pairing timeout will be introduced that increases the timeout to 60 seconds when pairing is triggered. If a broken devices now puts the stack into an unforeseen state, the worst that happens is the disconnect timeout triggers after 120 seconds instead of 4 seconds. This allows successful pairings with legacy and broken devices now. Based on a report by Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2009-04-27 02:01:22 +08:00
hci_conn_hold(conn);
conn->disc_timeout = HCI_PAIRING_TIMEOUT;
hci_conn_drop(conn);
Bluetooth: Add different pairing timeout for Legacy Pairing The Bluetooth stack uses a reference counting for all established ACL links and if no user (L2CAP connection) is present, the link will be terminated to save power. The problem part is the dedicated pairing when using Legacy Pairing (Bluetooth 2.0 and before). At that point no user is present and pairing attempts will be disconnected within 10 seconds or less. In previous kernel version this was not a problem since the disconnect timeout wasn't triggered on incoming connections for the first time. However this caused issues with broken host stacks that kept the connections around after dedicated pairing. When the support for Simple Pairing got added, the link establishment procedure needed to be changed and now causes issues when using Legacy Pairing When using Simple Pairing it is possible to do a proper reference counting of ACL link users. With Legacy Pairing this is not possible since the specification is unclear in some areas and too many broken Bluetooth devices have already been deployed. So instead of trying to deal with all the broken devices, a special pairing timeout will be introduced that increases the timeout to 60 seconds when pairing is triggered. If a broken devices now puts the stack into an unforeseen state, the worst that happens is the disconnect timeout triggers after 120 seconds instead of 4 seconds. This allows successful pairings with legacy and broken devices now. Based on a report by Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2009-04-27 02:01:22 +08:00
}
if (!hci_dev_test_flag(hdev, HCI_BONDABLE) &&
!test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags)) {
hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
sizeof(ev->bdaddr), &ev->bdaddr);
} else if (hci_dev_test_flag(hdev, HCI_MGMT)) {
u8 secure;
if (conn->pending_sec_level == BT_SECURITY_HIGH)
secure = 1;
else
secure = 0;
mgmt_pin_code_request(hdev, &ev->bdaddr, secure);
}
unlock:
Bluetooth: Add different pairing timeout for Legacy Pairing The Bluetooth stack uses a reference counting for all established ACL links and if no user (L2CAP connection) is present, the link will be terminated to save power. The problem part is the dedicated pairing when using Legacy Pairing (Bluetooth 2.0 and before). At that point no user is present and pairing attempts will be disconnected within 10 seconds or less. In previous kernel version this was not a problem since the disconnect timeout wasn't triggered on incoming connections for the first time. However this caused issues with broken host stacks that kept the connections around after dedicated pairing. When the support for Simple Pairing got added, the link establishment procedure needed to be changed and now causes issues when using Legacy Pairing When using Simple Pairing it is possible to do a proper reference counting of ACL link users. With Legacy Pairing this is not possible since the specification is unclear in some areas and too many broken Bluetooth devices have already been deployed. So instead of trying to deal with all the broken devices, a special pairing timeout will be introduced that increases the timeout to 60 seconds when pairing is triggered. If a broken devices now puts the stack into an unforeseen state, the worst that happens is the disconnect timeout triggers after 120 seconds instead of 4 seconds. This allows successful pairings with legacy and broken devices now. Based on a report by Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2009-04-27 02:01:22 +08:00
hci_dev_unlock(hdev);
}
static void conn_set_key(struct hci_conn *conn, u8 key_type, u8 pin_len)
{
if (key_type == HCI_LK_CHANGED_COMBINATION)
return;
conn->pin_length = pin_len;
conn->key_type = key_type;
switch (key_type) {
case HCI_LK_LOCAL_UNIT:
case HCI_LK_REMOTE_UNIT:
case HCI_LK_DEBUG_COMBINATION:
return;
case HCI_LK_COMBINATION:
if (pin_len == 16)
conn->pending_sec_level = BT_SECURITY_HIGH;
else
conn->pending_sec_level = BT_SECURITY_MEDIUM;
break;
case HCI_LK_UNAUTH_COMBINATION_P192:
case HCI_LK_UNAUTH_COMBINATION_P256:
conn->pending_sec_level = BT_SECURITY_MEDIUM;
break;
case HCI_LK_AUTH_COMBINATION_P192:
conn->pending_sec_level = BT_SECURITY_HIGH;
break;
case HCI_LK_AUTH_COMBINATION_P256:
conn->pending_sec_level = BT_SECURITY_FIPS;
break;
}
}
static void hci_link_key_request_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_link_key_req *ev = data;
struct hci_cp_link_key_reply cp;
struct hci_conn *conn;
struct link_key *key;
bt_dev_dbg(hdev, "");
if (!hci_dev_test_flag(hdev, HCI_MGMT))
return;
hci_dev_lock(hdev);
key = hci_find_link_key(hdev, &ev->bdaddr);
if (!key) {
bt_dev_dbg(hdev, "link key not found for %pMR", &ev->bdaddr);
goto not_found;
}
bt_dev_dbg(hdev, "found key type %u for %pMR", key->type, &ev->bdaddr);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (conn) {
clear_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 ||
key->type == HCI_LK_UNAUTH_COMBINATION_P256) &&
conn->auth_type != 0xff && (conn->auth_type & 0x01)) {
bt_dev_dbg(hdev, "ignoring unauthenticated key");
goto not_found;
}
if (key->type == HCI_LK_COMBINATION && key->pin_len < 16 &&
(conn->pending_sec_level == BT_SECURITY_HIGH ||
conn->pending_sec_level == BT_SECURITY_FIPS)) {
bt_dev_dbg(hdev, "ignoring key unauthenticated for high security");
goto not_found;
}
conn_set_key(conn, key->type, key->pin_len);
}
bacpy(&cp.bdaddr, &ev->bdaddr);
memcpy(cp.link_key, key->val, HCI_LINK_KEY_SIZE);
hci_send_cmd(hdev, HCI_OP_LINK_KEY_REPLY, sizeof(cp), &cp);
hci_dev_unlock(hdev);
return;
not_found:
hci_send_cmd(hdev, HCI_OP_LINK_KEY_NEG_REPLY, 6, &ev->bdaddr);
hci_dev_unlock(hdev);
}
static void hci_link_key_notify_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_link_key_notify *ev = data;
Bluetooth: Add different pairing timeout for Legacy Pairing The Bluetooth stack uses a reference counting for all established ACL links and if no user (L2CAP connection) is present, the link will be terminated to save power. The problem part is the dedicated pairing when using Legacy Pairing (Bluetooth 2.0 and before). At that point no user is present and pairing attempts will be disconnected within 10 seconds or less. In previous kernel version this was not a problem since the disconnect timeout wasn't triggered on incoming connections for the first time. However this caused issues with broken host stacks that kept the connections around after dedicated pairing. When the support for Simple Pairing got added, the link establishment procedure needed to be changed and now causes issues when using Legacy Pairing When using Simple Pairing it is possible to do a proper reference counting of ACL link users. With Legacy Pairing this is not possible since the specification is unclear in some areas and too many broken Bluetooth devices have already been deployed. So instead of trying to deal with all the broken devices, a special pairing timeout will be introduced that increases the timeout to 60 seconds when pairing is triggered. If a broken devices now puts the stack into an unforeseen state, the worst that happens is the disconnect timeout triggers after 120 seconds instead of 4 seconds. This allows successful pairings with legacy and broken devices now. Based on a report by Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2009-04-27 02:01:22 +08:00
struct hci_conn *conn;
struct link_key *key;
bool persistent;
u8 pin_len = 0;
Bluetooth: Add different pairing timeout for Legacy Pairing The Bluetooth stack uses a reference counting for all established ACL links and if no user (L2CAP connection) is present, the link will be terminated to save power. The problem part is the dedicated pairing when using Legacy Pairing (Bluetooth 2.0 and before). At that point no user is present and pairing attempts will be disconnected within 10 seconds or less. In previous kernel version this was not a problem since the disconnect timeout wasn't triggered on incoming connections for the first time. However this caused issues with broken host stacks that kept the connections around after dedicated pairing. When the support for Simple Pairing got added, the link establishment procedure needed to be changed and now causes issues when using Legacy Pairing When using Simple Pairing it is possible to do a proper reference counting of ACL link users. With Legacy Pairing this is not possible since the specification is unclear in some areas and too many broken Bluetooth devices have already been deployed. So instead of trying to deal with all the broken devices, a special pairing timeout will be introduced that increases the timeout to 60 seconds when pairing is triggered. If a broken devices now puts the stack into an unforeseen state, the worst that happens is the disconnect timeout triggers after 120 seconds instead of 4 seconds. This allows successful pairings with legacy and broken devices now. Based on a report by Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2009-04-27 02:01:22 +08:00
bt_dev_dbg(hdev, "");
Bluetooth: Add different pairing timeout for Legacy Pairing The Bluetooth stack uses a reference counting for all established ACL links and if no user (L2CAP connection) is present, the link will be terminated to save power. The problem part is the dedicated pairing when using Legacy Pairing (Bluetooth 2.0 and before). At that point no user is present and pairing attempts will be disconnected within 10 seconds or less. In previous kernel version this was not a problem since the disconnect timeout wasn't triggered on incoming connections for the first time. However this caused issues with broken host stacks that kept the connections around after dedicated pairing. When the support for Simple Pairing got added, the link establishment procedure needed to be changed and now causes issues when using Legacy Pairing When using Simple Pairing it is possible to do a proper reference counting of ACL link users. With Legacy Pairing this is not possible since the specification is unclear in some areas and too many broken Bluetooth devices have already been deployed. So instead of trying to deal with all the broken devices, a special pairing timeout will be introduced that increases the timeout to 60 seconds when pairing is triggered. If a broken devices now puts the stack into an unforeseen state, the worst that happens is the disconnect timeout triggers after 120 seconds instead of 4 seconds. This allows successful pairings with legacy and broken devices now. Based on a report by Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2009-04-27 02:01:22 +08:00
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (!conn)
goto unlock;
hci_conn_hold(conn);
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
hci_conn_drop(conn);
set_bit(HCI_CONN_NEW_LINK_KEY, &conn->flags);
conn_set_key(conn, ev->key_type, conn->pin_length);
Bluetooth: Add different pairing timeout for Legacy Pairing The Bluetooth stack uses a reference counting for all established ACL links and if no user (L2CAP connection) is present, the link will be terminated to save power. The problem part is the dedicated pairing when using Legacy Pairing (Bluetooth 2.0 and before). At that point no user is present and pairing attempts will be disconnected within 10 seconds or less. In previous kernel version this was not a problem since the disconnect timeout wasn't triggered on incoming connections for the first time. However this caused issues with broken host stacks that kept the connections around after dedicated pairing. When the support for Simple Pairing got added, the link establishment procedure needed to be changed and now causes issues when using Legacy Pairing When using Simple Pairing it is possible to do a proper reference counting of ACL link users. With Legacy Pairing this is not possible since the specification is unclear in some areas and too many broken Bluetooth devices have already been deployed. So instead of trying to deal with all the broken devices, a special pairing timeout will be introduced that increases the timeout to 60 seconds when pairing is triggered. If a broken devices now puts the stack into an unforeseen state, the worst that happens is the disconnect timeout triggers after 120 seconds instead of 4 seconds. This allows successful pairings with legacy and broken devices now. Based on a report by Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2009-04-27 02:01:22 +08:00
if (!hci_dev_test_flag(hdev, HCI_MGMT))
goto unlock;
key = hci_add_link_key(hdev, conn, &ev->bdaddr, ev->link_key,
ev->key_type, pin_len, &persistent);
if (!key)
goto unlock;
/* Update connection information since adding the key will have
* fixed up the type in the case of changed combination keys.
*/
if (ev->key_type == HCI_LK_CHANGED_COMBINATION)
conn_set_key(conn, key->type, key->pin_len);
mgmt_new_link_key(hdev, key, persistent);
/* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag
* is set. If it's not set simply remove the key from the kernel
* list (we've still notified user space about it but with
* store_hint being 0).
*/
if (key->type == HCI_LK_DEBUG_COMBINATION &&
!hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS)) {
list_del_rcu(&key->list);
kfree_rcu(key, rcu);
goto unlock;
}
if (persistent)
clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
else
set_bit(HCI_CONN_FLUSH_KEY, &conn->flags);
unlock:
Bluetooth: Add different pairing timeout for Legacy Pairing The Bluetooth stack uses a reference counting for all established ACL links and if no user (L2CAP connection) is present, the link will be terminated to save power. The problem part is the dedicated pairing when using Legacy Pairing (Bluetooth 2.0 and before). At that point no user is present and pairing attempts will be disconnected within 10 seconds or less. In previous kernel version this was not a problem since the disconnect timeout wasn't triggered on incoming connections for the first time. However this caused issues with broken host stacks that kept the connections around after dedicated pairing. When the support for Simple Pairing got added, the link establishment procedure needed to be changed and now causes issues when using Legacy Pairing When using Simple Pairing it is possible to do a proper reference counting of ACL link users. With Legacy Pairing this is not possible since the specification is unclear in some areas and too many broken Bluetooth devices have already been deployed. So instead of trying to deal with all the broken devices, a special pairing timeout will be introduced that increases the timeout to 60 seconds when pairing is triggered. If a broken devices now puts the stack into an unforeseen state, the worst that happens is the disconnect timeout triggers after 120 seconds instead of 4 seconds. This allows successful pairings with legacy and broken devices now. Based on a report by Johan Hedberg <johan.hedberg@nokia.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2009-04-27 02:01:22 +08:00
hci_dev_unlock(hdev);
}
static void hci_clock_offset_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_clock_offset *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (conn && !ev->status) {
struct inquiry_entry *ie;
ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
if (ie) {
ie->data.clock_offset = ev->clock_offset;
ie->timestamp = jiffies;
}
}
hci_dev_unlock(hdev);
}
static void hci_pkt_type_change_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_pkt_type_change *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (conn && !ev->status)
conn->pkt_type = __le16_to_cpu(ev->pkt_type);
hci_dev_unlock(hdev);
}
static void hci_pscan_rep_mode_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_pscan_rep_mode *ev = data;
struct inquiry_entry *ie;
bt_dev_dbg(hdev, "");
hci_dev_lock(hdev);
ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
if (ie) {
ie->data.pscan_rep_mode = ev->pscan_rep_mode;
ie->timestamp = jiffies;
}
hci_dev_unlock(hdev);
}
static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, void *edata,
struct sk_buff *skb)
{
struct hci_ev_inquiry_result_rssi *ev = edata;
struct inquiry_data data;
int i;
bt_dev_dbg(hdev, "num_rsp %d", ev->num);
if (!ev->num)
return;
if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
return;
hci_dev_lock(hdev);
if (skb->len == array_size(ev->num,
sizeof(struct inquiry_info_rssi_pscan))) {
struct inquiry_info_rssi_pscan *info;
for (i = 0; i < ev->num; i++) {
u32 flags;
info = hci_ev_skb_pull(hdev, skb,
HCI_EV_INQUIRY_RESULT_WITH_RSSI,
sizeof(*info));
if (!info) {
bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
HCI_EV_INQUIRY_RESULT_WITH_RSSI);
goto unlock;
}
bacpy(&data.bdaddr, &info->bdaddr);
data.pscan_rep_mode = info->pscan_rep_mode;
data.pscan_period_mode = info->pscan_period_mode;
data.pscan_mode = info->pscan_mode;
memcpy(data.dev_class, info->dev_class, 3);
data.clock_offset = info->clock_offset;
data.rssi = info->rssi;
data.ssp_mode = 0x00;
flags = hci_inquiry_cache_update(hdev, &data, false);
mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
info->dev_class, info->rssi,
flags, NULL, 0, NULL, 0);
}
} else if (skb->len == array_size(ev->num,
sizeof(struct inquiry_info_rssi))) {
struct inquiry_info_rssi *info;
for (i = 0; i < ev->num; i++) {
u32 flags;
info = hci_ev_skb_pull(hdev, skb,
HCI_EV_INQUIRY_RESULT_WITH_RSSI,
sizeof(*info));
if (!info) {
bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
HCI_EV_INQUIRY_RESULT_WITH_RSSI);
goto unlock;
}
bacpy(&data.bdaddr, &info->bdaddr);
data.pscan_rep_mode = info->pscan_rep_mode;
data.pscan_period_mode = info->pscan_period_mode;
data.pscan_mode = 0x00;
memcpy(data.dev_class, info->dev_class, 3);
data.clock_offset = info->clock_offset;
data.rssi = info->rssi;
data.ssp_mode = 0x00;
flags = hci_inquiry_cache_update(hdev, &data, false);
mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
info->dev_class, info->rssi,
flags, NULL, 0, NULL, 0);
}
} else {
bt_dev_err(hdev, "Malformed HCI Event: 0x%2.2x",
HCI_EV_INQUIRY_RESULT_WITH_RSSI);
}
unlock:
hci_dev_unlock(hdev);
}
static void hci_remote_ext_features_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_remote_ext_features *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (!conn)
goto unlock;
if (ev->page < HCI_MAX_PAGES)
memcpy(conn->features[ev->page], ev->features, 8);
if (!ev->status && ev->page == 0x01) {
struct inquiry_entry *ie;
ie = hci_inquiry_cache_lookup(hdev, &conn->dst);
if (ie)
ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
Bluetooth: Fix incorrect SSP mode bit for non SSP devices Some faulty non SSP devices send extended inquiry response during device discovery which is a violation of 2.1 specification. So for these devices we set SSP bit during acl connection initiation thinking that it is an SSP device. But for these devices, in remote host features event SSP supported bit will be off. But we are not clearing the SSP bit in that case and eventually SSP bit in conn flag will be incorrectly set for these devices. The software which has caused this issue is MecApp http://www.mecel.se/products/bluetooth/downloads/MecApp_download This patch does a workaround by clearing the SSP bit if it is not supported in remote host features event hcidump log ---------- < HCI Command: Inquiry (0x01|0x0001) plen 5 lap 0x9e8b33 len 4 num 0 > HCI Event: Command Status (0x0f) plen 4 Inquiry (0x01|0x0001) status 0x00 ncmd 1 > HCI Event: Extended Inquiry Result (0x2f) plen 255 bdaddr 00:1B:DC:05:B5:25 mode 1 clkoffset 0x3263 class 0x3c0000 rssi -77 Unknown type 0x42 with 8 bytes data Unknown type 0x1e with 2 bytes data > HCI Event: Inquiry Complete (0x01) plen 1 status 0x00 < HCI Command: Create Connection (0x01|0x0005) plen 13 bdaddr 00:1B:DC:05:B5:25 ptype 0xcc18 rswitch 0x01 clkoffset 0x0000 Packet type: DM1 DM3 DM5 DH1 DH3 DH5 > HCI Event: Command Status (0x0f) plen 4 Create Connection (0x01|0x0005) status 0x00 ncmd 1 > HCI Event: Connect Complete (0x03) plen 11 status 0x00 handle 12 bdaddr 00:1B:DC:05:B5:25 type ACL encrypt 0x00 < HCI Command: Read Remote Supported Features (0x01|0x001b) plen 2 handle 12 > HCI Event: Command Status (0x0f) plen 4 Read Remote Supported Features (0x01|0x001b) status 0x00 ncmd 1 > HCI Event: Read Remote Supported Features (0x0b) plen 11 status 0x00 handle 12 Features: 0xff 0xff 0x8f 0x7e 0xd8 0x1f 0x5b 0x87 < HCI Command: Read Remote Extended Features (0x01|0x001c) plen 3 handle 12 page 1 > HCI Event: Command Status (0x0f) plen 4 Read Remote Extended Features (0x01|0x001c) status 0x00 ncmd 1 > HCI Event: Page Scan Repetition Mode Change (0x20) plen 7 bdaddr 00:1B:DC:05:B5:25 mode 1 > HCI Event: Max Slots Change (0x1b) plen 3 handle 12 slots 5 > HCI Event: Read Remote Extended Features (0x23) plen 13 status 0x00 handle 12 page 1 max 0 Features: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 < HCI Command: Remote Name Request (0x01|0x0019) plen 10 bdaddr 00:1B:DC:05:B5:25 mode 2 clkoffset 0x0000 > HCI Event: Command Status (0x0f) plen 4 Remote Name Request (0x01|0x0019) status 0x00 ncmd 1 > HCI Event: Remote Name Req Complete (0x07) plen 255 status 0x00 bdaddr 00:1B:DC:05:B5:25 name 'Bluetooth PTS Radio v4' < HCI Command: Authentication Requested (0x01|0x0011) plen 2 handle 12 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) status 0x00 ncmd 1 > HCI Event: Link Key Request (0x17) plen 6 bdaddr 00:1B:DC:05:B5:25 < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 bdaddr 00:1B:DC:05:B5:25 > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 status 0x00 bdaddr 00:1B:DC:05:B5:25 > HCI Event: PIN Code Request (0x16) plen 6 bdaddr 00:1B:DC:05:B5:25 Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
2013-04-16 22:46:30 +08:00
if (ev->features[0] & LMP_HOST_SSP) {
set_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
Bluetooth: Fix incorrect SSP mode bit for non SSP devices Some faulty non SSP devices send extended inquiry response during device discovery which is a violation of 2.1 specification. So for these devices we set SSP bit during acl connection initiation thinking that it is an SSP device. But for these devices, in remote host features event SSP supported bit will be off. But we are not clearing the SSP bit in that case and eventually SSP bit in conn flag will be incorrectly set for these devices. The software which has caused this issue is MecApp http://www.mecel.se/products/bluetooth/downloads/MecApp_download This patch does a workaround by clearing the SSP bit if it is not supported in remote host features event hcidump log ---------- < HCI Command: Inquiry (0x01|0x0001) plen 5 lap 0x9e8b33 len 4 num 0 > HCI Event: Command Status (0x0f) plen 4 Inquiry (0x01|0x0001) status 0x00 ncmd 1 > HCI Event: Extended Inquiry Result (0x2f) plen 255 bdaddr 00:1B:DC:05:B5:25 mode 1 clkoffset 0x3263 class 0x3c0000 rssi -77 Unknown type 0x42 with 8 bytes data Unknown type 0x1e with 2 bytes data > HCI Event: Inquiry Complete (0x01) plen 1 status 0x00 < HCI Command: Create Connection (0x01|0x0005) plen 13 bdaddr 00:1B:DC:05:B5:25 ptype 0xcc18 rswitch 0x01 clkoffset 0x0000 Packet type: DM1 DM3 DM5 DH1 DH3 DH5 > HCI Event: Command Status (0x0f) plen 4 Create Connection (0x01|0x0005) status 0x00 ncmd 1 > HCI Event: Connect Complete (0x03) plen 11 status 0x00 handle 12 bdaddr 00:1B:DC:05:B5:25 type ACL encrypt 0x00 < HCI Command: Read Remote Supported Features (0x01|0x001b) plen 2 handle 12 > HCI Event: Command Status (0x0f) plen 4 Read Remote Supported Features (0x01|0x001b) status 0x00 ncmd 1 > HCI Event: Read Remote Supported Features (0x0b) plen 11 status 0x00 handle 12 Features: 0xff 0xff 0x8f 0x7e 0xd8 0x1f 0x5b 0x87 < HCI Command: Read Remote Extended Features (0x01|0x001c) plen 3 handle 12 page 1 > HCI Event: Command Status (0x0f) plen 4 Read Remote Extended Features (0x01|0x001c) status 0x00 ncmd 1 > HCI Event: Page Scan Repetition Mode Change (0x20) plen 7 bdaddr 00:1B:DC:05:B5:25 mode 1 > HCI Event: Max Slots Change (0x1b) plen 3 handle 12 slots 5 > HCI Event: Read Remote Extended Features (0x23) plen 13 status 0x00 handle 12 page 1 max 0 Features: 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 < HCI Command: Remote Name Request (0x01|0x0019) plen 10 bdaddr 00:1B:DC:05:B5:25 mode 2 clkoffset 0x0000 > HCI Event: Command Status (0x0f) plen 4 Remote Name Request (0x01|0x0019) status 0x00 ncmd 1 > HCI Event: Remote Name Req Complete (0x07) plen 255 status 0x00 bdaddr 00:1B:DC:05:B5:25 name 'Bluetooth PTS Radio v4' < HCI Command: Authentication Requested (0x01|0x0011) plen 2 handle 12 > HCI Event: Command Status (0x0f) plen 4 Authentication Requested (0x01|0x0011) status 0x00 ncmd 1 > HCI Event: Link Key Request (0x17) plen 6 bdaddr 00:1B:DC:05:B5:25 < HCI Command: Link Key Request Negative Reply (0x01|0x000c) plen 6 bdaddr 00:1B:DC:05:B5:25 > HCI Event: Command Complete (0x0e) plen 10 Link Key Request Negative Reply (0x01|0x000c) ncmd 1 status 0x00 bdaddr 00:1B:DC:05:B5:25 > HCI Event: PIN Code Request (0x16) plen 6 bdaddr 00:1B:DC:05:B5:25 Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
2013-04-16 22:46:30 +08:00
} else {
/* It is mandatory by the Bluetooth specification that
* Extended Inquiry Results are only used when Secure
* Simple Pairing is enabled, but some devices violate
* this.
*
* To make these devices work, the internal SSP
* enabled flag needs to be cleared if the remote host
* features do not indicate SSP support */
clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags);
}
if (ev->features[0] & LMP_HOST_SC)
set_bit(HCI_CONN_SC_ENABLED, &conn->flags);
}
if (conn->state != BT_CONFIG)
goto unlock;
if (!ev->status && !test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) {
struct hci_cp_remote_name_req cp;
memset(&cp, 0, sizeof(cp));
bacpy(&cp.bdaddr, &conn->dst);
cp.pscan_rep_mode = 0x02;
hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp);
} else if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
mgmt_device_connected(hdev, conn, NULL, 0);
if (!hci_outgoing_auth_needed(hdev, conn)) {
conn->state = BT_CONNECTED;
hci_connect_cfm(conn, ev->status);
hci_conn_drop(conn);
}
unlock:
hci_dev_unlock(hdev);
}
static void hci_sync_conn_complete_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_sync_conn_complete *ev = data;
struct hci_conn *conn;
switch (ev->link_type) {
case SCO_LINK:
case ESCO_LINK:
break;
default:
/* As per Core 5.3 Vol 4 Part E 7.7.35 (p.2219), Link_Type
* for HCI_Synchronous_Connection_Complete is limited to
* either SCO or eSCO
*/
bt_dev_err(hdev, "Ignoring connect complete event for invalid link type");
return;
}
if (__le16_to_cpu(ev->handle) > HCI_CONN_HANDLE_MAX) {
bt_dev_err(hdev, "Ignoring HCI_Sync_Conn_Complete for invalid handle");
return;
}
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr);
if (!conn) {
if (ev->link_type == ESCO_LINK)
goto unlock;
Bluetooth: Fix SCO link type handling on connection complete Synchronous connections are initially created with type eSCO. Link manager may reject proposed link parameters, which triggers connection setup retry with a different set. Link type embedded in responses should be disregarded until Synchronous Connect Complete returns Success (0x00). Current code updates link type every time which creates an issue when link type changes to SCO and back to eSCO on further attepts. Issue happens with BlackBerry 9100 and 9700 with Intel WilkinsPeak on third connection setup attept 2015-05-18 01:27:57.332242 < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 handle 256 voice setting 0x0060 ptype 0x0380 2015-05-18 01:27:57.333604 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 2015-05-18 01:27:57.334614 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x1a handle 0 bdaddr 30:7C:30:B3:A8:86 type SCO Error: Unsupported Remote Feature / Unsupported LMP Feature 2015-05-18 01:27:57.334895 < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 handle 256 voice setting 0x0060 ptype 0x0380 2015-05-18 01:27:57.335601 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 2015-05-18 01:27:57.336610 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x1a handle 0 bdaddr 30:7C:30:B3:A8:86 type SCO Error: Unsupported Remote Feature / Unsupported LMP Feature 2015-05-18 01:27:57.336685 < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 handle 256 voice setting 0x0060 ptype 0x03c8 2015-05-18 01:27:57.337603 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 2015-05-18 01:27:57.342608 > HCI Event: Max Slots Change (0x1b) plen 3 handle 256 slots 1 2015-05-18 01:27:57.377631 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x00 handle 257 bdaddr 30:7C:30:B3:A8:86 type eSCO Air mode: CVSD Signed-off-by: Kuba Pawlak <kubax.t.pawlak@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2015-08-28 20:05:22 +08:00
/* When the link type in the event indicates SCO connection
* and lookup of the connection object fails, then check
* if an eSCO connection object exists.
*
* The core limits the synchronous connections to either
* SCO or eSCO. The eSCO connection is preferred and tried
* to be setup first and until successfully established,
* the link type will be hinted as eSCO.
*/
conn = hci_conn_hash_lookup_ba(hdev, ESCO_LINK, &ev->bdaddr);
if (!conn)
goto unlock;
}
/* The HCI_Synchronous_Connection_Complete event is only sent once per connection.
* Processing it more than once per connection can corrupt kernel memory.
*
* As the connection handle is set here for the first time, it indicates
* whether the connection is already set up.
*/
if (conn->handle != HCI_CONN_HANDLE_UNSET) {
bt_dev_err(hdev, "Ignoring HCI_Sync_Conn_Complete event for existing connection");
goto unlock;
}
switch (ev->status) {
case 0x00:
conn->handle = __le16_to_cpu(ev->handle);
conn->state = BT_CONNECTED;
Bluetooth: Fix SCO link type handling on connection complete Synchronous connections are initially created with type eSCO. Link manager may reject proposed link parameters, which triggers connection setup retry with a different set. Link type embedded in responses should be disregarded until Synchronous Connect Complete returns Success (0x00). Current code updates link type every time which creates an issue when link type changes to SCO and back to eSCO on further attepts. Issue happens with BlackBerry 9100 and 9700 with Intel WilkinsPeak on third connection setup attept 2015-05-18 01:27:57.332242 < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 handle 256 voice setting 0x0060 ptype 0x0380 2015-05-18 01:27:57.333604 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 2015-05-18 01:27:57.334614 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x1a handle 0 bdaddr 30:7C:30:B3:A8:86 type SCO Error: Unsupported Remote Feature / Unsupported LMP Feature 2015-05-18 01:27:57.334895 < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 handle 256 voice setting 0x0060 ptype 0x0380 2015-05-18 01:27:57.335601 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 2015-05-18 01:27:57.336610 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x1a handle 0 bdaddr 30:7C:30:B3:A8:86 type SCO Error: Unsupported Remote Feature / Unsupported LMP Feature 2015-05-18 01:27:57.336685 < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 handle 256 voice setting 0x0060 ptype 0x03c8 2015-05-18 01:27:57.337603 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 2015-05-18 01:27:57.342608 > HCI Event: Max Slots Change (0x1b) plen 3 handle 256 slots 1 2015-05-18 01:27:57.377631 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x00 handle 257 bdaddr 30:7C:30:B3:A8:86 type eSCO Air mode: CVSD Signed-off-by: Kuba Pawlak <kubax.t.pawlak@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2015-08-28 20:05:22 +08:00
conn->type = ev->link_type;
hci_debugfs_create_conn(conn);
hci_conn_add_sysfs(conn);
break;
case 0x10: /* Connection Accept Timeout */
Bluetooth: Handle specific error for SCO connection fallback Synchronous Connection Complete event can return error "Connection Rejected due to Limited resources (0x10)". Handling this error is required for SCO connection fallback. This error happens when the server tried to accept the connection but failed to negotiate settings. This error code has been verified experimentally by sending a T2 request to a T1 only SCO listener. Client dump follows : < HCI Command (0x01|0x0028) plen 17 [hci0] 3.696064 Handle: 12 Transmit bandwidth: 8000 Receive bandwidth: 8000 Max latency: 13 Setting: 0x0003 Retransmission effort: Optimize for link quality (0x02) Packet type: 0x0380 > HCI Event (0x0f) plen 4 [hci0] 3.697034 Setup Synchronous Connection (0x01|0x0028) ncmd 1 Status: Success (0x00) > HCI Event (0x2c) plen 17 [hci0] 3.736059 Status: Connection Rejected due to Limited Resources (0x0d) Handle: 0 Address: xx:xx:xx:xx:xx:AB (OUI 70-F3-95) Link type: eSCO (0x02) Transmission interval: 0x0c Retransmission window: 0x06 RX packet length: 60 TX packet length: 60 Air mode: Transparent (0x03) Server dump follows : > HCI Event (0x04) plen 10 [hci0] 4.741513 Address: xx:xx:xx:xx:xx:D9 (OUI 20-68-9D) Class: 0x620100 Major class: Computer (desktop, notebook, PDA, organizers) Minor class: Uncategorized, code for device not assigned Networking (LAN, Ad hoc) Audio (Speaker, Microphone, Headset) Telephony (Cordless telephony, Modem, Headset) Link type: eSCO (0x02) < HCI Command (0x01|0x0029) plen 21 [hci0] 4.743269 Address: xx:xx:xx:xx:xx:D9 (OUI 20-68-9D) Transmit bandwidth: 8000 Receive bandwidth: 8000 Max latency: 13 Setting: 0x0003 Retransmission effort: Optimize for link quality (0x02) Packet type: 0x03c1 > HCI Event (0x0f) plen 4 [hci0] 4.745517 Accept Synchronous Connection (0x01|0x0029) ncmd 1 Status: Success (0x00) > HCI Event (0x2c) plen 17 [hci0] 4.749508 Status: Connection Rejected due to Limited Resources (0x0d) Handle: 0 Address: xx:xx:xx:xx:xx:D9 (OUI 20-68-9D) Link type: eSCO (0x02) Transmission interval: 0x0c Retransmission window: 0x06 RX packet length: 60 TX packet length: 60 Air mode: Transparent (0x03) Signed-off-by: Frédéric Dalleau <frederic.dalleau@linux.intel.com> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
2013-08-19 20:24:02 +08:00
case 0x0d: /* Connection Rejected due to Limited Resources */
case 0x11: /* Unsupported Feature or Parameter Value */
case 0x1c: /* SCO interval rejected */
case 0x1a: /* Unsupported Remote Feature */
Bluetooth: Add SCO fallback for invalid LMP parameters error Bluetooth PTS test case HFP/AG/ACC/BI-12-I accepts SCO connection with invalid parameter at the first SCO request expecting AG to attempt another SCO request with the use of "safe settings" for given codec, base on section 5.7.1.2 of HFP 1.7 specification. This patch addresses it by adding "Invalid LMP Parameters" (0x1e) to the SCO fallback case. Verified with below log: < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 Handle: 256 Transmit bandwidth: 8000 Receive bandwidth: 8000 Max latency: 13 Setting: 0x0003 Input Coding: Linear Input Data Format: 1's complement Input Sample Size: 8-bit # of bits padding at MSB: 0 Air Coding Format: Transparent Data Retransmission effort: Optimize for link quality (0x02) Packet type: 0x0380 3-EV3 may not be used 2-EV5 may not be used 3-EV5 may not be used > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) ncmd 1 Status: Success (0x00) > HCI Event: Number of Completed Packets (0x13) plen 5 Num handles: 1 Handle: 256 Count: 1 > HCI Event: Max Slots Change (0x1b) plen 3 Handle: 256 Max slots: 1 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 Status: Invalid LMP Parameters / Invalid LL Parameters (0x1e) Handle: 0 Address: 00:1B:DC:F2:21:59 (OUI 00-1B-DC) Link type: eSCO (0x02) Transmission interval: 0x00 Retransmission window: 0x02 RX packet length: 0 TX packet length: 0 Air mode: Transparent (0x03) < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 Handle: 256 Transmit bandwidth: 8000 Receive bandwidth: 8000 Max latency: 8 Setting: 0x0003 Input Coding: Linear Input Data Format: 1's complement Input Sample Size: 8-bit # of bits padding at MSB: 0 Air Coding Format: Transparent Data Retransmission effort: Optimize for link quality (0x02) Packet type: 0x03c8 EV3 may be used 2-EV3 may not be used 3-EV3 may not be used 2-EV5 may not be used 3-EV5 may not be used > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) ncmd 1 Status: Success (0x00) > HCI Event: Max Slots Change (0x1b) plen 3 Handle: 256 Max slots: 5 > HCI Event: Max Slots Change (0x1b) plen 3 Handle: 256 Max slots: 1 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 Status: Success (0x00) Handle: 257 Address: 00:1B:DC:F2:21:59 (OUI 00-1B-DC) Link type: eSCO (0x02) Transmission interval: 0x06 Retransmission window: 0x04 RX packet length: 30 TX packet length: 30 Air mode: Transparent (0x03) Signed-off-by: Hsin-Yu Chao <hychao@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-05-15 17:27:04 +08:00
case 0x1e: /* Invalid LMP Parameters */
case 0x1f: /* Unspecified error */
Bluetooth: Fix aborting eSCO connection in case of error 0x20 Add additional error case to attempt alternative configuration for SCO. Error occurs with Intel BT controller where fallback is not attempted as the error 0x20 Unsupported LMP Parameter value is not included in the list of errors where a retry should be attempted. The problem also affects PTS test case TC_HF_ACS_BV_05_I. See the HCI log below for details: < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 handle 256 voice setting 0x0060 ptype 0x0380 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 > HCI Event: Max Slots Change (0x1b) plen 3 handle 256 slots 1 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x20 handle 0 bdaddr 00:80:98:09:0B:19 type eSCO Error: Unsupported LMP Parameter Value < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 handle 256 voice setting 0x0060 ptype 0x0380 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 > HCI Event: Max Slots Change (0x1b) plen 3 handle 256 slots 5 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x20 handle 0 bdaddr 00:80:98:09:0B:19 type eSCO Error: Unsupported LMP Parameter Value < HCI Command: Setup Synchronous Connection (0x01|0x0028) plen 17 handle 256 voice setting 0x0060 ptype 0x03c8 > HCI Event: Command Status (0x0f) plen 4 Setup Synchronous Connection (0x01|0x0028) status 0x00 ncmd 1 > HCI Event: Max Slots Change (0x1b) plen 3 handle 256 slots 1 > HCI Event: Synchronous Connect Complete (0x2c) plen 17 status 0x00 handle 257 bdaddr 00:80:98:09:0B:19 type eSCO Air mode: CVSD See btmon log for further details: > HCI Event (0x0f) plen 4 [hci0] 44.888063 Setup Synchronous Connection (0x01|0x0028) ncmd 1 Status: Success (0x00) > HCI Event (0x1b) plen 3 [hci0] 44.893064 Handle: 256 Max slots: 1 > HCI Event (0x2c) plen 17 [hci0] 44.942080 Status: Unsupported LMP Parameter Value (0x20) Handle: 0 Address: 00:1B:DC:06:04:B0 (OUI 00-1B-DC) Link type: eSCO (0x02) Transmission interval: 0x00 Retransmission window: 0x01 RX packet length: 0 TX packet length: 0 Air mode: CVSD (0x02) > HCI Event (0x1b) plen 3 [hci0] 44.948054 Handle: 256 Max slots: 5 Signed-off-by: Andrew Earl <andrewx.earl@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-03-10 18:31:04 +08:00
case 0x20: /* Unsupported LMP Parameter value */
if (conn->out) {
conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) |
(hdev->esco_type & EDR_ESCO_MASK);
if (hci_setup_sync(conn, conn->link->handle))
goto unlock;
}
fallthrough;
default:
conn->state = BT_CLOSED;
break;
}
bt_dev_dbg(hdev, "SCO connected with air mode: %02x", ev->air_mode);
/* Notify only in case of SCO over HCI transport data path which
* is zero and non-zero value shall be non-HCI transport data path
*/
if (conn->codec.data_path == 0 && hdev->notify) {
switch (ev->air_mode) {
case 0x02:
hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_CVSD);
break;
case 0x03:
hdev->notify(hdev, HCI_NOTIFY_ENABLE_SCO_TRANSP);
break;
}
}
hci_connect_cfm(conn, ev->status);
if (ev->status)
hci_conn_del(conn);
unlock:
hci_dev_unlock(hdev);
}
static inline size_t eir_get_length(u8 *eir, size_t eir_len)
{
size_t parsed = 0;
while (parsed < eir_len) {
u8 field_len = eir[0];
if (field_len == 0)
return parsed;
parsed += field_len + 1;
eir += field_len + 1;
}
return eir_len;
}
static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, void *edata,
struct sk_buff *skb)
{
struct hci_ev_ext_inquiry_result *ev = edata;
struct inquiry_data data;
size_t eir_len;
int i;
if (!hci_ev_skb_pull(hdev, skb, HCI_EV_EXTENDED_INQUIRY_RESULT,
flex_array_size(ev, info, ev->num)))
return;
bt_dev_dbg(hdev, "num %d", ev->num);
if (!ev->num)
return;
if (hci_dev_test_flag(hdev, HCI_PERIODIC_INQ))
return;
hci_dev_lock(hdev);
for (i = 0; i < ev->num; i++) {
struct extended_inquiry_info *info = &ev->info[i];
u32 flags;
bool name_known;
bacpy(&data.bdaddr, &info->bdaddr);
data.pscan_rep_mode = info->pscan_rep_mode;
data.pscan_period_mode = info->pscan_period_mode;
data.pscan_mode = 0x00;
memcpy(data.dev_class, info->dev_class, 3);
data.clock_offset = info->clock_offset;
data.rssi = info->rssi;
data.ssp_mode = 0x01;
if (hci_dev_test_flag(hdev, HCI_MGMT))
name_known = eir_get_data(info->data,
sizeof(info->data),
EIR_NAME_COMPLETE, NULL);
else
name_known = true;
flags = hci_inquiry_cache_update(hdev, &data, name_known);
eir_len = eir_get_length(info->data, sizeof(info->data));
mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00,
info->dev_class, info->rssi,
flags, info->data, eir_len, NULL, 0);
}
hci_dev_unlock(hdev);
}
static void hci_key_refresh_complete_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_key_refresh_complete *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x handle 0x%4.4x", ev->status,
__le16_to_cpu(ev->handle));
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (!conn)
goto unlock;
/* For BR/EDR the necessary steps are taken through the
* auth_complete event.
*/
if (conn->type != LE_LINK)
goto unlock;
if (!ev->status)
conn->sec_level = conn->pending_sec_level;
clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags);
if (ev->status && conn->state == BT_CONNECTED) {
hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE);
hci_conn_drop(conn);
goto unlock;
}
if (conn->state == BT_CONFIG) {
if (!ev->status)
conn->state = BT_CONNECTED;
hci_connect_cfm(conn, ev->status);
hci_conn_drop(conn);
} else {
hci_auth_cfm(conn, ev->status);
hci_conn_hold(conn);
conn->disc_timeout = HCI_DISCONN_TIMEOUT;
hci_conn_drop(conn);
}
unlock:
hci_dev_unlock(hdev);
}
static u8 hci_get_auth_req(struct hci_conn *conn)
{
/* If remote requests no-bonding follow that lead */
if (conn->remote_auth == HCI_AT_NO_BONDING ||
conn->remote_auth == HCI_AT_NO_BONDING_MITM)
return conn->remote_auth | (conn->auth_type & 0x01);
/* If both remote and local have enough IO capabilities, require
* MITM protection
*/
if (conn->remote_cap != HCI_IO_NO_INPUT_OUTPUT &&
conn->io_capability != HCI_IO_NO_INPUT_OUTPUT)
return conn->remote_auth | 0x01;
/* No MITM protection possible so ignore remote requirement */
return (conn->remote_auth & ~0x01) | (conn->auth_type & 0x01);
}
static u8 bredr_oob_data_present(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
struct oob_data *data;
data = hci_find_remote_oob_data(hdev, &conn->dst, BDADDR_BREDR);
if (!data)
return 0x00;
if (bredr_sc_enabled(hdev)) {
/* When Secure Connections is enabled, then just
* return the present value stored with the OOB
* data. The stored value contains the right present
* information. However it can only be trusted when
* not in Secure Connection Only mode.
*/
if (!hci_dev_test_flag(hdev, HCI_SC_ONLY))
return data->present;
/* When Secure Connections Only mode is enabled, then
* the P-256 values are required. If they are not
* available, then do not declare that OOB data is
* present.
*/
if (!memcmp(data->rand256, ZERO_KEY, 16) ||
!memcmp(data->hash256, ZERO_KEY, 16))
return 0x00;
return 0x02;
}
/* When Secure Connections is not enabled or actually
* not supported by the hardware, then check that if
* P-192 data values are present.
*/
if (!memcmp(data->rand192, ZERO_KEY, 16) ||
!memcmp(data->hash192, ZERO_KEY, 16))
return 0x00;
return 0x01;
}
static void hci_io_capa_request_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_io_capa_request *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "");
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (!conn)
goto unlock;
hci_conn_hold(conn);
if (!hci_dev_test_flag(hdev, HCI_MGMT))
goto unlock;
/* Allow pairing if we're pairable, the initiators of the
* pairing or if the remote is not requesting bonding.
*/
if (hci_dev_test_flag(hdev, HCI_BONDABLE) ||
test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags) ||
(conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) {
struct hci_cp_io_capability_reply cp;
bacpy(&cp.bdaddr, &ev->bdaddr);
/* Change the IO capability from KeyboardDisplay
* to DisplayYesNo as it is not supported by BT spec. */
cp.capability = (conn->io_capability == 0x04) ?
HCI_IO_DISPLAY_YESNO : conn->io_capability;
/* If we are initiators, there is no remote information yet */
if (conn->remote_auth == 0xff) {
/* Request MITM protection if our IO caps allow it
* except for the no-bonding case.
*/
if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
conn->auth_type != HCI_AT_NO_BONDING)
conn->auth_type |= 0x01;
} else {
conn->auth_type = hci_get_auth_req(conn);
}
/* If we're not bondable, force one of the non-bondable
* authentication requirement values.
*/
if (!hci_dev_test_flag(hdev, HCI_BONDABLE))
conn->auth_type &= HCI_AT_NO_BONDING_MITM;
cp.authentication = conn->auth_type;
cp.oob_data = bredr_oob_data_present(conn);
hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_REPLY,
sizeof(cp), &cp);
} else {
struct hci_cp_io_capability_neg_reply cp;
bacpy(&cp.bdaddr, &ev->bdaddr);
cp.reason = HCI_ERROR_PAIRING_NOT_ALLOWED;
hci_send_cmd(hdev, HCI_OP_IO_CAPABILITY_NEG_REPLY,
sizeof(cp), &cp);
}
unlock:
hci_dev_unlock(hdev);
}
static void hci_io_capa_reply_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_io_capa_reply *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "");
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (!conn)
goto unlock;
conn->remote_cap = ev->capability;
conn->remote_auth = ev->authentication;
unlock:
hci_dev_unlock(hdev);
}
static void hci_user_confirm_request_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_user_confirm_req *ev = data;
int loc_mitm, rem_mitm, confirm_hint = 0;
struct hci_conn *conn;
bt_dev_dbg(hdev, "");
hci_dev_lock(hdev);
if (!hci_dev_test_flag(hdev, HCI_MGMT))
goto unlock;
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (!conn)
goto unlock;
loc_mitm = (conn->auth_type & 0x01);
rem_mitm = (conn->remote_auth & 0x01);
/* If we require MITM but the remote device can't provide that
* (it has NoInputNoOutput) then reject the confirmation
* request. We check the security level here since it doesn't
* necessarily match conn->auth_type.
*/
if (conn->pending_sec_level > BT_SECURITY_MEDIUM &&
conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) {
bt_dev_dbg(hdev, "Rejecting request: remote device can't provide MITM");
hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY,
sizeof(ev->bdaddr), &ev->bdaddr);
goto unlock;
}
/* If no side requires MITM protection; auto-accept */
if ((!loc_mitm || conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) &&
(!rem_mitm || conn->io_capability == HCI_IO_NO_INPUT_OUTPUT)) {
/* If we're not the initiators request authorization to
* proceed from user space (mgmt_user_confirm with
* confirm_hint set to 1). The exception is if neither
* side had MITM or if the local IO capability is
* NoInputNoOutput, in which case we do auto-accept
*/
if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) &&
conn->io_capability != HCI_IO_NO_INPUT_OUTPUT &&
(loc_mitm || rem_mitm)) {
bt_dev_dbg(hdev, "Confirming auto-accept as acceptor");
confirm_hint = 1;
goto confirm;
}
Bluetooth: secure bluetooth stack from bluedump attack Attack scenario: 1. A Chromebook (let's call this device A) is paired to a legitimate Bluetooth classic device (e.g. a speaker) (let's call this device B). 2. A malicious device (let's call this device C) pretends to be the Bluetooth speaker by using the same BT address. 3. If device A is not currently connected to device B, device A will be ready to accept connection from device B in the background (technically, doing Page Scan). 4. Therefore, device C can initiate connection to device A (because device A is doing Page Scan) and device A will accept the connection because device A trusts device C's address which is the same as device B's address. 5. Device C won't be able to communicate at any high level Bluetooth profile with device A because device A enforces that device C is encrypted with their common Link Key, which device C doesn't have. But device C can initiate pairing with device A with just-works model without requiring user interaction (there is only pairing notification). After pairing, device A now trusts device C with a new different link key, common between device A and C. 6. From now on, device A trusts device C, so device C can at anytime connect to device A to do any kind of high-level hijacking, e.g. speaker hijack or mouse/keyboard hijack. Since we don't know whether the repairing is legitimate or not, leave the decision to user space if all the conditions below are met. - the pairing is initialized by peer - the authorization method is just-work - host already had the link key to the peer Signed-off-by: Howard Chung <howardchung@google.com> Acked-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2020-02-14 19:16:41 +08:00
/* If there already exists link key in local host, leave the
* decision to user space since the remote device could be
* legitimate or malicious.
*/
if (hci_find_link_key(hdev, &ev->bdaddr)) {
bt_dev_dbg(hdev, "Local host already has link key");
confirm_hint = 1;
goto confirm;
}
BT_DBG("Auto-accept of user confirmation with %ums delay",
hdev->auto_accept_delay);
if (hdev->auto_accept_delay > 0) {
int delay = msecs_to_jiffies(hdev->auto_accept_delay);
queue_delayed_work(conn->hdev->workqueue,
&conn->auto_accept_work, delay);
goto unlock;
}
hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_REPLY,
sizeof(ev->bdaddr), &ev->bdaddr);
goto unlock;
}
confirm:
mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0,
le32_to_cpu(ev->passkey), confirm_hint);
unlock:
hci_dev_unlock(hdev);
}
static void hci_user_passkey_request_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_user_passkey_req *ev = data;
bt_dev_dbg(hdev, "");
if (hci_dev_test_flag(hdev, HCI_MGMT))
mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0);
}
static void hci_user_passkey_notify_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_user_passkey_notify *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "");
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 (hci_dev_test_flag(hdev, HCI_MGMT))
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, void *data,
struct sk_buff *skb)
{
struct hci_ev_keypress_notify *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "");
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 (hci_dev_test_flag(hdev, HCI_MGMT))
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, void *data,
struct sk_buff *skb)
{
struct hci_ev_simple_pair_complete *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "");
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (!conn)
goto unlock;
/* Reset the authentication requirement to unknown */
conn->remote_auth = 0xff;
/* To avoid duplicate auth_failed events to user space we check
* the HCI_CONN_AUTH_PEND flag which will be set if we
* 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)
mgmt_auth_failed(conn, ev->status);
hci_conn_drop(conn);
unlock:
hci_dev_unlock(hdev);
}
static void hci_remote_host_features_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_remote_host_features *ev = data;
struct inquiry_entry *ie;
struct hci_conn *conn;
bt_dev_dbg(hdev, "");
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr);
if (conn)
memcpy(conn->features[1], ev->features, 8);
ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr);
if (ie)
ie->data.ssp_mode = (ev->features[0] & LMP_HOST_SSP);
hci_dev_unlock(hdev);
}
static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, void *edata,
struct sk_buff *skb)
{
struct hci_ev_remote_oob_data_request *ev = edata;
struct oob_data *data;
bt_dev_dbg(hdev, "");
hci_dev_lock(hdev);
if (!hci_dev_test_flag(hdev, HCI_MGMT))
goto unlock;
data = hci_find_remote_oob_data(hdev, &ev->bdaddr, BDADDR_BREDR);
if (!data) {
struct hci_cp_remote_oob_data_neg_reply cp;
bacpy(&cp.bdaddr, &ev->bdaddr);
hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY,
sizeof(cp), &cp);
goto unlock;
}
if (bredr_sc_enabled(hdev)) {
struct hci_cp_remote_oob_ext_data_reply cp;
bacpy(&cp.bdaddr, &ev->bdaddr);
if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
memset(cp.hash192, 0, sizeof(cp.hash192));
memset(cp.rand192, 0, sizeof(cp.rand192));
} else {
memcpy(cp.hash192, data->hash192, sizeof(cp.hash192));
memcpy(cp.rand192, data->rand192, sizeof(cp.rand192));
}
memcpy(cp.hash256, data->hash256, sizeof(cp.hash256));
memcpy(cp.rand256, data->rand256, sizeof(cp.rand256));
hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY,
sizeof(cp), &cp);
} else {
struct hci_cp_remote_oob_data_reply cp;
bacpy(&cp.bdaddr, &ev->bdaddr);
memcpy(cp.hash, data->hash192, sizeof(cp.hash));
memcpy(cp.rand, data->rand192, sizeof(cp.rand));
hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY,
sizeof(cp), &cp);
}
unlock:
hci_dev_unlock(hdev);
}
#if IS_ENABLED(CONFIG_BT_HS)
static void hci_chan_selected_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_channel_selected *ev = data;
struct hci_conn *hcon;
bt_dev_dbg(hdev, "handle 0x%2.2x", ev->phy_handle);
hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
if (!hcon)
return;
amp_read_loc_assoc_final_data(hdev, hcon);
}
static void hci_phy_link_complete_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_phy_link_complete *ev = data;
struct hci_conn *hcon, *bredr_hcon;
bt_dev_dbg(hdev, "handle 0x%2.2x status 0x%2.2x", ev->phy_handle,
ev->status);
hci_dev_lock(hdev);
hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
if (!hcon)
goto unlock;
if (!hcon->amp_mgr)
goto unlock;
if (ev->status) {
hci_conn_del(hcon);
goto unlock;
}
bredr_hcon = hcon->amp_mgr->l2cap_conn->hcon;
hcon->state = BT_CONNECTED;
bacpy(&hcon->dst, &bredr_hcon->dst);
hci_conn_hold(hcon);
hcon->disc_timeout = HCI_DISCONN_TIMEOUT;
hci_conn_drop(hcon);
hci_debugfs_create_conn(hcon);
hci_conn_add_sysfs(hcon);
amp_physical_cfm(bredr_hcon, hcon);
unlock:
hci_dev_unlock(hdev);
}
static void hci_loglink_complete_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_logical_link_complete *ev = data;
struct hci_conn *hcon;
struct hci_chan *hchan;
struct amp_mgr *mgr;
bt_dev_dbg(hdev, "log_handle 0x%4.4x phy_handle 0x%2.2x status 0x%2.2x",
le16_to_cpu(ev->handle), ev->phy_handle, ev->status);
hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
if (!hcon)
return;
/* Create AMP hchan */
hchan = hci_chan_create(hcon);
if (!hchan)
return;
hchan->handle = le16_to_cpu(ev->handle);
Bluetooth: verify AMP hci_chan before amp_destroy hci_chan can be created in 2 places: hci_loglink_complete_evt() if it is an AMP hci_chan, or l2cap_conn_add() otherwise. In theory, Only AMP hci_chan should be removed by a call to hci_disconn_loglink_complete_evt(). However, the controller might mess up, call that function, and destroy an hci_chan which is not initiated by hci_loglink_complete_evt(). This patch adds a verification that the destroyed hci_chan must have been init'd by hci_loglink_complete_evt(). Example crash call trace: Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xe3/0x144 lib/dump_stack.c:118 print_address_description+0x67/0x22a mm/kasan/report.c:256 kasan_report_error mm/kasan/report.c:354 [inline] kasan_report mm/kasan/report.c:412 [inline] kasan_report+0x251/0x28f mm/kasan/report.c:396 hci_send_acl+0x3b/0x56e net/bluetooth/hci_core.c:4072 l2cap_send_cmd+0x5af/0x5c2 net/bluetooth/l2cap_core.c:877 l2cap_send_move_chan_cfm_icid+0x8e/0xb1 net/bluetooth/l2cap_core.c:4661 l2cap_move_fail net/bluetooth/l2cap_core.c:5146 [inline] l2cap_move_channel_rsp net/bluetooth/l2cap_core.c:5185 [inline] l2cap_bredr_sig_cmd net/bluetooth/l2cap_core.c:5464 [inline] l2cap_sig_channel net/bluetooth/l2cap_core.c:5799 [inline] l2cap_recv_frame+0x1d12/0x51aa net/bluetooth/l2cap_core.c:7023 l2cap_recv_acldata+0x2ea/0x693 net/bluetooth/l2cap_core.c:7596 hci_acldata_packet net/bluetooth/hci_core.c:4606 [inline] hci_rx_work+0x2bd/0x45e net/bluetooth/hci_core.c:4796 process_one_work+0x6f8/0xb50 kernel/workqueue.c:2175 worker_thread+0x4fc/0x670 kernel/workqueue.c:2321 kthread+0x2f0/0x304 kernel/kthread.c:253 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:415 Allocated by task 38: set_track mm/kasan/kasan.c:460 [inline] kasan_kmalloc+0x8d/0x9a mm/kasan/kasan.c:553 kmem_cache_alloc_trace+0x102/0x129 mm/slub.c:2787 kmalloc include/linux/slab.h:515 [inline] kzalloc include/linux/slab.h:709 [inline] hci_chan_create+0x86/0x26d net/bluetooth/hci_conn.c:1674 l2cap_conn_add.part.0+0x1c/0x814 net/bluetooth/l2cap_core.c:7062 l2cap_conn_add net/bluetooth/l2cap_core.c:7059 [inline] l2cap_connect_cfm+0x134/0x852 net/bluetooth/l2cap_core.c:7381 hci_connect_cfm+0x9d/0x122 include/net/bluetooth/hci_core.h:1404 hci_remote_ext_features_evt net/bluetooth/hci_event.c:4161 [inline] hci_event_packet+0x463f/0x72fa net/bluetooth/hci_event.c:5981 hci_rx_work+0x197/0x45e net/bluetooth/hci_core.c:4791 process_one_work+0x6f8/0xb50 kernel/workqueue.c:2175 worker_thread+0x4fc/0x670 kernel/workqueue.c:2321 kthread+0x2f0/0x304 kernel/kthread.c:253 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:415 Freed by task 1732: set_track mm/kasan/kasan.c:460 [inline] __kasan_slab_free mm/kasan/kasan.c:521 [inline] __kasan_slab_free+0x106/0x128 mm/kasan/kasan.c:493 slab_free_hook mm/slub.c:1409 [inline] slab_free_freelist_hook+0xaa/0xf6 mm/slub.c:1436 slab_free mm/slub.c:3009 [inline] kfree+0x182/0x21e mm/slub.c:3972 hci_disconn_loglink_complete_evt net/bluetooth/hci_event.c:4891 [inline] hci_event_packet+0x6a1c/0x72fa net/bluetooth/hci_event.c:6050 hci_rx_work+0x197/0x45e net/bluetooth/hci_core.c:4791 process_one_work+0x6f8/0xb50 kernel/workqueue.c:2175 worker_thread+0x4fc/0x670 kernel/workqueue.c:2321 kthread+0x2f0/0x304 kernel/kthread.c:253 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:415 The buggy address belongs to the object at ffff8881d7af9180 which belongs to the cache kmalloc-128 of size 128 The buggy address is located 24 bytes inside of 128-byte region [ffff8881d7af9180, ffff8881d7af9200) The buggy address belongs to the page: page:ffffea00075ebe40 count:1 mapcount:0 mapping:ffff8881da403200 index:0x0 flags: 0x8000000000000200(slab) raw: 8000000000000200 dead000000000100 dead000000000200 ffff8881da403200 raw: 0000000000000000 0000000080150015 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff8881d7af9080: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb ffff8881d7af9100: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc >ffff8881d7af9180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ^ ffff8881d7af9200: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ffff8881d7af9280: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc Signed-off-by: Archie Pusaka <apusaka@chromium.org> Reported-by: syzbot+98228e7407314d2d4ba2@syzkaller.appspotmail.com Reviewed-by: Alain Michaud <alainm@chromium.org> Reviewed-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-03-22 14:03:11 +08:00
hchan->amp = true;
BT_DBG("hcon %p mgr %p hchan %p", hcon, hcon->amp_mgr, hchan);
mgr = hcon->amp_mgr;
if (mgr && mgr->bredr_chan) {
struct l2cap_chan *bredr_chan = mgr->bredr_chan;
l2cap_chan_lock(bredr_chan);
bredr_chan->conn->mtu = hdev->block_mtu;
l2cap_logical_cfm(bredr_chan, hchan, 0);
hci_conn_hold(hcon);
l2cap_chan_unlock(bredr_chan);
}
}
static void hci_disconn_loglink_complete_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_disconn_logical_link_complete *ev = data;
struct hci_chan *hchan;
bt_dev_dbg(hdev, "handle 0x%4.4x status 0x%2.2x",
le16_to_cpu(ev->handle), ev->status);
if (ev->status)
return;
hci_dev_lock(hdev);
hchan = hci_chan_lookup_handle(hdev, le16_to_cpu(ev->handle));
Bluetooth: verify AMP hci_chan before amp_destroy hci_chan can be created in 2 places: hci_loglink_complete_evt() if it is an AMP hci_chan, or l2cap_conn_add() otherwise. In theory, Only AMP hci_chan should be removed by a call to hci_disconn_loglink_complete_evt(). However, the controller might mess up, call that function, and destroy an hci_chan which is not initiated by hci_loglink_complete_evt(). This patch adds a verification that the destroyed hci_chan must have been init'd by hci_loglink_complete_evt(). Example crash call trace: Call Trace: __dump_stack lib/dump_stack.c:77 [inline] dump_stack+0xe3/0x144 lib/dump_stack.c:118 print_address_description+0x67/0x22a mm/kasan/report.c:256 kasan_report_error mm/kasan/report.c:354 [inline] kasan_report mm/kasan/report.c:412 [inline] kasan_report+0x251/0x28f mm/kasan/report.c:396 hci_send_acl+0x3b/0x56e net/bluetooth/hci_core.c:4072 l2cap_send_cmd+0x5af/0x5c2 net/bluetooth/l2cap_core.c:877 l2cap_send_move_chan_cfm_icid+0x8e/0xb1 net/bluetooth/l2cap_core.c:4661 l2cap_move_fail net/bluetooth/l2cap_core.c:5146 [inline] l2cap_move_channel_rsp net/bluetooth/l2cap_core.c:5185 [inline] l2cap_bredr_sig_cmd net/bluetooth/l2cap_core.c:5464 [inline] l2cap_sig_channel net/bluetooth/l2cap_core.c:5799 [inline] l2cap_recv_frame+0x1d12/0x51aa net/bluetooth/l2cap_core.c:7023 l2cap_recv_acldata+0x2ea/0x693 net/bluetooth/l2cap_core.c:7596 hci_acldata_packet net/bluetooth/hci_core.c:4606 [inline] hci_rx_work+0x2bd/0x45e net/bluetooth/hci_core.c:4796 process_one_work+0x6f8/0xb50 kernel/workqueue.c:2175 worker_thread+0x4fc/0x670 kernel/workqueue.c:2321 kthread+0x2f0/0x304 kernel/kthread.c:253 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:415 Allocated by task 38: set_track mm/kasan/kasan.c:460 [inline] kasan_kmalloc+0x8d/0x9a mm/kasan/kasan.c:553 kmem_cache_alloc_trace+0x102/0x129 mm/slub.c:2787 kmalloc include/linux/slab.h:515 [inline] kzalloc include/linux/slab.h:709 [inline] hci_chan_create+0x86/0x26d net/bluetooth/hci_conn.c:1674 l2cap_conn_add.part.0+0x1c/0x814 net/bluetooth/l2cap_core.c:7062 l2cap_conn_add net/bluetooth/l2cap_core.c:7059 [inline] l2cap_connect_cfm+0x134/0x852 net/bluetooth/l2cap_core.c:7381 hci_connect_cfm+0x9d/0x122 include/net/bluetooth/hci_core.h:1404 hci_remote_ext_features_evt net/bluetooth/hci_event.c:4161 [inline] hci_event_packet+0x463f/0x72fa net/bluetooth/hci_event.c:5981 hci_rx_work+0x197/0x45e net/bluetooth/hci_core.c:4791 process_one_work+0x6f8/0xb50 kernel/workqueue.c:2175 worker_thread+0x4fc/0x670 kernel/workqueue.c:2321 kthread+0x2f0/0x304 kernel/kthread.c:253 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:415 Freed by task 1732: set_track mm/kasan/kasan.c:460 [inline] __kasan_slab_free mm/kasan/kasan.c:521 [inline] __kasan_slab_free+0x106/0x128 mm/kasan/kasan.c:493 slab_free_hook mm/slub.c:1409 [inline] slab_free_freelist_hook+0xaa/0xf6 mm/slub.c:1436 slab_free mm/slub.c:3009 [inline] kfree+0x182/0x21e mm/slub.c:3972 hci_disconn_loglink_complete_evt net/bluetooth/hci_event.c:4891 [inline] hci_event_packet+0x6a1c/0x72fa net/bluetooth/hci_event.c:6050 hci_rx_work+0x197/0x45e net/bluetooth/hci_core.c:4791 process_one_work+0x6f8/0xb50 kernel/workqueue.c:2175 worker_thread+0x4fc/0x670 kernel/workqueue.c:2321 kthread+0x2f0/0x304 kernel/kthread.c:253 ret_from_fork+0x3a/0x50 arch/x86/entry/entry_64.S:415 The buggy address belongs to the object at ffff8881d7af9180 which belongs to the cache kmalloc-128 of size 128 The buggy address is located 24 bytes inside of 128-byte region [ffff8881d7af9180, ffff8881d7af9200) The buggy address belongs to the page: page:ffffea00075ebe40 count:1 mapcount:0 mapping:ffff8881da403200 index:0x0 flags: 0x8000000000000200(slab) raw: 8000000000000200 dead000000000100 dead000000000200 ffff8881da403200 raw: 0000000000000000 0000000080150015 00000001ffffffff 0000000000000000 page dumped because: kasan: bad access detected Memory state around the buggy address: ffff8881d7af9080: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb ffff8881d7af9100: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc >ffff8881d7af9180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb ^ ffff8881d7af9200: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc ffff8881d7af9280: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc Signed-off-by: Archie Pusaka <apusaka@chromium.org> Reported-by: syzbot+98228e7407314d2d4ba2@syzkaller.appspotmail.com Reviewed-by: Alain Michaud <alainm@chromium.org> Reviewed-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-03-22 14:03:11 +08:00
if (!hchan || !hchan->amp)
goto unlock;
amp_destroy_logical_link(hchan, ev->reason);
unlock:
hci_dev_unlock(hdev);
}
static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_disconn_phy_link_complete *ev = data;
struct hci_conn *hcon;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
if (ev->status)
return;
hci_dev_lock(hdev);
hcon = hci_conn_hash_lookup_handle(hdev, ev->phy_handle);
if (hcon) {
hcon->state = BT_CLOSED;
hci_conn_del(hcon);
}
hci_dev_unlock(hdev);
}
#endif
static void le_conn_update_addr(struct hci_conn *conn, bdaddr_t *bdaddr,
u8 bdaddr_type, bdaddr_t *local_rpa)
{
if (conn->out) {
conn->dst_type = bdaddr_type;
conn->resp_addr_type = bdaddr_type;
bacpy(&conn->resp_addr, bdaddr);
/* Check if the controller has set a Local RPA then it must be
* used instead or hdev->rpa.
*/
if (local_rpa && bacmp(local_rpa, BDADDR_ANY)) {
conn->init_addr_type = ADDR_LE_DEV_RANDOM;
bacpy(&conn->init_addr, local_rpa);
} else if (hci_dev_test_flag(conn->hdev, HCI_PRIVACY)) {
conn->init_addr_type = ADDR_LE_DEV_RANDOM;
bacpy(&conn->init_addr, &conn->hdev->rpa);
} else {
hci_copy_identity_address(conn->hdev, &conn->init_addr,
&conn->init_addr_type);
}
} else {
conn->resp_addr_type = conn->hdev->adv_addr_type;
/* Check if the controller has set a Local RPA then it must be
* used instead or hdev->rpa.
*/
if (local_rpa && bacmp(local_rpa, BDADDR_ANY)) {
conn->resp_addr_type = ADDR_LE_DEV_RANDOM;
bacpy(&conn->resp_addr, local_rpa);
} else if (conn->hdev->adv_addr_type == ADDR_LE_DEV_RANDOM) {
/* In case of ext adv, resp_addr will be updated in
* Adv Terminated event.
*/
if (!ext_adv_capable(conn->hdev))
bacpy(&conn->resp_addr,
&conn->hdev->random_addr);
} else {
bacpy(&conn->resp_addr, &conn->hdev->bdaddr);
}
conn->init_addr_type = bdaddr_type;
bacpy(&conn->init_addr, bdaddr);
/* For incoming connections, set the default minimum
* and maximum connection interval. They will be used
* to check if the parameters are in range and if not
* trigger the connection update procedure.
*/
conn->le_conn_min_interval = conn->hdev->le_conn_min_interval;
conn->le_conn_max_interval = conn->hdev->le_conn_max_interval;
}
}
static void le_conn_complete_evt(struct hci_dev *hdev, u8 status,
bdaddr_t *bdaddr, u8 bdaddr_type,
bdaddr_t *local_rpa, u8 role, u16 handle,
u16 interval, u16 latency,
u16 supervision_timeout)
{
struct hci_conn_params *params;
struct hci_conn *conn;
struct smp_irk *irk;
u8 addr_type;
if (handle > HCI_CONN_HANDLE_MAX) {
bt_dev_err(hdev, "Ignoring HCI_LE_Connection_Complete for invalid handle");
return;
}
hci_dev_lock(hdev);
/* All controllers implicitly stop advertising in the event of a
* connection, so ensure that the state bit is cleared.
*/
hci_dev_clear_flag(hdev, HCI_LE_ADV);
conn = hci_lookup_le_connect(hdev);
if (!conn) {
conn = hci_conn_add(hdev, LE_LINK, bdaddr, role);
if (!conn) {
bt_dev_err(hdev, "no memory for new connection");
goto unlock;
}
conn->dst_type = bdaddr_type;
/* If we didn't have a hci_conn object previously
* but we're in central role this must be something
* initiated using an accept list. Since accept list based
* connections are not "first class citizens" we don't
* have full tracking of them. Therefore, we go ahead
* with a "best effort" approach of determining the
* initiator address based on the HCI_PRIVACY flag.
*/
if (conn->out) {
conn->resp_addr_type = bdaddr_type;
bacpy(&conn->resp_addr, bdaddr);
if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
conn->init_addr_type = ADDR_LE_DEV_RANDOM;
bacpy(&conn->init_addr, &hdev->rpa);
} else {
hci_copy_identity_address(hdev,
&conn->init_addr,
&conn->init_addr_type);
}
}
} else {
cancel_delayed_work(&conn->le_conn_timeout);
}
/* The HCI_LE_Connection_Complete event is only sent once per connection.
* Processing it more than once per connection can corrupt kernel memory.
*
* As the connection handle is set here for the first time, it indicates
* whether the connection is already set up.
*/
if (conn->handle != HCI_CONN_HANDLE_UNSET) {
bt_dev_err(hdev, "Ignoring HCI_Connection_Complete for existing connection");
goto unlock;
}
le_conn_update_addr(conn, bdaddr, bdaddr_type, local_rpa);
/* Lookup the identity address from the stored connection
* address and address type.
*
* When establishing connections to an identity address, the
* connection procedure will store the resolvable random
* address first. Now if it can be converted back into the
* identity address, start using the identity address from
* now on.
*/
irk = hci_get_irk(hdev, &conn->dst, conn->dst_type);
if (irk) {
bacpy(&conn->dst, &irk->bdaddr);
conn->dst_type = irk->addr_type;
}
conn->dst_type = ev_bdaddr_type(hdev, conn->dst_type, NULL);
if (status) {
hci_le_conn_failed(conn, status);
goto unlock;
}
if (conn->dst_type == ADDR_LE_DEV_PUBLIC)
addr_type = BDADDR_LE_PUBLIC;
else
addr_type = BDADDR_LE_RANDOM;
/* Drop the connection if the device is blocked */
if (hci_bdaddr_list_lookup(&hdev->reject_list, &conn->dst, addr_type)) {
hci_conn_drop(conn);
goto unlock;
}
if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
mgmt_device_connected(hdev, conn, NULL, 0);
conn->sec_level = BT_SECURITY_LOW;
conn->handle = handle;
conn->state = BT_CONFIG;
/* Store current advertising instance as connection advertising instance
* when sotfware rotation is in use so it can be re-enabled when
* disconnected.
*/
if (!ext_adv_capable(hdev))
conn->adv_instance = hdev->cur_adv_instance;
conn->le_conn_interval = interval;
conn->le_conn_latency = latency;
conn->le_supv_timeout = supervision_timeout;
hci_debugfs_create_conn(conn);
hci_conn_add_sysfs(conn);
/* The remote features procedure is defined for central
* role only. So only in case of an initiated connection
* request the remote features.
*
* If the local controller supports peripheral-initiated features
* exchange, then requesting the remote features in peripheral
* role is possible. Otherwise just transition into the
* connected state without requesting the remote features.
*/
if (conn->out ||
(hdev->le_features[0] & HCI_LE_PERIPHERAL_FEATURES)) {
struct hci_cp_le_read_remote_features cp;
cp.handle = __cpu_to_le16(conn->handle);
hci_send_cmd(hdev, HCI_OP_LE_READ_REMOTE_FEATURES,
sizeof(cp), &cp);
hci_conn_hold(conn);
} else {
conn->state = BT_CONNECTED;
hci_connect_cfm(conn, status);
}
params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst,
conn->dst_type);
if (params) {
list_del_init(&params->action);
if (params->conn) {
hci_conn_drop(params->conn);
hci_conn_put(params->conn);
params->conn = NULL;
}
}
Bluetooth: Introduce LE auto connection infrastructure This patch introduces the LE auto connection infrastructure which will be used to implement the LE auto connection options. In summary, the auto connection mechanism works as follows: Once the first pending LE connection is created, the background scanning is started. When the target device is found in range, the kernel autonomously starts the connection attempt. If connection is established successfully, that pending LE connection is deleted and the background is stopped. To achieve that, this patch introduces the hci_update_background_scan() which controls the background scanning state. This function starts or stops the background scanning based on the hdev->pend_le_conns list. If there is no pending LE connection, the background scanning is stopped. Otherwise, we start the background scanning. Then, every time a pending LE connection is added we call hci_update_ background_scan() so the background scanning is started (in case it is not already running). Likewise, every time a pending LE connection is deleted we call hci_update_background_scan() so the background scanning is stopped (in case this was the last pending LE connection) or it is started again (in case we have more pending LE connections). Finally, we also call hci_update_background_scan() in hci_le_conn_failed() so the background scan is restarted in case the connection establishment fails. This way the background scanning keeps running until all pending LE connection are established. At this point, resolvable addresses are not support by this infrastructure. The proper support is added in upcoming patches. Signed-off-by: Andre Guedes <andre.guedes@openbossa.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-02-27 07:21:47 +08:00
unlock:
hci_update_passive_scan(hdev);
hci_dev_unlock(hdev);
}
static void hci_le_conn_complete_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_le_conn_complete *ev = data;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type,
NULL, ev->role, le16_to_cpu(ev->handle),
le16_to_cpu(ev->interval),
le16_to_cpu(ev->latency),
le16_to_cpu(ev->supervision_timeout));
}
static void hci_le_enh_conn_complete_evt(struct hci_dev *hdev, void *data,
Bluetooth: Use extended LE Connection if supported This implements extended LE craete connection and enhanced LE conn complete event if the controller supports. For now it is as good as legacy LE connection and event as no new features in the extended connection is handled. < HCI Command: LE Extended Create Connection (0x08|0x0043) plen 26 Filter policy: White list is not used (0x00) Own address type: Public (0x00) Peer address type: Random (0x01) Peer address: DB:7E:2E:1D:85:E8 (Static) Initiating PHYs: 0x01 Entry 0: LE 1M Scan interval: 60.000 msec (0x0060) Scan window: 60.000 msec (0x0060) Min connection interval: 50.00 msec (0x0028) Max connection interval: 70.00 msec (0x0038) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Min connection length: 0.000 msec (0x0000) Max connection length: 0.000 msec (0x0000) > HCI Event: Command Status (0x0f) plen 4 LE Extended Create Connection (0x08|0x0043) ncmd 2 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 31 LE Enhanced Connection Complete (0x0a) Status: Success (0x00) Handle: 3585 Role: Master (0x00) Peer address type: Random (0x01) Peer address: DB:7E:2E:1D:85:E8 (Static) Local resolvable private address: 00:00:00:00:00:00 (Non-Resolvable) Peer resolvable private address: 00:00:00:00:00:00 (Non-Resolvable) Connection interval: 67.50 msec (0x0036) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Master clock accuracy: 0x00 @ MGMT Event: Device Connected (0x000b) plen 40 LE Address: DB:7E:2E:1D:85:E8 (Static) Flags: 0x00000000 Data length: 27 Name (complete): Designer Mouse Appearance: Mouse (0x03c2) Flags: 0x05 LE Limited Discoverable Mode BR/EDR Not Supported 16-bit Service UUIDs (complete): 1 entry Human Interface Device (0x1812) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-07 04:50:32 +08:00
struct sk_buff *skb)
{
struct hci_ev_le_enh_conn_complete *ev = data;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
Bluetooth: Use extended LE Connection if supported This implements extended LE craete connection and enhanced LE conn complete event if the controller supports. For now it is as good as legacy LE connection and event as no new features in the extended connection is handled. < HCI Command: LE Extended Create Connection (0x08|0x0043) plen 26 Filter policy: White list is not used (0x00) Own address type: Public (0x00) Peer address type: Random (0x01) Peer address: DB:7E:2E:1D:85:E8 (Static) Initiating PHYs: 0x01 Entry 0: LE 1M Scan interval: 60.000 msec (0x0060) Scan window: 60.000 msec (0x0060) Min connection interval: 50.00 msec (0x0028) Max connection interval: 70.00 msec (0x0038) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Min connection length: 0.000 msec (0x0000) Max connection length: 0.000 msec (0x0000) > HCI Event: Command Status (0x0f) plen 4 LE Extended Create Connection (0x08|0x0043) ncmd 2 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 31 LE Enhanced Connection Complete (0x0a) Status: Success (0x00) Handle: 3585 Role: Master (0x00) Peer address type: Random (0x01) Peer address: DB:7E:2E:1D:85:E8 (Static) Local resolvable private address: 00:00:00:00:00:00 (Non-Resolvable) Peer resolvable private address: 00:00:00:00:00:00 (Non-Resolvable) Connection interval: 67.50 msec (0x0036) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Master clock accuracy: 0x00 @ MGMT Event: Device Connected (0x000b) plen 40 LE Address: DB:7E:2E:1D:85:E8 (Static) Flags: 0x00000000 Data length: 27 Name (complete): Designer Mouse Appearance: Mouse (0x03c2) Flags: 0x05 LE Limited Discoverable Mode BR/EDR Not Supported 16-bit Service UUIDs (complete): 1 entry Human Interface Device (0x1812) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-07 04:50:32 +08:00
le_conn_complete_evt(hdev, ev->status, &ev->bdaddr, ev->bdaddr_type,
&ev->local_rpa, ev->role, le16_to_cpu(ev->handle),
Bluetooth: Use extended LE Connection if supported This implements extended LE craete connection and enhanced LE conn complete event if the controller supports. For now it is as good as legacy LE connection and event as no new features in the extended connection is handled. < HCI Command: LE Extended Create Connection (0x08|0x0043) plen 26 Filter policy: White list is not used (0x00) Own address type: Public (0x00) Peer address type: Random (0x01) Peer address: DB:7E:2E:1D:85:E8 (Static) Initiating PHYs: 0x01 Entry 0: LE 1M Scan interval: 60.000 msec (0x0060) Scan window: 60.000 msec (0x0060) Min connection interval: 50.00 msec (0x0028) Max connection interval: 70.00 msec (0x0038) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Min connection length: 0.000 msec (0x0000) Max connection length: 0.000 msec (0x0000) > HCI Event: Command Status (0x0f) plen 4 LE Extended Create Connection (0x08|0x0043) ncmd 2 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 31 LE Enhanced Connection Complete (0x0a) Status: Success (0x00) Handle: 3585 Role: Master (0x00) Peer address type: Random (0x01) Peer address: DB:7E:2E:1D:85:E8 (Static) Local resolvable private address: 00:00:00:00:00:00 (Non-Resolvable) Peer resolvable private address: 00:00:00:00:00:00 (Non-Resolvable) Connection interval: 67.50 msec (0x0036) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Master clock accuracy: 0x00 @ MGMT Event: Device Connected (0x000b) plen 40 LE Address: DB:7E:2E:1D:85:E8 (Static) Flags: 0x00000000 Data length: 27 Name (complete): Designer Mouse Appearance: Mouse (0x03c2) Flags: 0x05 LE Limited Discoverable Mode BR/EDR Not Supported 16-bit Service UUIDs (complete): 1 entry Human Interface Device (0x1812) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-07 04:50:32 +08:00
le16_to_cpu(ev->interval),
le16_to_cpu(ev->latency),
le16_to_cpu(ev->supervision_timeout));
}
static void hci_le_ext_adv_term_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_evt_le_ext_adv_set_term *ev = data;
struct hci_conn *conn;
struct adv_info *adv, *n;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
Bluetooth: Ignore HCI_ERROR_CANCELLED_BY_HOST on adv set terminated event This event is received when the controller stops advertising, specifically for these three reasons: (a) Connection is successfully created (success). (b) Timeout is reached (error). (c) Number of advertising events is reached (error). (*) This event is NOT generated when the host stops the advertisement. Refer to the BT spec ver 5.3 vol 4 part E sec 7.7.65.18. Note that the section was revised from BT spec ver 5.0 vol 2 part E sec 7.7.65.18 which was ambiguous about (*). Some chips (e.g. RTL8822CE) send this event when the host stops the advertisement with status = HCI_ERROR_CANCELLED_BY_HOST (due to (*) above). This is treated as an error and the advertisement will be removed and userspace will be informed via MGMT event. On suspend, we are supposed to temporarily disable advertisements, and continue advertising on resume. However, due to the behavior above, the advertisements are removed instead. This patch returns early if HCI_ERROR_CANCELLED_BY_HOST is received. Btmon snippet of the unexpected behavior: @ MGMT Command: Remove Advertising (0x003f) plen 1 Instance: 1 < HCI Command: LE Set Extended Advertising Enable (0x08|0x0039) plen 6 Extended advertising: Disabled (0x00) Number of sets: 1 (0x01) Entry 0 Handle: 0x01 Duration: 0 ms (0x00) Max ext adv events: 0 > HCI Event: LE Meta Event (0x3e) plen 6 LE Advertising Set Terminated (0x12) Status: Operation Cancelled by Host (0x44) Handle: 1 Connection handle: 0 Number of completed extended advertising events: 5 > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Advertising Enable (0x08|0x0039) ncmd 2 Status: Success (0x00) Signed-off-by: Archie Pusaka <apusaka@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-11-11 13:20:53 +08:00
/* The Bluetooth Core 5.3 specification clearly states that this event
* shall not be sent when the Host disables the advertising set. So in
* case of HCI_ERROR_CANCELLED_BY_HOST, just ignore the event.
*
* When the Host disables an advertising set, all cleanup is done via
* its command callback and not needed to be duplicated here.
*/
if (ev->status == HCI_ERROR_CANCELLED_BY_HOST) {
bt_dev_warn_ratelimited(hdev, "Unexpected advertising set terminated event");
return;
}
hci_dev_lock(hdev);
adv = hci_find_adv_instance(hdev, ev->handle);
if (ev->status) {
if (!adv)
goto unlock;
/* Remove advertising as it has been terminated */
hci_remove_adv_instance(hdev, ev->handle);
mgmt_advertising_removed(NULL, hdev, ev->handle);
list_for_each_entry_safe(adv, n, &hdev->adv_instances, list) {
if (adv->enabled)
goto unlock;
}
/* We are no longer advertising, clear HCI_LE_ADV */
hci_dev_clear_flag(hdev, HCI_LE_ADV);
goto unlock;
}
if (adv)
adv->enabled = false;
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->conn_handle));
if (conn) {
/* Store handle in the connection so the correct advertising
* instance can be re-enabled when disconnected.
*/
conn->adv_instance = ev->handle;
if (hdev->adv_addr_type != ADDR_LE_DEV_RANDOM ||
bacmp(&conn->resp_addr, BDADDR_ANY))
goto unlock;
if (!ev->handle) {
bacpy(&conn->resp_addr, &hdev->random_addr);
goto unlock;
}
if (adv)
bacpy(&conn->resp_addr, &adv->random_addr);
}
unlock:
hci_dev_unlock(hdev);
}
static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_le_conn_update_complete *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
if (ev->status)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (conn) {
conn->le_conn_interval = le16_to_cpu(ev->interval);
conn->le_conn_latency = le16_to_cpu(ev->latency);
conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout);
}
hci_dev_unlock(hdev);
}
Bluetooth: Introduce LE auto connection infrastructure This patch introduces the LE auto connection infrastructure which will be used to implement the LE auto connection options. In summary, the auto connection mechanism works as follows: Once the first pending LE connection is created, the background scanning is started. When the target device is found in range, the kernel autonomously starts the connection attempt. If connection is established successfully, that pending LE connection is deleted and the background is stopped. To achieve that, this patch introduces the hci_update_background_scan() which controls the background scanning state. This function starts or stops the background scanning based on the hdev->pend_le_conns list. If there is no pending LE connection, the background scanning is stopped. Otherwise, we start the background scanning. Then, every time a pending LE connection is added we call hci_update_ background_scan() so the background scanning is started (in case it is not already running). Likewise, every time a pending LE connection is deleted we call hci_update_background_scan() so the background scanning is stopped (in case this was the last pending LE connection) or it is started again (in case we have more pending LE connections). Finally, we also call hci_update_background_scan() in hci_le_conn_failed() so the background scan is restarted in case the connection establishment fails. This way the background scanning keeps running until all pending LE connection are established. At this point, resolvable addresses are not support by this infrastructure. The proper support is added in upcoming patches. Signed-off-by: Andre Guedes <andre.guedes@openbossa.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-02-27 07:21:47 +08:00
/* This function requires the caller holds hdev->lock */
static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,
bdaddr_t *addr,
u8 addr_type, bool addr_resolved,
u8 adv_type)
Bluetooth: Introduce LE auto connection infrastructure This patch introduces the LE auto connection infrastructure which will be used to implement the LE auto connection options. In summary, the auto connection mechanism works as follows: Once the first pending LE connection is created, the background scanning is started. When the target device is found in range, the kernel autonomously starts the connection attempt. If connection is established successfully, that pending LE connection is deleted and the background is stopped. To achieve that, this patch introduces the hci_update_background_scan() which controls the background scanning state. This function starts or stops the background scanning based on the hdev->pend_le_conns list. If there is no pending LE connection, the background scanning is stopped. Otherwise, we start the background scanning. Then, every time a pending LE connection is added we call hci_update_ background_scan() so the background scanning is started (in case it is not already running). Likewise, every time a pending LE connection is deleted we call hci_update_background_scan() so the background scanning is stopped (in case this was the last pending LE connection) or it is started again (in case we have more pending LE connections). Finally, we also call hci_update_background_scan() in hci_le_conn_failed() so the background scan is restarted in case the connection establishment fails. This way the background scanning keeps running until all pending LE connection are established. At this point, resolvable addresses are not support by this infrastructure. The proper support is added in upcoming patches. Signed-off-by: Andre Guedes <andre.guedes@openbossa.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-02-27 07:21:47 +08:00
{
struct hci_conn *conn;
struct hci_conn_params *params;
Bluetooth: Introduce LE auto connection infrastructure This patch introduces the LE auto connection infrastructure which will be used to implement the LE auto connection options. In summary, the auto connection mechanism works as follows: Once the first pending LE connection is created, the background scanning is started. When the target device is found in range, the kernel autonomously starts the connection attempt. If connection is established successfully, that pending LE connection is deleted and the background is stopped. To achieve that, this patch introduces the hci_update_background_scan() which controls the background scanning state. This function starts or stops the background scanning based on the hdev->pend_le_conns list. If there is no pending LE connection, the background scanning is stopped. Otherwise, we start the background scanning. Then, every time a pending LE connection is added we call hci_update_ background_scan() so the background scanning is started (in case it is not already running). Likewise, every time a pending LE connection is deleted we call hci_update_background_scan() so the background scanning is stopped (in case this was the last pending LE connection) or it is started again (in case we have more pending LE connections). Finally, we also call hci_update_background_scan() in hci_le_conn_failed() so the background scan is restarted in case the connection establishment fails. This way the background scanning keeps running until all pending LE connection are established. At this point, resolvable addresses are not support by this infrastructure. The proper support is added in upcoming patches. Signed-off-by: Andre Guedes <andre.guedes@openbossa.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-02-27 07:21:47 +08:00
/* If the event is not connectable don't proceed further */
if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND)
return NULL;
/* Ignore if the device is blocked or hdev is suspended */
if (hci_bdaddr_list_lookup(&hdev->reject_list, addr, addr_type) ||
hdev->suspended)
return NULL;
/* Most controller will fail if we try to create new connections
* while we have an existing one in peripheral role.
*/
if (hdev->conn_hash.le_num_peripheral > 0 &&
(!test_bit(HCI_QUIRK_VALID_LE_STATES, &hdev->quirks) ||
!(hdev->le_states[3] & 0x10)))
return NULL;
/* If we're not connectable only connect devices that we have in
* our pend_le_conns list.
*/
params = hci_pend_le_action_lookup(&hdev->pend_le_conns, addr,
addr_type);
if (!params)
return NULL;
if (!params->explicit_connect) {
switch (params->auto_connect) {
case HCI_AUTO_CONN_DIRECT:
/* Only devices advertising with ADV_DIRECT_IND are
* triggering a connection attempt. This is allowing
* incoming connections from peripheral devices.
*/
if (adv_type != LE_ADV_DIRECT_IND)
return NULL;
break;
case HCI_AUTO_CONN_ALWAYS:
/* Devices advertising with ADV_IND or ADV_DIRECT_IND
* are triggering a connection attempt. This means
* that incoming connections from peripheral device are
* accepted and also outgoing connections to peripheral
* devices are established when found.
*/
break;
default:
return NULL;
}
}
Bluetooth: Introduce LE auto connection infrastructure This patch introduces the LE auto connection infrastructure which will be used to implement the LE auto connection options. In summary, the auto connection mechanism works as follows: Once the first pending LE connection is created, the background scanning is started. When the target device is found in range, the kernel autonomously starts the connection attempt. If connection is established successfully, that pending LE connection is deleted and the background is stopped. To achieve that, this patch introduces the hci_update_background_scan() which controls the background scanning state. This function starts or stops the background scanning based on the hdev->pend_le_conns list. If there is no pending LE connection, the background scanning is stopped. Otherwise, we start the background scanning. Then, every time a pending LE connection is added we call hci_update_ background_scan() so the background scanning is started (in case it is not already running). Likewise, every time a pending LE connection is deleted we call hci_update_background_scan() so the background scanning is stopped (in case this was the last pending LE connection) or it is started again (in case we have more pending LE connections). Finally, we also call hci_update_background_scan() in hci_le_conn_failed() so the background scan is restarted in case the connection establishment fails. This way the background scanning keeps running until all pending LE connection are established. At this point, resolvable addresses are not support by this infrastructure. The proper support is added in upcoming patches. Signed-off-by: Andre Guedes <andre.guedes@openbossa.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-02-27 07:21:47 +08:00
conn = hci_connect_le(hdev, addr, addr_type, addr_resolved,
BT_SECURITY_LOW, hdev->def_le_autoconnect_timeout,
HCI_ROLE_MASTER);
if (!IS_ERR(conn)) {
/* If HCI_AUTO_CONN_EXPLICIT is set, conn is already owned
* by higher layer that tried to connect, if no then
* store the pointer since we don't really have any
* other owner of the object besides the params that
* triggered it. This way we can abort the connection if
* the parameters get removed and keep the reference
* count consistent once the connection is established.
*/
if (!params->explicit_connect)
params->conn = hci_conn_get(conn);
return conn;
}
Bluetooth: Introduce LE auto connection infrastructure This patch introduces the LE auto connection infrastructure which will be used to implement the LE auto connection options. In summary, the auto connection mechanism works as follows: Once the first pending LE connection is created, the background scanning is started. When the target device is found in range, the kernel autonomously starts the connection attempt. If connection is established successfully, that pending LE connection is deleted and the background is stopped. To achieve that, this patch introduces the hci_update_background_scan() which controls the background scanning state. This function starts or stops the background scanning based on the hdev->pend_le_conns list. If there is no pending LE connection, the background scanning is stopped. Otherwise, we start the background scanning. Then, every time a pending LE connection is added we call hci_update_ background_scan() so the background scanning is started (in case it is not already running). Likewise, every time a pending LE connection is deleted we call hci_update_background_scan() so the background scanning is stopped (in case this was the last pending LE connection) or it is started again (in case we have more pending LE connections). Finally, we also call hci_update_background_scan() in hci_le_conn_failed() so the background scan is restarted in case the connection establishment fails. This way the background scanning keeps running until all pending LE connection are established. At this point, resolvable addresses are not support by this infrastructure. The proper support is added in upcoming patches. Signed-off-by: Andre Guedes <andre.guedes@openbossa.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-02-27 07:21:47 +08:00
switch (PTR_ERR(conn)) {
case -EBUSY:
/* If hci_connect() returns -EBUSY it means there is already
* an LE connection attempt going on. Since controllers don't
* support more than one connection attempt at the time, we
* don't consider this an error case.
*/
break;
default:
BT_DBG("Failed to connect: err %ld", PTR_ERR(conn));
return NULL;
Bluetooth: Introduce LE auto connection infrastructure This patch introduces the LE auto connection infrastructure which will be used to implement the LE auto connection options. In summary, the auto connection mechanism works as follows: Once the first pending LE connection is created, the background scanning is started. When the target device is found in range, the kernel autonomously starts the connection attempt. If connection is established successfully, that pending LE connection is deleted and the background is stopped. To achieve that, this patch introduces the hci_update_background_scan() which controls the background scanning state. This function starts or stops the background scanning based on the hdev->pend_le_conns list. If there is no pending LE connection, the background scanning is stopped. Otherwise, we start the background scanning. Then, every time a pending LE connection is added we call hci_update_ background_scan() so the background scanning is started (in case it is not already running). Likewise, every time a pending LE connection is deleted we call hci_update_background_scan() so the background scanning is stopped (in case this was the last pending LE connection) or it is started again (in case we have more pending LE connections). Finally, we also call hci_update_background_scan() in hci_le_conn_failed() so the background scan is restarted in case the connection establishment fails. This way the background scanning keeps running until all pending LE connection are established. At this point, resolvable addresses are not support by this infrastructure. The proper support is added in upcoming patches. Signed-off-by: Andre Guedes <andre.guedes@openbossa.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-02-27 07:21:47 +08:00
}
return NULL;
Bluetooth: Introduce LE auto connection infrastructure This patch introduces the LE auto connection infrastructure which will be used to implement the LE auto connection options. In summary, the auto connection mechanism works as follows: Once the first pending LE connection is created, the background scanning is started. When the target device is found in range, the kernel autonomously starts the connection attempt. If connection is established successfully, that pending LE connection is deleted and the background is stopped. To achieve that, this patch introduces the hci_update_background_scan() which controls the background scanning state. This function starts or stops the background scanning based on the hdev->pend_le_conns list. If there is no pending LE connection, the background scanning is stopped. Otherwise, we start the background scanning. Then, every time a pending LE connection is added we call hci_update_ background_scan() so the background scanning is started (in case it is not already running). Likewise, every time a pending LE connection is deleted we call hci_update_background_scan() so the background scanning is stopped (in case this was the last pending LE connection) or it is started again (in case we have more pending LE connections). Finally, we also call hci_update_background_scan() in hci_le_conn_failed() so the background scan is restarted in case the connection establishment fails. This way the background scanning keeps running until all pending LE connection are established. At this point, resolvable addresses are not support by this infrastructure. The proper support is added in upcoming patches. Signed-off-by: Andre Guedes <andre.guedes@openbossa.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-02-27 07:21:47 +08:00
}
static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
u8 bdaddr_type, bdaddr_t *direct_addr,
Bluetooth: fix kernel oops in store_pending_adv_report Fix kernel oops observed when an ext adv data is larger than 31 bytes. This can be reproduced by setting up an advertiser with advertisement larger than 31 bytes. The issue is not sensitive to the advertisement content. In particular, this was reproduced with an advertisement of 229 bytes filled with 'A'. See stack trace below. This is fixed by not catching ext_adv as legacy adv are only cached to be able to concatenate a scanable adv with its scan response before sending it up through mgmt. With ext_adv, this is no longer necessary. general protection fault: 0000 [#1] SMP PTI CPU: 6 PID: 205 Comm: kworker/u17:0 Not tainted 5.4.0-37-generic #41-Ubuntu Hardware name: Dell Inc. XPS 15 7590/0CF6RR, BIOS 1.7.0 05/11/2020 Workqueue: hci0 hci_rx_work [bluetooth] RIP: 0010:hci_bdaddr_list_lookup+0x1e/0x40 [bluetooth] Code: ff ff e9 26 ff ff ff 0f 1f 44 00 00 0f 1f 44 00 00 55 48 8b 07 48 89 e5 48 39 c7 75 0a eb 24 48 8b 00 48 39 f8 74 1c 44 8b 06 <44> 39 40 10 75 ef 44 0f b7 4e 04 66 44 39 48 14 75 e3 38 50 16 75 RSP: 0018:ffffbc6a40493c70 EFLAGS: 00010286 RAX: 4141414141414141 RBX: 000000000000001b RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff9903e76c100f RDI: ffff9904289d4b28 RBP: ffffbc6a40493c70 R08: 0000000093570362 R09: 0000000000000000 R10: 0000000000000000 R11: ffff9904344eae38 R12: ffff9904289d4000 R13: 0000000000000000 R14: 00000000ffffffa3 R15: ffff9903e76c100f FS: 0000000000000000(0000) GS:ffff990434580000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007feed125a000 CR3: 00000001b860a003 CR4: 00000000003606e0 Call Trace: process_adv_report+0x12e/0x560 [bluetooth] hci_le_meta_evt+0x7b2/0xba0 [bluetooth] hci_event_packet+0x1c29/0x2a90 [bluetooth] hci_rx_work+0x19b/0x360 [bluetooth] process_one_work+0x1eb/0x3b0 worker_thread+0x4d/0x400 kthread+0x104/0x140 Fixes: c215e9397b00 ("Bluetooth: Process extended ADV report event") Reported-by: Andy Nguyen <theflow@google.com> Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Reported-by: Balakrishna Godavarthi <bgodavar@codeaurora.org> Signed-off-by: Alain Michaud <alainm@chromium.org> Tested-by: Sonny Sasaka <sonnysasaka@chromium.org> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2020-07-28 04:48:55 +08:00
u8 direct_addr_type, s8 rssi, u8 *data, u8 len,
bool ext_adv)
{
struct discovery_state *d = &hdev->discovery;
struct smp_irk *irk;
struct hci_conn *conn;
bool match, bdaddr_resolved;
u32 flags;
Bluetooth: Remove spurious error message Even with rate limited reporting this is very spammy and since it is remote device that is providing bogus data there is no need to report this as error. Since real_len variable was used only to allow conditional error message it is now also removed. [72454.143336] bt_err_ratelimited: 10 callbacks suppressed [72454.143337] Bluetooth: hci0: advertising data len corrected [72454.296314] Bluetooth: hci0: advertising data len corrected [72454.892329] Bluetooth: hci0: advertising data len corrected [72455.051319] Bluetooth: hci0: advertising data len corrected [72455.357326] Bluetooth: hci0: advertising data len corrected [72455.663295] Bluetooth: hci0: advertising data len corrected [72455.787278] Bluetooth: hci0: advertising data len corrected [72455.942278] Bluetooth: hci0: advertising data len corrected [72456.094276] Bluetooth: hci0: advertising data len corrected [72456.249137] Bluetooth: hci0: advertising data len corrected [72459.416333] bt_err_ratelimited: 13 callbacks suppressed [72459.416334] Bluetooth: hci0: advertising data len corrected [72459.721334] Bluetooth: hci0: advertising data len corrected [72460.011317] Bluetooth: hci0: advertising data len corrected [72460.327171] Bluetooth: hci0: advertising data len corrected [72460.638294] Bluetooth: hci0: advertising data len corrected [72460.946350] Bluetooth: hci0: advertising data len corrected [72461.225320] Bluetooth: hci0: advertising data len corrected [72461.690322] Bluetooth: hci0: advertising data len corrected [72462.118318] Bluetooth: hci0: advertising data len corrected [72462.427319] Bluetooth: hci0: advertising data len corrected [72464.546319] bt_err_ratelimited: 7 callbacks suppressed [72464.546319] Bluetooth: hci0: advertising data len corrected [72464.857318] Bluetooth: hci0: advertising data len corrected [72465.163332] Bluetooth: hci0: advertising data len corrected [72465.278331] Bluetooth: hci0: advertising data len corrected [72465.432323] Bluetooth: hci0: advertising data len corrected [72465.891334] Bluetooth: hci0: advertising data len corrected [72466.045334] Bluetooth: hci0: advertising data len corrected [72466.197321] Bluetooth: hci0: advertising data len corrected [72466.340318] Bluetooth: hci0: advertising data len corrected [72466.498335] Bluetooth: hci0: advertising data len corrected [72469.803299] bt_err_ratelimited: 10 callbacks suppressed Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl> Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=203753 Cc: stable@vger.kernel.org Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-05-18 22:54:36 +08:00
u8 *ptr;
Bluetooth: Fix reporting incorrect EIR in device found mgmt event Some remote devices (ie Gigaset G-Tag) misbehave with ADV data length. This can lead to incorrect EIR format in device found event when ADV_DATA and SCAN_RSP are merged (terminator field before SCAN_RSP part). Fix this by inspecting ADV_DATA and correct its length if terminator is found. > HCI Event: LE Meta Event (0x3e) plen 42 [hci0] 32.172182 LE Advertising Report (0x02) Num reports: 1 Event type: Connectable undirected - ADV_IND (0x00) Address type: Public (0x00) Address: 7C:2F:80:94:97:5A (Gigaset Communications GmbH) Data length: 30 Flags: 0x06 LE General Discoverable Mode BR/EDR Not Supported Company: Gigaset Communications GmbH (384) Data: 021512348094975abbc5 16-bit Service UUIDs (partial): 1 entry Battery Service (0x180f) RSSI: -65 dBm (0xbf) > HCI Event: LE Meta Event (0x3e) plen 27 [hci0] 32.172191 LE Advertising Report (0x02) Num reports: 1 Event type: Scan response - SCAN_RSP (0x04) Address type: Public (0x00) Address: 7C:2F:80:94:97:5A (Gigaset Communications GmbH) Data length: 15 Name (complete): Gigaset G-tag RSSI: -59 dBm (0xc5) Note "Data length: 30" in ADV_DATA which results in 9 extra zero bytes after Battery Service UUID. Terminator field present in the middle of EIR in Device Found event resulted in userspace stop parsing EIR and skipping device name. @ Device Found: 7C:2F:80:94:97:5A (1) rssi -59 flags 0x0000 02 01 06 0d ff 80 01 02 15 12 34 80 94 97 5a bb ..........4...Z. c5 03 02 0f 18 00 00 00 00 00 00 00 00 00 0e 09 ................ 47 69 67 61 73 65 74 20 47 2d 74 61 67 Gigaset G-tag With this fix EIR with merged ADV_DATA and SCAN_RSP in device found event is properly formatted: @ Device Found: 7C:2F:80:94:97:5A (1) rssi -59 flags 0x0000 02 01 06 0d ff 80 01 02 15 12 34 80 94 97 5a bb ..........4...Z. c5 03 02 0f 18 0e 09 47 69 67 61 73 65 74 20 47 .......Gigaset G 2d 74 61 67 -tag Signed-off-by: Szymon Janc <ext.szymon.janc@tieto.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2015-09-17 02:21:54 +08:00
switch (type) {
case LE_ADV_IND:
case LE_ADV_DIRECT_IND:
case LE_ADV_SCAN_IND:
case LE_ADV_NONCONN_IND:
case LE_ADV_SCAN_RSP:
break;
default:
bt_dev_err_ratelimited(hdev, "unknown advertising packet "
"type: 0x%02x", type);
return;
}
Bluetooth: fix kernel oops in store_pending_adv_report Fix kernel oops observed when an ext adv data is larger than 31 bytes. This can be reproduced by setting up an advertiser with advertisement larger than 31 bytes. The issue is not sensitive to the advertisement content. In particular, this was reproduced with an advertisement of 229 bytes filled with 'A'. See stack trace below. This is fixed by not catching ext_adv as legacy adv are only cached to be able to concatenate a scanable adv with its scan response before sending it up through mgmt. With ext_adv, this is no longer necessary. general protection fault: 0000 [#1] SMP PTI CPU: 6 PID: 205 Comm: kworker/u17:0 Not tainted 5.4.0-37-generic #41-Ubuntu Hardware name: Dell Inc. XPS 15 7590/0CF6RR, BIOS 1.7.0 05/11/2020 Workqueue: hci0 hci_rx_work [bluetooth] RIP: 0010:hci_bdaddr_list_lookup+0x1e/0x40 [bluetooth] Code: ff ff e9 26 ff ff ff 0f 1f 44 00 00 0f 1f 44 00 00 55 48 8b 07 48 89 e5 48 39 c7 75 0a eb 24 48 8b 00 48 39 f8 74 1c 44 8b 06 <44> 39 40 10 75 ef 44 0f b7 4e 04 66 44 39 48 14 75 e3 38 50 16 75 RSP: 0018:ffffbc6a40493c70 EFLAGS: 00010286 RAX: 4141414141414141 RBX: 000000000000001b RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff9903e76c100f RDI: ffff9904289d4b28 RBP: ffffbc6a40493c70 R08: 0000000093570362 R09: 0000000000000000 R10: 0000000000000000 R11: ffff9904344eae38 R12: ffff9904289d4000 R13: 0000000000000000 R14: 00000000ffffffa3 R15: ffff9903e76c100f FS: 0000000000000000(0000) GS:ffff990434580000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007feed125a000 CR3: 00000001b860a003 CR4: 00000000003606e0 Call Trace: process_adv_report+0x12e/0x560 [bluetooth] hci_le_meta_evt+0x7b2/0xba0 [bluetooth] hci_event_packet+0x1c29/0x2a90 [bluetooth] hci_rx_work+0x19b/0x360 [bluetooth] process_one_work+0x1eb/0x3b0 worker_thread+0x4d/0x400 kthread+0x104/0x140 Fixes: c215e9397b00 ("Bluetooth: Process extended ADV report event") Reported-by: Andy Nguyen <theflow@google.com> Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Reported-by: Balakrishna Godavarthi <bgodavar@codeaurora.org> Signed-off-by: Alain Michaud <alainm@chromium.org> Tested-by: Sonny Sasaka <sonnysasaka@chromium.org> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2020-07-28 04:48:55 +08:00
if (!ext_adv && len > HCI_MAX_AD_LENGTH) {
bt_dev_err_ratelimited(hdev, "legacy adv larger than 31 bytes");
return;
}
Bluetooth: Fix reporting incorrect EIR in device found mgmt event Some remote devices (ie Gigaset G-Tag) misbehave with ADV data length. This can lead to incorrect EIR format in device found event when ADV_DATA and SCAN_RSP are merged (terminator field before SCAN_RSP part). Fix this by inspecting ADV_DATA and correct its length if terminator is found. > HCI Event: LE Meta Event (0x3e) plen 42 [hci0] 32.172182 LE Advertising Report (0x02) Num reports: 1 Event type: Connectable undirected - ADV_IND (0x00) Address type: Public (0x00) Address: 7C:2F:80:94:97:5A (Gigaset Communications GmbH) Data length: 30 Flags: 0x06 LE General Discoverable Mode BR/EDR Not Supported Company: Gigaset Communications GmbH (384) Data: 021512348094975abbc5 16-bit Service UUIDs (partial): 1 entry Battery Service (0x180f) RSSI: -65 dBm (0xbf) > HCI Event: LE Meta Event (0x3e) plen 27 [hci0] 32.172191 LE Advertising Report (0x02) Num reports: 1 Event type: Scan response - SCAN_RSP (0x04) Address type: Public (0x00) Address: 7C:2F:80:94:97:5A (Gigaset Communications GmbH) Data length: 15 Name (complete): Gigaset G-tag RSSI: -59 dBm (0xc5) Note "Data length: 30" in ADV_DATA which results in 9 extra zero bytes after Battery Service UUID. Terminator field present in the middle of EIR in Device Found event resulted in userspace stop parsing EIR and skipping device name. @ Device Found: 7C:2F:80:94:97:5A (1) rssi -59 flags 0x0000 02 01 06 0d ff 80 01 02 15 12 34 80 94 97 5a bb ..........4...Z. c5 03 02 0f 18 00 00 00 00 00 00 00 00 00 0e 09 ................ 47 69 67 61 73 65 74 20 47 2d 74 61 67 Gigaset G-tag With this fix EIR with merged ADV_DATA and SCAN_RSP in device found event is properly formatted: @ Device Found: 7C:2F:80:94:97:5A (1) rssi -59 flags 0x0000 02 01 06 0d ff 80 01 02 15 12 34 80 94 97 5a bb ..........4...Z. c5 03 02 0f 18 0e 09 47 69 67 61 73 65 74 20 47 .......Gigaset G 2d 74 61 67 -tag Signed-off-by: Szymon Janc <ext.szymon.janc@tieto.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2015-09-17 02:21:54 +08:00
/* Find the end of the data in case the report contains padded zero
* bytes at the end causing an invalid length value.
*
* When data is NULL, len is 0 so there is no need for extra ptr
* check as 'ptr < data + 0' is already false in such case.
*/
for (ptr = data; ptr < data + len && *ptr; ptr += *ptr + 1) {
if (ptr + 1 + *ptr > data + len)
break;
}
Bluetooth: Remove spurious error message Even with rate limited reporting this is very spammy and since it is remote device that is providing bogus data there is no need to report this as error. Since real_len variable was used only to allow conditional error message it is now also removed. [72454.143336] bt_err_ratelimited: 10 callbacks suppressed [72454.143337] Bluetooth: hci0: advertising data len corrected [72454.296314] Bluetooth: hci0: advertising data len corrected [72454.892329] Bluetooth: hci0: advertising data len corrected [72455.051319] Bluetooth: hci0: advertising data len corrected [72455.357326] Bluetooth: hci0: advertising data len corrected [72455.663295] Bluetooth: hci0: advertising data len corrected [72455.787278] Bluetooth: hci0: advertising data len corrected [72455.942278] Bluetooth: hci0: advertising data len corrected [72456.094276] Bluetooth: hci0: advertising data len corrected [72456.249137] Bluetooth: hci0: advertising data len corrected [72459.416333] bt_err_ratelimited: 13 callbacks suppressed [72459.416334] Bluetooth: hci0: advertising data len corrected [72459.721334] Bluetooth: hci0: advertising data len corrected [72460.011317] Bluetooth: hci0: advertising data len corrected [72460.327171] Bluetooth: hci0: advertising data len corrected [72460.638294] Bluetooth: hci0: advertising data len corrected [72460.946350] Bluetooth: hci0: advertising data len corrected [72461.225320] Bluetooth: hci0: advertising data len corrected [72461.690322] Bluetooth: hci0: advertising data len corrected [72462.118318] Bluetooth: hci0: advertising data len corrected [72462.427319] Bluetooth: hci0: advertising data len corrected [72464.546319] bt_err_ratelimited: 7 callbacks suppressed [72464.546319] Bluetooth: hci0: advertising data len corrected [72464.857318] Bluetooth: hci0: advertising data len corrected [72465.163332] Bluetooth: hci0: advertising data len corrected [72465.278331] Bluetooth: hci0: advertising data len corrected [72465.432323] Bluetooth: hci0: advertising data len corrected [72465.891334] Bluetooth: hci0: advertising data len corrected [72466.045334] Bluetooth: hci0: advertising data len corrected [72466.197321] Bluetooth: hci0: advertising data len corrected [72466.340318] Bluetooth: hci0: advertising data len corrected [72466.498335] Bluetooth: hci0: advertising data len corrected [72469.803299] bt_err_ratelimited: 10 callbacks suppressed Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl> Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=203753 Cc: stable@vger.kernel.org Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-05-18 22:54:36 +08:00
/* Adjust for actual length. This handles the case when remote
* device is advertising with incorrect data length.
*/
len = ptr - data;
/* If the direct address is present, then this report is from
* a LE Direct Advertising Report event. In that case it is
* important to see if the address is matching the local
* controller address.
*/
if (direct_addr) {
direct_addr_type = ev_bdaddr_type(hdev, direct_addr_type,
&bdaddr_resolved);
/* Only resolvable random addresses are valid for these
* kind of reports and others can be ignored.
*/
if (!hci_bdaddr_is_rpa(direct_addr, direct_addr_type))
return;
/* If the controller is not using resolvable random
* addresses, then this report can be ignored.
*/
if (!hci_dev_test_flag(hdev, HCI_PRIVACY))
return;
/* If the local IRK of the controller does not match
* with the resolvable random address provided, then
* this report can be ignored.
*/
if (!smp_irk_matches(hdev, hdev->irk, direct_addr))
return;
}
/* Check if we need to convert to identity address */
irk = hci_get_irk(hdev, bdaddr, bdaddr_type);
if (irk) {
bdaddr = &irk->bdaddr;
bdaddr_type = irk->addr_type;
}
bdaddr_type = ev_bdaddr_type(hdev, bdaddr_type, &bdaddr_resolved);
Bluetooth: Fix connection if directed advertising and privacy is used Local random address needs to be updated before creating connection if RPA from LE Direct Advertising Report was resolved in host. Otherwise remote device might ignore connection request due to address mismatch. This was affecting following qualification test cases: GAP/CONN/SCEP/BV-03-C, GAP/CONN/GCEP/BV-05-C, GAP/CONN/DCEP/BV-05-C Before patch: < HCI Command: LE Set Random Address (0x08|0x0005) plen 6 #11350 [hci0] 84680.231216 Address: 56:BC:E8:24:11:68 (Resolvable) Identity type: Random (0x01) Identity: F2:F1:06:3D:9C:42 (Static) > HCI Event: Command Complete (0x0e) plen 4 #11351 [hci0] 84680.246022 LE Set Random Address (0x08|0x0005) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Scan Parameters (0x08|0x000b) plen 7 #11352 [hci0] 84680.246417 Type: Passive (0x00) Interval: 60.000 msec (0x0060) Window: 30.000 msec (0x0030) Own address type: Random (0x01) Filter policy: Accept all advertisement, inc. directed unresolved RPA (0x02) > HCI Event: Command Complete (0x0e) plen 4 #11353 [hci0] 84680.248854 LE Set Scan Parameters (0x08|0x000b) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 #11354 [hci0] 84680.249466 Scanning: Enabled (0x01) Filter duplicates: Enabled (0x01) > HCI Event: Command Complete (0x0e) plen 4 #11355 [hci0] 84680.253222 LE Set Scan Enable (0x08|0x000c) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 18 #11356 [hci0] 84680.458387 LE Direct Advertising Report (0x0b) Num reports: 1 Event type: Connectable directed - ADV_DIRECT_IND (0x01) Address type: Random (0x01) Address: 53:38:DA:46:8C:45 (Resolvable) Identity type: Public (0x00) Identity: 11:22:33:44:55:66 (OUI 11-22-33) Direct address type: Random (0x01) Direct address: 7C:D6:76:8C:DF:82 (Resolvable) Identity type: Random (0x01) Identity: F2:F1:06:3D:9C:42 (Static) RSSI: -74 dBm (0xb6) < HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 #11357 [hci0] 84680.458737 Scanning: Disabled (0x00) Filter duplicates: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 4 #11358 [hci0] 84680.469982 LE Set Scan Enable (0x08|0x000c) ncmd 1 Status: Success (0x00) < HCI Command: LE Create Connection (0x08|0x000d) plen 25 #11359 [hci0] 84680.470444 Scan interval: 60.000 msec (0x0060) Scan window: 60.000 msec (0x0060) Filter policy: White list is not used (0x00) Peer address type: Random (0x01) Peer address: 53:38:DA:46:8C:45 (Resolvable) Identity type: Public (0x00) Identity: 11:22:33:44:55:66 (OUI 11-22-33) Own address type: Random (0x01) Min connection interval: 30.00 msec (0x0018) Max connection interval: 50.00 msec (0x0028) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Min connection length: 0.000 msec (0x0000) Max connection length: 0.000 msec (0x0000) > HCI Event: Command Status (0x0f) plen 4 #11360 [hci0] 84680.474971 LE Create Connection (0x08|0x000d) ncmd 1 Status: Success (0x00) < HCI Command: LE Create Connection Cancel (0x08|0x000e) plen 0 #11361 [hci0] 84682.545385 > HCI Event: Command Complete (0x0e) plen 4 #11362 [hci0] 84682.551014 LE Create Connection Cancel (0x08|0x000e) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 19 #11363 [hci0] 84682.551074 LE Connection Complete (0x01) Status: Unknown Connection Identifier (0x02) Handle: 0 Role: Master (0x00) Peer address type: Public (0x00) Peer address: 00:00:00:00:00:00 (OUI 00-00-00) Connection interval: 0.00 msec (0x0000) Connection latency: 0 (0x0000) Supervision timeout: 0 msec (0x0000) Master clock accuracy: 0x00 After patch: < HCI Command: LE Set Scan Parameters (0x08|0x000b) plen 7 #210 [hci0] 667.152459 Type: Passive (0x00) Interval: 60.000 msec (0x0060) Window: 30.000 msec (0x0030) Own address type: Random (0x01) Filter policy: Accept all advertisement, inc. directed unresolved RPA (0x02) > HCI Event: Command Complete (0x0e) plen 4 #211 [hci0] 667.153613 LE Set Scan Parameters (0x08|0x000b) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 #212 [hci0] 667.153704 Scanning: Enabled (0x01) Filter duplicates: Enabled (0x01) > HCI Event: Command Complete (0x0e) plen 4 #213 [hci0] 667.154584 LE Set Scan Enable (0x08|0x000c) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 18 #214 [hci0] 667.182619 LE Direct Advertising Report (0x0b) Num reports: 1 Event type: Connectable directed - ADV_DIRECT_IND (0x01) Address type: Random (0x01) Address: 50:52:D9:A6:48:A0 (Resolvable) Identity type: Public (0x00) Identity: 11:22:33:44:55:66 (OUI 11-22-33) Direct address type: Random (0x01) Direct address: 7C:C1:57:A5:B7:A8 (Resolvable) Identity type: Random (0x01) Identity: F4:28:73:5D:38:B0 (Static) RSSI: -70 dBm (0xba) < HCI Command: LE Set Scan Enable (0x08|0x000c) plen 2 #215 [hci0] 667.182704 Scanning: Disabled (0x00) Filter duplicates: Disabled (0x00) > HCI Event: Command Complete (0x0e) plen 4 #216 [hci0] 667.183599 LE Set Scan Enable (0x08|0x000c) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Random Address (0x08|0x0005) plen 6 #217 [hci0] 667.183645 Address: 7C:C1:57:A5:B7:A8 (Resolvable) Identity type: Random (0x01) Identity: F4:28:73:5D:38:B0 (Static) > HCI Event: Command Complete (0x0e) plen 4 #218 [hci0] 667.184590 LE Set Random Address (0x08|0x0005) ncmd 1 Status: Success (0x00) < HCI Command: LE Create Connection (0x08|0x000d) plen 25 #219 [hci0] 667.184613 Scan interval: 60.000 msec (0x0060) Scan window: 60.000 msec (0x0060) Filter policy: White list is not used (0x00) Peer address type: Random (0x01) Peer address: 50:52:D9:A6:48:A0 (Resolvable) Identity type: Public (0x00) Identity: 11:22:33:44:55:66 (OUI 11-22-33) Own address type: Random (0x01) Min connection interval: 30.00 msec (0x0018) Max connection interval: 50.00 msec (0x0028) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Min connection length: 0.000 msec (0x0000) Max connection length: 0.000 msec (0x0000) > HCI Event: Command Status (0x0f) plen 4 #220 [hci0] 667.186558 LE Create Connection (0x08|0x000d) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 19 #221 [hci0] 667.485824 LE Connection Complete (0x01) Status: Success (0x00) Handle: 0 Role: Master (0x00) Peer address type: Random (0x01) Peer address: 50:52:D9:A6:48:A0 (Resolvable) Identity type: Public (0x00) Identity: 11:22:33:44:55:66 (OUI 11-22-33) Connection interval: 50.00 msec (0x0028) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Master clock accuracy: 0x07 @ MGMT Event: Device Connected (0x000b) plen 13 {0x0002} [hci0] 667.485996 LE Address: 11:22:33:44:55:66 (OUI 11-22-33) Flags: 0x00000000 Data length: 0 Signed-off-by: Szymon Janc <szymon.janc@codecoup.pl> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Cc: stable@vger.kernel.org
2018-04-03 19:40:06 +08:00
/* Check if we have been requested to connect to this device.
*
* direct_addr is set only for directed advertising reports (it is NULL
* for advertising reports) and is already verified to be RPA above.
*/
conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, bdaddr_resolved,
type);
Bluetooth: fix kernel oops in store_pending_adv_report Fix kernel oops observed when an ext adv data is larger than 31 bytes. This can be reproduced by setting up an advertiser with advertisement larger than 31 bytes. The issue is not sensitive to the advertisement content. In particular, this was reproduced with an advertisement of 229 bytes filled with 'A'. See stack trace below. This is fixed by not catching ext_adv as legacy adv are only cached to be able to concatenate a scanable adv with its scan response before sending it up through mgmt. With ext_adv, this is no longer necessary. general protection fault: 0000 [#1] SMP PTI CPU: 6 PID: 205 Comm: kworker/u17:0 Not tainted 5.4.0-37-generic #41-Ubuntu Hardware name: Dell Inc. XPS 15 7590/0CF6RR, BIOS 1.7.0 05/11/2020 Workqueue: hci0 hci_rx_work [bluetooth] RIP: 0010:hci_bdaddr_list_lookup+0x1e/0x40 [bluetooth] Code: ff ff e9 26 ff ff ff 0f 1f 44 00 00 0f 1f 44 00 00 55 48 8b 07 48 89 e5 48 39 c7 75 0a eb 24 48 8b 00 48 39 f8 74 1c 44 8b 06 <44> 39 40 10 75 ef 44 0f b7 4e 04 66 44 39 48 14 75 e3 38 50 16 75 RSP: 0018:ffffbc6a40493c70 EFLAGS: 00010286 RAX: 4141414141414141 RBX: 000000000000001b RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff9903e76c100f RDI: ffff9904289d4b28 RBP: ffffbc6a40493c70 R08: 0000000093570362 R09: 0000000000000000 R10: 0000000000000000 R11: ffff9904344eae38 R12: ffff9904289d4000 R13: 0000000000000000 R14: 00000000ffffffa3 R15: ffff9903e76c100f FS: 0000000000000000(0000) GS:ffff990434580000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007feed125a000 CR3: 00000001b860a003 CR4: 00000000003606e0 Call Trace: process_adv_report+0x12e/0x560 [bluetooth] hci_le_meta_evt+0x7b2/0xba0 [bluetooth] hci_event_packet+0x1c29/0x2a90 [bluetooth] hci_rx_work+0x19b/0x360 [bluetooth] process_one_work+0x1eb/0x3b0 worker_thread+0x4d/0x400 kthread+0x104/0x140 Fixes: c215e9397b00 ("Bluetooth: Process extended ADV report event") Reported-by: Andy Nguyen <theflow@google.com> Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Reported-by: Balakrishna Godavarthi <bgodavar@codeaurora.org> Signed-off-by: Alain Michaud <alainm@chromium.org> Tested-by: Sonny Sasaka <sonnysasaka@chromium.org> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2020-07-28 04:48:55 +08:00
if (!ext_adv && conn && type == LE_ADV_IND && len <= HCI_MAX_AD_LENGTH) {
/* Store report for later inclusion by
* mgmt_device_connected
*/
memcpy(conn->le_adv_data, data, len);
conn->le_adv_data_len = len;
}
/* Passive scanning shouldn't trigger any device found events,
* except for devices marked as CONN_REPORT for which we do send
* device found events, or advertisement monitoring requested.
*/
if (hdev->le_scan_type == LE_SCAN_PASSIVE) {
if (type == LE_ADV_DIRECT_IND)
return;
if (!hci_pend_le_action_lookup(&hdev->pend_le_reports,
bdaddr, bdaddr_type) &&
idr_is_empty(&hdev->adv_monitors_idr))
return;
if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND)
flags = MGMT_DEV_FOUND_NOT_CONNECTABLE;
else
flags = 0;
mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
rssi, flags, data, len, NULL, 0);
return;
}
/* When receiving non-connectable or scannable undirected
* advertising reports, this means that the remote device is
* not connectable and then clearly indicate this in the
* device found event.
*
* When receiving a scan response, then there is no way to
* know if the remote device is connectable or not. However
* since scan responses are merged with a previously seen
* advertising report, the flags field from that report
* will be used.
*
* In the really unlikely case that a controller get confused
* and just sends a scan response event, then it is marked as
* not connectable as well.
*/
if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND ||
type == LE_ADV_SCAN_RSP)
flags = MGMT_DEV_FOUND_NOT_CONNECTABLE;
else
flags = 0;
/* If there's nothing pending either store the data from this
* event or send an immediate device found event if the data
* should not be stored for later.
*/
Bluetooth: fix kernel oops in store_pending_adv_report Fix kernel oops observed when an ext adv data is larger than 31 bytes. This can be reproduced by setting up an advertiser with advertisement larger than 31 bytes. The issue is not sensitive to the advertisement content. In particular, this was reproduced with an advertisement of 229 bytes filled with 'A'. See stack trace below. This is fixed by not catching ext_adv as legacy adv are only cached to be able to concatenate a scanable adv with its scan response before sending it up through mgmt. With ext_adv, this is no longer necessary. general protection fault: 0000 [#1] SMP PTI CPU: 6 PID: 205 Comm: kworker/u17:0 Not tainted 5.4.0-37-generic #41-Ubuntu Hardware name: Dell Inc. XPS 15 7590/0CF6RR, BIOS 1.7.0 05/11/2020 Workqueue: hci0 hci_rx_work [bluetooth] RIP: 0010:hci_bdaddr_list_lookup+0x1e/0x40 [bluetooth] Code: ff ff e9 26 ff ff ff 0f 1f 44 00 00 0f 1f 44 00 00 55 48 8b 07 48 89 e5 48 39 c7 75 0a eb 24 48 8b 00 48 39 f8 74 1c 44 8b 06 <44> 39 40 10 75 ef 44 0f b7 4e 04 66 44 39 48 14 75 e3 38 50 16 75 RSP: 0018:ffffbc6a40493c70 EFLAGS: 00010286 RAX: 4141414141414141 RBX: 000000000000001b RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff9903e76c100f RDI: ffff9904289d4b28 RBP: ffffbc6a40493c70 R08: 0000000093570362 R09: 0000000000000000 R10: 0000000000000000 R11: ffff9904344eae38 R12: ffff9904289d4000 R13: 0000000000000000 R14: 00000000ffffffa3 R15: ffff9903e76c100f FS: 0000000000000000(0000) GS:ffff990434580000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007feed125a000 CR3: 00000001b860a003 CR4: 00000000003606e0 Call Trace: process_adv_report+0x12e/0x560 [bluetooth] hci_le_meta_evt+0x7b2/0xba0 [bluetooth] hci_event_packet+0x1c29/0x2a90 [bluetooth] hci_rx_work+0x19b/0x360 [bluetooth] process_one_work+0x1eb/0x3b0 worker_thread+0x4d/0x400 kthread+0x104/0x140 Fixes: c215e9397b00 ("Bluetooth: Process extended ADV report event") Reported-by: Andy Nguyen <theflow@google.com> Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Reported-by: Balakrishna Godavarthi <bgodavar@codeaurora.org> Signed-off-by: Alain Michaud <alainm@chromium.org> Tested-by: Sonny Sasaka <sonnysasaka@chromium.org> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2020-07-28 04:48:55 +08:00
if (!ext_adv && !has_pending_adv_report(hdev)) {
/* If the report will trigger a SCAN_REQ store it for
* later merging.
*/
if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
store_pending_adv_report(hdev, bdaddr, bdaddr_type,
rssi, flags, data, len);
return;
}
mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
rssi, flags, data, len, NULL, 0);
return;
}
/* Check if the pending report is for the same device as the new one */
match = (!bacmp(bdaddr, &d->last_adv_addr) &&
bdaddr_type == d->last_adv_addr_type);
/* If the pending data doesn't match this report or this isn't a
* scan response (e.g. we got a duplicate ADV_IND) then force
* sending of the pending data.
*/
if (type != LE_ADV_SCAN_RSP || !match) {
/* Send out whatever is in the cache, but skip duplicates */
if (!match)
mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
d->last_adv_addr_type, NULL,
d->last_adv_rssi, d->last_adv_flags,
d->last_adv_data,
d->last_adv_data_len, NULL, 0);
/* If the new report will trigger a SCAN_REQ store it for
* later merging.
*/
Bluetooth: fix kernel oops in store_pending_adv_report Fix kernel oops observed when an ext adv data is larger than 31 bytes. This can be reproduced by setting up an advertiser with advertisement larger than 31 bytes. The issue is not sensitive to the advertisement content. In particular, this was reproduced with an advertisement of 229 bytes filled with 'A'. See stack trace below. This is fixed by not catching ext_adv as legacy adv are only cached to be able to concatenate a scanable adv with its scan response before sending it up through mgmt. With ext_adv, this is no longer necessary. general protection fault: 0000 [#1] SMP PTI CPU: 6 PID: 205 Comm: kworker/u17:0 Not tainted 5.4.0-37-generic #41-Ubuntu Hardware name: Dell Inc. XPS 15 7590/0CF6RR, BIOS 1.7.0 05/11/2020 Workqueue: hci0 hci_rx_work [bluetooth] RIP: 0010:hci_bdaddr_list_lookup+0x1e/0x40 [bluetooth] Code: ff ff e9 26 ff ff ff 0f 1f 44 00 00 0f 1f 44 00 00 55 48 8b 07 48 89 e5 48 39 c7 75 0a eb 24 48 8b 00 48 39 f8 74 1c 44 8b 06 <44> 39 40 10 75 ef 44 0f b7 4e 04 66 44 39 48 14 75 e3 38 50 16 75 RSP: 0018:ffffbc6a40493c70 EFLAGS: 00010286 RAX: 4141414141414141 RBX: 000000000000001b RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff9903e76c100f RDI: ffff9904289d4b28 RBP: ffffbc6a40493c70 R08: 0000000093570362 R09: 0000000000000000 R10: 0000000000000000 R11: ffff9904344eae38 R12: ffff9904289d4000 R13: 0000000000000000 R14: 00000000ffffffa3 R15: ffff9903e76c100f FS: 0000000000000000(0000) GS:ffff990434580000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007feed125a000 CR3: 00000001b860a003 CR4: 00000000003606e0 Call Trace: process_adv_report+0x12e/0x560 [bluetooth] hci_le_meta_evt+0x7b2/0xba0 [bluetooth] hci_event_packet+0x1c29/0x2a90 [bluetooth] hci_rx_work+0x19b/0x360 [bluetooth] process_one_work+0x1eb/0x3b0 worker_thread+0x4d/0x400 kthread+0x104/0x140 Fixes: c215e9397b00 ("Bluetooth: Process extended ADV report event") Reported-by: Andy Nguyen <theflow@google.com> Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Reported-by: Balakrishna Godavarthi <bgodavar@codeaurora.org> Signed-off-by: Alain Michaud <alainm@chromium.org> Tested-by: Sonny Sasaka <sonnysasaka@chromium.org> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2020-07-28 04:48:55 +08:00
if (!ext_adv && (type == LE_ADV_IND ||
type == LE_ADV_SCAN_IND)) {
store_pending_adv_report(hdev, bdaddr, bdaddr_type,
rssi, flags, data, len);
return;
}
/* The advertising reports cannot be merged, so clear
* the pending report and send out a device found event.
*/
clear_pending_adv_report(hdev);
mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL,
rssi, flags, data, len, NULL, 0);
return;
}
/* If we get here we've got a pending ADV_IND or ADV_SCAN_IND and
* the new event is a SCAN_RSP. We can therefore proceed with
* sending a merged device found event.
*/
mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK,
d->last_adv_addr_type, NULL, rssi, d->last_adv_flags,
d->last_adv_data, d->last_adv_data_len, data, len);
clear_pending_adv_report(hdev);
}
static void hci_le_adv_report_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_le_advertising_report *ev = data;
if (!ev->num)
return;
Bluetooth: Introduce LE auto connection infrastructure This patch introduces the LE auto connection infrastructure which will be used to implement the LE auto connection options. In summary, the auto connection mechanism works as follows: Once the first pending LE connection is created, the background scanning is started. When the target device is found in range, the kernel autonomously starts the connection attempt. If connection is established successfully, that pending LE connection is deleted and the background is stopped. To achieve that, this patch introduces the hci_update_background_scan() which controls the background scanning state. This function starts or stops the background scanning based on the hdev->pend_le_conns list. If there is no pending LE connection, the background scanning is stopped. Otherwise, we start the background scanning. Then, every time a pending LE connection is added we call hci_update_ background_scan() so the background scanning is started (in case it is not already running). Likewise, every time a pending LE connection is deleted we call hci_update_background_scan() so the background scanning is stopped (in case this was the last pending LE connection) or it is started again (in case we have more pending LE connections). Finally, we also call hci_update_background_scan() in hci_le_conn_failed() so the background scan is restarted in case the connection establishment fails. This way the background scanning keeps running until all pending LE connection are established. At this point, resolvable addresses are not support by this infrastructure. The proper support is added in upcoming patches. Signed-off-by: Andre Guedes <andre.guedes@openbossa.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-02-27 07:21:47 +08:00
hci_dev_lock(hdev);
while (ev->num--) {
struct hci_ev_le_advertising_info *info;
s8 rssi;
Bluetooth: Introduce LE auto connection infrastructure This patch introduces the LE auto connection infrastructure which will be used to implement the LE auto connection options. In summary, the auto connection mechanism works as follows: Once the first pending LE connection is created, the background scanning is started. When the target device is found in range, the kernel autonomously starts the connection attempt. If connection is established successfully, that pending LE connection is deleted and the background is stopped. To achieve that, this patch introduces the hci_update_background_scan() which controls the background scanning state. This function starts or stops the background scanning based on the hdev->pend_le_conns list. If there is no pending LE connection, the background scanning is stopped. Otherwise, we start the background scanning. Then, every time a pending LE connection is added we call hci_update_ background_scan() so the background scanning is started (in case it is not already running). Likewise, every time a pending LE connection is deleted we call hci_update_background_scan() so the background scanning is stopped (in case this was the last pending LE connection) or it is started again (in case we have more pending LE connections). Finally, we also call hci_update_background_scan() in hci_le_conn_failed() so the background scan is restarted in case the connection establishment fails. This way the background scanning keeps running until all pending LE connection are established. At this point, resolvable addresses are not support by this infrastructure. The proper support is added in upcoming patches. Signed-off-by: Andre Guedes <andre.guedes@openbossa.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-02-27 07:21:47 +08:00
info = hci_le_ev_skb_pull(hdev, skb,
HCI_EV_LE_ADVERTISING_REPORT,
sizeof(*info));
if (!info)
break;
if (!hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_ADVERTISING_REPORT,
info->length + 1))
break;
if (info->length <= HCI_MAX_AD_LENGTH) {
rssi = info->data[info->length];
process_adv_report(hdev, info->type, &info->bdaddr,
info->bdaddr_type, NULL, 0, rssi,
info->data, info->length, false);
} else {
bt_dev_err(hdev, "Dropping invalid advertising data");
}
}
Bluetooth: Introduce LE auto connection infrastructure This patch introduces the LE auto connection infrastructure which will be used to implement the LE auto connection options. In summary, the auto connection mechanism works as follows: Once the first pending LE connection is created, the background scanning is started. When the target device is found in range, the kernel autonomously starts the connection attempt. If connection is established successfully, that pending LE connection is deleted and the background is stopped. To achieve that, this patch introduces the hci_update_background_scan() which controls the background scanning state. This function starts or stops the background scanning based on the hdev->pend_le_conns list. If there is no pending LE connection, the background scanning is stopped. Otherwise, we start the background scanning. Then, every time a pending LE connection is added we call hci_update_ background_scan() so the background scanning is started (in case it is not already running). Likewise, every time a pending LE connection is deleted we call hci_update_background_scan() so the background scanning is stopped (in case this was the last pending LE connection) or it is started again (in case we have more pending LE connections). Finally, we also call hci_update_background_scan() in hci_le_conn_failed() so the background scan is restarted in case the connection establishment fails. This way the background scanning keeps running until all pending LE connection are established. At this point, resolvable addresses are not support by this infrastructure. The proper support is added in upcoming patches. Signed-off-by: Andre Guedes <andre.guedes@openbossa.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-02-27 07:21:47 +08:00
hci_dev_unlock(hdev);
}
static u8 ext_evt_type_to_legacy(struct hci_dev *hdev, u16 evt_type)
{
if (evt_type & LE_EXT_ADV_LEGACY_PDU) {
switch (evt_type) {
case LE_LEGACY_ADV_IND:
return LE_ADV_IND;
case LE_LEGACY_ADV_DIRECT_IND:
return LE_ADV_DIRECT_IND;
case LE_LEGACY_ADV_SCAN_IND:
return LE_ADV_SCAN_IND;
case LE_LEGACY_NONCONN_IND:
return LE_ADV_NONCONN_IND;
case LE_LEGACY_SCAN_RSP_ADV:
case LE_LEGACY_SCAN_RSP_ADV_SCAN:
return LE_ADV_SCAN_RSP;
}
goto invalid;
}
if (evt_type & LE_EXT_ADV_CONN_IND) {
if (evt_type & LE_EXT_ADV_DIRECT_IND)
return LE_ADV_DIRECT_IND;
return LE_ADV_IND;
}
if (evt_type & LE_EXT_ADV_SCAN_RSP)
return LE_ADV_SCAN_RSP;
if (evt_type & LE_EXT_ADV_SCAN_IND)
return LE_ADV_SCAN_IND;
if (evt_type == LE_EXT_ADV_NON_CONN_IND ||
evt_type & LE_EXT_ADV_DIRECT_IND)
return LE_ADV_NONCONN_IND;
invalid:
bt_dev_err_ratelimited(hdev, "Unknown advertising packet type: 0x%02x",
evt_type);
return LE_ADV_INVALID;
}
static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_le_ext_adv_report *ev = data;
if (!ev->num)
return;
hci_dev_lock(hdev);
while (ev->num--) {
struct hci_ev_le_ext_adv_info *info;
u8 legacy_evt_type;
u16 evt_type;
info = hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT,
sizeof(*info));
if (!info)
break;
if (!hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_EXT_ADV_REPORT,
info->length))
break;
evt_type = __le16_to_cpu(info->type);
legacy_evt_type = ext_evt_type_to_legacy(hdev, evt_type);
if (legacy_evt_type != LE_ADV_INVALID) {
process_adv_report(hdev, legacy_evt_type, &info->bdaddr,
info->bdaddr_type, NULL, 0,
info->rssi, info->data, info->length,
Bluetooth: fix kernel oops in store_pending_adv_report Fix kernel oops observed when an ext adv data is larger than 31 bytes. This can be reproduced by setting up an advertiser with advertisement larger than 31 bytes. The issue is not sensitive to the advertisement content. In particular, this was reproduced with an advertisement of 229 bytes filled with 'A'. See stack trace below. This is fixed by not catching ext_adv as legacy adv are only cached to be able to concatenate a scanable adv with its scan response before sending it up through mgmt. With ext_adv, this is no longer necessary. general protection fault: 0000 [#1] SMP PTI CPU: 6 PID: 205 Comm: kworker/u17:0 Not tainted 5.4.0-37-generic #41-Ubuntu Hardware name: Dell Inc. XPS 15 7590/0CF6RR, BIOS 1.7.0 05/11/2020 Workqueue: hci0 hci_rx_work [bluetooth] RIP: 0010:hci_bdaddr_list_lookup+0x1e/0x40 [bluetooth] Code: ff ff e9 26 ff ff ff 0f 1f 44 00 00 0f 1f 44 00 00 55 48 8b 07 48 89 e5 48 39 c7 75 0a eb 24 48 8b 00 48 39 f8 74 1c 44 8b 06 <44> 39 40 10 75 ef 44 0f b7 4e 04 66 44 39 48 14 75 e3 38 50 16 75 RSP: 0018:ffffbc6a40493c70 EFLAGS: 00010286 RAX: 4141414141414141 RBX: 000000000000001b RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff9903e76c100f RDI: ffff9904289d4b28 RBP: ffffbc6a40493c70 R08: 0000000093570362 R09: 0000000000000000 R10: 0000000000000000 R11: ffff9904344eae38 R12: ffff9904289d4000 R13: 0000000000000000 R14: 00000000ffffffa3 R15: ffff9903e76c100f FS: 0000000000000000(0000) GS:ffff990434580000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007feed125a000 CR3: 00000001b860a003 CR4: 00000000003606e0 Call Trace: process_adv_report+0x12e/0x560 [bluetooth] hci_le_meta_evt+0x7b2/0xba0 [bluetooth] hci_event_packet+0x1c29/0x2a90 [bluetooth] hci_rx_work+0x19b/0x360 [bluetooth] process_one_work+0x1eb/0x3b0 worker_thread+0x4d/0x400 kthread+0x104/0x140 Fixes: c215e9397b00 ("Bluetooth: Process extended ADV report event") Reported-by: Andy Nguyen <theflow@google.com> Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Reported-by: Balakrishna Godavarthi <bgodavar@codeaurora.org> Signed-off-by: Alain Michaud <alainm@chromium.org> Tested-by: Sonny Sasaka <sonnysasaka@chromium.org> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2020-07-28 04:48:55 +08:00
!(evt_type & LE_EXT_ADV_LEGACY_PDU));
}
}
hci_dev_unlock(hdev);
}
static void hci_le_remote_feat_complete_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_le_remote_feat_complete *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (conn) {
if (!ev->status)
memcpy(conn->features[0], ev->features, 8);
if (conn->state == BT_CONFIG) {
__u8 status;
/* If the local controller supports peripheral-initiated
* features exchange, but the remote controller does
* not, then it is possible that the error code 0x1a
* for unsupported remote feature gets returned.
*
* In this specific case, allow the connection to
* transition into connected state and mark it as
* successful.
*/
if (!conn->out && ev->status == 0x1a &&
(hdev->le_features[0] & HCI_LE_PERIPHERAL_FEATURES))
status = 0x00;
else
status = ev->status;
conn->state = BT_CONNECTED;
hci_connect_cfm(conn, status);
hci_conn_drop(conn);
}
}
hci_dev_unlock(hdev);
}
static void hci_le_ltk_request_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_le_ltk_req *ev = data;
struct hci_cp_le_ltk_reply cp;
struct hci_cp_le_ltk_neg_reply neg;
struct hci_conn *conn;
struct smp_ltk *ltk;
bt_dev_dbg(hdev, "handle 0x%4.4x", __le16_to_cpu(ev->handle));
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (conn == NULL)
goto not_found;
ltk = hci_find_ltk(hdev, &conn->dst, conn->dst_type, conn->role);
if (!ltk)
goto not_found;
if (smp_ltk_is_sc(ltk)) {
/* With SC both EDiv and Rand are set to zero */
if (ev->ediv || ev->rand)
goto not_found;
} else {
/* For non-SC keys check that EDiv and Rand match */
if (ev->ediv != ltk->ediv || ev->rand != ltk->rand)
goto not_found;
}
memcpy(cp.ltk, ltk->val, ltk->enc_size);
memset(cp.ltk + ltk->enc_size, 0, sizeof(cp.ltk) - ltk->enc_size);
cp.handle = cpu_to_le16(conn->handle);
conn->pending_sec_level = smp_ltk_sec_level(ltk);
conn->enc_key_size = ltk->enc_size;
hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp);
Bluetooth: Fix removing Long Term Key This patch fixes authentication failure on LE link re-connection when BlueZ acts as slave (peripheral). LTK is removed from the internal list after its first use causing PIN or Key missing reply when re-connecting the link. The LE Long Term Key Request event indicates that the master is attempting to encrypt or re-encrypt the link. Pre-condition: BlueZ host paired and running as slave. How to reproduce(master): 1) Establish an ACL LE encrypted link 2) Disconnect the link 3) Try to re-establish the ACL LE encrypted link (fails) > HCI Event: LE Meta Event (0x3e) plen 19 LE Connection Complete (0x01) Status: Success (0x00) Handle: 64 Role: Slave (0x01) ... @ Device Connected: 00:02:72:DC:29:C9 (1) flags 0x0000 > HCI Event: LE Meta Event (0x3e) plen 13 LE Long Term Key Request (0x05) Handle: 64 Random number: 875be18439d9aa37 Encryption diversifier: 0x76ed < HCI Command: LE Long Term Key Request Reply (0x08|0x001a) plen 18 Handle: 64 Long term key: 2aa531db2fce9f00a0569c7d23d17409 > HCI Event: Command Complete (0x0e) plen 6 LE Long Term Key Request Reply (0x08|0x001a) ncmd 1 Status: Success (0x00) Handle: 64 > HCI Event: Encryption Change (0x08) plen 4 Status: Success (0x00) Handle: 64 Encryption: Enabled with AES-CCM (0x01) ... @ Device Disconnected: 00:02:72:DC:29:C9 (1) reason 3 < HCI Command: LE Set Advertise Enable (0x08|0x000a) plen 1 Advertising: Enabled (0x01) > HCI Event: Command Complete (0x0e) plen 4 LE Set Advertise Enable (0x08|0x000a) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 19 LE Connection Complete (0x01) Status: Success (0x00) Handle: 64 Role: Slave (0x01) ... @ Device Connected: 00:02:72:DC:29:C9 (1) flags 0x0000 > HCI Event: LE Meta Event (0x3e) plen 13 LE Long Term Key Request (0x05) Handle: 64 Random number: 875be18439d9aa37 Encryption diversifier: 0x76ed < HCI Command: LE Long Term Key Request Neg Reply (0x08|0x001b) plen 2 Handle: 64 > HCI Event: Command Complete (0x0e) plen 6 LE Long Term Key Request Neg Reply (0x08|0x001b) ncmd 1 Status: Success (0x00) Handle: 64 > HCI Event: Disconnect Complete (0x05) plen 4 Status: Success (0x00) Handle: 64 Reason: Authentication Failure (0x05) @ Device Disconnected: 00:02:72:DC:29:C9 (1) reason 0 Signed-off-by: Claudio Takahasi <claudio.takahasi@openbossa.org> Cc: stable@vger.kernel.org Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2013-07-26 03:34:24 +08:00
/* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a
* temporary key used to encrypt a connection following
* pairing. It is used during the Encrypted Session Setup to
* distribute the keys. Later, security can be re-established
* using a distributed LTK.
*/
if (ltk->type == SMP_STK) {
set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
list_del_rcu(&ltk->list);
kfree_rcu(ltk, rcu);
} else {
clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags);
}
hci_dev_unlock(hdev);
return;
not_found:
neg.handle = ev->handle;
hci_send_cmd(hdev, HCI_OP_LE_LTK_NEG_REPLY, sizeof(neg), &neg);
hci_dev_unlock(hdev);
}
static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle,
u8 reason)
{
struct hci_cp_le_conn_param_req_neg_reply cp;
cp.handle = cpu_to_le16(handle);
cp.reason = reason;
hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, sizeof(cp),
&cp);
}
static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_le_remote_conn_param_req *ev = data;
struct hci_cp_le_conn_param_req_reply cp;
struct hci_conn *hcon;
u16 handle, min, max, latency, timeout;
bt_dev_dbg(hdev, "handle 0x%4.4x", __le16_to_cpu(ev->handle));
handle = le16_to_cpu(ev->handle);
min = le16_to_cpu(ev->interval_min);
max = le16_to_cpu(ev->interval_max);
latency = le16_to_cpu(ev->latency);
timeout = le16_to_cpu(ev->timeout);
hcon = hci_conn_hash_lookup_handle(hdev, handle);
if (!hcon || hcon->state != BT_CONNECTED)
return send_conn_param_neg_reply(hdev, handle,
HCI_ERROR_UNKNOWN_CONN_ID);
if (hci_check_conn_params(min, max, latency, timeout))
return send_conn_param_neg_reply(hdev, handle,
HCI_ERROR_INVALID_LL_PARAMS);
if (hcon->role == HCI_ROLE_MASTER) {
struct hci_conn_params *params;
u8 store_hint;
hci_dev_lock(hdev);
params = hci_conn_params_lookup(hdev, &hcon->dst,
hcon->dst_type);
if (params) {
params->conn_min_interval = min;
params->conn_max_interval = max;
params->conn_latency = latency;
params->supervision_timeout = timeout;
store_hint = 0x01;
} else {
store_hint = 0x00;
}
hci_dev_unlock(hdev);
mgmt_new_conn_param(hdev, &hcon->dst, hcon->dst_type,
store_hint, min, max, latency, timeout);
}
cp.handle = ev->handle;
cp.interval_min = ev->interval_min;
cp.interval_max = ev->interval_max;
cp.latency = ev->latency;
cp.timeout = ev->timeout;
cp.min_ce_len = 0;
cp.max_ce_len = 0;
hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp);
}
static void hci_le_direct_adv_report_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_le_direct_adv_report *ev = data;
int i;
if (!hci_le_ev_skb_pull(hdev, skb, HCI_EV_LE_DIRECT_ADV_REPORT,
flex_array_size(ev, info, ev->num)))
return;
if (!ev->num)
return;
hci_dev_lock(hdev);
for (i = 0; i < ev->num; i++) {
struct hci_ev_le_direct_adv_info *info = &ev->info[i];
process_adv_report(hdev, info->type, &info->bdaddr,
info->bdaddr_type, &info->direct_addr,
info->direct_addr_type, info->rssi, NULL, 0,
Bluetooth: fix kernel oops in store_pending_adv_report Fix kernel oops observed when an ext adv data is larger than 31 bytes. This can be reproduced by setting up an advertiser with advertisement larger than 31 bytes. The issue is not sensitive to the advertisement content. In particular, this was reproduced with an advertisement of 229 bytes filled with 'A'. See stack trace below. This is fixed by not catching ext_adv as legacy adv are only cached to be able to concatenate a scanable adv with its scan response before sending it up through mgmt. With ext_adv, this is no longer necessary. general protection fault: 0000 [#1] SMP PTI CPU: 6 PID: 205 Comm: kworker/u17:0 Not tainted 5.4.0-37-generic #41-Ubuntu Hardware name: Dell Inc. XPS 15 7590/0CF6RR, BIOS 1.7.0 05/11/2020 Workqueue: hci0 hci_rx_work [bluetooth] RIP: 0010:hci_bdaddr_list_lookup+0x1e/0x40 [bluetooth] Code: ff ff e9 26 ff ff ff 0f 1f 44 00 00 0f 1f 44 00 00 55 48 8b 07 48 89 e5 48 39 c7 75 0a eb 24 48 8b 00 48 39 f8 74 1c 44 8b 06 <44> 39 40 10 75 ef 44 0f b7 4e 04 66 44 39 48 14 75 e3 38 50 16 75 RSP: 0018:ffffbc6a40493c70 EFLAGS: 00010286 RAX: 4141414141414141 RBX: 000000000000001b RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff9903e76c100f RDI: ffff9904289d4b28 RBP: ffffbc6a40493c70 R08: 0000000093570362 R09: 0000000000000000 R10: 0000000000000000 R11: ffff9904344eae38 R12: ffff9904289d4000 R13: 0000000000000000 R14: 00000000ffffffa3 R15: ffff9903e76c100f FS: 0000000000000000(0000) GS:ffff990434580000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007feed125a000 CR3: 00000001b860a003 CR4: 00000000003606e0 Call Trace: process_adv_report+0x12e/0x560 [bluetooth] hci_le_meta_evt+0x7b2/0xba0 [bluetooth] hci_event_packet+0x1c29/0x2a90 [bluetooth] hci_rx_work+0x19b/0x360 [bluetooth] process_one_work+0x1eb/0x3b0 worker_thread+0x4d/0x400 kthread+0x104/0x140 Fixes: c215e9397b00 ("Bluetooth: Process extended ADV report event") Reported-by: Andy Nguyen <theflow@google.com> Reported-by: Linus Torvalds <torvalds@linux-foundation.org> Reported-by: Balakrishna Godavarthi <bgodavar@codeaurora.org> Signed-off-by: Alain Michaud <alainm@chromium.org> Tested-by: Sonny Sasaka <sonnysasaka@chromium.org> Acked-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2020-07-28 04:48:55 +08:00
false);
}
hci_dev_unlock(hdev);
}
static void hci_le_phy_update_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb)
{
struct hci_ev_le_phy_update_complete *ev = data;
struct hci_conn *conn;
bt_dev_dbg(hdev, "status 0x%2.2x", ev->status);
if (ev->status)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (!conn)
goto unlock;
conn->le_tx_phy = ev->tx_phy;
conn->le_rx_phy = ev->rx_phy;
unlock:
hci_dev_unlock(hdev);
}
#define HCI_LE_EV_VL(_op, _func, _min_len, _max_len) \
[_op] = { \
.func = _func, \
.min_len = _min_len, \
.max_len = _max_len, \
}
#define HCI_LE_EV(_op, _func, _len) \
HCI_LE_EV_VL(_op, _func, _len, _len)
#define HCI_LE_EV_STATUS(_op, _func) \
HCI_LE_EV(_op, _func, sizeof(struct hci_ev_status))
/* Entries in this table shall have their position according to the subevent
* opcode they handle so the use of the macros above is recommend since it does
* attempt to initialize at its proper index using Designated Initializers that
* way events without a callback function can be ommited.
*/
static const struct hci_le_ev {
void (*func)(struct hci_dev *hdev, void *data, struct sk_buff *skb);
u16 min_len;
u16 max_len;
} hci_le_ev_table[U8_MAX + 1] = {
/* [0x01 = HCI_EV_LE_CONN_COMPLETE] */
HCI_LE_EV(HCI_EV_LE_CONN_COMPLETE, hci_le_conn_complete_evt,
sizeof(struct hci_ev_le_conn_complete)),
/* [0x02 = HCI_EV_LE_ADVERTISING_REPORT] */
HCI_LE_EV_VL(HCI_EV_LE_ADVERTISING_REPORT, hci_le_adv_report_evt,
sizeof(struct hci_ev_le_advertising_report),
HCI_MAX_EVENT_SIZE),
/* [0x03 = HCI_EV_LE_CONN_UPDATE_COMPLETE] */
HCI_LE_EV(HCI_EV_LE_CONN_UPDATE_COMPLETE,
hci_le_conn_update_complete_evt,
sizeof(struct hci_ev_le_conn_update_complete)),
/* [0x04 = HCI_EV_LE_REMOTE_FEAT_COMPLETE] */
HCI_LE_EV(HCI_EV_LE_REMOTE_FEAT_COMPLETE,
hci_le_remote_feat_complete_evt,
sizeof(struct hci_ev_le_remote_feat_complete)),
/* [0x05 = HCI_EV_LE_LTK_REQ] */
HCI_LE_EV(HCI_EV_LE_LTK_REQ, hci_le_ltk_request_evt,
sizeof(struct hci_ev_le_ltk_req)),
/* [0x06 = HCI_EV_LE_REMOTE_CONN_PARAM_REQ] */
HCI_LE_EV(HCI_EV_LE_REMOTE_CONN_PARAM_REQ,
hci_le_remote_conn_param_req_evt,
sizeof(struct hci_ev_le_remote_conn_param_req)),
/* [0x0a = HCI_EV_LE_ENHANCED_CONN_COMPLETE] */
HCI_LE_EV(HCI_EV_LE_ENHANCED_CONN_COMPLETE,
hci_le_enh_conn_complete_evt,
sizeof(struct hci_ev_le_enh_conn_complete)),
/* [0x0b = HCI_EV_LE_DIRECT_ADV_REPORT] */
HCI_LE_EV_VL(HCI_EV_LE_DIRECT_ADV_REPORT, hci_le_direct_adv_report_evt,
sizeof(struct hci_ev_le_direct_adv_report),
HCI_MAX_EVENT_SIZE),
/* [0x0c = HCI_EV_LE_PHY_UPDATE_COMPLETE] */
HCI_LE_EV(HCI_EV_LE_PHY_UPDATE_COMPLETE, hci_le_phy_update_evt,
sizeof(struct hci_ev_le_phy_update_complete)),
/* [0x0d = HCI_EV_LE_EXT_ADV_REPORT] */
HCI_LE_EV_VL(HCI_EV_LE_EXT_ADV_REPORT, hci_le_ext_adv_report_evt,
sizeof(struct hci_ev_le_ext_adv_report),
HCI_MAX_EVENT_SIZE),
/* [0x12 = HCI_EV_LE_EXT_ADV_SET_TERM] */
HCI_LE_EV(HCI_EV_LE_EXT_ADV_SET_TERM, hci_le_ext_adv_term_evt,
sizeof(struct hci_evt_le_ext_adv_set_term)),
};
static void hci_le_meta_evt(struct hci_dev *hdev, void *data,
struct sk_buff *skb, u16 *opcode, u8 *status,
hci_req_complete_t *req_complete,
hci_req_complete_skb_t *req_complete_skb)
{
struct hci_ev_le_meta *ev = data;
const struct hci_le_ev *subev;
bt_dev_dbg(hdev, "subevent 0x%2.2x", ev->subevent);
/* Only match event if command OGF is for LE */
if (hdev->sent_cmd &&
hci_opcode_ogf(hci_skb_opcode(hdev->sent_cmd)) == 0x08 &&
hci_skb_event(hdev->sent_cmd) == ev->subevent) {
*opcode = hci_skb_opcode(hdev->sent_cmd);
hci_req_cmd_complete(hdev, *opcode, 0x00, req_complete,
req_complete_skb);
}
subev = &hci_le_ev_table[ev->subevent];
if (!subev->func)
return;
if (skb->len < subev->min_len) {
bt_dev_err(hdev, "unexpected subevent 0x%2.2x length: %u < %u",
ev->subevent, skb->len, subev->min_len);
return;
}
/* Just warn if the length is over max_len size it still be
* possible to partially parse the event so leave to callback to
* decide if that is acceptable.
*/
if (skb->len > subev->max_len)
bt_dev_warn(hdev, "unexpected subevent 0x%2.2x length: %u > %u",
ev->subevent, skb->len, subev->max_len);
Bluetooth: Use extended LE Connection if supported This implements extended LE craete connection and enhanced LE conn complete event if the controller supports. For now it is as good as legacy LE connection and event as no new features in the extended connection is handled. < HCI Command: LE Extended Create Connection (0x08|0x0043) plen 26 Filter policy: White list is not used (0x00) Own address type: Public (0x00) Peer address type: Random (0x01) Peer address: DB:7E:2E:1D:85:E8 (Static) Initiating PHYs: 0x01 Entry 0: LE 1M Scan interval: 60.000 msec (0x0060) Scan window: 60.000 msec (0x0060) Min connection interval: 50.00 msec (0x0028) Max connection interval: 70.00 msec (0x0038) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Min connection length: 0.000 msec (0x0000) Max connection length: 0.000 msec (0x0000) > HCI Event: Command Status (0x0f) plen 4 LE Extended Create Connection (0x08|0x0043) ncmd 2 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 31 LE Enhanced Connection Complete (0x0a) Status: Success (0x00) Handle: 3585 Role: Master (0x00) Peer address type: Random (0x01) Peer address: DB:7E:2E:1D:85:E8 (Static) Local resolvable private address: 00:00:00:00:00:00 (Non-Resolvable) Peer resolvable private address: 00:00:00:00:00:00 (Non-Resolvable) Connection interval: 67.50 msec (0x0036) Connection latency: 0 (0x0000) Supervision timeout: 420 msec (0x002a) Master clock accuracy: 0x00 @ MGMT Event: Device Connected (0x000b) plen 40 LE Address: DB:7E:2E:1D:85:E8 (Static) Flags: 0x00000000 Data length: 27 Name (complete): Designer Mouse Appearance: Mouse (0x03c2) Flags: 0x05 LE Limited Discoverable Mode BR/EDR Not Supported 16-bit Service UUIDs (complete): 1 entry Human Interface Device (0x1812) Signed-off-by: Jaganath Kanakkassery <jaganathx.kanakkassery@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2018-07-07 04:50:32 +08:00
data = hci_le_ev_skb_pull(hdev, skb, ev->subevent, subev->min_len);
if (!data)
return;
subev->func(hdev, data, skb);
}
static bool hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode,
u8 event, struct sk_buff *skb)
{
struct hci_ev_cmd_complete *ev;
struct hci_event_hdr *hdr;
if (!skb)
return false;
hdr = hci_ev_skb_pull(hdev, skb, event, sizeof(*hdr));
if (!hdr)
return false;
if (event) {
if (hdr->evt != event)
return false;
return true;
}
/* Check if request ended in Command Status - no way to retrieve
* any extra parameters in this case.
*/
if (hdr->evt == HCI_EV_CMD_STATUS)
return false;
if (hdr->evt != HCI_EV_CMD_COMPLETE) {
bt_dev_err(hdev, "last event is not cmd complete (0x%2.2x)",
hdr->evt);
return false;
}
ev = hci_cc_skb_pull(hdev, skb, opcode, sizeof(*ev));
if (!ev)
return false;
if (opcode != __le16_to_cpu(ev->opcode)) {
BT_DBG("opcode doesn't match (0x%2.2x != 0x%2.2x)", opcode,
__le16_to_cpu(ev->opcode));
return false;
}
return true;
}
static void hci_store_wake_reason(struct hci_dev *hdev, u8 event,
struct sk_buff *skb)
{
struct hci_ev_le_advertising_info *adv;
struct hci_ev_le_direct_adv_info *direct_adv;
struct hci_ev_le_ext_adv_info *ext_adv;
const struct hci_ev_conn_complete *conn_complete = (void *)skb->data;
const struct hci_ev_conn_request *conn_request = (void *)skb->data;
hci_dev_lock(hdev);
/* If we are currently suspended and this is the first BT event seen,
* save the wake reason associated with the event.
*/
if (!hdev->suspended || hdev->wake_reason)
goto unlock;
/* Default to remote wake. Values for wake_reason are documented in the
* Bluez mgmt api docs.
*/
hdev->wake_reason = MGMT_WAKE_REASON_REMOTE_WAKE;
/* Once configured for remote wakeup, we should only wake up for
* reconnections. It's useful to see which device is waking us up so
* keep track of the bdaddr of the connection event that woke us up.
*/
if (event == HCI_EV_CONN_REQUEST) {
bacpy(&hdev->wake_addr, &conn_complete->bdaddr);
hdev->wake_addr_type = BDADDR_BREDR;
} else if (event == HCI_EV_CONN_COMPLETE) {
bacpy(&hdev->wake_addr, &conn_request->bdaddr);
hdev->wake_addr_type = BDADDR_BREDR;
} else if (event == HCI_EV_LE_META) {
struct hci_ev_le_meta *le_ev = (void *)skb->data;
u8 subevent = le_ev->subevent;
u8 *ptr = &skb->data[sizeof(*le_ev)];
u8 num_reports = *ptr;
if ((subevent == HCI_EV_LE_ADVERTISING_REPORT ||
subevent == HCI_EV_LE_DIRECT_ADV_REPORT ||
subevent == HCI_EV_LE_EXT_ADV_REPORT) &&
num_reports) {
adv = (void *)(ptr + 1);
direct_adv = (void *)(ptr + 1);
ext_adv = (void *)(ptr + 1);
switch (subevent) {
case HCI_EV_LE_ADVERTISING_REPORT:
bacpy(&hdev->wake_addr, &adv->bdaddr);
hdev->wake_addr_type = adv->bdaddr_type;
break;
case HCI_EV_LE_DIRECT_ADV_REPORT:
bacpy(&hdev->wake_addr, &direct_adv->bdaddr);
hdev->wake_addr_type = direct_adv->bdaddr_type;
break;
case HCI_EV_LE_EXT_ADV_REPORT:
bacpy(&hdev->wake_addr, &ext_adv->bdaddr);
hdev->wake_addr_type = ext_adv->bdaddr_type;
break;
}
}
} else {
hdev->wake_reason = MGMT_WAKE_REASON_UNEXPECTED;
}
unlock:
hci_dev_unlock(hdev);
}
#define HCI_EV_VL(_op, _func, _min_len, _max_len) \
[_op] = { \
.req = false, \
.func = _func, \
.min_len = _min_len, \
.max_len = _max_len, \
}
#define HCI_EV(_op, _func, _len) \
HCI_EV_VL(_op, _func, _len, _len)
#define HCI_EV_STATUS(_op, _func) \
HCI_EV(_op, _func, sizeof(struct hci_ev_status))
#define HCI_EV_REQ_VL(_op, _func, _min_len, _max_len) \
[_op] = { \
.req = true, \
.func_req = _func, \
.min_len = _min_len, \
.max_len = _max_len, \
}
#define HCI_EV_REQ(_op, _func, _len) \
HCI_EV_REQ_VL(_op, _func, _len, _len)
/* Entries in this table shall have their position according to the event opcode
* they handle so the use of the macros above is recommend since it does attempt
* to initialize at its proper index using Designated Initializers that way
* events without a callback function don't have entered.
*/
static const struct hci_ev {
bool req;
union {
void (*func)(struct hci_dev *hdev, void *data,
struct sk_buff *skb);
void (*func_req)(struct hci_dev *hdev, void *data,
struct sk_buff *skb, u16 *opcode, u8 *status,
hci_req_complete_t *req_complete,
hci_req_complete_skb_t *req_complete_skb);
};
u16 min_len;
u16 max_len;
} hci_ev_table[U8_MAX + 1] = {
/* [0x01 = HCI_EV_INQUIRY_COMPLETE] */
HCI_EV_STATUS(HCI_EV_INQUIRY_COMPLETE, hci_inquiry_complete_evt),
/* [0x02 = HCI_EV_INQUIRY_RESULT] */
HCI_EV_VL(HCI_EV_INQUIRY_RESULT, hci_inquiry_result_evt,
sizeof(struct hci_ev_inquiry_result), HCI_MAX_EVENT_SIZE),
/* [0x03 = HCI_EV_CONN_COMPLETE] */
HCI_EV(HCI_EV_CONN_COMPLETE, hci_conn_complete_evt,
sizeof(struct hci_ev_conn_complete)),
/* [0x04 = HCI_EV_CONN_REQUEST] */
HCI_EV(HCI_EV_CONN_REQUEST, hci_conn_request_evt,
sizeof(struct hci_ev_conn_request)),
/* [0x05 = HCI_EV_DISCONN_COMPLETE] */
HCI_EV(HCI_EV_DISCONN_COMPLETE, hci_disconn_complete_evt,
sizeof(struct hci_ev_disconn_complete)),
/* [0x06 = HCI_EV_AUTH_COMPLETE] */
HCI_EV(HCI_EV_AUTH_COMPLETE, hci_auth_complete_evt,
sizeof(struct hci_ev_auth_complete)),
/* [0x07 = HCI_EV_REMOTE_NAME] */
HCI_EV(HCI_EV_REMOTE_NAME, hci_remote_name_evt,
sizeof(struct hci_ev_remote_name)),
/* [0x08 = HCI_EV_ENCRYPT_CHANGE] */
HCI_EV(HCI_EV_ENCRYPT_CHANGE, hci_encrypt_change_evt,
sizeof(struct hci_ev_encrypt_change)),
/* [0x09 = HCI_EV_CHANGE_LINK_KEY_COMPLETE] */
HCI_EV(HCI_EV_CHANGE_LINK_KEY_COMPLETE,
hci_change_link_key_complete_evt,
sizeof(struct hci_ev_change_link_key_complete)),
/* [0x0b = HCI_EV_REMOTE_FEATURES] */
HCI_EV(HCI_EV_REMOTE_FEATURES, hci_remote_features_evt,
sizeof(struct hci_ev_remote_features)),
/* [0x0e = HCI_EV_CMD_COMPLETE] */
HCI_EV_REQ_VL(HCI_EV_CMD_COMPLETE, hci_cmd_complete_evt,
sizeof(struct hci_ev_cmd_complete), HCI_MAX_EVENT_SIZE),
/* [0x0f = HCI_EV_CMD_STATUS] */
HCI_EV_REQ(HCI_EV_CMD_STATUS, hci_cmd_status_evt,
sizeof(struct hci_ev_cmd_status)),
/* [0x10 = HCI_EV_CMD_STATUS] */
HCI_EV(HCI_EV_HARDWARE_ERROR, hci_hardware_error_evt,
sizeof(struct hci_ev_hardware_error)),
/* [0x12 = HCI_EV_ROLE_CHANGE] */
HCI_EV(HCI_EV_ROLE_CHANGE, hci_role_change_evt,
sizeof(struct hci_ev_role_change)),
/* [0x13 = HCI_EV_NUM_COMP_PKTS] */
HCI_EV_VL(HCI_EV_NUM_COMP_PKTS, hci_num_comp_pkts_evt,
sizeof(struct hci_ev_num_comp_pkts), HCI_MAX_EVENT_SIZE),
/* [0x14 = HCI_EV_MODE_CHANGE] */
HCI_EV(HCI_EV_MODE_CHANGE, hci_mode_change_evt,
sizeof(struct hci_ev_mode_change)),
/* [0x16 = HCI_EV_PIN_CODE_REQ] */
HCI_EV(HCI_EV_PIN_CODE_REQ, hci_pin_code_request_evt,
sizeof(struct hci_ev_pin_code_req)),
/* [0x17 = HCI_EV_LINK_KEY_REQ] */
HCI_EV(HCI_EV_LINK_KEY_REQ, hci_link_key_request_evt,
sizeof(struct hci_ev_link_key_req)),
/* [0x18 = HCI_EV_LINK_KEY_NOTIFY] */
HCI_EV(HCI_EV_LINK_KEY_NOTIFY, hci_link_key_notify_evt,
sizeof(struct hci_ev_link_key_notify)),
/* [0x1c = HCI_EV_CLOCK_OFFSET] */
HCI_EV(HCI_EV_CLOCK_OFFSET, hci_clock_offset_evt,
sizeof(struct hci_ev_clock_offset)),
/* [0x1d = HCI_EV_PKT_TYPE_CHANGE] */
HCI_EV(HCI_EV_PKT_TYPE_CHANGE, hci_pkt_type_change_evt,
sizeof(struct hci_ev_pkt_type_change)),
/* [0x20 = HCI_EV_PSCAN_REP_MODE] */
HCI_EV(HCI_EV_PSCAN_REP_MODE, hci_pscan_rep_mode_evt,
sizeof(struct hci_ev_pscan_rep_mode)),
/* [0x22 = HCI_EV_INQUIRY_RESULT_WITH_RSSI] */
HCI_EV_VL(HCI_EV_INQUIRY_RESULT_WITH_RSSI,
hci_inquiry_result_with_rssi_evt,
sizeof(struct hci_ev_inquiry_result_rssi),
HCI_MAX_EVENT_SIZE),
/* [0x23 = HCI_EV_REMOTE_EXT_FEATURES] */
HCI_EV(HCI_EV_REMOTE_EXT_FEATURES, hci_remote_ext_features_evt,
sizeof(struct hci_ev_remote_ext_features)),
/* [0x2c = HCI_EV_SYNC_CONN_COMPLETE] */
HCI_EV(HCI_EV_SYNC_CONN_COMPLETE, hci_sync_conn_complete_evt,
sizeof(struct hci_ev_sync_conn_complete)),
/* [0x2d = HCI_EV_EXTENDED_INQUIRY_RESULT] */
HCI_EV_VL(HCI_EV_EXTENDED_INQUIRY_RESULT,
hci_extended_inquiry_result_evt,
sizeof(struct hci_ev_ext_inquiry_result), HCI_MAX_EVENT_SIZE),
/* [0x30 = HCI_EV_KEY_REFRESH_COMPLETE] */
HCI_EV(HCI_EV_KEY_REFRESH_COMPLETE, hci_key_refresh_complete_evt,
sizeof(struct hci_ev_key_refresh_complete)),
/* [0x31 = HCI_EV_IO_CAPA_REQUEST] */
HCI_EV(HCI_EV_IO_CAPA_REQUEST, hci_io_capa_request_evt,
sizeof(struct hci_ev_io_capa_request)),
/* [0x32 = HCI_EV_IO_CAPA_REPLY] */
HCI_EV(HCI_EV_IO_CAPA_REPLY, hci_io_capa_reply_evt,
sizeof(struct hci_ev_io_capa_reply)),
/* [0x33 = HCI_EV_USER_CONFIRM_REQUEST] */
HCI_EV(HCI_EV_USER_CONFIRM_REQUEST, hci_user_confirm_request_evt,
sizeof(struct hci_ev_user_confirm_req)),
/* [0x34 = HCI_EV_USER_PASSKEY_REQUEST] */
HCI_EV(HCI_EV_USER_PASSKEY_REQUEST, hci_user_passkey_request_evt,
sizeof(struct hci_ev_user_passkey_req)),
/* [0x35 = HCI_EV_REMOTE_OOB_DATA_REQUEST] */
HCI_EV(HCI_EV_REMOTE_OOB_DATA_REQUEST, hci_remote_oob_data_request_evt,
sizeof(struct hci_ev_remote_oob_data_request)),
/* [0x36 = HCI_EV_SIMPLE_PAIR_COMPLETE] */
HCI_EV(HCI_EV_SIMPLE_PAIR_COMPLETE, hci_simple_pair_complete_evt,
sizeof(struct hci_ev_simple_pair_complete)),
/* [0x3b = HCI_EV_USER_PASSKEY_NOTIFY] */
HCI_EV(HCI_EV_USER_PASSKEY_NOTIFY, hci_user_passkey_notify_evt,
sizeof(struct hci_ev_user_passkey_notify)),
/* [0x3c = HCI_EV_KEYPRESS_NOTIFY] */
HCI_EV(HCI_EV_KEYPRESS_NOTIFY, hci_keypress_notify_evt,
sizeof(struct hci_ev_keypress_notify)),
/* [0x3d = HCI_EV_REMOTE_HOST_FEATURES] */
HCI_EV(HCI_EV_REMOTE_HOST_FEATURES, hci_remote_host_features_evt,
sizeof(struct hci_ev_remote_host_features)),
/* [0x3e = HCI_EV_LE_META] */
HCI_EV_REQ_VL(HCI_EV_LE_META, hci_le_meta_evt,
sizeof(struct hci_ev_le_meta), HCI_MAX_EVENT_SIZE),
#if IS_ENABLED(CONFIG_BT_HS)
/* [0x40 = HCI_EV_PHY_LINK_COMPLETE] */
HCI_EV(HCI_EV_PHY_LINK_COMPLETE, hci_phy_link_complete_evt,
sizeof(struct hci_ev_phy_link_complete)),
/* [0x41 = HCI_EV_CHANNEL_SELECTED] */
HCI_EV(HCI_EV_CHANNEL_SELECTED, hci_chan_selected_evt,
sizeof(struct hci_ev_channel_selected)),
/* [0x42 = HCI_EV_DISCONN_PHY_LINK_COMPLETE] */
HCI_EV(HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE,
hci_disconn_loglink_complete_evt,
sizeof(struct hci_ev_disconn_logical_link_complete)),
/* [0x45 = HCI_EV_LOGICAL_LINK_COMPLETE] */
HCI_EV(HCI_EV_LOGICAL_LINK_COMPLETE, hci_loglink_complete_evt,
sizeof(struct hci_ev_logical_link_complete)),
/* [0x46 = HCI_EV_DISCONN_LOGICAL_LINK_COMPLETE] */
HCI_EV(HCI_EV_DISCONN_PHY_LINK_COMPLETE,
hci_disconn_phylink_complete_evt,
sizeof(struct hci_ev_disconn_phy_link_complete)),
#endif
/* [0x48 = HCI_EV_NUM_COMP_BLOCKS] */
HCI_EV(HCI_EV_NUM_COMP_BLOCKS, hci_num_comp_blocks_evt,
sizeof(struct hci_ev_num_comp_blocks)),
/* [0xff = HCI_EV_VENDOR] */
HCI_EV_VL(HCI_EV_VENDOR, msft_vendor_evt, 0, HCI_MAX_EVENT_SIZE),
};
static void hci_event_func(struct hci_dev *hdev, u8 event, struct sk_buff *skb,
u16 *opcode, u8 *status,
hci_req_complete_t *req_complete,
hci_req_complete_skb_t *req_complete_skb)
{
const struct hci_ev *ev = &hci_ev_table[event];
void *data;
if (!ev->func)
return;
if (skb->len < ev->min_len) {
bt_dev_err(hdev, "unexpected event 0x%2.2x length: %u < %u",
event, skb->len, ev->min_len);
return;
}
/* Just warn if the length is over max_len size it still be
* possible to partially parse the event so leave to callback to
* decide if that is acceptable.
*/
if (skb->len > ev->max_len)
bt_dev_warn_ratelimited(hdev,
"unexpected event 0x%2.2x length: %u > %u",
event, skb->len, ev->max_len);
data = hci_ev_skb_pull(hdev, skb, event, ev->min_len);
if (!data)
return;
if (ev->req)
ev->func_req(hdev, data, skb, opcode, status, req_complete,
req_complete_skb);
else
ev->func(hdev, data, skb);
}
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_event_hdr *hdr = (void *) skb->data;
hci_req_complete_t req_complete = NULL;
hci_req_complete_skb_t req_complete_skb = NULL;
struct sk_buff *orig_skb = NULL;
u8 status = 0, event, req_evt = 0;
u16 opcode = HCI_OP_NOP;
if (skb->len < sizeof(*hdr)) {
bt_dev_err(hdev, "Malformed HCI Event");
goto done;
}
event = hdr->evt;
if (!event) {
bt_dev_warn(hdev, "Received unexpected HCI Event 0x%2.2x",
event);
goto done;
}
/* Only match event if command OGF is not for LE */
if (hdev->sent_cmd &&
hci_opcode_ogf(hci_skb_opcode(hdev->sent_cmd)) != 0x08 &&
hci_skb_event(hdev->sent_cmd) == event) {
hci_req_cmd_complete(hdev, hci_skb_opcode(hdev->sent_cmd),
status, &req_complete, &req_complete_skb);
req_evt = event;
}
/* If it looks like we might end up having to call
* req_complete_skb, store a pristine copy of the skb since the
* various handlers may modify the original one through
* skb_pull() calls, etc.
*/
if (req_complete_skb || event == HCI_EV_CMD_STATUS ||
event == HCI_EV_CMD_COMPLETE)
orig_skb = skb_clone(skb, GFP_KERNEL);
skb_pull(skb, HCI_EVENT_HDR_SIZE);
/* Store wake reason if we're suspended */
hci_store_wake_reason(hdev, event, skb);
bt_dev_dbg(hdev, "event 0x%2.2x", event);
hci_event_func(hdev, event, skb, &opcode, &status, &req_complete,
&req_complete_skb);
if (req_complete) {
req_complete(hdev, status, opcode);
} else if (req_complete_skb) {
if (!hci_get_cmd_complete(hdev, opcode, req_evt, orig_skb)) {
kfree_skb(orig_skb);
orig_skb = NULL;
}
req_complete_skb(hdev, status, opcode, orig_skb);
}
done:
kfree_skb(orig_skb);
kfree_skb(skb);
hdev->stat.evt_rx++;
}