linux-stable/net/bluetooth/mgmt.c

10467 lines
263 KiB
C
Raw Normal View History

/*
BlueZ - Bluetooth protocol stack for Linux
Copyright (C) 2010 Nokia Corporation
Copyright (C) 2011-2012 Intel Corporation
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 Management interface */
#include <linux/module.h>
#include <asm/unaligned.h>
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include <net/bluetooth/hci_sock.h>
#include <net/bluetooth/l2cap.h>
#include <net/bluetooth/mgmt.h>
#include "hci_request.h"
#include "smp.h"
#include "mgmt_util.h"
#include "mgmt_config.h"
#include "msft.h"
#include "eir.h"
#include "aosp.h"
#define MGMT_VERSION 1
#define MGMT_REVISION 22
static const u16 mgmt_commands[] = {
MGMT_OP_READ_INDEX_LIST,
MGMT_OP_READ_INFO,
MGMT_OP_SET_POWERED,
MGMT_OP_SET_DISCOVERABLE,
MGMT_OP_SET_CONNECTABLE,
MGMT_OP_SET_FAST_CONNECTABLE,
MGMT_OP_SET_BONDABLE,
MGMT_OP_SET_LINK_SECURITY,
MGMT_OP_SET_SSP,
MGMT_OP_SET_HS,
MGMT_OP_SET_LE,
MGMT_OP_SET_DEV_CLASS,
MGMT_OP_SET_LOCAL_NAME,
MGMT_OP_ADD_UUID,
MGMT_OP_REMOVE_UUID,
MGMT_OP_LOAD_LINK_KEYS,
MGMT_OP_LOAD_LONG_TERM_KEYS,
MGMT_OP_DISCONNECT,
MGMT_OP_GET_CONNECTIONS,
MGMT_OP_PIN_CODE_REPLY,
MGMT_OP_PIN_CODE_NEG_REPLY,
MGMT_OP_SET_IO_CAPABILITY,
MGMT_OP_PAIR_DEVICE,
MGMT_OP_CANCEL_PAIR_DEVICE,
MGMT_OP_UNPAIR_DEVICE,
MGMT_OP_USER_CONFIRM_REPLY,
MGMT_OP_USER_CONFIRM_NEG_REPLY,
MGMT_OP_USER_PASSKEY_REPLY,
MGMT_OP_USER_PASSKEY_NEG_REPLY,
MGMT_OP_READ_LOCAL_OOB_DATA,
MGMT_OP_ADD_REMOTE_OOB_DATA,
MGMT_OP_REMOVE_REMOTE_OOB_DATA,
MGMT_OP_START_DISCOVERY,
MGMT_OP_STOP_DISCOVERY,
MGMT_OP_CONFIRM_NAME,
MGMT_OP_BLOCK_DEVICE,
MGMT_OP_UNBLOCK_DEVICE,
MGMT_OP_SET_DEVICE_ID,
MGMT_OP_SET_ADVERTISING,
MGMT_OP_SET_BREDR,
MGMT_OP_SET_STATIC_ADDRESS,
MGMT_OP_SET_SCAN_PARAMS,
MGMT_OP_SET_SECURE_CONN,
MGMT_OP_SET_DEBUG_KEYS,
MGMT_OP_SET_PRIVACY,
MGMT_OP_LOAD_IRKS,
MGMT_OP_GET_CONN_INFO,
MGMT_OP_GET_CLOCK_INFO,
MGMT_OP_ADD_DEVICE,
MGMT_OP_REMOVE_DEVICE,
MGMT_OP_LOAD_CONN_PARAM,
MGMT_OP_READ_UNCONF_INDEX_LIST,
MGMT_OP_READ_CONFIG_INFO,
MGMT_OP_SET_EXTERNAL_CONFIG,
MGMT_OP_SET_PUBLIC_ADDRESS,
MGMT_OP_START_SERVICE_DISCOVERY,
MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
MGMT_OP_READ_EXT_INDEX_LIST,
MGMT_OP_READ_ADV_FEATURES,
MGMT_OP_ADD_ADVERTISING,
MGMT_OP_REMOVE_ADVERTISING,
MGMT_OP_GET_ADV_SIZE_INFO,
MGMT_OP_START_LIMITED_DISCOVERY,
MGMT_OP_READ_EXT_INFO,
MGMT_OP_SET_APPEARANCE,
MGMT_OP_GET_PHY_CONFIGURATION,
MGMT_OP_SET_PHY_CONFIGURATION,
MGMT_OP_SET_BLOCKED_KEYS,
MGMT_OP_SET_WIDEBAND_SPEECH,
MGMT_OP_READ_CONTROLLER_CAP,
MGMT_OP_READ_EXP_FEATURES_INFO,
MGMT_OP_SET_EXP_FEATURE,
MGMT_OP_READ_DEF_SYSTEM_CONFIG,
MGMT_OP_SET_DEF_SYSTEM_CONFIG,
MGMT_OP_READ_DEF_RUNTIME_CONFIG,
MGMT_OP_SET_DEF_RUNTIME_CONFIG,
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
MGMT_OP_GET_DEVICE_FLAGS,
MGMT_OP_SET_DEVICE_FLAGS,
MGMT_OP_READ_ADV_MONITOR_FEATURES,
MGMT_OP_ADD_ADV_PATTERNS_MONITOR,
MGMT_OP_REMOVE_ADV_MONITOR,
MGMT_OP_ADD_EXT_ADV_PARAMS,
MGMT_OP_ADD_EXT_ADV_DATA,
MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI,
MGMT_OP_SET_MESH_RECEIVER,
MGMT_OP_MESH_READ_FEATURES,
MGMT_OP_MESH_SEND,
MGMT_OP_MESH_SEND_CANCEL,
};
static const u16 mgmt_events[] = {
MGMT_EV_CONTROLLER_ERROR,
MGMT_EV_INDEX_ADDED,
MGMT_EV_INDEX_REMOVED,
MGMT_EV_NEW_SETTINGS,
MGMT_EV_CLASS_OF_DEV_CHANGED,
MGMT_EV_LOCAL_NAME_CHANGED,
MGMT_EV_NEW_LINK_KEY,
MGMT_EV_NEW_LONG_TERM_KEY,
MGMT_EV_DEVICE_CONNECTED,
MGMT_EV_DEVICE_DISCONNECTED,
MGMT_EV_CONNECT_FAILED,
MGMT_EV_PIN_CODE_REQUEST,
MGMT_EV_USER_CONFIRM_REQUEST,
MGMT_EV_USER_PASSKEY_REQUEST,
MGMT_EV_AUTH_FAILED,
MGMT_EV_DEVICE_FOUND,
MGMT_EV_DISCOVERING,
MGMT_EV_DEVICE_BLOCKED,
MGMT_EV_DEVICE_UNBLOCKED,
MGMT_EV_DEVICE_UNPAIRED,
MGMT_EV_PASSKEY_NOTIFY,
MGMT_EV_NEW_IRK,
MGMT_EV_NEW_CSRK,
MGMT_EV_DEVICE_ADDED,
MGMT_EV_DEVICE_REMOVED,
MGMT_EV_NEW_CONN_PARAM,
MGMT_EV_UNCONF_INDEX_ADDED,
MGMT_EV_UNCONF_INDEX_REMOVED,
MGMT_EV_NEW_CONFIG_OPTIONS,
MGMT_EV_EXT_INDEX_ADDED,
MGMT_EV_EXT_INDEX_REMOVED,
MGMT_EV_LOCAL_OOB_DATA_UPDATED,
MGMT_EV_ADVERTISING_ADDED,
MGMT_EV_ADVERTISING_REMOVED,
MGMT_EV_EXT_INFO_CHANGED,
MGMT_EV_PHY_CONFIGURATION_CHANGED,
MGMT_EV_EXP_FEATURE_CHANGED,
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
MGMT_EV_DEVICE_FLAGS_CHANGED,
MGMT_EV_ADV_MONITOR_ADDED,
MGMT_EV_ADV_MONITOR_REMOVED,
MGMT_EV_CONTROLLER_SUSPEND,
MGMT_EV_CONTROLLER_RESUME,
MGMT_EV_ADV_MONITOR_DEVICE_FOUND,
MGMT_EV_ADV_MONITOR_DEVICE_LOST,
};
static const u16 mgmt_untrusted_commands[] = {
MGMT_OP_READ_INDEX_LIST,
MGMT_OP_READ_INFO,
MGMT_OP_READ_UNCONF_INDEX_LIST,
MGMT_OP_READ_CONFIG_INFO,
MGMT_OP_READ_EXT_INDEX_LIST,
MGMT_OP_READ_EXT_INFO,
MGMT_OP_READ_CONTROLLER_CAP,
MGMT_OP_READ_EXP_FEATURES_INFO,
MGMT_OP_READ_DEF_SYSTEM_CONFIG,
MGMT_OP_READ_DEF_RUNTIME_CONFIG,
};
static const u16 mgmt_untrusted_events[] = {
MGMT_EV_INDEX_ADDED,
MGMT_EV_INDEX_REMOVED,
MGMT_EV_NEW_SETTINGS,
MGMT_EV_CLASS_OF_DEV_CHANGED,
MGMT_EV_LOCAL_NAME_CHANGED,
MGMT_EV_UNCONF_INDEX_ADDED,
MGMT_EV_UNCONF_INDEX_REMOVED,
MGMT_EV_NEW_CONFIG_OPTIONS,
MGMT_EV_EXT_INDEX_ADDED,
MGMT_EV_EXT_INDEX_REMOVED,
MGMT_EV_EXT_INFO_CHANGED,
MGMT_EV_EXP_FEATURE_CHANGED,
};
#define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000)
#define ZERO_KEY "\x00\x00\x00\x00\x00\x00\x00\x00" \
"\x00\x00\x00\x00\x00\x00\x00\x00"
/* HCI to MGMT error code conversion table */
static const u8 mgmt_status_table[] = {
MGMT_STATUS_SUCCESS,
MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
MGMT_STATUS_NOT_CONNECTED, /* No Connection */
MGMT_STATUS_FAILED, /* Hardware Failure */
MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */
MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */
MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */
MGMT_STATUS_NO_RESOURCES, /* Memory Full */
MGMT_STATUS_TIMEOUT, /* Connection Timeout */
MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */
MGMT_STATUS_NO_RESOURCES, /* Max Number of SCO Connections */
MGMT_STATUS_ALREADY_CONNECTED, /* ACL Connection Exists */
MGMT_STATUS_BUSY, /* Command Disallowed */
MGMT_STATUS_NO_RESOURCES, /* Rejected Limited Resources */
MGMT_STATUS_REJECTED, /* Rejected Security */
MGMT_STATUS_REJECTED, /* Rejected Personal */
MGMT_STATUS_TIMEOUT, /* Host Timeout */
MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Feature */
MGMT_STATUS_INVALID_PARAMS, /* Invalid Parameters */
MGMT_STATUS_DISCONNECTED, /* OE User Ended Connection */
MGMT_STATUS_NO_RESOURCES, /* OE Low Resources */
MGMT_STATUS_DISCONNECTED, /* OE Power Off */
MGMT_STATUS_DISCONNECTED, /* Connection Terminated */
MGMT_STATUS_BUSY, /* Repeated Attempts */
MGMT_STATUS_REJECTED, /* Pairing Not Allowed */
MGMT_STATUS_FAILED, /* Unknown LMP PDU */
MGMT_STATUS_NOT_SUPPORTED, /* Unsupported Remote Feature */
MGMT_STATUS_REJECTED, /* SCO Offset Rejected */
MGMT_STATUS_REJECTED, /* SCO Interval Rejected */
MGMT_STATUS_REJECTED, /* Air Mode Rejected */
MGMT_STATUS_INVALID_PARAMS, /* Invalid LMP Parameters */
MGMT_STATUS_FAILED, /* Unspecified Error */
MGMT_STATUS_NOT_SUPPORTED, /* Unsupported LMP Parameter Value */
MGMT_STATUS_FAILED, /* Role Change Not Allowed */
MGMT_STATUS_TIMEOUT, /* LMP Response Timeout */
MGMT_STATUS_FAILED, /* LMP Error Transaction Collision */
MGMT_STATUS_FAILED, /* LMP PDU Not Allowed */
MGMT_STATUS_REJECTED, /* Encryption Mode Not Accepted */
MGMT_STATUS_FAILED, /* Unit Link Key Used */
MGMT_STATUS_NOT_SUPPORTED, /* QoS Not Supported */
MGMT_STATUS_TIMEOUT, /* Instant Passed */
MGMT_STATUS_NOT_SUPPORTED, /* Pairing Not Supported */
MGMT_STATUS_FAILED, /* Transaction Collision */
MGMT_STATUS_FAILED, /* Reserved for future use */
MGMT_STATUS_INVALID_PARAMS, /* Unacceptable Parameter */
MGMT_STATUS_REJECTED, /* QoS Rejected */
MGMT_STATUS_NOT_SUPPORTED, /* Classification Not Supported */
MGMT_STATUS_REJECTED, /* Insufficient Security */
MGMT_STATUS_INVALID_PARAMS, /* Parameter Out Of Range */
MGMT_STATUS_FAILED, /* Reserved for future use */
MGMT_STATUS_BUSY, /* Role Switch Pending */
MGMT_STATUS_FAILED, /* Reserved for future use */
MGMT_STATUS_FAILED, /* Slot Violation */
MGMT_STATUS_FAILED, /* Role Switch Failed */
MGMT_STATUS_INVALID_PARAMS, /* EIR Too Large */
MGMT_STATUS_NOT_SUPPORTED, /* Simple Pairing Not Supported */
MGMT_STATUS_BUSY, /* Host Busy Pairing */
MGMT_STATUS_REJECTED, /* Rejected, No Suitable Channel */
MGMT_STATUS_BUSY, /* Controller Busy */
MGMT_STATUS_INVALID_PARAMS, /* Unsuitable Connection Interval */
MGMT_STATUS_TIMEOUT, /* Directed Advertising Timeout */
MGMT_STATUS_AUTH_FAILED, /* Terminated Due to MIC Failure */
MGMT_STATUS_CONNECT_FAILED, /* Connection Establishment Failed */
MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */
};
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
static u8 mgmt_errno_status(int err)
{
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
switch (err) {
case 0:
return MGMT_STATUS_SUCCESS;
case -EPERM:
return MGMT_STATUS_REJECTED;
case -EINVAL:
return MGMT_STATUS_INVALID_PARAMS;
case -EOPNOTSUPP:
return MGMT_STATUS_NOT_SUPPORTED;
case -EBUSY:
return MGMT_STATUS_BUSY;
case -ETIMEDOUT:
return MGMT_STATUS_AUTH_FAILED;
case -ENOMEM:
return MGMT_STATUS_NO_RESOURCES;
case -EISCONN:
return MGMT_STATUS_ALREADY_CONNECTED;
case -ENOTCONN:
return MGMT_STATUS_DISCONNECTED;
}
return MGMT_STATUS_FAILED;
}
static u8 mgmt_status(int err)
{
if (err < 0)
return mgmt_errno_status(err);
if (err < ARRAY_SIZE(mgmt_status_table))
return mgmt_status_table[err];
return MGMT_STATUS_FAILED;
}
static int mgmt_index_event(u16 event, struct hci_dev *hdev, void *data,
u16 len, int flag)
{
return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
flag, NULL);
}
static int mgmt_limited_event(u16 event, struct hci_dev *hdev, void *data,
u16 len, int flag, struct sock *skip_sk)
{
return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
flag, skip_sk);
}
static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 len,
struct sock *skip_sk)
{
return mgmt_send_event(event, hdev, HCI_CHANNEL_CONTROL, data, len,
HCI_SOCK_TRUSTED, skip_sk);
}
static int mgmt_event_skb(struct sk_buff *skb, struct sock *skip_sk)
{
return mgmt_send_event_skb(HCI_CHANNEL_CONTROL, skb, HCI_SOCK_TRUSTED,
skip_sk);
}
static u8 le_addr_type(u8 mgmt_addr_type)
{
if (mgmt_addr_type == BDADDR_LE_PUBLIC)
return ADDR_LE_DEV_PUBLIC;
else
return ADDR_LE_DEV_RANDOM;
}
void mgmt_fill_version_info(void *ver)
{
struct mgmt_rp_read_version *rp = ver;
rp->version = MGMT_VERSION;
rp->revision = cpu_to_le16(MGMT_REVISION);
}
static int read_version(struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len)
{
struct mgmt_rp_read_version rp;
bt_dev_dbg(hdev, "sock %p", sk);
mgmt_fill_version_info(&rp);
return mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0,
&rp, sizeof(rp));
}
static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len)
{
struct mgmt_rp_read_commands *rp;
u16 num_commands, num_events;
size_t rp_size;
int i, err;
bt_dev_dbg(hdev, "sock %p", sk);
if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
num_commands = ARRAY_SIZE(mgmt_commands);
num_events = ARRAY_SIZE(mgmt_events);
} else {
num_commands = ARRAY_SIZE(mgmt_untrusted_commands);
num_events = ARRAY_SIZE(mgmt_untrusted_events);
}
rp_size = sizeof(*rp) + ((num_commands + num_events) * sizeof(u16));
rp = kmalloc(rp_size, GFP_KERNEL);
if (!rp)
return -ENOMEM;
rp->num_commands = cpu_to_le16(num_commands);
rp->num_events = cpu_to_le16(num_events);
if (hci_sock_test_flag(sk, HCI_SOCK_TRUSTED)) {
__le16 *opcode = rp->opcodes;
for (i = 0; i < num_commands; i++, opcode++)
put_unaligned_le16(mgmt_commands[i], opcode);
for (i = 0; i < num_events; i++, opcode++)
put_unaligned_le16(mgmt_events[i], opcode);
} else {
__le16 *opcode = rp->opcodes;
for (i = 0; i < num_commands; i++, opcode++)
put_unaligned_le16(mgmt_untrusted_commands[i], opcode);
for (i = 0; i < num_events; i++, opcode++)
put_unaligned_le16(mgmt_untrusted_events[i], opcode);
}
err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_COMMANDS, 0,
rp, rp_size);
kfree(rp);
return err;
}
static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len)
{
struct mgmt_rp_read_index_list *rp;
struct hci_dev *d;
size_t rp_len;
u16 count;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
read_lock(&hci_dev_list_lock);
count = 0;
list_for_each_entry(d, &hci_dev_list, list) {
if (!hci_dev_test_flag(d, HCI_UNCONFIGURED))
count++;
}
rp_len = sizeof(*rp) + (2 * count);
rp = kmalloc(rp_len, GFP_ATOMIC);
if (!rp) {
read_unlock(&hci_dev_list_lock);
return -ENOMEM;
}
count = 0;
list_for_each_entry(d, &hci_dev_list, list) {
if (hci_dev_test_flag(d, HCI_SETUP) ||
hci_dev_test_flag(d, HCI_CONFIG) ||
hci_dev_test_flag(d, HCI_USER_CHANNEL))
continue;
/* Devices marked as raw-only are neither configured
* nor unconfigured controllers.
*/
if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
continue;
if (!hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
rp->index[count++] = cpu_to_le16(d->id);
bt_dev_dbg(hdev, "Added hci%u", d->id);
}
}
rp->num_controllers = cpu_to_le16(count);
rp_len = sizeof(*rp) + (2 * count);
read_unlock(&hci_dev_list_lock);
err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST,
0, rp, rp_len);
kfree(rp);
return err;
}
static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
struct mgmt_rp_read_unconf_index_list *rp;
struct hci_dev *d;
size_t rp_len;
u16 count;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
read_lock(&hci_dev_list_lock);
count = 0;
list_for_each_entry(d, &hci_dev_list, list) {
if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
count++;
}
rp_len = sizeof(*rp) + (2 * count);
rp = kmalloc(rp_len, GFP_ATOMIC);
if (!rp) {
read_unlock(&hci_dev_list_lock);
return -ENOMEM;
}
count = 0;
list_for_each_entry(d, &hci_dev_list, list) {
if (hci_dev_test_flag(d, HCI_SETUP) ||
hci_dev_test_flag(d, HCI_CONFIG) ||
hci_dev_test_flag(d, HCI_USER_CHANNEL))
continue;
/* Devices marked as raw-only are neither configured
* nor unconfigured controllers.
*/
if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
continue;
if (hci_dev_test_flag(d, HCI_UNCONFIGURED)) {
rp->index[count++] = cpu_to_le16(d->id);
bt_dev_dbg(hdev, "Added hci%u", d->id);
}
}
rp->num_controllers = cpu_to_le16(count);
rp_len = sizeof(*rp) + (2 * count);
read_unlock(&hci_dev_list_lock);
err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
MGMT_OP_READ_UNCONF_INDEX_LIST, 0, rp, rp_len);
kfree(rp);
return err;
}
static int read_ext_index_list(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
struct mgmt_rp_read_ext_index_list *rp;
struct hci_dev *d;
u16 count;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
read_lock(&hci_dev_list_lock);
count = 0;
list_for_each_entry(d, &hci_dev_list, list)
count++;
rp = kmalloc(struct_size(rp, entry, count), GFP_ATOMIC);
if (!rp) {
read_unlock(&hci_dev_list_lock);
return -ENOMEM;
}
count = 0;
list_for_each_entry(d, &hci_dev_list, list) {
if (hci_dev_test_flag(d, HCI_SETUP) ||
hci_dev_test_flag(d, HCI_CONFIG) ||
hci_dev_test_flag(d, HCI_USER_CHANNEL))
continue;
/* Devices marked as raw-only are neither configured
* nor unconfigured controllers.
*/
if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks))
continue;
if (hci_dev_test_flag(d, HCI_UNCONFIGURED))
rp->entry[count].type = 0x01;
else
rp->entry[count].type = 0x00;
rp->entry[count].bus = d->bus;
rp->entry[count++].index = cpu_to_le16(d->id);
bt_dev_dbg(hdev, "Added hci%u", d->id);
}
rp->num_controllers = cpu_to_le16(count);
read_unlock(&hci_dev_list_lock);
/* If this command is called at least once, then all the
* default index and unconfigured index events are disabled
* and from now on only extended index events are used.
*/
hci_sock_set_flag(sk, HCI_MGMT_EXT_INDEX_EVENTS);
hci_sock_clear_flag(sk, HCI_MGMT_INDEX_EVENTS);
hci_sock_clear_flag(sk, HCI_MGMT_UNCONF_INDEX_EVENTS);
err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
MGMT_OP_READ_EXT_INDEX_LIST, 0, rp,
struct_size(rp, entry, count));
kfree(rp);
return err;
}
static bool is_configured(struct hci_dev *hdev)
{
if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
!hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
return false;
if ((test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) ||
test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) &&
!bacmp(&hdev->public_addr, BDADDR_ANY))
return false;
return true;
}
static __le32 get_missing_options(struct hci_dev *hdev)
{
u32 options = 0;
if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) &&
!hci_dev_test_flag(hdev, HCI_EXT_CONFIGURED))
options |= MGMT_OPTION_EXTERNAL_CONFIG;
if ((test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) ||
test_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks)) &&
!bacmp(&hdev->public_addr, BDADDR_ANY))
options |= MGMT_OPTION_PUBLIC_ADDRESS;
return cpu_to_le32(options);
}
static int new_options(struct hci_dev *hdev, struct sock *skip)
{
__le32 options = get_missing_options(hdev);
return mgmt_limited_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options,
sizeof(options), HCI_MGMT_OPTION_EVENTS, skip);
}
static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
{
__le32 options = get_missing_options(hdev);
return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &options,
sizeof(options));
}
static int read_config_info(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
struct mgmt_rp_read_config_info rp;
u32 options = 0;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
memset(&rp, 0, sizeof(rp));
rp.manufacturer = cpu_to_le16(hdev->manufacturer);
if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
options |= MGMT_OPTION_EXTERNAL_CONFIG;
if (hdev->set_bdaddr)
options |= MGMT_OPTION_PUBLIC_ADDRESS;
rp.supported_options = cpu_to_le32(options);
rp.missing_options = get_missing_options(hdev);
hci_dev_unlock(hdev);
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0,
&rp, sizeof(rp));
}
static u32 get_supported_phys(struct hci_dev *hdev)
{
u32 supported_phys = 0;
if (lmp_bredr_capable(hdev)) {
supported_phys |= MGMT_PHY_BR_1M_1SLOT;
if (hdev->features[0][0] & LMP_3SLOT)
supported_phys |= MGMT_PHY_BR_1M_3SLOT;
if (hdev->features[0][0] & LMP_5SLOT)
supported_phys |= MGMT_PHY_BR_1M_5SLOT;
if (lmp_edr_2m_capable(hdev)) {
supported_phys |= MGMT_PHY_EDR_2M_1SLOT;
if (lmp_edr_3slot_capable(hdev))
supported_phys |= MGMT_PHY_EDR_2M_3SLOT;
if (lmp_edr_5slot_capable(hdev))
supported_phys |= MGMT_PHY_EDR_2M_5SLOT;
if (lmp_edr_3m_capable(hdev)) {
supported_phys |= MGMT_PHY_EDR_3M_1SLOT;
if (lmp_edr_3slot_capable(hdev))
supported_phys |= MGMT_PHY_EDR_3M_3SLOT;
if (lmp_edr_5slot_capable(hdev))
supported_phys |= MGMT_PHY_EDR_3M_5SLOT;
}
}
}
if (lmp_le_capable(hdev)) {
supported_phys |= MGMT_PHY_LE_1M_TX;
supported_phys |= MGMT_PHY_LE_1M_RX;
if (hdev->le_features[1] & HCI_LE_PHY_2M) {
supported_phys |= MGMT_PHY_LE_2M_TX;
supported_phys |= MGMT_PHY_LE_2M_RX;
}
if (hdev->le_features[1] & HCI_LE_PHY_CODED) {
supported_phys |= MGMT_PHY_LE_CODED_TX;
supported_phys |= MGMT_PHY_LE_CODED_RX;
}
}
return supported_phys;
}
static u32 get_selected_phys(struct hci_dev *hdev)
{
u32 selected_phys = 0;
if (lmp_bredr_capable(hdev)) {
selected_phys |= MGMT_PHY_BR_1M_1SLOT;
if (hdev->pkt_type & (HCI_DM3 | HCI_DH3))
selected_phys |= MGMT_PHY_BR_1M_3SLOT;
if (hdev->pkt_type & (HCI_DM5 | HCI_DH5))
selected_phys |= MGMT_PHY_BR_1M_5SLOT;
if (lmp_edr_2m_capable(hdev)) {
if (!(hdev->pkt_type & HCI_2DH1))
selected_phys |= MGMT_PHY_EDR_2M_1SLOT;
if (lmp_edr_3slot_capable(hdev) &&
!(hdev->pkt_type & HCI_2DH3))
selected_phys |= MGMT_PHY_EDR_2M_3SLOT;
if (lmp_edr_5slot_capable(hdev) &&
!(hdev->pkt_type & HCI_2DH5))
selected_phys |= MGMT_PHY_EDR_2M_5SLOT;
if (lmp_edr_3m_capable(hdev)) {
if (!(hdev->pkt_type & HCI_3DH1))
selected_phys |= MGMT_PHY_EDR_3M_1SLOT;
if (lmp_edr_3slot_capable(hdev) &&
!(hdev->pkt_type & HCI_3DH3))
selected_phys |= MGMT_PHY_EDR_3M_3SLOT;
if (lmp_edr_5slot_capable(hdev) &&
!(hdev->pkt_type & HCI_3DH5))
selected_phys |= MGMT_PHY_EDR_3M_5SLOT;
}
}
}
if (lmp_le_capable(hdev)) {
if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_1M)
selected_phys |= MGMT_PHY_LE_1M_TX;
if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_1M)
selected_phys |= MGMT_PHY_LE_1M_RX;
if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_2M)
selected_phys |= MGMT_PHY_LE_2M_TX;
if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_2M)
selected_phys |= MGMT_PHY_LE_2M_RX;
if (hdev->le_tx_def_phys & HCI_LE_SET_PHY_CODED)
selected_phys |= MGMT_PHY_LE_CODED_TX;
if (hdev->le_rx_def_phys & HCI_LE_SET_PHY_CODED)
selected_phys |= MGMT_PHY_LE_CODED_RX;
}
return selected_phys;
}
static u32 get_configurable_phys(struct hci_dev *hdev)
{
return (get_supported_phys(hdev) & ~MGMT_PHY_BR_1M_1SLOT &
~MGMT_PHY_LE_1M_TX & ~MGMT_PHY_LE_1M_RX);
}
static u32 get_supported_settings(struct hci_dev *hdev)
{
u32 settings = 0;
settings |= MGMT_SETTING_POWERED;
settings |= MGMT_SETTING_BONDABLE;
settings |= MGMT_SETTING_DEBUG_KEYS;
settings |= MGMT_SETTING_CONNECTABLE;
settings |= MGMT_SETTING_DISCOVERABLE;
if (lmp_bredr_capable(hdev)) {
if (hdev->hci_ver >= BLUETOOTH_VER_1_2)
settings |= MGMT_SETTING_FAST_CONNECTABLE;
settings |= MGMT_SETTING_BREDR;
settings |= MGMT_SETTING_LINK_SECURITY;
if (lmp_ssp_capable(hdev)) {
settings |= MGMT_SETTING_SSP;
}
if (lmp_sc_capable(hdev))
settings |= MGMT_SETTING_SECURE_CONN;
if (test_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED,
&hdev->quirks))
settings |= MGMT_SETTING_WIDEBAND_SPEECH;
}
if (lmp_le_capable(hdev)) {
settings |= MGMT_SETTING_LE;
settings |= MGMT_SETTING_SECURE_CONN;
settings |= MGMT_SETTING_PRIVACY;
settings |= MGMT_SETTING_STATIC_ADDRESS;
Bluetooth: hci_sync: Enable advertising when LL privacy is enabled This enables advertising when LL privacy is enabled and changes the command sequence when resolving list is updated to also account for when advertising is enabled using the following sequence: If there are devices to scan: Disable Scanning -> Update Accept List -> use_ll_privacy((Disable Advertising) -> Disable Resolving List -> Update Resolving List -> Enable Resolving List -> (Enable Advertising)) -> Enable Scanning Otherwise: Disable Scanning Errors during the Update Accept List stage are handled gracefully by restoring any previous state (e.g. advertising) and disabling the use of accept list as either accept list or resolving list could not be updated. Tested with: mgmt-tester -s "LL Privacy" Test Summary ------------ LL Privacy - Add Device 1 (Add to WL) Passed LL Privacy - Add Device 2 (Add to RL) Passed LL Privacy - Add Device 3 (Enable RL) Passed LL Privacy - Add Device 4 (2 Devices to WL) Passed LL Privacy - Add Device 5 (2 Devices to RL) Passed LL Privacy - Add Device 6 (RL is full) Passed LL Privacy - Add Device 7 (WL is full) Passed LL Privacy - Add Device 8 (Disable Adv) Passed LL Privacy - Add Device 9 (Multi Adv) Passed LL Privacy - Add Device 10 (Multi Dev and Multi Adv) Passed LL Privacy - Remove Device 1 (Remove from WL) Passed LL Privacy - Remove Device 2 (Remove from RL) Passed LL Privacy - Remove Device 3 (Disable RL) Passed LL Privacy - Remove Device 4 (Disable Adv) Passed LL Privacy - Remove Device 5 (Multi Adv) Passed LL Privacy - Start Discovery 1 (Disable RL) Passed LL Privacy - Start Discovery 2 (Disable RL) Passed Total: 18, Passed: 18 (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-27 23:58:42 +00:00
settings |= MGMT_SETTING_ADVERTISING;
}
if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) ||
hdev->set_bdaddr)
settings |= MGMT_SETTING_CONFIGURATION;
if (cis_central_capable(hdev))
settings |= MGMT_SETTING_CIS_CENTRAL;
if (cis_peripheral_capable(hdev))
settings |= MGMT_SETTING_CIS_PERIPHERAL;
settings |= MGMT_SETTING_PHY_CONFIGURATION;
return settings;
}
static u32 get_current_settings(struct hci_dev *hdev)
{
u32 settings = 0;
if (hdev_is_powered(hdev))
settings |= MGMT_SETTING_POWERED;
if (hci_dev_test_flag(hdev, HCI_CONNECTABLE))
settings |= MGMT_SETTING_CONNECTABLE;
if (hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE))
settings |= MGMT_SETTING_FAST_CONNECTABLE;
if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
settings |= MGMT_SETTING_DISCOVERABLE;
if (hci_dev_test_flag(hdev, HCI_BONDABLE))
settings |= MGMT_SETTING_BONDABLE;
if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
settings |= MGMT_SETTING_BREDR;
if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
settings |= MGMT_SETTING_LE;
if (hci_dev_test_flag(hdev, HCI_LINK_SECURITY))
settings |= MGMT_SETTING_LINK_SECURITY;
if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
settings |= MGMT_SETTING_SSP;
if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
settings |= MGMT_SETTING_ADVERTISING;
if (hci_dev_test_flag(hdev, HCI_SC_ENABLED))
settings |= MGMT_SETTING_SECURE_CONN;
if (hci_dev_test_flag(hdev, HCI_KEEP_DEBUG_KEYS))
settings |= MGMT_SETTING_DEBUG_KEYS;
if (hci_dev_test_flag(hdev, HCI_PRIVACY))
settings |= MGMT_SETTING_PRIVACY;
/* The current setting for static address has two purposes. The
* first is to indicate if the static address will be used and
* the second is to indicate if it is actually set.
*
* This means if the static address is not configured, this flag
* will never be set. If the address is configured, then if the
* address is actually used decides if the flag is set or not.
*
* For single mode LE only controllers and dual-mode controllers
* with BR/EDR disabled, the existence of the static address will
* be evaluated.
*/
if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
!bacmp(&hdev->bdaddr, BDADDR_ANY)) {
if (bacmp(&hdev->static_addr, BDADDR_ANY))
settings |= MGMT_SETTING_STATIC_ADDRESS;
}
if (hci_dev_test_flag(hdev, HCI_WIDEBAND_SPEECH_ENABLED))
settings |= MGMT_SETTING_WIDEBAND_SPEECH;
if (cis_central_capable(hdev))
settings |= MGMT_SETTING_CIS_CENTRAL;
if (cis_peripheral_capable(hdev))
settings |= MGMT_SETTING_CIS_PERIPHERAL;
if (bis_capable(hdev))
settings |= MGMT_SETTING_ISO_BROADCASTER;
if (sync_recv_capable(hdev))
settings |= MGMT_SETTING_ISO_SYNC_RECEIVER;
return settings;
}
static struct mgmt_pending_cmd *pending_find(u16 opcode, struct hci_dev *hdev)
{
return mgmt_pending_find(HCI_CHANNEL_CONTROL, opcode, hdev);
}
u8 mgmt_get_adv_discov_flags(struct hci_dev *hdev)
{
struct mgmt_pending_cmd *cmd;
/* If there's a pending mgmt command the flags will not yet have
* their final values, so check for this first.
*/
cmd = pending_find(MGMT_OP_SET_DISCOVERABLE, hdev);
if (cmd) {
struct mgmt_mode *cp = cmd->param;
if (cp->val == 0x01)
return LE_AD_GENERAL;
else if (cp->val == 0x02)
return LE_AD_LIMITED;
} else {
if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE))
return LE_AD_LIMITED;
else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE))
return LE_AD_GENERAL;
}
return 0;
}
bool mgmt_get_connectable(struct hci_dev *hdev)
{
struct mgmt_pending_cmd *cmd;
/* If there's a pending mgmt command the flag will not yet have
* it's final value, so check for this first.
*/
cmd = pending_find(MGMT_OP_SET_CONNECTABLE, hdev);
if (cmd) {
struct mgmt_mode *cp = cmd->param;
return cp->val;
}
return hci_dev_test_flag(hdev, HCI_CONNECTABLE);
}
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
static int service_cache_sync(struct hci_dev *hdev, void *data)
{
hci_update_eir_sync(hdev);
hci_update_class_sync(hdev);
return 0;
}
static void service_cache_off(struct work_struct *work)
{
struct hci_dev *hdev = container_of(work, struct hci_dev,
service_cache.work);
if (!hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE))
return;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
hci_cmd_sync_queue(hdev, service_cache_sync, NULL, NULL);
}
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-27 23:58:40 +00:00
static int rpa_expired_sync(struct hci_dev *hdev, void *data)
{
/* The generation of a new RPA and programming it into the
* controller happens in the hci_req_enable_advertising()
* function.
*/
if (ext_adv_capable(hdev))
return hci_start_ext_adv_sync(hdev, hdev->cur_adv_instance);
else
return hci_enable_advertising_sync(hdev);
}
static void rpa_expired(struct work_struct *work)
{
struct hci_dev *hdev = container_of(work, struct hci_dev,
rpa_expired.work);
bt_dev_dbg(hdev, "");
hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
if (!hci_dev_test_flag(hdev, HCI_ADVERTISING))
return;
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-27 23:58:40 +00:00
hci_cmd_sync_queue(hdev, rpa_expired_sync, NULL, NULL);
}
static int set_discoverable_sync(struct hci_dev *hdev, void *data);
static void discov_off(struct work_struct *work)
{
struct hci_dev *hdev = container_of(work, struct hci_dev,
discov_off.work);
bt_dev_dbg(hdev, "");
hci_dev_lock(hdev);
/* When discoverable timeout triggers, then just make sure
* the limited discoverable flag is cleared. Even in the case
* of a timeout triggered from general discoverable, it is
* safe to unconditionally clear the flag.
*/
hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
hdev->discov_timeout = 0;
hci_cmd_sync_queue(hdev, set_discoverable_sync, NULL, NULL);
mgmt_new_settings(hdev);
hci_dev_unlock(hdev);
}
static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev);
static void mesh_send_complete(struct hci_dev *hdev,
struct mgmt_mesh_tx *mesh_tx, bool silent)
{
u8 handle = mesh_tx->handle;
if (!silent)
mgmt_event(MGMT_EV_MESH_PACKET_CMPLT, hdev, &handle,
sizeof(handle), NULL);
mgmt_mesh_remove(mesh_tx);
}
static int mesh_send_done_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_mesh_tx *mesh_tx;
hci_dev_clear_flag(hdev, HCI_MESH_SENDING);
hci_disable_advertising_sync(hdev);
mesh_tx = mgmt_mesh_next(hdev, NULL);
if (mesh_tx)
mesh_send_complete(hdev, mesh_tx, false);
return 0;
}
static int mesh_send_sync(struct hci_dev *hdev, void *data);
static void mesh_send_start_complete(struct hci_dev *hdev, void *data, int err);
static void mesh_next(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_mesh_tx *mesh_tx = mgmt_mesh_next(hdev, NULL);
if (!mesh_tx)
return;
err = hci_cmd_sync_queue(hdev, mesh_send_sync, mesh_tx,
mesh_send_start_complete);
if (err < 0)
mesh_send_complete(hdev, mesh_tx, false);
else
hci_dev_set_flag(hdev, HCI_MESH_SENDING);
}
static void mesh_send_done(struct work_struct *work)
{
struct hci_dev *hdev = container_of(work, struct hci_dev,
mesh_send_done.work);
if (!hci_dev_test_flag(hdev, HCI_MESH_SENDING))
return;
hci_cmd_sync_queue(hdev, mesh_send_done_sync, NULL, mesh_next);
}
static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev)
{
if (hci_dev_test_flag(hdev, HCI_MGMT))
return;
BT_INFO("MGMT ver %d.%d", MGMT_VERSION, MGMT_REVISION);
INIT_DELAYED_WORK(&hdev->discov_off, discov_off);
INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off);
INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired);
INIT_DELAYED_WORK(&hdev->mesh_send_done, mesh_send_done);
/* Non-mgmt controlled devices get this bit set
* implicitly so that pairing works for them, however
* for mgmt we require user-space to explicitly enable
* it
*/
hci_dev_clear_flag(hdev, HCI_BONDABLE);
hci_dev_set_flag(hdev, HCI_MGMT);
}
static int read_controller_info(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
struct mgmt_rp_read_info rp;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
memset(&rp, 0, sizeof(rp));
bacpy(&rp.bdaddr, &hdev->bdaddr);
rp.version = hdev->hci_ver;
rp.manufacturer = cpu_to_le16(hdev->manufacturer);
rp.supported_settings = cpu_to_le32(get_supported_settings(hdev));
rp.current_settings = cpu_to_le32(get_current_settings(hdev));
memcpy(rp.dev_class, hdev->dev_class, 3);
memcpy(rp.name, hdev->dev_name, sizeof(hdev->dev_name));
memcpy(rp.short_name, hdev->short_name, sizeof(hdev->short_name));
hci_dev_unlock(hdev);
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_INFO, 0, &rp,
sizeof(rp));
}
static u16 append_eir_data_to_buf(struct hci_dev *hdev, u8 *eir)
{
u16 eir_len = 0;
size_t name_len;
if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
eir_len = eir_append_data(eir, eir_len, EIR_CLASS_OF_DEV,
hdev->dev_class, 3);
if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
eir_len = eir_append_le16(eir, eir_len, EIR_APPEARANCE,
hdev->appearance);
name_len = strnlen(hdev->dev_name, sizeof(hdev->dev_name));
eir_len = eir_append_data(eir, eir_len, EIR_NAME_COMPLETE,
hdev->dev_name, name_len);
name_len = strnlen(hdev->short_name, sizeof(hdev->short_name));
eir_len = eir_append_data(eir, eir_len, EIR_NAME_SHORT,
hdev->short_name, name_len);
return eir_len;
}
static int read_ext_controller_info(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
char buf[512];
struct mgmt_rp_read_ext_info *rp = (void *)buf;
u16 eir_len;
bt_dev_dbg(hdev, "sock %p", sk);
memset(&buf, 0, sizeof(buf));
hci_dev_lock(hdev);
bacpy(&rp->bdaddr, &hdev->bdaddr);
rp->version = hdev->hci_ver;
rp->manufacturer = cpu_to_le16(hdev->manufacturer);
rp->supported_settings = cpu_to_le32(get_supported_settings(hdev));
rp->current_settings = cpu_to_le32(get_current_settings(hdev));
eir_len = append_eir_data_to_buf(hdev, rp->eir);
rp->eir_len = cpu_to_le16(eir_len);
hci_dev_unlock(hdev);
/* If this command is called at least once, then the events
* for class of device and local name changes are disabled
* and only the new extended controller information event
* is used.
*/
hci_sock_set_flag(sk, HCI_MGMT_EXT_INFO_EVENTS);
hci_sock_clear_flag(sk, HCI_MGMT_DEV_CLASS_EVENTS);
hci_sock_clear_flag(sk, HCI_MGMT_LOCAL_NAME_EVENTS);
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_EXT_INFO, 0, rp,
sizeof(*rp) + eir_len);
}
static int ext_info_changed(struct hci_dev *hdev, struct sock *skip)
{
char buf[512];
struct mgmt_ev_ext_info_changed *ev = (void *)buf;
u16 eir_len;
memset(buf, 0, sizeof(buf));
eir_len = append_eir_data_to_buf(hdev, ev->eir);
ev->eir_len = cpu_to_le16(eir_len);
return mgmt_limited_event(MGMT_EV_EXT_INFO_CHANGED, hdev, ev,
sizeof(*ev) + eir_len,
HCI_MGMT_EXT_INFO_EVENTS, skip);
}
static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev)
{
__le32 settings = cpu_to_le32(get_current_settings(hdev));
return mgmt_cmd_complete(sk, hdev->id, opcode, 0, &settings,
sizeof(settings));
}
void mgmt_advertising_added(struct sock *sk, struct hci_dev *hdev, u8 instance)
{
struct mgmt_ev_advertising_added ev;
ev.instance = instance;
mgmt_event(MGMT_EV_ADVERTISING_ADDED, hdev, &ev, sizeof(ev), sk);
}
void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev,
u8 instance)
{
struct mgmt_ev_advertising_removed ev;
ev.instance = instance;
mgmt_event(MGMT_EV_ADVERTISING_REMOVED, hdev, &ev, sizeof(ev), sk);
}
static void cancel_adv_timeout(struct hci_dev *hdev)
{
if (hdev->adv_instance_timeout) {
hdev->adv_instance_timeout = 0;
cancel_delayed_work(&hdev->adv_instance_expire);
}
}
/* This function requires the caller holds hdev->lock */
static void restart_le_actions(struct hci_dev *hdev)
{
struct hci_conn_params *p;
list_for_each_entry(p, &hdev->le_conn_params, list) {
/* Needed for AUTO_OFF case where might not "really"
* have been powered off.
*/
Bluetooth: use RCU for hci_conn_params and iterate safely in hci_sync hci_update_accept_list_sync iterates over hdev->pend_le_conns and hdev->pend_le_reports, and waits for controller events in the loop body, without holding hdev lock. Meanwhile, these lists and the items may be modified e.g. by le_scan_cleanup. This can invalidate the list cursor or any other item in the list, resulting to invalid behavior (eg use-after-free). Use RCU for the hci_conn_params action lists. Since the loop bodies in hci_sync block and we cannot use RCU or hdev->lock for the whole loop, copy list items first and then iterate on the copy. Only the flags field is written from elsewhere, so READ_ONCE/WRITE_ONCE should guarantee we read valid values. Free params everywhere with hci_conn_params_free so the cleanup is guaranteed to be done properly. This fixes the following, which can be triggered e.g. by BlueZ new mgmt-tester case "Add + Remove Device Nowait - Success", or by changing hci_le_set_cig_params to always return false, and running iso-tester: ================================================================== BUG: KASAN: slab-use-after-free in hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) Read of size 8 at addr ffff888001265018 by task kworker/u3:0/32 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-1.fc38 04/01/2014 Workqueue: hci0 hci_cmd_sync_work Call Trace: <TASK> dump_stack_lvl (./arch/x86/include/asm/irqflags.h:134 lib/dump_stack.c:107) print_report (mm/kasan/report.c:320 mm/kasan/report.c:430) ? __virt_addr_valid (./include/linux/mmzone.h:1915 ./include/linux/mmzone.h:2011 arch/x86/mm/physaddr.c:65) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) kasan_report (mm/kasan/report.c:538) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) ? __pfx_hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2780) ? mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_unlock (kernel/locking/mutex.c:538) ? __pfx_update_passive_scan_sync (net/bluetooth/hci_sync.c:2861) hci_cmd_sync_work (net/bluetooth/hci_sync.c:306) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) ? __pfx_worker_thread (kernel/workqueue.c:2480) kthread (kernel/kthread.c:376) ? __pfx_kthread (kernel/kthread.c:331) ret_from_fork (arch/x86/entry/entry_64.S:314) </TASK> Allocated by task 31: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) __kasan_kmalloc (mm/kasan/common.c:374 mm/kasan/common.c:383) hci_conn_params_add (./include/linux/slab.h:580 ./include/linux/slab.h:720 net/bluetooth/hci_core.c:2277) hci_connect_le_scan (net/bluetooth/hci_conn.c:1419 net/bluetooth/hci_conn.c:1589) hci_connect_cis (net/bluetooth/hci_conn.c:2266) iso_connect_cis (net/bluetooth/iso.c:390) iso_sock_connect (net/bluetooth/iso.c:899) __sys_connect (net/socket.c:2003 net/socket.c:2020) __x64_sys_connect (net/socket.c:2027) do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) Freed by task 15: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) kasan_save_free_info (mm/kasan/generic.c:523) __kasan_slab_free (mm/kasan/common.c:238 mm/kasan/common.c:200 mm/kasan/common.c:244) __kmem_cache_free (mm/slub.c:1807 mm/slub.c:3787 mm/slub.c:3800) hci_conn_params_del (net/bluetooth/hci_core.c:2323) le_scan_cleanup (net/bluetooth/hci_conn.c:202) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) kthread (kernel/kthread.c:376) ret_from_fork (arch/x86/entry/entry_64.S:314) ================================================================== Fixes: e8907f76544f ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 3") Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-06-18 22:04:31 +00:00
hci_pend_le_list_del_init(p);
switch (p->auto_connect) {
case HCI_AUTO_CONN_DIRECT:
case HCI_AUTO_CONN_ALWAYS:
Bluetooth: use RCU for hci_conn_params and iterate safely in hci_sync hci_update_accept_list_sync iterates over hdev->pend_le_conns and hdev->pend_le_reports, and waits for controller events in the loop body, without holding hdev lock. Meanwhile, these lists and the items may be modified e.g. by le_scan_cleanup. This can invalidate the list cursor or any other item in the list, resulting to invalid behavior (eg use-after-free). Use RCU for the hci_conn_params action lists. Since the loop bodies in hci_sync block and we cannot use RCU or hdev->lock for the whole loop, copy list items first and then iterate on the copy. Only the flags field is written from elsewhere, so READ_ONCE/WRITE_ONCE should guarantee we read valid values. Free params everywhere with hci_conn_params_free so the cleanup is guaranteed to be done properly. This fixes the following, which can be triggered e.g. by BlueZ new mgmt-tester case "Add + Remove Device Nowait - Success", or by changing hci_le_set_cig_params to always return false, and running iso-tester: ================================================================== BUG: KASAN: slab-use-after-free in hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) Read of size 8 at addr ffff888001265018 by task kworker/u3:0/32 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-1.fc38 04/01/2014 Workqueue: hci0 hci_cmd_sync_work Call Trace: <TASK> dump_stack_lvl (./arch/x86/include/asm/irqflags.h:134 lib/dump_stack.c:107) print_report (mm/kasan/report.c:320 mm/kasan/report.c:430) ? __virt_addr_valid (./include/linux/mmzone.h:1915 ./include/linux/mmzone.h:2011 arch/x86/mm/physaddr.c:65) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) kasan_report (mm/kasan/report.c:538) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) ? __pfx_hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2780) ? mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_unlock (kernel/locking/mutex.c:538) ? __pfx_update_passive_scan_sync (net/bluetooth/hci_sync.c:2861) hci_cmd_sync_work (net/bluetooth/hci_sync.c:306) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) ? __pfx_worker_thread (kernel/workqueue.c:2480) kthread (kernel/kthread.c:376) ? __pfx_kthread (kernel/kthread.c:331) ret_from_fork (arch/x86/entry/entry_64.S:314) </TASK> Allocated by task 31: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) __kasan_kmalloc (mm/kasan/common.c:374 mm/kasan/common.c:383) hci_conn_params_add (./include/linux/slab.h:580 ./include/linux/slab.h:720 net/bluetooth/hci_core.c:2277) hci_connect_le_scan (net/bluetooth/hci_conn.c:1419 net/bluetooth/hci_conn.c:1589) hci_connect_cis (net/bluetooth/hci_conn.c:2266) iso_connect_cis (net/bluetooth/iso.c:390) iso_sock_connect (net/bluetooth/iso.c:899) __sys_connect (net/socket.c:2003 net/socket.c:2020) __x64_sys_connect (net/socket.c:2027) do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) Freed by task 15: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) kasan_save_free_info (mm/kasan/generic.c:523) __kasan_slab_free (mm/kasan/common.c:238 mm/kasan/common.c:200 mm/kasan/common.c:244) __kmem_cache_free (mm/slub.c:1807 mm/slub.c:3787 mm/slub.c:3800) hci_conn_params_del (net/bluetooth/hci_core.c:2323) le_scan_cleanup (net/bluetooth/hci_conn.c:202) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) kthread (kernel/kthread.c:376) ret_from_fork (arch/x86/entry/entry_64.S:314) ================================================================== Fixes: e8907f76544f ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 3") Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-06-18 22:04:31 +00:00
hci_pend_le_list_add(p, &hdev->pend_le_conns);
break;
case HCI_AUTO_CONN_REPORT:
Bluetooth: use RCU for hci_conn_params and iterate safely in hci_sync hci_update_accept_list_sync iterates over hdev->pend_le_conns and hdev->pend_le_reports, and waits for controller events in the loop body, without holding hdev lock. Meanwhile, these lists and the items may be modified e.g. by le_scan_cleanup. This can invalidate the list cursor or any other item in the list, resulting to invalid behavior (eg use-after-free). Use RCU for the hci_conn_params action lists. Since the loop bodies in hci_sync block and we cannot use RCU or hdev->lock for the whole loop, copy list items first and then iterate on the copy. Only the flags field is written from elsewhere, so READ_ONCE/WRITE_ONCE should guarantee we read valid values. Free params everywhere with hci_conn_params_free so the cleanup is guaranteed to be done properly. This fixes the following, which can be triggered e.g. by BlueZ new mgmt-tester case "Add + Remove Device Nowait - Success", or by changing hci_le_set_cig_params to always return false, and running iso-tester: ================================================================== BUG: KASAN: slab-use-after-free in hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) Read of size 8 at addr ffff888001265018 by task kworker/u3:0/32 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-1.fc38 04/01/2014 Workqueue: hci0 hci_cmd_sync_work Call Trace: <TASK> dump_stack_lvl (./arch/x86/include/asm/irqflags.h:134 lib/dump_stack.c:107) print_report (mm/kasan/report.c:320 mm/kasan/report.c:430) ? __virt_addr_valid (./include/linux/mmzone.h:1915 ./include/linux/mmzone.h:2011 arch/x86/mm/physaddr.c:65) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) kasan_report (mm/kasan/report.c:538) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) ? __pfx_hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2780) ? mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_unlock (kernel/locking/mutex.c:538) ? __pfx_update_passive_scan_sync (net/bluetooth/hci_sync.c:2861) hci_cmd_sync_work (net/bluetooth/hci_sync.c:306) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) ? __pfx_worker_thread (kernel/workqueue.c:2480) kthread (kernel/kthread.c:376) ? __pfx_kthread (kernel/kthread.c:331) ret_from_fork (arch/x86/entry/entry_64.S:314) </TASK> Allocated by task 31: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) __kasan_kmalloc (mm/kasan/common.c:374 mm/kasan/common.c:383) hci_conn_params_add (./include/linux/slab.h:580 ./include/linux/slab.h:720 net/bluetooth/hci_core.c:2277) hci_connect_le_scan (net/bluetooth/hci_conn.c:1419 net/bluetooth/hci_conn.c:1589) hci_connect_cis (net/bluetooth/hci_conn.c:2266) iso_connect_cis (net/bluetooth/iso.c:390) iso_sock_connect (net/bluetooth/iso.c:899) __sys_connect (net/socket.c:2003 net/socket.c:2020) __x64_sys_connect (net/socket.c:2027) do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) Freed by task 15: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) kasan_save_free_info (mm/kasan/generic.c:523) __kasan_slab_free (mm/kasan/common.c:238 mm/kasan/common.c:200 mm/kasan/common.c:244) __kmem_cache_free (mm/slub.c:1807 mm/slub.c:3787 mm/slub.c:3800) hci_conn_params_del (net/bluetooth/hci_core.c:2323) le_scan_cleanup (net/bluetooth/hci_conn.c:202) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) kthread (kernel/kthread.c:376) ret_from_fork (arch/x86/entry/entry_64.S:314) ================================================================== Fixes: e8907f76544f ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 3") Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-06-18 22:04:31 +00:00
hci_pend_le_list_add(p, &hdev->pend_le_reports);
break;
default:
break;
}
}
}
static int new_settings(struct hci_dev *hdev, struct sock *skip)
{
__le32 ev = cpu_to_le32(get_current_settings(hdev));
return mgmt_limited_event(MGMT_EV_NEW_SETTINGS, hdev, &ev,
sizeof(ev), HCI_MGMT_SETTING_EVENTS, skip);
}
static void mgmt_set_powered_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_mode *cp;
/* Make sure cmd still outstanding. */
if (cmd != pending_find(MGMT_OP_SET_POWERED, hdev))
return;
cp = cmd->param;
bt_dev_dbg(hdev, "err %d", err);
if (!err) {
if (cp->val) {
hci_dev_lock(hdev);
restart_le_actions(hdev);
hci_update_passive_scan(hdev);
hci_dev_unlock(hdev);
}
send_settings_rsp(cmd->sk, cmd->opcode, hdev);
/* Only call new_setting for power on as power off is deferred
* to hdev->power_off work which does call hci_dev_do_close.
*/
if (cp->val)
new_settings(hdev, cmd->sk);
} else {
mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED,
mgmt_status(err));
}
mgmt_pending_remove(cmd);
}
static int set_powered_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_mode *cp = cmd->param;
BT_DBG("%s", hdev->name);
return hci_set_powered_sync(hdev, cp->val);
}
static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_mode *cp = data;
struct mgmt_pending_cmd *cmd;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (cp->val != 0x00 && cp->val != 0x01)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
if (!cp->val) {
if (hci_dev_test_flag(hdev, HCI_POWERING_DOWN)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
MGMT_STATUS_BUSY);
goto failed;
}
}
if (pending_find(MGMT_OP_SET_POWERED, hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_POWERED,
MGMT_STATUS_BUSY);
goto failed;
}
if (!!cp->val == hdev_is_powered(hdev)) {
err = send_settings_rsp(sk, MGMT_OP_SET_POWERED, hdev);
goto failed;
}
cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
}
/* Cancel potentially blocking sync operation before power off */
if (cp->val == 0x00) {
hci_cmd_sync_cancel_sync(hdev, -EHOSTDOWN);
err = hci_cmd_sync_queue(hdev, set_powered_sync, cmd,
mgmt_set_powered_complete);
} else {
/* Use hci_cmd_sync_submit since hdev might not be running */
err = hci_cmd_sync_submit(hdev, set_powered_sync, cmd,
mgmt_set_powered_complete);
}
if (err < 0)
mgmt_pending_remove(cmd);
failed:
hci_dev_unlock(hdev);
return err;
}
int mgmt_new_settings(struct hci_dev *hdev)
{
return new_settings(hdev, NULL);
}
struct cmd_lookup {
struct sock *sk;
struct hci_dev *hdev;
u8 mgmt_status;
};
static void settings_rsp(struct mgmt_pending_cmd *cmd, void *data)
{
struct cmd_lookup *match = data;
send_settings_rsp(cmd->sk, cmd->opcode, match->hdev);
list_del(&cmd->list);
if (match->sk == NULL) {
match->sk = cmd->sk;
sock_hold(match->sk);
}
mgmt_pending_free(cmd);
}
static void cmd_status_rsp(struct mgmt_pending_cmd *cmd, void *data)
{
u8 *status = data;
mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, *status);
mgmt_pending_remove(cmd);
}
static void cmd_complete_rsp(struct mgmt_pending_cmd *cmd, void *data)
{
if (cmd->cmd_complete) {
u8 *status = data;
cmd->cmd_complete(cmd, *status);
mgmt_pending_remove(cmd);
return;
}
cmd_status_rsp(cmd, data);
}
static int generic_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
{
return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
cmd->param, cmd->param_len);
}
static int addr_cmd_complete(struct mgmt_pending_cmd *cmd, u8 status)
{
return mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status,
cmd->param, sizeof(struct mgmt_addr_info));
}
static u8 mgmt_bredr_support(struct hci_dev *hdev)
{
if (!lmp_bredr_capable(hdev))
return MGMT_STATUS_NOT_SUPPORTED;
else if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
return MGMT_STATUS_REJECTED;
else
return MGMT_STATUS_SUCCESS;
}
static u8 mgmt_le_support(struct hci_dev *hdev)
{
if (!lmp_le_capable(hdev))
return MGMT_STATUS_NOT_SUPPORTED;
else if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
return MGMT_STATUS_REJECTED;
else
return MGMT_STATUS_SUCCESS;
}
static void mgmt_set_discoverable_complete(struct hci_dev *hdev, void *data,
int err)
{
struct mgmt_pending_cmd *cmd = data;
bt_dev_dbg(hdev, "err %d", err);
/* Make sure cmd still outstanding. */
if (cmd != pending_find(MGMT_OP_SET_DISCOVERABLE, hdev))
return;
hci_dev_lock(hdev);
if (err) {
u8 mgmt_err = mgmt_status(err);
mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
goto done;
}
if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
hdev->discov_timeout > 0) {
int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
queue_delayed_work(hdev->req_workqueue, &hdev->discov_off, to);
}
send_settings_rsp(cmd->sk, MGMT_OP_SET_DISCOVERABLE, hdev);
new_settings(hdev, cmd->sk);
done:
mgmt_pending_remove(cmd);
hci_dev_unlock(hdev);
}
static int set_discoverable_sync(struct hci_dev *hdev, void *data)
{
BT_DBG("%s", hdev->name);
return hci_update_discoverable_sync(hdev);
}
static int set_discoverable(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_set_discoverable *cp = data;
struct mgmt_pending_cmd *cmd;
u16 timeout;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_REJECTED);
if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_INVALID_PARAMS);
timeout = __le16_to_cpu(cp->timeout);
/* Disabling discoverable requires that no timeout is set,
* and enabling limited discoverable requires a timeout.
*/
if ((cp->val == 0x00 && timeout > 0) ||
(cp->val == 0x02 && timeout == 0))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev) && timeout > 0) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_NOT_POWERED);
goto failed;
}
if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_BUSY);
goto failed;
}
if (!hci_dev_test_flag(hdev, HCI_CONNECTABLE)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_REJECTED);
goto failed;
}
if (hdev->advertising_paused) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DISCOVERABLE,
MGMT_STATUS_BUSY);
goto failed;
}
if (!hdev_is_powered(hdev)) {
bool changed = false;
/* Setting limited discoverable when powered off is
* not a valid operation since it requires a timeout
* and so no need to check HCI_LIMITED_DISCOVERABLE.
*/
if (!!cp->val != hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) {
hci_dev_change_flag(hdev, HCI_DISCOVERABLE);
changed = true;
}
err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
if (err < 0)
goto failed;
if (changed)
err = new_settings(hdev, sk);
goto failed;
}
/* If the current mode is the same, then just update the timeout
* value with the new value. And if only the timeout gets updated,
* then no need for any HCI transactions.
*/
if (!!cp->val == hci_dev_test_flag(hdev, HCI_DISCOVERABLE) &&
(cp->val == 0x02) == hci_dev_test_flag(hdev,
HCI_LIMITED_DISCOVERABLE)) {
cancel_delayed_work(&hdev->discov_off);
hdev->discov_timeout = timeout;
if (cp->val && hdev->discov_timeout > 0) {
int to = msecs_to_jiffies(hdev->discov_timeout * 1000);
queue_delayed_work(hdev->req_workqueue,
&hdev->discov_off, to);
}
err = send_settings_rsp(sk, MGMT_OP_SET_DISCOVERABLE, hdev);
goto failed;
}
cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
}
/* Cancel any potential discoverable timeout that might be
* still active and store new timeout value. The arming of
* the timeout happens in the complete handler.
*/
cancel_delayed_work(&hdev->discov_off);
hdev->discov_timeout = timeout;
if (cp->val)
hci_dev_set_flag(hdev, HCI_DISCOVERABLE);
else
hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
/* Limited discoverable mode */
if (cp->val == 0x02)
hci_dev_set_flag(hdev, HCI_LIMITED_DISCOVERABLE);
else
hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
err = hci_cmd_sync_queue(hdev, set_discoverable_sync, cmd,
mgmt_set_discoverable_complete);
if (err < 0)
mgmt_pending_remove(cmd);
failed:
hci_dev_unlock(hdev);
return err;
}
static void mgmt_set_connectable_complete(struct hci_dev *hdev, void *data,
int err)
{
struct mgmt_pending_cmd *cmd = data;
bt_dev_dbg(hdev, "err %d", err);
/* Make sure cmd still outstanding. */
if (cmd != pending_find(MGMT_OP_SET_CONNECTABLE, hdev))
return;
hci_dev_lock(hdev);
if (err) {
u8 mgmt_err = mgmt_status(err);
mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
goto done;
}
send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev);
new_settings(hdev, cmd->sk);
done:
mgmt_pending_remove(cmd);
hci_dev_unlock(hdev);
}
static int set_connectable_update_settings(struct hci_dev *hdev,
struct sock *sk, u8 val)
{
bool changed = false;
int err;
if (!!val != hci_dev_test_flag(hdev, HCI_CONNECTABLE))
changed = true;
if (val) {
hci_dev_set_flag(hdev, HCI_CONNECTABLE);
} else {
hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
}
err = send_settings_rsp(sk, MGMT_OP_SET_CONNECTABLE, hdev);
if (err < 0)
return err;
if (changed) {
hci_update_scan(hdev);
hci_update_passive_scan(hdev);
return new_settings(hdev, sk);
}
return 0;
}
static int set_connectable_sync(struct hci_dev *hdev, void *data)
{
BT_DBG("%s", hdev->name);
return hci_update_connectable_sync(hdev);
}
static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_mode *cp = data;
struct mgmt_pending_cmd *cmd;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) &&
!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
MGMT_STATUS_REJECTED);
if (cp->val != 0x00 && cp->val != 0x01)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
err = set_connectable_update_settings(hdev, sk, cp->val);
goto failed;
}
if (pending_find(MGMT_OP_SET_DISCOVERABLE, hdev) ||
pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_CONNECTABLE,
MGMT_STATUS_BUSY);
goto failed;
}
cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
}
if (cp->val) {
hci_dev_set_flag(hdev, HCI_CONNECTABLE);
} else {
if (hdev->discov_timeout > 0)
cancel_delayed_work(&hdev->discov_off);
hci_dev_clear_flag(hdev, HCI_LIMITED_DISCOVERABLE);
hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
hci_dev_clear_flag(hdev, HCI_CONNECTABLE);
}
err = hci_cmd_sync_queue(hdev, set_connectable_sync, cmd,
mgmt_set_connectable_complete);
if (err < 0)
mgmt_pending_remove(cmd);
failed:
hci_dev_unlock(hdev);
return err;
}
static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_mode *cp = data;
bool changed;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (cp->val != 0x00 && cp->val != 0x01)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
if (cp->val)
changed = !hci_dev_test_and_set_flag(hdev, HCI_BONDABLE);
else
changed = hci_dev_test_and_clear_flag(hdev, HCI_BONDABLE);
err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev);
if (err < 0)
goto unlock;
if (changed) {
/* In limited privacy mode the change of bondable mode
* may affect the local advertising address.
*/
hci_update_discoverable(hdev);
err = new_settings(hdev, sk);
}
unlock:
hci_dev_unlock(hdev);
return err;
}
static int set_link_security(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_mode *cp = data;
struct mgmt_pending_cmd *cmd;
u8 val, status;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
status = mgmt_bredr_support(hdev);
if (status)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
status);
if (cp->val != 0x00 && cp->val != 0x01)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
bool changed = false;
if (!!cp->val != hci_dev_test_flag(hdev, HCI_LINK_SECURITY)) {
hci_dev_change_flag(hdev, HCI_LINK_SECURITY);
changed = true;
}
err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
if (err < 0)
goto failed;
if (changed)
err = new_settings(hdev, sk);
goto failed;
}
if (pending_find(MGMT_OP_SET_LINK_SECURITY, hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LINK_SECURITY,
MGMT_STATUS_BUSY);
goto failed;
}
val = !!cp->val;
if (test_bit(HCI_AUTH, &hdev->flags) == val) {
err = send_settings_rsp(sk, MGMT_OP_SET_LINK_SECURITY, hdev);
goto failed;
}
cmd = mgmt_pending_add(sk, MGMT_OP_SET_LINK_SECURITY, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
}
err = hci_send_cmd(hdev, HCI_OP_WRITE_AUTH_ENABLE, sizeof(val), &val);
if (err < 0) {
mgmt_pending_remove(cmd);
goto failed;
}
failed:
hci_dev_unlock(hdev);
return err;
}
static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)
{
struct cmd_lookup match = { NULL, hdev };
struct mgmt_pending_cmd *cmd = data;
struct mgmt_mode *cp = cmd->param;
u8 enable = cp->val;
bool changed;
/* Make sure cmd still outstanding. */
if (cmd != pending_find(MGMT_OP_SET_SSP, hdev))
return;
if (err) {
u8 mgmt_err = mgmt_status(err);
if (enable && hci_dev_test_and_clear_flag(hdev,
HCI_SSP_ENABLED)) {
new_settings(hdev, NULL);
}
mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, cmd_status_rsp,
&mgmt_err);
return;
}
if (enable) {
changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
} else {
changed = hci_dev_test_and_clear_flag(hdev, HCI_SSP_ENABLED);
}
mgmt_pending_foreach(MGMT_OP_SET_SSP, hdev, settings_rsp, &match);
if (changed)
new_settings(hdev, match.sk);
if (match.sk)
sock_put(match.sk);
hci_update_eir_sync(hdev);
}
static int set_ssp_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_mode *cp = cmd->param;
bool changed = false;
int err;
if (cp->val)
changed = !hci_dev_test_and_set_flag(hdev, HCI_SSP_ENABLED);
err = hci_write_ssp_mode_sync(hdev, cp->val);
if (!err && changed)
hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
return err;
}
static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{
struct mgmt_mode *cp = data;
struct mgmt_pending_cmd *cmd;
u8 status;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
status = mgmt_bredr_support(hdev);
if (status)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, status);
if (!lmp_ssp_capable(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
MGMT_STATUS_NOT_SUPPORTED);
if (cp->val != 0x00 && cp->val != 0x01)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
bool changed;
if (cp->val) {
changed = !hci_dev_test_and_set_flag(hdev,
HCI_SSP_ENABLED);
} else {
changed = hci_dev_test_and_clear_flag(hdev,
HCI_SSP_ENABLED);
}
err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
if (err < 0)
goto failed;
if (changed)
err = new_settings(hdev, sk);
goto failed;
}
if (pending_find(MGMT_OP_SET_SSP, hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
MGMT_STATUS_BUSY);
goto failed;
}
if (!!cp->val == hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
err = send_settings_rsp(sk, MGMT_OP_SET_SSP, hdev);
goto failed;
}
cmd = mgmt_pending_add(sk, MGMT_OP_SET_SSP, hdev, data, len);
if (!cmd)
err = -ENOMEM;
else
err = hci_cmd_sync_queue(hdev, set_ssp_sync, cmd,
set_ssp_complete);
if (err < 0) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SSP,
MGMT_STATUS_FAILED);
if (cmd)
mgmt_pending_remove(cmd);
}
failed:
hci_dev_unlock(hdev);
return err;
}
static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{
bt_dev_dbg(hdev, "sock %p", sk);
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
MGMT_STATUS_NOT_SUPPORTED);
}
static void set_le_complete(struct hci_dev *hdev, void *data, int err)
{
struct cmd_lookup match = { NULL, hdev };
u8 status = mgmt_status(err);
bt_dev_dbg(hdev, "err %d", err);
Bluetooth: Fix missing hci_dev_lock/unlock in mgmt req_complete() mgmt_pending_remove() should be called with hci_dev_lock protection and currently the rule to take dev lock is that all mgmt req_complete functions should take dev lock. So this patch fixes the same in the missing functions Without this patch there is a chance of invalid memory access while accessing the mgmt_pending list like below bluetoothd: 392] [0] Backtrace: bluetoothd: 392] [0] [<c04ec770>] (pending_eir_or_class+0x0/0x68) from [<c04f1830>] (add_uuid+0x34/0x1c4) bluetoothd: 392] [0] [<c04f17fc>] (add_uuid+0x0/0x1c4) from [<c04f3cc4>] (mgmt_control+0x204/0x274) bluetoothd: 392] [0] [<c04f3ac0>] (mgmt_control+0x0/0x274) from [<c04f609c>] (hci_sock_sendmsg+0x80/0x308) bluetoothd: 392] [0] [<c04f601c>] (hci_sock_sendmsg+0x0/0x308) from [<c03d4d68>] (sock_aio_write+0x144/0x174) bluetoothd: 392] [0] r8:00000000 r7 7c1be90 r6 7c1be18 r5:00000017 r4 a90ea80 bluetoothd: 392] [0] [<c03d4c24>] (sock_aio_write+0x0/0x174) from [<c00e2d4c>] (do_sync_write+0xb0/0xe0) bluetoothd: 392] [0] [<c00e2c9c>] (do_sync_write+0x0/0xe0) from [<c00e371c>] (vfs_write+0x134/0x13c) bluetoothd: 392] [0] r8:00000000 r7 7c1bf70 r6:beeca5c8 r5:00000017 r4 7c05900 bluetoothd: 392] [0] [<c00e35e8>] (vfs_write+0x0/0x13c) from [<c00e3910>] (sys_write+0x44/0x70) bluetoothd: 392] [0] r8:00000000 r7:00000004 r6:00000017 r5:beeca5c8 r4 7c05900 bluetoothd: 392] [0] [<c00e38cc>] (sys_write+0x0/0x70) from [<c000e3c0>] (ret_fast_syscall+0x0/0x30) bluetoothd: 392] [0] r9 7c1a000 r8:c000e568 r6:400b5f10 r5:403896d8 r4:beeca604 bluetoothd: 392] [0] Code: e28cc00c e152000c 0a00000f e3a00001 (e1d210b8) bluetoothd: 392] [0] ---[ end trace 67b6ac67435864c4 ]--- bluetoothd: 392] [0] Kernel panic - not syncing: Fatal exception Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-12-11 06:13:12 +00:00
if (status) {
mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, cmd_status_rsp,
&status);
return;
}
mgmt_pending_foreach(MGMT_OP_SET_LE, hdev, settings_rsp, &match);
new_settings(hdev, match.sk);
if (match.sk)
sock_put(match.sk);
}
static int set_le_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_mode *cp = cmd->param;
u8 val = !!cp->val;
int err;
if (!val) {
hci_clear_adv_instance_sync(hdev, NULL, 0x00, true);
if (hci_dev_test_flag(hdev, HCI_LE_ADV))
hci_disable_advertising_sync(hdev);
if (ext_adv_capable(hdev))
hci_remove_ext_adv_instance_sync(hdev, 0, cmd->sk);
} else {
hci_dev_set_flag(hdev, HCI_LE_ENABLED);
}
err = hci_write_le_host_supported_sync(hdev, val, 0);
/* Make sure the controller has a good default for
* advertising data. Restrict the update to when LE
* has actually been enabled. During power on, the
* update in powered_update_hci will take care of it.
*/
if (!err && hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
if (ext_adv_capable(hdev)) {
int status;
status = hci_setup_ext_adv_instance_sync(hdev, 0x00);
if (!status)
hci_update_scan_rsp_data_sync(hdev, 0x00);
} else {
hci_update_adv_data_sync(hdev, 0x00);
hci_update_scan_rsp_data_sync(hdev, 0x00);
}
hci_update_passive_scan(hdev);
}
Bluetooth: Fix missing hci_dev_lock/unlock in mgmt req_complete() mgmt_pending_remove() should be called with hci_dev_lock protection and currently the rule to take dev lock is that all mgmt req_complete functions should take dev lock. So this patch fixes the same in the missing functions Without this patch there is a chance of invalid memory access while accessing the mgmt_pending list like below bluetoothd: 392] [0] Backtrace: bluetoothd: 392] [0] [<c04ec770>] (pending_eir_or_class+0x0/0x68) from [<c04f1830>] (add_uuid+0x34/0x1c4) bluetoothd: 392] [0] [<c04f17fc>] (add_uuid+0x0/0x1c4) from [<c04f3cc4>] (mgmt_control+0x204/0x274) bluetoothd: 392] [0] [<c04f3ac0>] (mgmt_control+0x0/0x274) from [<c04f609c>] (hci_sock_sendmsg+0x80/0x308) bluetoothd: 392] [0] [<c04f601c>] (hci_sock_sendmsg+0x0/0x308) from [<c03d4d68>] (sock_aio_write+0x144/0x174) bluetoothd: 392] [0] r8:00000000 r7 7c1be90 r6 7c1be18 r5:00000017 r4 a90ea80 bluetoothd: 392] [0] [<c03d4c24>] (sock_aio_write+0x0/0x174) from [<c00e2d4c>] (do_sync_write+0xb0/0xe0) bluetoothd: 392] [0] [<c00e2c9c>] (do_sync_write+0x0/0xe0) from [<c00e371c>] (vfs_write+0x134/0x13c) bluetoothd: 392] [0] r8:00000000 r7 7c1bf70 r6:beeca5c8 r5:00000017 r4 7c05900 bluetoothd: 392] [0] [<c00e35e8>] (vfs_write+0x0/0x13c) from [<c00e3910>] (sys_write+0x44/0x70) bluetoothd: 392] [0] r8:00000000 r7:00000004 r6:00000017 r5:beeca5c8 r4 7c05900 bluetoothd: 392] [0] [<c00e38cc>] (sys_write+0x0/0x70) from [<c000e3c0>] (ret_fast_syscall+0x0/0x30) bluetoothd: 392] [0] r9 7c1a000 r8:c000e568 r6:400b5f10 r5:403896d8 r4:beeca604 bluetoothd: 392] [0] Code: e28cc00c e152000c 0a00000f e3a00001 (e1d210b8) bluetoothd: 392] [0] ---[ end trace 67b6ac67435864c4 ]--- bluetoothd: 392] [0] Kernel panic - not syncing: Fatal exception Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-12-11 06:13:12 +00:00
return err;
}
static void set_mesh_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_pending_cmd *cmd = data;
u8 status = mgmt_status(err);
struct sock *sk = cmd->sk;
if (status) {
mgmt_pending_foreach(MGMT_OP_SET_MESH_RECEIVER, hdev,
cmd_status_rsp, &status);
return;
}
mgmt_pending_remove(cmd);
mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER, 0, NULL, 0);
}
static int set_mesh_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_set_mesh *cp = cmd->param;
size_t len = cmd->param_len;
memset(hdev->mesh_ad_types, 0, sizeof(hdev->mesh_ad_types));
if (cp->enable)
hci_dev_set_flag(hdev, HCI_MESH);
else
hci_dev_clear_flag(hdev, HCI_MESH);
len -= sizeof(*cp);
/* If filters don't fit, forward all adv pkts */
if (len <= sizeof(hdev->mesh_ad_types))
memcpy(hdev->mesh_ad_types, cp->ad_types, len);
hci_update_passive_scan_sync(hdev);
return 0;
}
static int set_mesh(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{
struct mgmt_cp_set_mesh *cp = data;
struct mgmt_pending_cmd *cmd;
int err = 0;
bt_dev_dbg(hdev, "sock %p", sk);
if (!lmp_le_capable(hdev) ||
!hci_dev_test_flag(hdev, HCI_MESH_EXPERIMENTAL))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER,
MGMT_STATUS_NOT_SUPPORTED);
if (cp->enable != 0x00 && cp->enable != 0x01)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
cmd = mgmt_pending_add(sk, MGMT_OP_SET_MESH_RECEIVER, hdev, data, len);
if (!cmd)
err = -ENOMEM;
else
err = hci_cmd_sync_queue(hdev, set_mesh_sync, cmd,
set_mesh_complete);
if (err < 0) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_MESH_RECEIVER,
MGMT_STATUS_FAILED);
if (cmd)
mgmt_pending_remove(cmd);
}
hci_dev_unlock(hdev);
return err;
}
static void mesh_send_start_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_mesh_tx *mesh_tx = data;
struct mgmt_cp_mesh_send *send = (void *)mesh_tx->param;
unsigned long mesh_send_interval;
u8 mgmt_err = mgmt_status(err);
/* Report any errors here, but don't report completion */
if (mgmt_err) {
hci_dev_clear_flag(hdev, HCI_MESH_SENDING);
/* Send Complete Error Code for handle */
mesh_send_complete(hdev, mesh_tx, false);
return;
}
mesh_send_interval = msecs_to_jiffies((send->cnt) * 25);
queue_delayed_work(hdev->req_workqueue, &hdev->mesh_send_done,
mesh_send_interval);
}
static int mesh_send_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_mesh_tx *mesh_tx = data;
struct mgmt_cp_mesh_send *send = (void *)mesh_tx->param;
struct adv_info *adv, *next_instance;
u8 instance = hdev->le_num_of_adv_sets + 1;
u16 timeout, duration;
int err = 0;
if (hdev->le_num_of_adv_sets <= hdev->adv_instance_cnt)
return MGMT_STATUS_BUSY;
timeout = 1000;
duration = send->cnt * INTERVAL_TO_MS(hdev->le_adv_max_interval);
adv = hci_add_adv_instance(hdev, instance, 0,
send->adv_data_len, send->adv_data,
0, NULL,
timeout, duration,
HCI_ADV_TX_POWER_NO_PREFERENCE,
hdev->le_adv_min_interval,
hdev->le_adv_max_interval,
mesh_tx->handle);
if (!IS_ERR(adv))
mesh_tx->instance = instance;
else
err = PTR_ERR(adv);
if (hdev->cur_adv_instance == instance) {
/* If the currently advertised instance is being changed then
* cancel the current advertising and schedule the next
* instance. If there is only one instance then the overridden
* advertising data will be visible right away.
*/
cancel_adv_timeout(hdev);
next_instance = hci_get_next_instance(hdev, instance);
if (next_instance)
instance = next_instance->instance;
else
instance = 0;
} else if (hdev->adv_instance_timeout) {
/* Immediately advertise the new instance if no other, or
* let it go naturally from queue if ADV is already happening
*/
instance = 0;
}
if (instance)
return hci_schedule_adv_instance_sync(hdev, instance, true);
return err;
}
static void send_count(struct mgmt_mesh_tx *mesh_tx, void *data)
{
struct mgmt_rp_mesh_read_features *rp = data;
if (rp->used_handles >= rp->max_handles)
return;
rp->handles[rp->used_handles++] = mesh_tx->handle;
}
static int mesh_features(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_rp_mesh_read_features rp;
if (!lmp_le_capable(hdev) ||
!hci_dev_test_flag(hdev, HCI_MESH_EXPERIMENTAL))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_MESH_READ_FEATURES,
MGMT_STATUS_NOT_SUPPORTED);
memset(&rp, 0, sizeof(rp));
rp.index = cpu_to_le16(hdev->id);
if (hci_dev_test_flag(hdev, HCI_LE_ENABLED))
rp.max_handles = MESH_HANDLES_MAX;
hci_dev_lock(hdev);
if (rp.max_handles)
mgmt_mesh_foreach(hdev, send_count, &rp, sk);
mgmt_cmd_complete(sk, hdev->id, MGMT_OP_MESH_READ_FEATURES, 0, &rp,
rp.used_handles + sizeof(rp) - MESH_HANDLES_MAX);
hci_dev_unlock(hdev);
return 0;
}
static int send_cancel(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_mesh_send_cancel *cancel = (void *)cmd->param;
struct mgmt_mesh_tx *mesh_tx;
if (!cancel->handle) {
do {
mesh_tx = mgmt_mesh_next(hdev, cmd->sk);
if (mesh_tx)
mesh_send_complete(hdev, mesh_tx, false);
} while (mesh_tx);
} else {
mesh_tx = mgmt_mesh_find(hdev, cancel->handle);
if (mesh_tx && mesh_tx->sk == cmd->sk)
mesh_send_complete(hdev, mesh_tx, false);
}
mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_MESH_SEND_CANCEL,
0, NULL, 0);
mgmt_pending_free(cmd);
return 0;
}
static int mesh_send_cancel(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_pending_cmd *cmd;
int err;
if (!lmp_le_capable(hdev) ||
!hci_dev_test_flag(hdev, HCI_MESH_EXPERIMENTAL))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_MESH_SEND_CANCEL,
MGMT_STATUS_NOT_SUPPORTED);
if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_MESH_SEND_CANCEL,
MGMT_STATUS_REJECTED);
hci_dev_lock(hdev);
cmd = mgmt_pending_new(sk, MGMT_OP_MESH_SEND_CANCEL, hdev, data, len);
if (!cmd)
err = -ENOMEM;
else
err = hci_cmd_sync_queue(hdev, send_cancel, cmd, NULL);
if (err < 0) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_MESH_SEND_CANCEL,
MGMT_STATUS_FAILED);
if (cmd)
mgmt_pending_free(cmd);
}
hci_dev_unlock(hdev);
return err;
}
static int mesh_send(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{
struct mgmt_mesh_tx *mesh_tx;
struct mgmt_cp_mesh_send *send = data;
struct mgmt_rp_mesh_read_features rp;
bool sending;
int err = 0;
if (!lmp_le_capable(hdev) ||
!hci_dev_test_flag(hdev, HCI_MESH_EXPERIMENTAL))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_MESH_SEND,
MGMT_STATUS_NOT_SUPPORTED);
if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED) ||
len <= MGMT_MESH_SEND_SIZE ||
len > (MGMT_MESH_SEND_SIZE + 31))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_MESH_SEND,
MGMT_STATUS_REJECTED);
hci_dev_lock(hdev);
memset(&rp, 0, sizeof(rp));
rp.max_handles = MESH_HANDLES_MAX;
mgmt_mesh_foreach(hdev, send_count, &rp, sk);
if (rp.max_handles <= rp.used_handles) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_MESH_SEND,
MGMT_STATUS_BUSY);
goto done;
}
sending = hci_dev_test_flag(hdev, HCI_MESH_SENDING);
mesh_tx = mgmt_mesh_add(sk, hdev, send, len);
if (!mesh_tx)
err = -ENOMEM;
else if (!sending)
err = hci_cmd_sync_queue(hdev, mesh_send_sync, mesh_tx,
mesh_send_start_complete);
if (err < 0) {
bt_dev_err(hdev, "Send Mesh Failed %d", err);
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_MESH_SEND,
MGMT_STATUS_FAILED);
if (mesh_tx) {
if (sending)
mgmt_mesh_remove(mesh_tx);
}
} else {
hci_dev_set_flag(hdev, HCI_MESH_SENDING);
mgmt_cmd_complete(sk, hdev->id, MGMT_OP_MESH_SEND, 0,
&mesh_tx->handle, 1);
}
done:
hci_dev_unlock(hdev);
return err;
}
static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{
struct mgmt_mode *cp = data;
struct mgmt_pending_cmd *cmd;
int err;
u8 val, enabled;
bt_dev_dbg(hdev, "sock %p", sk);
if (!lmp_le_capable(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_NOT_SUPPORTED);
if (cp->val != 0x00 && cp->val != 0x01)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_INVALID_PARAMS);
/* Bluetooth single mode LE only controllers or dual-mode
* controllers configured as LE only devices, do not allow
* switching LE off. These have either LE enabled explicitly
* or BR/EDR has been previously switched off.
*
* When trying to enable an already enabled LE, then gracefully
* send a positive response. Trying to disable it however will
* result into rejection.
*/
if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
if (cp->val == 0x01)
return send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_REJECTED);
}
hci_dev_lock(hdev);
val = !!cp->val;
enabled = lmp_host_le_capable(hdev);
if (!hdev_is_powered(hdev) || val == enabled) {
bool changed = false;
if (val != hci_dev_test_flag(hdev, HCI_LE_ENABLED)) {
hci_dev_change_flag(hdev, HCI_LE_ENABLED);
changed = true;
}
if (!val && hci_dev_test_flag(hdev, HCI_ADVERTISING)) {
hci_dev_clear_flag(hdev, HCI_ADVERTISING);
changed = true;
}
err = send_settings_rsp(sk, MGMT_OP_SET_LE, hdev);
if (err < 0)
goto unlock;
if (changed)
err = new_settings(hdev, sk);
goto unlock;
}
if (pending_find(MGMT_OP_SET_LE, hdev) ||
pending_find(MGMT_OP_SET_ADVERTISING, hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_BUSY);
goto unlock;
}
cmd = mgmt_pending_add(sk, MGMT_OP_SET_LE, hdev, data, len);
if (!cmd)
err = -ENOMEM;
else
err = hci_cmd_sync_queue(hdev, set_le_sync, cmd,
set_le_complete);
if (err < 0) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LE,
MGMT_STATUS_FAILED);
if (cmd)
mgmt_pending_remove(cmd);
}
unlock:
hci_dev_unlock(hdev);
return err;
}
/* This is a helper function to test for pending mgmt commands that can
* cause CoD or EIR HCI commands. We can only allow one such pending
* mgmt command at a time since otherwise we cannot easily track what
* the current values are, will be, and based on that calculate if a new
* HCI command needs to be sent and if yes with what value.
*/
static bool pending_eir_or_class(struct hci_dev *hdev)
{
struct mgmt_pending_cmd *cmd;
list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
switch (cmd->opcode) {
case MGMT_OP_ADD_UUID:
case MGMT_OP_REMOVE_UUID:
case MGMT_OP_SET_DEV_CLASS:
case MGMT_OP_SET_POWERED:
return true;
}
}
return false;
}
static const u8 bluetooth_base_uuid[] = {
0xfb, 0x34, 0x9b, 0x5f, 0x80, 0x00, 0x00, 0x80,
0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
static u8 get_uuid_size(const u8 *uuid)
{
u32 val;
if (memcmp(uuid, bluetooth_base_uuid, 12))
return 128;
val = get_unaligned_le32(&uuid[12]);
if (val > 0xffff)
return 32;
return 16;
}
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
static void mgmt_class_complete(struct hci_dev *hdev, void *data, int err)
{
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
struct mgmt_pending_cmd *cmd = data;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
bt_dev_dbg(hdev, "err %d", err);
mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
mgmt_status(err), hdev->dev_class, 3);
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
mgmt_pending_free(cmd);
}
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
static int add_uuid_sync(struct hci_dev *hdev, void *data)
{
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
int err;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
err = hci_update_class_sync(hdev);
if (err)
return err;
return hci_update_eir_sync(hdev);
}
static int add_uuid(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{
struct mgmt_cp_add_uuid *cp = data;
struct mgmt_pending_cmd *cmd;
struct bt_uuid *uuid;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
if (pending_eir_or_class(hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_UUID,
MGMT_STATUS_BUSY);
goto failed;
}
uuid = kmalloc(sizeof(*uuid), GFP_KERNEL);
if (!uuid) {
err = -ENOMEM;
goto failed;
}
memcpy(uuid->uuid, cp->uuid, 16);
uuid->svc_hint = cp->svc_hint;
uuid->size = get_uuid_size(cp->uuid);
list_add_tail(&uuid->list, &hdev->uuids);
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
cmd = mgmt_pending_new(sk, MGMT_OP_ADD_UUID, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
}
/* MGMT_OP_ADD_UUID don't require adapter the UP/Running so use
* hci_cmd_sync_submit instead of hci_cmd_sync_queue.
*/
err = hci_cmd_sync_submit(hdev, add_uuid_sync, cmd,
mgmt_class_complete);
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
if (err < 0) {
mgmt_pending_free(cmd);
goto failed;
}
failed:
hci_dev_unlock(hdev);
return err;
}
static bool enable_service_cache(struct hci_dev *hdev)
{
if (!hdev_is_powered(hdev))
return false;
if (!hci_dev_test_and_set_flag(hdev, HCI_SERVICE_CACHE)) {
queue_delayed_work(hdev->workqueue, &hdev->service_cache,
CACHE_TIMEOUT);
return true;
}
return false;
}
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
static int remove_uuid_sync(struct hci_dev *hdev, void *data)
{
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
int err;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
err = hci_update_class_sync(hdev);
if (err)
return err;
return hci_update_eir_sync(hdev);
}
static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_remove_uuid *cp = data;
struct mgmt_pending_cmd *cmd;
struct bt_uuid *match, *tmp;
static const u8 bt_uuid_any[] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
int err, found;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
if (pending_eir_or_class(hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
MGMT_STATUS_BUSY);
goto unlock;
}
if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) {
hci_uuids_clear(hdev);
if (enable_service_cache(hdev)) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_REMOVE_UUID,
0, hdev->dev_class, 3);
goto unlock;
}
goto update_class;
}
found = 0;
list_for_each_entry_safe(match, tmp, &hdev->uuids, list) {
if (memcmp(match->uuid, cp->uuid, 16) != 0)
continue;
list_del(&match->list);
kfree(match);
found++;
}
if (found == 0) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_UUID,
MGMT_STATUS_INVALID_PARAMS);
goto unlock;
}
update_class:
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
cmd = mgmt_pending_new(sk, MGMT_OP_REMOVE_UUID, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
goto unlock;
}
/* MGMT_OP_REMOVE_UUID don't require adapter the UP/Running so use
* hci_cmd_sync_submit instead of hci_cmd_sync_queue.
*/
err = hci_cmd_sync_submit(hdev, remove_uuid_sync, cmd,
mgmt_class_complete);
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
if (err < 0)
mgmt_pending_free(cmd);
unlock:
hci_dev_unlock(hdev);
return err;
}
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
static int set_class_sync(struct hci_dev *hdev, void *data)
{
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
int err = 0;
if (hci_dev_test_and_clear_flag(hdev, HCI_SERVICE_CACHE)) {
cancel_delayed_work_sync(&hdev->service_cache);
err = hci_update_eir_sync(hdev);
}
if (err)
return err;
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
return hci_update_class_sync(hdev);
}
static int set_dev_class(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_set_dev_class *cp = data;
struct mgmt_pending_cmd *cmd;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (!lmp_bredr_capable(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
MGMT_STATUS_NOT_SUPPORTED);
hci_dev_lock(hdev);
if (pending_eir_or_class(hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
MGMT_STATUS_BUSY);
goto unlock;
}
if ((cp->minor & 0x03) != 0 || (cp->major & 0xe0) != 0) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEV_CLASS,
MGMT_STATUS_INVALID_PARAMS);
goto unlock;
}
hdev->major_class = cp->major;
hdev->minor_class = cp->minor;
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEV_CLASS, 0,
hdev->dev_class, 3);
goto unlock;
}
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
cmd = mgmt_pending_new(sk, MGMT_OP_SET_DEV_CLASS, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
goto unlock;
}
/* MGMT_OP_SET_DEV_CLASS don't require adapter the UP/Running so use
* hci_cmd_sync_submit instead of hci_cmd_sync_queue.
*/
err = hci_cmd_sync_submit(hdev, set_class_sync, cmd,
mgmt_class_complete);
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
if (err < 0)
mgmt_pending_free(cmd);
unlock:
hci_dev_unlock(hdev);
return err;
}
static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_load_link_keys *cp = data;
const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
sizeof(struct mgmt_link_key_info));
u16 key_count, expected_len;
bool changed;
int i;
bt_dev_dbg(hdev, "sock %p", sk);
if (!lmp_bredr_capable(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
MGMT_STATUS_NOT_SUPPORTED);
key_count = __le16_to_cpu(cp->key_count);
if (key_count > max_key_count) {
bt_dev_err(hdev, "load_link_keys: too big key_count value %u",
key_count);
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
MGMT_STATUS_INVALID_PARAMS);
}
expected_len = struct_size(cp, keys, key_count);
if (expected_len != len) {
bt_dev_err(hdev, "load_link_keys: expected %u bytes, got %u bytes",
expected_len, len);
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
MGMT_STATUS_INVALID_PARAMS);
}
if (cp->debug_keys != 0x00 && cp->debug_keys != 0x01)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS,
MGMT_STATUS_INVALID_PARAMS);
bt_dev_dbg(hdev, "debug_keys %u key_count %u", cp->debug_keys,
key_count);
for (i = 0; i < key_count; i++) {
struct mgmt_link_key_info *key = &cp->keys[i];
Bluetooth: MGMT/SMP: Fix address type when using SMP over BREDR/LE If two Bluetooth devices both support BR/EDR and BLE, and also support Secure Connections, then they only need to pair once. The LTK generated during the LE pairing process may be converted into a BR/EDR link key for BR/EDR transport, and conversely, a link key generated during the BR/EDR SSP pairing process can be converted into an LTK for LE transport. Hence, the link type of the link key and LTK is not fixed, they can be either an LE LINK or an ACL LINK. Currently, in the mgmt_new_irk/ltk/crsk/link_key functions, the link type is fixed, which could lead to incorrect address types being reported to the application layer. Therefore, it is necessary to add link_type/addr_type to the smp_irk/ltk/crsk and link_key, to ensure the generation of the correct address type. SMP over BREDR: Before Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) After Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) SMP over LE: Before Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5F:5C:07:37:47:D5 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) After Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5E:03:1C:00:38:21 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 Store hint: Yes (0x01) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) Cc: stable@vger.kernel.org Signed-off-by: Xiao Yao <xiaoyao@rock-chips.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-12-11 16:27:18 +00:00
/* Considering SMP over BREDR/LE, there is no need to check addr_type */
if (key->type > 0x08)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_LOAD_LINK_KEYS,
MGMT_STATUS_INVALID_PARAMS);
}
hci_dev_lock(hdev);
hci_link_keys_clear(hdev);
if (cp->debug_keys)
changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
else
changed = hci_dev_test_and_clear_flag(hdev,
HCI_KEEP_DEBUG_KEYS);
if (changed)
new_settings(hdev, NULL);
for (i = 0; i < key_count; i++) {
struct mgmt_link_key_info *key = &cp->keys[i];
if (hci_is_blocked_key(hdev,
HCI_BLOCKED_KEY_TYPE_LINKKEY,
key->val)) {
bt_dev_warn(hdev, "Skipping blocked link key for %pMR",
&key->addr.bdaddr);
continue;
}
/* Always ignore debug keys and require a new pairing if
* the user wants to use them.
*/
if (key->type == HCI_LK_DEBUG_COMBINATION)
continue;
hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val,
key->type, key->pin_len, NULL);
}
mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0);
hci_dev_unlock(hdev);
return 0;
}
static int device_unpaired(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type, struct sock *skip_sk)
{
struct mgmt_ev_device_unpaired ev;
bacpy(&ev.addr.bdaddr, bdaddr);
ev.addr.type = addr_type;
return mgmt_event(MGMT_EV_DEVICE_UNPAIRED, hdev, &ev, sizeof(ev),
skip_sk);
}
static void unpair_device_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_unpair_device *cp = cmd->param;
if (!err)
device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
cmd->cmd_complete(cmd, err);
mgmt_pending_free(cmd);
}
static int unpair_device_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_unpair_device *cp = cmd->param;
struct hci_conn *conn;
if (cp->addr.type == BDADDR_BREDR)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
&cp->addr.bdaddr);
else
conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr,
le_addr_type(cp->addr.type));
if (!conn)
return 0;
return hci_abort_conn_sync(hdev, conn, HCI_ERROR_REMOTE_USER_TERM);
}
static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_unpair_device *cp = data;
struct mgmt_rp_unpair_device rp;
struct hci_conn_params *params;
struct mgmt_pending_cmd *cmd;
struct hci_conn *conn;
u8 addr_type;
int err;
memset(&rp, 0, sizeof(rp));
bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
rp.addr.type = cp->addr.type;
if (!bdaddr_type_is_valid(cp->addr.type))
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&rp, sizeof(rp));
if (cp->disconnect != 0x00 && cp->disconnect != 0x01)
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&rp, sizeof(rp));
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
MGMT_STATUS_NOT_POWERED, &rp,
sizeof(rp));
goto unlock;
}
if (cp->addr.type == BDADDR_BREDR) {
/* If disconnection is requested, then look up the
* connection. If the remote device is connected, it
* will be later used to terminate the link.
*
* Setting it to NULL explicitly will cause no
* termination of the link.
*/
if (cp->disconnect)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
&cp->addr.bdaddr);
else
conn = NULL;
err = hci_remove_link_key(hdev, &cp->addr.bdaddr);
if (err < 0) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_UNPAIR_DEVICE,
MGMT_STATUS_NOT_PAIRED, &rp,
sizeof(rp));
goto unlock;
}
goto done;
}
/* LE address type */
addr_type = le_addr_type(cp->addr.type);
Bluetooth: SMP: fix crash in unpairing In case unpair_device() was called through mgmt interface at the same time when pairing was in progress, Bluetooth kernel module crash was seen. [ 600.351225] general protection fault: 0000 [#1] SMP PTI [ 600.351235] CPU: 1 PID: 11096 Comm: btmgmt Tainted: G OE 4.19.0-rc1+ #1 [ 600.351238] Hardware name: Dell Inc. Latitude E5440/08RCYC, BIOS A18 05/14/2017 [ 600.351272] RIP: 0010:smp_chan_destroy.isra.10+0xce/0x2c0 [bluetooth] [ 600.351276] Code: c0 0f 84 b4 01 00 00 80 78 28 04 0f 84 53 01 00 00 4d 85 ed 0f 85 ab 00 00 00 48 8b 08 48 8b 50 08 be 10 00 00 00 48 89 51 08 <48> 89 0a 48 b9 00 02 00 00 00 00 ad de 48 89 48 08 48 8b 83 00 01 [ 600.351279] RSP: 0018:ffffa9be839b3b50 EFLAGS: 00010246 [ 600.351282] RAX: ffff9c999ac565a0 RBX: ffff9c9996e98c00 RCX: ffff9c999aa28b60 [ 600.351285] RDX: dead000000000200 RSI: 0000000000000010 RDI: ffff9c999e403500 [ 600.351287] RBP: ffffa9be839b3b70 R08: 0000000000000000 R09: ffffffff92a25c00 [ 600.351290] R10: ffffa9be839b3ae8 R11: 0000000000000001 R12: ffff9c995375b800 [ 600.351292] R13: 0000000000000000 R14: ffff9c99619a5000 R15: ffff9c9962a01c00 [ 600.351295] FS: 00007fb2be27c700(0000) GS:ffff9c999e880000(0000) knlGS:0000000000000000 [ 600.351298] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 600.351300] CR2: 00007fb2bdadbad0 CR3: 000000041c328001 CR4: 00000000001606e0 [ 600.351302] Call Trace: [ 600.351325] smp_failure+0x4f/0x70 [bluetooth] [ 600.351345] smp_cancel_pairing+0x74/0x80 [bluetooth] [ 600.351370] unpair_device+0x1c1/0x330 [bluetooth] [ 600.351399] hci_sock_sendmsg+0x960/0x9f0 [bluetooth] [ 600.351409] ? apparmor_socket_sendmsg+0x1e/0x20 [ 600.351417] sock_sendmsg+0x3e/0x50 [ 600.351422] sock_write_iter+0x85/0xf0 [ 600.351429] do_iter_readv_writev+0x12b/0x1b0 [ 600.351434] do_iter_write+0x87/0x1a0 [ 600.351439] vfs_writev+0x98/0x110 [ 600.351443] ? ep_poll+0x16d/0x3d0 [ 600.351447] ? ep_modify+0x73/0x170 [ 600.351451] do_writev+0x61/0xf0 [ 600.351455] ? do_writev+0x61/0xf0 [ 600.351460] __x64_sys_writev+0x1c/0x20 [ 600.351465] do_syscall_64+0x5a/0x110 [ 600.351471] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 600.351474] RIP: 0033:0x7fb2bdb62fe0 [ 600.351477] Code: 73 01 c3 48 8b 0d b8 6e 2c 00 f7 d8 64 89 01 48 83 c8 ff c3 66 0f 1f 44 00 00 83 3d 69 c7 2c 00 00 75 10 b8 14 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 31 c3 48 83 ec 08 e8 de 80 01 00 48 89 04 24 [ 600.351479] RSP: 002b:00007ffe062cb8f8 EFLAGS: 00000246 ORIG_RAX: 0000000000000014 [ 600.351484] RAX: ffffffffffffffda RBX: 000000000255b3d0 RCX: 00007fb2bdb62fe0 [ 600.351487] RDX: 0000000000000001 RSI: 00007ffe062cb920 RDI: 0000000000000004 [ 600.351490] RBP: 00007ffe062cb920 R08: 000000000255bd80 R09: 0000000000000000 [ 600.351494] R10: 0000000000000353 R11: 0000000000000246 R12: 0000000000000001 [ 600.351497] R13: 00007ffe062cbbe0 R14: 0000000000000000 R15: 0000000000000000 [ 600.351501] Modules linked in: algif_hash algif_skcipher af_alg cmac ipt_MASQUERADE nf_conntrack_netlink nfnetlink xfrm_user xfrm_algo iptable_nat nf_nat_ipv4 xt_addrtype iptable_filter ip_tables xt_conntrack x_tables nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 libcrc32c br_netfilter bridge stp llc overlay arc4 nls_iso8859_1 dm_crypt intel_rapl x86_pkg_temp_thermal intel_powerclamp coretemp dell_laptop kvm_intel crct10dif_pclmul dell_smm_hwmon crc32_pclmul ghash_clmulni_intel pcbc aesni_intel aes_x86_64 crypto_simd cryptd glue_helper intel_cstate intel_rapl_perf uvcvideo videobuf2_vmalloc videobuf2_memops videobuf2_v4l2 videobuf2_common videodev media hid_multitouch input_leds joydev serio_raw dell_wmi snd_hda_codec_hdmi snd_hda_codec_realtek snd_hda_codec_generic dell_smbios dcdbas sparse_keymap [ 600.351569] snd_hda_intel btusb snd_hda_codec btrtl btbcm btintel snd_hda_core bluetooth(OE) snd_hwdep snd_pcm iwlmvm ecdh_generic wmi_bmof dell_wmi_descriptor snd_seq_midi mac80211 snd_seq_midi_event lpc_ich iwlwifi snd_rawmidi snd_seq snd_seq_device snd_timer cfg80211 snd soundcore mei_me mei dell_rbtn dell_smo8800 mac_hid parport_pc ppdev lp parport autofs4 hid_generic usbhid hid i915 nouveau kvmgt vfio_mdev mdev vfio_iommu_type1 vfio kvm irqbypass i2c_algo_bit ttm drm_kms_helper syscopyarea sysfillrect sysimgblt mxm_wmi psmouse ahci sdhci_pci cqhci libahci fb_sys_fops sdhci drm e1000e video wmi [ 600.351637] ---[ end trace e49e9f1df09c94fb ]--- [ 600.351664] RIP: 0010:smp_chan_destroy.isra.10+0xce/0x2c0 [bluetooth] [ 600.351666] Code: c0 0f 84 b4 01 00 00 80 78 28 04 0f 84 53 01 00 00 4d 85 ed 0f 85 ab 00 00 00 48 8b 08 48 8b 50 08 be 10 00 00 00 48 89 51 08 <48> 89 0a 48 b9 00 02 00 00 00 00 ad de 48 89 48 08 48 8b 83 00 01 [ 600.351669] RSP: 0018:ffffa9be839b3b50 EFLAGS: 00010246 [ 600.351672] RAX: ffff9c999ac565a0 RBX: ffff9c9996e98c00 RCX: ffff9c999aa28b60 [ 600.351674] RDX: dead000000000200 RSI: 0000000000000010 RDI: ffff9c999e403500 [ 600.351676] RBP: ffffa9be839b3b70 R08: 0000000000000000 R09: ffffffff92a25c00 [ 600.351679] R10: ffffa9be839b3ae8 R11: 0000000000000001 R12: ffff9c995375b800 [ 600.351681] R13: 0000000000000000 R14: ffff9c99619a5000 R15: ffff9c9962a01c00 [ 600.351684] FS: 00007fb2be27c700(0000) GS:ffff9c999e880000(0000) knlGS:0000000000000000 [ 600.351686] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 600.351689] CR2: 00007fb2bdadbad0 CR3: 000000041c328001 CR4: 00000000001606e0 Crash happened because list_del_rcu() was called twice for smp->ltk. This was possible if unpair_device was called right after ltk was generated but before keys were distributed. In this commit smp_cancel_pairing was refactored to cancel pairing if it is in progress and otherwise just removes keys. Once keys are removed from rcu list, pointers to smp context's keys are set to NULL to make sure removed list items are not accessed later. This commit also adjusts the functionality of mgmt unpair_device() little bit. Previously pairing was canceled only if pairing was in state that keys were already generated. With this commit unpair_device() cancels pairing already in earlier states. Bug was found by fuzzing kernel SMP implementation using Synopsys Defensics. Reported-by: Pekka Oikarainen <pekka.oikarainen@synopsys.com> Signed-off-by: Matias Karhumaa <matias.karhumaa@gmail.com> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2018-09-26 06:13:46 +00:00
/* Abort any ongoing SMP pairing. Removes ltk and irk if they exist. */
err = smp_cancel_and_remove_pairing(hdev, &cp->addr.bdaddr, addr_type);
if (err < 0) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE,
MGMT_STATUS_NOT_PAIRED, &rp,
sizeof(rp));
goto unlock;
}
conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr, addr_type);
if (!conn) {
hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type);
goto done;
}
Bluetooth: Fix crash in SMP when unpairing When unpairing the keys stored in hci_dev are removed. If SMP is ongoing the SMP context will also have references to these keys, so removing them from the hci_dev lists will make the pointers invalid. This can result in the following type of crashes: BUG: unable to handle kernel paging request at 6b6b6b6b IP: [<c11f26be>] __list_del_entry+0x44/0x71 *pde = 00000000 Oops: 0000 [#1] PREEMPT SMP DEBUG_PAGEALLOC Modules linked in: hci_uart btqca btusb btintel btbcm btrtl hci_vhci rfcomm bluetooth_6lowpan bluetooth CPU: 0 PID: 723 Comm: kworker/u5:0 Not tainted 4.3.0-rc3+ #1379 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.8.1-20150318_183358- 04/01/2014 Workqueue: hci0 hci_rx_work [bluetooth] task: f19da940 ti: f1a94000 task.ti: f1a94000 EIP: 0060:[<c11f26be>] EFLAGS: 00010202 CPU: 0 EIP is at __list_del_entry+0x44/0x71 EAX: c0088d20 EBX: f30fcac0 ECX: 6b6b6b6b EDX: 6b6b6b6b ESI: f4b60000 EDI: c0088d20 EBP: f1a95d90 ESP: f1a95d8c DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 CR0: 8005003b CR2: 6b6b6b6b CR3: 319e5000 CR4: 00000690 Stack: f30fcac0 f1a95db0 f82dc3e1 f1bfc000 00000000 c106524f f1bfc000 f30fd020 f1a95dc0 f1a95dd0 f82dcbdb f1a95de0 f82dcbdb 00000067 f1bfc000 f30fd020 f1a95de0 f1a95df0 f82d1126 00000067 f82d1126 00000006 f30fd020 f1bfc000 Call Trace: [<f82dc3e1>] smp_chan_destroy+0x192/0x240 [bluetooth] [<c106524f>] ? trace_hardirqs_on_caller+0x14e/0x169 [<f82dcbdb>] smp_teardown_cb+0x47/0x64 [bluetooth] [<f82dcbdb>] ? smp_teardown_cb+0x47/0x64 [bluetooth] [<f82d1126>] l2cap_chan_del+0x5d/0x14d [bluetooth] [<f82d1126>] ? l2cap_chan_del+0x5d/0x14d [bluetooth] [<f82d40ef>] l2cap_conn_del+0x109/0x17b [bluetooth] [<f82d40ef>] ? l2cap_conn_del+0x109/0x17b [bluetooth] [<f82c0205>] ? hci_event_packet+0x5b1/0x2092 [bluetooth] [<f82d41aa>] l2cap_disconn_cfm+0x49/0x50 [bluetooth] [<f82d41aa>] ? l2cap_disconn_cfm+0x49/0x50 [bluetooth] [<f82c0228>] hci_event_packet+0x5d4/0x2092 [bluetooth] [<c1332c16>] ? skb_release_data+0x6a/0x95 [<f82ce5d4>] ? hci_send_to_monitor+0xe7/0xf4 [bluetooth] [<c1409708>] ? _raw_spin_unlock_irqrestore+0x44/0x57 [<f82b3bb0>] hci_rx_work+0xf1/0x28b [bluetooth] [<f82b3bb0>] ? hci_rx_work+0xf1/0x28b [bluetooth] [<c10635a0>] ? __lock_is_held+0x2e/0x44 [<c104772e>] process_one_work+0x232/0x432 [<c1071ddc>] ? rcu_read_lock_sched_held+0x50/0x5a [<c104772e>] ? process_one_work+0x232/0x432 [<c1047d48>] worker_thread+0x1b8/0x255 [<c1047b90>] ? rescuer_thread+0x23c/0x23c [<c104bb71>] kthread+0x91/0x96 [<c14096a7>] ? _raw_spin_unlock_irq+0x27/0x44 [<c1409d61>] ret_from_kernel_thread+0x21/0x30 [<c104bae0>] ? kthread_parkme+0x1e/0x1e To solve the issue, introduce a new smp_cancel_pairing() API that can be used to clean up the SMP state before touching the hci_dev lists. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2015-10-22 06:38:35 +00:00
/* Defer clearing up the connection parameters until closing to
* give a chance of keeping them if a repairing happens.
*/
set_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
/* Disable auto-connection parameters if present */
params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, addr_type);
if (params) {
if (params->explicit_connect)
params->auto_connect = HCI_AUTO_CONN_EXPLICIT;
else
params->auto_connect = HCI_AUTO_CONN_DISABLED;
}
/* If disconnection is not requested, then clear the connection
* variable so that the link is not terminated.
*/
if (!cp->disconnect)
conn = NULL;
done:
/* If the connection variable is set, then termination of the
* link is requested.
*/
if (!conn) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, 0,
&rp, sizeof(rp));
device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, sk);
goto unlock;
}
cmd = mgmt_pending_new(sk, MGMT_OP_UNPAIR_DEVICE, hdev, cp,
sizeof(*cp));
if (!cmd) {
err = -ENOMEM;
goto unlock;
}
cmd->cmd_complete = addr_cmd_complete;
err = hci_cmd_sync_queue(hdev, unpair_device_sync, cmd,
unpair_device_complete);
if (err < 0)
mgmt_pending_free(cmd);
unlock:
hci_dev_unlock(hdev);
return err;
}
static int disconnect(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_disconnect *cp = data;
struct mgmt_rp_disconnect rp;
struct mgmt_pending_cmd *cmd;
struct hci_conn *conn;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
memset(&rp, 0, sizeof(rp));
bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
rp.addr.type = cp->addr.type;
if (!bdaddr_type_is_valid(cp->addr.type))
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
MGMT_STATUS_INVALID_PARAMS,
&rp, sizeof(rp));
hci_dev_lock(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
MGMT_STATUS_NOT_POWERED, &rp,
sizeof(rp));
goto failed;
}
if (pending_find(MGMT_OP_DISCONNECT, hdev)) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
MGMT_STATUS_BUSY, &rp, sizeof(rp));
goto failed;
}
if (cp->addr.type == BDADDR_BREDR)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
&cp->addr.bdaddr);
else
conn = hci_conn_hash_lookup_le(hdev, &cp->addr.bdaddr,
le_addr_type(cp->addr.type));
if (!conn || conn->state == BT_OPEN || conn->state == BT_CLOSED) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_DISCONNECT,
MGMT_STATUS_NOT_CONNECTED, &rp,
sizeof(rp));
goto failed;
}
cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
}
cmd->cmd_complete = generic_cmd_complete;
err = hci_disconnect(conn, HCI_ERROR_REMOTE_USER_TERM);
if (err < 0)
mgmt_pending_remove(cmd);
failed:
hci_dev_unlock(hdev);
return err;
}
static u8 link_to_bdaddr(u8 link_type, u8 addr_type)
{
switch (link_type) {
case ISO_LINK:
case LE_LINK:
switch (addr_type) {
case ADDR_LE_DEV_PUBLIC:
return BDADDR_LE_PUBLIC;
default:
/* Fallback to LE Random address type */
return BDADDR_LE_RANDOM;
}
default:
/* Fallback to BR/EDR type */
return BDADDR_BREDR;
}
}
static int get_connections(struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len)
{
struct mgmt_rp_get_connections *rp;
struct hci_conn *c;
int err;
u16 i;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_CONNECTIONS,
MGMT_STATUS_NOT_POWERED);
goto unlock;
}
i = 0;
list_for_each_entry(c, &hdev->conn_hash.list, list) {
if (test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
i++;
}
rp = kmalloc(struct_size(rp, addr, i), GFP_KERNEL);
if (!rp) {
err = -ENOMEM;
goto unlock;
}
i = 0;
list_for_each_entry(c, &hdev->conn_hash.list, list) {
if (!test_bit(HCI_CONN_MGMT_CONNECTED, &c->flags))
continue;
bacpy(&rp->addr[i].bdaddr, &c->dst);
rp->addr[i].type = link_to_bdaddr(c->type, c->dst_type);
if (c->type == SCO_LINK || c->type == ESCO_LINK)
continue;
i++;
}
rp->conn_count = cpu_to_le16(i);
/* Recalculate length in case of filtered SCO connections, etc */
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONNECTIONS, 0, rp,
struct_size(rp, addr, i));
kfree(rp);
unlock:
hci_dev_unlock(hdev);
return err;
}
static int send_pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
struct mgmt_cp_pin_code_neg_reply *cp)
{
struct mgmt_pending_cmd *cmd;
int err;
cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, hdev, cp,
sizeof(*cp));
if (!cmd)
return -ENOMEM;
Bluetooth: Fix NULL pointer dereference in mgmt context Adds missing callback assignment to cmd_complete in pending management command context. Dump path involves security procedure performed on legacy (pre-SSP) devices with service security requirements set to HIGH (16digits PIN). It fails when shorter PIN is delivered by user. [ 1.517950] Bluetooth: PIN code is not 16 bytes long [ 1.518491] BUG: unable to handle kernel NULL pointer dereference at (null) [ 1.518584] IP: [< (null)>] (null) [ 1.518584] PGD 9e08067 PUD 9fdf067 PMD 0 [ 1.518584] Oops: 0010 [#1] SMP [ 1.518584] Modules linked in: [ 1.518584] CPU: 0 PID: 1002 Comm: kworker/u3:2 Not tainted 4.8.0-rc6-354649-gaf4168c #16 [ 1.518584] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.9.3-20160701_074356-anatol 04/01/2014 [ 1.518584] Workqueue: hci0 hci_rx_work [ 1.518584] task: ffff880009ce14c0 task.stack: ffff880009e10000 [ 1.518584] RIP: 0010:[<0000000000000000>] [< (null)>] (null) [ 1.518584] RSP: 0018:ffff880009e13bc8 EFLAGS: 00010293 [ 1.518584] RAX: 0000000000000000 RBX: ffff880009eed100 RCX: 0000000000000006 [ 1.518584] RDX: ffff880009ddc000 RSI: 0000000000000000 RDI: ffff880009eed100 [ 1.518584] RBP: ffff880009e13be0 R08: 0000000000000000 R09: 0000000000000001 [ 1.518584] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000 [ 1.518584] R13: ffff880009e13ccd R14: ffff880009ddc000 R15: ffff880009ddc010 [ 1.518584] FS: 0000000000000000(0000) GS:ffff88000bc00000(0000) knlGS:0000000000000000 [ 1.518584] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 1.518584] CR2: 0000000000000000 CR3: 0000000009fdd000 CR4: 00000000000006f0 [ 1.518584] Stack: [ 1.518584] ffffffff81909808 ffff880009e13cce ffff880009e0d40b ffff880009e13c68 [ 1.518584] ffffffff818f428d 00000000024000c0 ffff880009e13c08 ffffffff810ca903 [ 1.518584] ffff880009e13c48 ffffffff811ade34 ffffffff8178c31f ffff880009ee6200 [ 1.518584] Call Trace: [ 1.518584] [<ffffffff81909808>] ? mgmt_pin_code_neg_reply_complete+0x38/0x60 [ 1.518584] [<ffffffff818f428d>] hci_cmd_complete_evt+0x69d/0x3200 [ 1.518584] [<ffffffff810ca903>] ? rcu_read_lock_sched_held+0x53/0x60 [ 1.518584] [<ffffffff811ade34>] ? kmem_cache_alloc+0x1a4/0x200 [ 1.518584] [<ffffffff8178c31f>] ? skb_clone+0x4f/0xa0 [ 1.518584] [<ffffffff818f9d81>] hci_event_packet+0x8e1/0x28e0 [ 1.518584] [<ffffffff81a421f1>] ? _raw_spin_unlock_irqrestore+0x31/0x50 [ 1.518584] [<ffffffff810aea3e>] ? trace_hardirqs_on_caller+0xee/0x1b0 [ 1.518584] [<ffffffff818e6bd1>] hci_rx_work+0x1e1/0x5b0 [ 1.518584] [<ffffffff8107e4bd>] ? process_one_work+0x1ed/0x6b0 [ 1.518584] [<ffffffff8107e538>] process_one_work+0x268/0x6b0 [ 1.518584] [<ffffffff8107e4bd>] ? process_one_work+0x1ed/0x6b0 [ 1.518584] [<ffffffff8107e9c3>] worker_thread+0x43/0x4e0 [ 1.518584] [<ffffffff8107e980>] ? process_one_work+0x6b0/0x6b0 [ 1.518584] [<ffffffff8107e980>] ? process_one_work+0x6b0/0x6b0 [ 1.518584] [<ffffffff8108505f>] kthread+0xdf/0x100 [ 1.518584] [<ffffffff81a4297f>] ret_from_fork+0x1f/0x40 [ 1.518584] [<ffffffff81084f80>] ? kthread_create_on_node+0x210/0x210 Signed-off-by: Arek Lichwa <arek.lichwa@gmail.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2016-09-22 12:08:05 +00:00
cmd->cmd_complete = addr_cmd_complete;
err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY,
sizeof(cp->addr.bdaddr), &cp->addr.bdaddr);
if (err < 0)
mgmt_pending_remove(cmd);
return err;
}
static int pin_code_reply(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct hci_conn *conn;
struct mgmt_cp_pin_code_reply *cp = data;
struct hci_cp_pin_code_reply reply;
struct mgmt_pending_cmd *cmd;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
MGMT_STATUS_NOT_POWERED);
goto failed;
}
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
if (!conn) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
MGMT_STATUS_NOT_CONNECTED);
goto failed;
}
if (conn->pending_sec_level == BT_SECURITY_HIGH && cp->pin_len != 16) {
struct mgmt_cp_pin_code_neg_reply ncp;
memcpy(&ncp.addr, &cp->addr, sizeof(ncp.addr));
bt_dev_err(hdev, "PIN code is not 16 bytes long");
err = send_pin_code_neg_reply(sk, hdev, &ncp);
if (err >= 0)
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_PIN_CODE_REPLY,
MGMT_STATUS_INVALID_PARAMS);
goto failed;
}
cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
}
cmd->cmd_complete = addr_cmd_complete;
bacpy(&reply.bdaddr, &cp->addr.bdaddr);
reply.pin_len = cp->pin_len;
memcpy(reply.pin_code, cp->pin_code, sizeof(reply.pin_code));
err = hci_send_cmd(hdev, HCI_OP_PIN_CODE_REPLY, sizeof(reply), &reply);
if (err < 0)
mgmt_pending_remove(cmd);
failed:
hci_dev_unlock(hdev);
return err;
}
static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_set_io_capability *cp = data;
bt_dev_dbg(hdev, "sock %p", sk);
if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
hdev->io_capability = cp->io_capability;
bt_dev_dbg(hdev, "IO capability set to 0x%02x", hdev->io_capability);
hci_dev_unlock(hdev);
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, 0,
NULL, 0);
}
static struct mgmt_pending_cmd *find_pairing(struct hci_conn *conn)
{
struct hci_dev *hdev = conn->hdev;
struct mgmt_pending_cmd *cmd;
list_for_each_entry(cmd, &hdev->mgmt_pending, list) {
if (cmd->opcode != MGMT_OP_PAIR_DEVICE)
continue;
if (cmd->user_data != conn)
continue;
return cmd;
}
return NULL;
}
static int pairing_complete(struct mgmt_pending_cmd *cmd, u8 status)
{
struct mgmt_rp_pair_device rp;
struct hci_conn *conn = cmd->user_data;
int err;
bacpy(&rp.addr.bdaddr, &conn->dst);
rp.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
err = mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE,
status, &rp, sizeof(rp));
/* So we don't get further callbacks for this connection */
conn->connect_cfm_cb = NULL;
conn->security_cfm_cb = NULL;
conn->disconn_cfm_cb = NULL;
hci_conn_drop(conn);
/* The device is paired so there is no need to remove
* its connection parameters anymore.
*/
clear_bit(HCI_CONN_PARAM_REMOVAL_PEND, &conn->flags);
hci_conn_put(conn);
return err;
}
void mgmt_smp_complete(struct hci_conn *conn, bool complete)
{
u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED;
struct mgmt_pending_cmd *cmd;
cmd = find_pairing(conn);
if (cmd) {
cmd->cmd_complete(cmd, status);
mgmt_pending_remove(cmd);
}
}
static void pairing_complete_cb(struct hci_conn *conn, u8 status)
{
struct mgmt_pending_cmd *cmd;
BT_DBG("status %u", status);
cmd = find_pairing(conn);
if (!cmd) {
BT_DBG("Unable to find a pending command");
return;
}
cmd->cmd_complete(cmd, mgmt_status(status));
mgmt_pending_remove(cmd);
}
static void le_pairing_complete_cb(struct hci_conn *conn, u8 status)
{
struct mgmt_pending_cmd *cmd;
BT_DBG("status %u", status);
if (!status)
return;
cmd = find_pairing(conn);
if (!cmd) {
BT_DBG("Unable to find a pending command");
return;
}
cmd->cmd_complete(cmd, mgmt_status(status));
mgmt_pending_remove(cmd);
}
static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_pair_device *cp = data;
struct mgmt_rp_pair_device rp;
struct mgmt_pending_cmd *cmd;
u8 sec_level, auth_type;
struct hci_conn *conn;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
memset(&rp, 0, sizeof(rp));
bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
rp.addr.type = cp->addr.type;
if (!bdaddr_type_is_valid(cp->addr.type))
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&rp, sizeof(rp));
if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY)
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&rp, sizeof(rp));
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
MGMT_STATUS_NOT_POWERED, &rp,
sizeof(rp));
goto unlock;
}
if (hci_bdaddr_is_paired(hdev, &cp->addr.bdaddr, cp->addr.type)) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
MGMT_STATUS_ALREADY_PAIRED, &rp,
sizeof(rp));
goto unlock;
}
sec_level = BT_SECURITY_MEDIUM;
auth_type = HCI_AT_DEDICATED_BONDING;
if (cp->addr.type == BDADDR_BREDR) {
conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level,
auth_type, CONN_REASON_PAIR_DEVICE,
HCI_ACL_CONN_TIMEOUT);
} else {
u8 addr_type = le_addr_type(cp->addr.type);
struct hci_conn_params *p;
/* When pairing a new device, it is expected to remember
* this device for future connections. Adding the connection
* parameter information ahead of time allows tracking
* of the peripheral preferred values and will speed up any
* further connection establishment.
*
* If connection parameters already exist, then they
* will be kept and this function does nothing.
*/
p = hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type);
if (p->auto_connect == HCI_AUTO_CONN_EXPLICIT)
p->auto_connect = HCI_AUTO_CONN_DISABLED;
conn = hci_connect_le_scan(hdev, &cp->addr.bdaddr, addr_type,
sec_level, HCI_LE_CONN_TIMEOUT,
CONN_REASON_PAIR_DEVICE);
}
if (IS_ERR(conn)) {
int status;
if (PTR_ERR(conn) == -EBUSY)
status = MGMT_STATUS_BUSY;
else if (PTR_ERR(conn) == -EOPNOTSUPP)
status = MGMT_STATUS_NOT_SUPPORTED;
else if (PTR_ERR(conn) == -ECONNREFUSED)
status = MGMT_STATUS_REJECTED;
else
status = MGMT_STATUS_CONNECT_FAILED;
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
status, &rp, sizeof(rp));
goto unlock;
}
if (conn->connect_cfm_cb) {
hci_conn_drop(conn);
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE,
MGMT_STATUS_BUSY, &rp, sizeof(rp));
goto unlock;
}
cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
hci_conn_drop(conn);
goto unlock;
}
cmd->cmd_complete = pairing_complete;
/* For LE, just connecting isn't a proof that the pairing finished */
if (cp->addr.type == BDADDR_BREDR) {
conn->connect_cfm_cb = pairing_complete_cb;
conn->security_cfm_cb = pairing_complete_cb;
conn->disconn_cfm_cb = pairing_complete_cb;
} else {
conn->connect_cfm_cb = le_pairing_complete_cb;
conn->security_cfm_cb = le_pairing_complete_cb;
conn->disconn_cfm_cb = le_pairing_complete_cb;
}
conn->io_capability = cp->io_cap;
cmd->user_data = hci_conn_get(conn);
if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) &&
hci_conn_security(conn, sec_level, auth_type, true)) {
cmd->cmd_complete(cmd, 0);
mgmt_pending_remove(cmd);
}
err = 0;
unlock:
hci_dev_unlock(hdev);
return err;
}
static int cancel_pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_addr_info *addr = data;
struct mgmt_pending_cmd *cmd;
struct hci_conn *conn;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
MGMT_STATUS_NOT_POWERED);
goto unlock;
}
cmd = pending_find(MGMT_OP_PAIR_DEVICE, hdev);
if (!cmd) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
MGMT_STATUS_INVALID_PARAMS);
goto unlock;
}
conn = cmd->user_data;
if (bacmp(&addr->bdaddr, &conn->dst) != 0) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE,
MGMT_STATUS_INVALID_PARAMS);
goto unlock;
}
cmd->cmd_complete(cmd, MGMT_STATUS_CANCELLED);
mgmt_pending_remove(cmd);
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CANCEL_PAIR_DEVICE, 0,
addr, sizeof(*addr));
/* Since user doesn't want to proceed with the connection, abort any
* ongoing pairing and then terminate the link if it was created
* because of the pair device action.
*/
if (addr->type == BDADDR_BREDR)
hci_remove_link_key(hdev, &addr->bdaddr);
else
smp_cancel_and_remove_pairing(hdev, &addr->bdaddr,
le_addr_type(addr->type));
if (conn->conn_reason == CONN_REASON_PAIR_DEVICE)
hci_abort_conn(conn, HCI_ERROR_REMOTE_USER_TERM);
unlock:
hci_dev_unlock(hdev);
return err;
}
static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev,
struct mgmt_addr_info *addr, u16 mgmt_op,
u16 hci_op, __le32 passkey)
{
struct mgmt_pending_cmd *cmd;
struct hci_conn *conn;
int err;
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
MGMT_STATUS_NOT_POWERED, addr,
sizeof(*addr));
goto done;
}
if (addr->type == BDADDR_BREDR)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &addr->bdaddr);
else
conn = hci_conn_hash_lookup_le(hdev, &addr->bdaddr,
le_addr_type(addr->type));
if (!conn) {
err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
MGMT_STATUS_NOT_CONNECTED, addr,
sizeof(*addr));
goto done;
}
if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) {
err = smp_user_confirm_reply(conn, mgmt_op, passkey);
if (!err)
err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
MGMT_STATUS_SUCCESS, addr,
sizeof(*addr));
else
err = mgmt_cmd_complete(sk, hdev->id, mgmt_op,
MGMT_STATUS_FAILED, addr,
sizeof(*addr));
goto done;
}
cmd = mgmt_pending_add(sk, mgmt_op, hdev, addr, sizeof(*addr));
if (!cmd) {
err = -ENOMEM;
goto done;
}
cmd->cmd_complete = addr_cmd_complete;
/* Continue with pairing via HCI */
if (hci_op == HCI_OP_USER_PASSKEY_REPLY) {
struct hci_cp_user_passkey_reply cp;
bacpy(&cp.bdaddr, &addr->bdaddr);
cp.passkey = passkey;
err = hci_send_cmd(hdev, hci_op, sizeof(cp), &cp);
} else
err = hci_send_cmd(hdev, hci_op, sizeof(addr->bdaddr),
&addr->bdaddr);
if (err < 0)
mgmt_pending_remove(cmd);
done:
hci_dev_unlock(hdev);
return err;
}
static int pin_code_neg_reply(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_cp_pin_code_neg_reply *cp = data;
bt_dev_dbg(hdev, "sock %p", sk);
return user_pairing_resp(sk, hdev, &cp->addr,
MGMT_OP_PIN_CODE_NEG_REPLY,
HCI_OP_PIN_CODE_NEG_REPLY, 0);
}
static int user_confirm_reply(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_user_confirm_reply *cp = data;
bt_dev_dbg(hdev, "sock %p", sk);
if (len != sizeof(*cp))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_USER_CONFIRM_REPLY,
MGMT_STATUS_INVALID_PARAMS);
return user_pairing_resp(sk, hdev, &cp->addr,
MGMT_OP_USER_CONFIRM_REPLY,
HCI_OP_USER_CONFIRM_REPLY, 0);
}
static int user_confirm_neg_reply(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_cp_user_confirm_neg_reply *cp = data;
bt_dev_dbg(hdev, "sock %p", sk);
return user_pairing_resp(sk, hdev, &cp->addr,
MGMT_OP_USER_CONFIRM_NEG_REPLY,
HCI_OP_USER_CONFIRM_NEG_REPLY, 0);
}
static int user_passkey_reply(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_user_passkey_reply *cp = data;
bt_dev_dbg(hdev, "sock %p", sk);
return user_pairing_resp(sk, hdev, &cp->addr,
MGMT_OP_USER_PASSKEY_REPLY,
HCI_OP_USER_PASSKEY_REPLY, cp->passkey);
}
static int user_passkey_neg_reply(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_cp_user_passkey_neg_reply *cp = data;
bt_dev_dbg(hdev, "sock %p", sk);
return user_pairing_resp(sk, hdev, &cp->addr,
MGMT_OP_USER_PASSKEY_NEG_REPLY,
HCI_OP_USER_PASSKEY_NEG_REPLY, 0);
}
static int adv_expire_sync(struct hci_dev *hdev, u32 flags)
{
struct adv_info *adv_instance;
adv_instance = hci_find_adv_instance(hdev, hdev->cur_adv_instance);
if (!adv_instance)
return 0;
/* stop if current instance doesn't need to be changed */
if (!(adv_instance->flags & flags))
return 0;
cancel_adv_timeout(hdev);
adv_instance = hci_get_next_instance(hdev, adv_instance->instance);
if (!adv_instance)
return 0;
hci_schedule_adv_instance_sync(hdev, adv_instance->instance, true);
return 0;
}
static int name_changed_sync(struct hci_dev *hdev, void *data)
{
return adv_expire_sync(hdev, MGMT_ADV_FLAG_LOCAL_NAME);
}
static void set_name_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_set_local_name *cp = cmd->param;
u8 status = mgmt_status(err);
bt_dev_dbg(hdev, "err %d", err);
if (cmd != pending_find(MGMT_OP_SET_LOCAL_NAME, hdev))
return;
if (status) {
mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
status);
} else {
mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
cp, sizeof(*cp));
if (hci_dev_test_flag(hdev, HCI_LE_ADV))
hci_cmd_sync_queue(hdev, name_changed_sync, NULL, NULL);
}
mgmt_pending_remove(cmd);
}
static int set_name_sync(struct hci_dev *hdev, void *data)
{
if (lmp_bredr_capable(hdev)) {
hci_update_name_sync(hdev);
hci_update_eir_sync(hdev);
}
/* The name is stored in the scan response data and so
* no need to update the advertising data here.
*/
if (lmp_le_capable(hdev) && hci_dev_test_flag(hdev, HCI_ADVERTISING))
hci_update_scan_rsp_data_sync(hdev, hdev->cur_adv_instance);
return 0;
}
static int set_local_name(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_set_local_name *cp = data;
struct mgmt_pending_cmd *cmd;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
/* If the old values are the same as the new ones just return a
* direct command complete event.
*/
if (!memcmp(hdev->dev_name, cp->name, sizeof(hdev->dev_name)) &&
!memcmp(hdev->short_name, cp->short_name,
sizeof(hdev->short_name))) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
data, len);
goto failed;
}
memcpy(hdev->short_name, cp->short_name, sizeof(hdev->short_name));
if (!hdev_is_powered(hdev)) {
memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME, 0,
data, len);
if (err < 0)
goto failed;
err = mgmt_limited_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, data,
len, HCI_MGMT_LOCAL_NAME_EVENTS, sk);
ext_info_changed(hdev, sk);
goto failed;
}
cmd = mgmt_pending_add(sk, MGMT_OP_SET_LOCAL_NAME, hdev, data, len);
if (!cmd)
err = -ENOMEM;
else
err = hci_cmd_sync_queue(hdev, set_name_sync, cmd,
set_name_complete);
if (err < 0) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_LOCAL_NAME,
MGMT_STATUS_FAILED);
if (cmd)
mgmt_pending_remove(cmd);
goto failed;
}
memcpy(hdev->dev_name, cp->name, sizeof(hdev->dev_name));
failed:
hci_dev_unlock(hdev);
return err;
}
static int appearance_changed_sync(struct hci_dev *hdev, void *data)
{
return adv_expire_sync(hdev, MGMT_ADV_FLAG_APPEARANCE);
}
static int set_appearance(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_set_appearance *cp = data;
u16 appearance;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (!lmp_le_capable(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_APPEARANCE,
MGMT_STATUS_NOT_SUPPORTED);
appearance = le16_to_cpu(cp->appearance);
hci_dev_lock(hdev);
if (hdev->appearance != appearance) {
hdev->appearance = appearance;
if (hci_dev_test_flag(hdev, HCI_LE_ADV))
hci_cmd_sync_queue(hdev, appearance_changed_sync, NULL,
NULL);
ext_info_changed(hdev, sk);
}
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_APPEARANCE, 0, NULL,
0);
hci_dev_unlock(hdev);
return err;
}
static int get_phy_configuration(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_rp_get_phy_configuration rp;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
memset(&rp, 0, sizeof(rp));
rp.supported_phys = cpu_to_le32(get_supported_phys(hdev));
rp.selected_phys = cpu_to_le32(get_selected_phys(hdev));
rp.configurable_phys = cpu_to_le32(get_configurable_phys(hdev));
hci_dev_unlock(hdev);
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_PHY_CONFIGURATION, 0,
&rp, sizeof(rp));
}
int mgmt_phy_configuration_changed(struct hci_dev *hdev, struct sock *skip)
{
struct mgmt_ev_phy_configuration_changed ev;
memset(&ev, 0, sizeof(ev));
ev.selected_phys = cpu_to_le32(get_selected_phys(hdev));
return mgmt_event(MGMT_EV_PHY_CONFIGURATION_CHANGED, hdev, &ev,
sizeof(ev), skip);
}
static void set_default_phy_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_pending_cmd *cmd = data;
struct sk_buff *skb = cmd->skb;
u8 status = mgmt_status(err);
if (cmd != pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev))
return;
if (!status) {
if (!skb)
status = MGMT_STATUS_FAILED;
else if (IS_ERR(skb))
status = mgmt_status(PTR_ERR(skb));
else
status = mgmt_status(skb->data[0]);
}
bt_dev_dbg(hdev, "status %d", status);
if (status) {
mgmt_cmd_status(cmd->sk, hdev->id,
MGMT_OP_SET_PHY_CONFIGURATION, status);
} else {
mgmt_cmd_complete(cmd->sk, hdev->id,
MGMT_OP_SET_PHY_CONFIGURATION, 0,
NULL, 0);
mgmt_phy_configuration_changed(hdev, cmd->sk);
}
if (skb && !IS_ERR(skb))
kfree_skb(skb);
mgmt_pending_remove(cmd);
}
static int set_default_phy_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_set_phy_configuration *cp = cmd->param;
struct hci_cp_le_set_default_phy cp_phy;
u32 selected_phys = __le32_to_cpu(cp->selected_phys);
memset(&cp_phy, 0, sizeof(cp_phy));
if (!(selected_phys & MGMT_PHY_LE_TX_MASK))
cp_phy.all_phys |= 0x01;
if (!(selected_phys & MGMT_PHY_LE_RX_MASK))
cp_phy.all_phys |= 0x02;
if (selected_phys & MGMT_PHY_LE_1M_TX)
cp_phy.tx_phys |= HCI_LE_SET_PHY_1M;
if (selected_phys & MGMT_PHY_LE_2M_TX)
cp_phy.tx_phys |= HCI_LE_SET_PHY_2M;
if (selected_phys & MGMT_PHY_LE_CODED_TX)
cp_phy.tx_phys |= HCI_LE_SET_PHY_CODED;
if (selected_phys & MGMT_PHY_LE_1M_RX)
cp_phy.rx_phys |= HCI_LE_SET_PHY_1M;
if (selected_phys & MGMT_PHY_LE_2M_RX)
cp_phy.rx_phys |= HCI_LE_SET_PHY_2M;
if (selected_phys & MGMT_PHY_LE_CODED_RX)
cp_phy.rx_phys |= HCI_LE_SET_PHY_CODED;
cmd->skb = __hci_cmd_sync(hdev, HCI_OP_LE_SET_DEFAULT_PHY,
sizeof(cp_phy), &cp_phy, HCI_CMD_TIMEOUT);
return 0;
}
static int set_phy_configuration(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_cp_set_phy_configuration *cp = data;
struct mgmt_pending_cmd *cmd;
u32 selected_phys, configurable_phys, supported_phys, unconfigure_phys;
u16 pkt_type = (HCI_DH1 | HCI_DM1);
bool changed = false;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
configurable_phys = get_configurable_phys(hdev);
supported_phys = get_supported_phys(hdev);
selected_phys = __le32_to_cpu(cp->selected_phys);
if (selected_phys & ~supported_phys)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_PHY_CONFIGURATION,
MGMT_STATUS_INVALID_PARAMS);
unconfigure_phys = supported_phys & ~configurable_phys;
if ((selected_phys & unconfigure_phys) != unconfigure_phys)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_PHY_CONFIGURATION,
MGMT_STATUS_INVALID_PARAMS);
if (selected_phys == get_selected_phys(hdev))
return mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_SET_PHY_CONFIGURATION,
0, NULL, 0);
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_PHY_CONFIGURATION,
MGMT_STATUS_REJECTED);
goto unlock;
}
if (pending_find(MGMT_OP_SET_PHY_CONFIGURATION, hdev)) {
err = mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_PHY_CONFIGURATION,
MGMT_STATUS_BUSY);
goto unlock;
}
if (selected_phys & MGMT_PHY_BR_1M_3SLOT)
pkt_type |= (HCI_DH3 | HCI_DM3);
else
pkt_type &= ~(HCI_DH3 | HCI_DM3);
if (selected_phys & MGMT_PHY_BR_1M_5SLOT)
pkt_type |= (HCI_DH5 | HCI_DM5);
else
pkt_type &= ~(HCI_DH5 | HCI_DM5);
if (selected_phys & MGMT_PHY_EDR_2M_1SLOT)
pkt_type &= ~HCI_2DH1;
else
pkt_type |= HCI_2DH1;
if (selected_phys & MGMT_PHY_EDR_2M_3SLOT)
pkt_type &= ~HCI_2DH3;
else
pkt_type |= HCI_2DH3;
if (selected_phys & MGMT_PHY_EDR_2M_5SLOT)
pkt_type &= ~HCI_2DH5;
else
pkt_type |= HCI_2DH5;
if (selected_phys & MGMT_PHY_EDR_3M_1SLOT)
pkt_type &= ~HCI_3DH1;
else
pkt_type |= HCI_3DH1;
if (selected_phys & MGMT_PHY_EDR_3M_3SLOT)
pkt_type &= ~HCI_3DH3;
else
pkt_type |= HCI_3DH3;
if (selected_phys & MGMT_PHY_EDR_3M_5SLOT)
pkt_type &= ~HCI_3DH5;
else
pkt_type |= HCI_3DH5;
if (pkt_type != hdev->pkt_type) {
hdev->pkt_type = pkt_type;
changed = true;
}
if ((selected_phys & MGMT_PHY_LE_MASK) ==
(get_selected_phys(hdev) & MGMT_PHY_LE_MASK)) {
if (changed)
mgmt_phy_configuration_changed(hdev, sk);
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_SET_PHY_CONFIGURATION,
0, NULL, 0);
goto unlock;
}
cmd = mgmt_pending_add(sk, MGMT_OP_SET_PHY_CONFIGURATION, hdev, data,
len);
if (!cmd)
err = -ENOMEM;
else
err = hci_cmd_sync_queue(hdev, set_default_phy_sync, cmd,
set_default_phy_complete);
if (err < 0) {
err = mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_PHY_CONFIGURATION,
MGMT_STATUS_FAILED);
if (cmd)
mgmt_pending_remove(cmd);
}
unlock:
hci_dev_unlock(hdev);
return err;
}
static int set_blocked_keys(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
int err = MGMT_STATUS_SUCCESS;
struct mgmt_cp_set_blocked_keys *keys = data;
const u16 max_key_count = ((U16_MAX - sizeof(*keys)) /
sizeof(struct mgmt_blocked_key_info));
u16 key_count, expected_len;
int i;
bt_dev_dbg(hdev, "sock %p", sk);
key_count = __le16_to_cpu(keys->key_count);
if (key_count > max_key_count) {
bt_dev_err(hdev, "too big key_count value %u", key_count);
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BLOCKED_KEYS,
MGMT_STATUS_INVALID_PARAMS);
}
expected_len = struct_size(keys, keys, key_count);
if (expected_len != len) {
bt_dev_err(hdev, "expected %u bytes, got %u bytes",
expected_len, len);
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BLOCKED_KEYS,
MGMT_STATUS_INVALID_PARAMS);
}
hci_dev_lock(hdev);
hci_blocked_keys_clear(hdev);
for (i = 0; i < key_count; ++i) {
struct blocked_key *b = kzalloc(sizeof(*b), GFP_KERNEL);
if (!b) {
err = MGMT_STATUS_NO_RESOURCES;
break;
}
b->type = keys->keys[i].type;
memcpy(b->val, keys->keys[i].val, sizeof(b->val));
list_add_rcu(&b->list, &hdev->blocked_keys);
}
hci_dev_unlock(hdev);
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_BLOCKED_KEYS,
err, NULL, 0);
}
static int set_wideband_speech(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_mode *cp = data;
int err;
bool changed = false;
bt_dev_dbg(hdev, "sock %p", sk);
if (!test_bit(HCI_QUIRK_WIDEBAND_SPEECH_SUPPORTED, &hdev->quirks))
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_WIDEBAND_SPEECH,
MGMT_STATUS_NOT_SUPPORTED);
if (cp->val != 0x00 && cp->val != 0x01)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_WIDEBAND_SPEECH,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
if (hdev_is_powered(hdev) &&
!!cp->val != hci_dev_test_flag(hdev,
HCI_WIDEBAND_SPEECH_ENABLED)) {
err = mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_WIDEBAND_SPEECH,
MGMT_STATUS_REJECTED);
goto unlock;
}
if (cp->val)
changed = !hci_dev_test_and_set_flag(hdev,
HCI_WIDEBAND_SPEECH_ENABLED);
else
changed = hci_dev_test_and_clear_flag(hdev,
HCI_WIDEBAND_SPEECH_ENABLED);
err = send_settings_rsp(sk, MGMT_OP_SET_WIDEBAND_SPEECH, hdev);
if (err < 0)
goto unlock;
if (changed)
err = new_settings(hdev, sk);
unlock:
hci_dev_unlock(hdev);
return err;
}
static int read_controller_cap(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
char buf[20];
struct mgmt_rp_read_controller_cap *rp = (void *)buf;
u16 cap_len = 0;
u8 flags = 0;
u8 tx_power_range[2];
bt_dev_dbg(hdev, "sock %p", sk);
memset(&buf, 0, sizeof(buf));
hci_dev_lock(hdev);
/* When the Read Simple Pairing Options command is supported, then
* the remote public key validation is supported.
*
* Alternatively, when Microsoft extensions are available, they can
* indicate support for public key validation as well.
*/
if ((hdev->commands[41] & 0x08) || msft_curve_validity(hdev))
flags |= 0x01; /* Remote public key validation (BR/EDR) */
flags |= 0x02; /* Remote public key validation (LE) */
/* When the Read Encryption Key Size command is supported, then the
* encryption key size is enforced.
*/
if (hdev->commands[20] & 0x10)
flags |= 0x04; /* Encryption key size enforcement (BR/EDR) */
flags |= 0x08; /* Encryption key size enforcement (LE) */
cap_len = eir_append_data(rp->cap, cap_len, MGMT_CAP_SEC_FLAGS,
&flags, 1);
/* When the Read Simple Pairing Options command is supported, then
* also max encryption key size information is provided.
*/
if (hdev->commands[41] & 0x08)
cap_len = eir_append_le16(rp->cap, cap_len,
MGMT_CAP_MAX_ENC_KEY_SIZE,
hdev->max_enc_key_size);
cap_len = eir_append_le16(rp->cap, cap_len,
MGMT_CAP_SMP_MAX_ENC_KEY_SIZE,
SMP_MAX_ENC_KEY_SIZE);
/* Append the min/max LE tx power parameters if we were able to fetch
* it from the controller
*/
if (hdev->commands[38] & 0x80) {
memcpy(&tx_power_range[0], &hdev->min_le_tx_power, 1);
memcpy(&tx_power_range[1], &hdev->max_le_tx_power, 1);
cap_len = eir_append_data(rp->cap, cap_len, MGMT_CAP_LE_TX_PWR,
tx_power_range, 2);
}
rp->cap_len = cpu_to_le16(cap_len);
hci_dev_unlock(hdev);
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_CONTROLLER_CAP, 0,
rp, sizeof(*rp) + cap_len);
}
#ifdef CONFIG_BT_FEATURE_DEBUG
/* d4992530-b9ec-469f-ab01-6c481c47da1c */
static const u8 debug_uuid[16] = {
0x1c, 0xda, 0x47, 0x1c, 0x48, 0x6c, 0x01, 0xab,
0x9f, 0x46, 0xec, 0xb9, 0x30, 0x25, 0x99, 0xd4,
};
#endif
/* 330859bc-7506-492d-9370-9a6f0614037f */
static const u8 quality_report_uuid[16] = {
0x7f, 0x03, 0x14, 0x06, 0x6f, 0x9a, 0x70, 0x93,
0x2d, 0x49, 0x06, 0x75, 0xbc, 0x59, 0x08, 0x33,
};
/* a6695ace-ee7f-4fb9-881a-5fac66c629af */
static const u8 offload_codecs_uuid[16] = {
0xaf, 0x29, 0xc6, 0x66, 0xac, 0x5f, 0x1a, 0x88,
0xb9, 0x4f, 0x7f, 0xee, 0xce, 0x5a, 0x69, 0xa6,
};
/* 671b10b5-42c0-4696-9227-eb28d1b049d6 */
static const u8 le_simultaneous_roles_uuid[16] = {
0xd6, 0x49, 0xb0, 0xd1, 0x28, 0xeb, 0x27, 0x92,
0x96, 0x46, 0xc0, 0x42, 0xb5, 0x10, 0x1b, 0x67,
};
/* 15c0a148-c273-11ea-b3de-0242ac130004 */
static const u8 rpa_resolution_uuid[16] = {
0x04, 0x00, 0x13, 0xac, 0x42, 0x02, 0xde, 0xb3,
0xea, 0x11, 0x73, 0xc2, 0x48, 0xa1, 0xc0, 0x15,
};
/* 6fbaf188-05e0-496a-9885-d6ddfdb4e03e */
static const u8 iso_socket_uuid[16] = {
0x3e, 0xe0, 0xb4, 0xfd, 0xdd, 0xd6, 0x85, 0x98,
0x6a, 0x49, 0xe0, 0x05, 0x88, 0xf1, 0xba, 0x6f,
};
/* 2ce463d7-7a03-4d8d-bf05-5f24e8f36e76 */
static const u8 mgmt_mesh_uuid[16] = {
0x76, 0x6e, 0xf3, 0xe8, 0x24, 0x5f, 0x05, 0xbf,
0x8d, 0x4d, 0x03, 0x7a, 0xd7, 0x63, 0xe4, 0x2c,
};
static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
struct mgmt_rp_read_exp_features_info *rp;
size_t len;
u16 idx = 0;
u32 flags;
int status;
bt_dev_dbg(hdev, "sock %p", sk);
/* Enough space for 7 features */
len = sizeof(*rp) + (sizeof(rp->features[0]) * 7);
rp = kzalloc(len, GFP_KERNEL);
if (!rp)
return -ENOMEM;
#ifdef CONFIG_BT_FEATURE_DEBUG
if (!hdev) {
flags = bt_dbg_get() ? BIT(0) : 0;
memcpy(rp->features[idx].uuid, debug_uuid, 16);
rp->features[idx].flags = cpu_to_le32(flags);
idx++;
}
#endif
if (hdev && hci_dev_le_state_simultaneous(hdev)) {
if (hci_dev_test_flag(hdev, HCI_LE_SIMULTANEOUS_ROLES))
flags = BIT(0);
else
flags = 0;
memcpy(rp->features[idx].uuid, le_simultaneous_roles_uuid, 16);
rp->features[idx].flags = cpu_to_le32(flags);
idx++;
}
Bluetooth: hci_sync: Enable advertising when LL privacy is enabled This enables advertising when LL privacy is enabled and changes the command sequence when resolving list is updated to also account for when advertising is enabled using the following sequence: If there are devices to scan: Disable Scanning -> Update Accept List -> use_ll_privacy((Disable Advertising) -> Disable Resolving List -> Update Resolving List -> Enable Resolving List -> (Enable Advertising)) -> Enable Scanning Otherwise: Disable Scanning Errors during the Update Accept List stage are handled gracefully by restoring any previous state (e.g. advertising) and disabling the use of accept list as either accept list or resolving list could not be updated. Tested with: mgmt-tester -s "LL Privacy" Test Summary ------------ LL Privacy - Add Device 1 (Add to WL) Passed LL Privacy - Add Device 2 (Add to RL) Passed LL Privacy - Add Device 3 (Enable RL) Passed LL Privacy - Add Device 4 (2 Devices to WL) Passed LL Privacy - Add Device 5 (2 Devices to RL) Passed LL Privacy - Add Device 6 (RL is full) Passed LL Privacy - Add Device 7 (WL is full) Passed LL Privacy - Add Device 8 (Disable Adv) Passed LL Privacy - Add Device 9 (Multi Adv) Passed LL Privacy - Add Device 10 (Multi Dev and Multi Adv) Passed LL Privacy - Remove Device 1 (Remove from WL) Passed LL Privacy - Remove Device 2 (Remove from RL) Passed LL Privacy - Remove Device 3 (Disable RL) Passed LL Privacy - Remove Device 4 (Disable Adv) Passed LL Privacy - Remove Device 5 (Multi Adv) Passed LL Privacy - Start Discovery 1 (Disable RL) Passed LL Privacy - Start Discovery 2 (Disable RL) Passed Total: 18, Passed: 18 (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-27 23:58:42 +00:00
if (hdev && ll_privacy_capable(hdev)) {
if (hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY))
flags = BIT(0) | BIT(1);
else
flags = BIT(1);
memcpy(rp->features[idx].uuid, rpa_resolution_uuid, 16);
rp->features[idx].flags = cpu_to_le32(flags);
idx++;
}
if (hdev && (aosp_has_quality_report(hdev) ||
hdev->set_quality_report)) {
if (hci_dev_test_flag(hdev, HCI_QUALITY_REPORT))
flags = BIT(0);
else
flags = 0;
memcpy(rp->features[idx].uuid, quality_report_uuid, 16);
rp->features[idx].flags = cpu_to_le32(flags);
idx++;
}
if (hdev && hdev->get_data_path_id) {
if (hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED))
flags = BIT(0);
else
flags = 0;
memcpy(rp->features[idx].uuid, offload_codecs_uuid, 16);
rp->features[idx].flags = cpu_to_le32(flags);
idx++;
}
if (IS_ENABLED(CONFIG_BT_LE)) {
flags = iso_enabled() ? BIT(0) : 0;
memcpy(rp->features[idx].uuid, iso_socket_uuid, 16);
rp->features[idx].flags = cpu_to_le32(flags);
idx++;
}
if (hdev && lmp_le_capable(hdev)) {
if (hci_dev_test_flag(hdev, HCI_MESH_EXPERIMENTAL))
flags = BIT(0);
else
flags = 0;
memcpy(rp->features[idx].uuid, mgmt_mesh_uuid, 16);
rp->features[idx].flags = cpu_to_le32(flags);
idx++;
}
rp->feature_count = cpu_to_le16(idx);
/* After reading the experimental features information, enable
* the events to update client on any future change.
*/
hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
status = mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
MGMT_OP_READ_EXP_FEATURES_INFO,
0, rp, sizeof(*rp) + (20 * idx));
kfree(rp);
return status;
}
static int exp_ll_privacy_feature_changed(bool enabled, struct hci_dev *hdev,
struct sock *skip)
{
struct mgmt_ev_exp_feature_changed ev;
memset(&ev, 0, sizeof(ev));
memcpy(ev.uuid, rpa_resolution_uuid, 16);
ev.flags = cpu_to_le32((enabled ? BIT(0) : 0) | BIT(1));
bluetooth: don't use bitmaps for random flag accesses The bluetooth code uses our bitmap infrastructure for the two bits (!) of connection setup flags, and in the process causes odd problems when it converts between a bitmap and just the regular values of said bits. It's completely pointless to do things like bitmap_to_arr32() to convert a bitmap into a u32. It shoudln't have been a bitmap in the first place. The reason to use bitmaps is if you have arbitrary number of bits you want to manage (not two!), or if you rely on the atomicity guarantees of the bitmap setting and clearing. The code could use an "atomic_t" and use "atomic_or/andnot()" to set and clear the bit values, but considering that it then copies the bitmaps around with "bitmap_to_arr32()" and friends, there clearly cannot be a lot of atomicity requirements. So just use a regular integer. In the process, this avoids the warnings about erroneous use of bitmap_from_u64() which were triggered on 32-bit architectures when conversion from a u64 would access two words (and, surprise, surprise, only one word is needed - and indeed overkill - for a 2-bit bitmap). That was always problematic, but the compiler seems to notice it and warn about the invalid pattern only after commit 0a97953fd221 ("lib: add bitmap_{from,to}_arr64") changed the exact implementation details of 'bitmap_from_u64()', as reported by Sudip Mukherjee and Stephen Rothwell. Fixes: fe92ee6425a2 ("Bluetooth: hci_core: Rework hci_conn_params flags") Link: https://lore.kernel.org/all/YpyJ9qTNHJzz0FHY@debian/ Link: https://lore.kernel.org/all/20220606080631.0c3014f2@canb.auug.org.au/ Link: https://lore.kernel.org/all/20220605162537.1604762-1-yury.norov@gmail.com/ Reported-by: Stephen Rothwell <sfr@canb.auug.org.au> Reported-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Reviewed-by: Yury Norov <yury.norov@gmail.com> Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Cc: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2022-06-05 18:51:48 +00:00
// Do we need to be atomic with the conn_flags?
if (enabled && privacy_mode_capable(hdev))
bluetooth: don't use bitmaps for random flag accesses The bluetooth code uses our bitmap infrastructure for the two bits (!) of connection setup flags, and in the process causes odd problems when it converts between a bitmap and just the regular values of said bits. It's completely pointless to do things like bitmap_to_arr32() to convert a bitmap into a u32. It shoudln't have been a bitmap in the first place. The reason to use bitmaps is if you have arbitrary number of bits you want to manage (not two!), or if you rely on the atomicity guarantees of the bitmap setting and clearing. The code could use an "atomic_t" and use "atomic_or/andnot()" to set and clear the bit values, but considering that it then copies the bitmaps around with "bitmap_to_arr32()" and friends, there clearly cannot be a lot of atomicity requirements. So just use a regular integer. In the process, this avoids the warnings about erroneous use of bitmap_from_u64() which were triggered on 32-bit architectures when conversion from a u64 would access two words (and, surprise, surprise, only one word is needed - and indeed overkill - for a 2-bit bitmap). That was always problematic, but the compiler seems to notice it and warn about the invalid pattern only after commit 0a97953fd221 ("lib: add bitmap_{from,to}_arr64") changed the exact implementation details of 'bitmap_from_u64()', as reported by Sudip Mukherjee and Stephen Rothwell. Fixes: fe92ee6425a2 ("Bluetooth: hci_core: Rework hci_conn_params flags") Link: https://lore.kernel.org/all/YpyJ9qTNHJzz0FHY@debian/ Link: https://lore.kernel.org/all/20220606080631.0c3014f2@canb.auug.org.au/ Link: https://lore.kernel.org/all/20220605162537.1604762-1-yury.norov@gmail.com/ Reported-by: Stephen Rothwell <sfr@canb.auug.org.au> Reported-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Reviewed-by: Yury Norov <yury.norov@gmail.com> Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Cc: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2022-06-05 18:51:48 +00:00
hdev->conn_flags |= HCI_CONN_FLAG_DEVICE_PRIVACY;
else
bluetooth: don't use bitmaps for random flag accesses The bluetooth code uses our bitmap infrastructure for the two bits (!) of connection setup flags, and in the process causes odd problems when it converts between a bitmap and just the regular values of said bits. It's completely pointless to do things like bitmap_to_arr32() to convert a bitmap into a u32. It shoudln't have been a bitmap in the first place. The reason to use bitmaps is if you have arbitrary number of bits you want to manage (not two!), or if you rely on the atomicity guarantees of the bitmap setting and clearing. The code could use an "atomic_t" and use "atomic_or/andnot()" to set and clear the bit values, but considering that it then copies the bitmaps around with "bitmap_to_arr32()" and friends, there clearly cannot be a lot of atomicity requirements. So just use a regular integer. In the process, this avoids the warnings about erroneous use of bitmap_from_u64() which were triggered on 32-bit architectures when conversion from a u64 would access two words (and, surprise, surprise, only one word is needed - and indeed overkill - for a 2-bit bitmap). That was always problematic, but the compiler seems to notice it and warn about the invalid pattern only after commit 0a97953fd221 ("lib: add bitmap_{from,to}_arr64") changed the exact implementation details of 'bitmap_from_u64()', as reported by Sudip Mukherjee and Stephen Rothwell. Fixes: fe92ee6425a2 ("Bluetooth: hci_core: Rework hci_conn_params flags") Link: https://lore.kernel.org/all/YpyJ9qTNHJzz0FHY@debian/ Link: https://lore.kernel.org/all/20220606080631.0c3014f2@canb.auug.org.au/ Link: https://lore.kernel.org/all/20220605162537.1604762-1-yury.norov@gmail.com/ Reported-by: Stephen Rothwell <sfr@canb.auug.org.au> Reported-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Reviewed-by: Yury Norov <yury.norov@gmail.com> Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Cc: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2022-06-05 18:51:48 +00:00
hdev->conn_flags &= ~HCI_CONN_FLAG_DEVICE_PRIVACY;
return mgmt_limited_event(MGMT_EV_EXP_FEATURE_CHANGED, hdev,
&ev, sizeof(ev),
HCI_MGMT_EXP_FEATURE_EVENTS, skip);
}
static int exp_feature_changed(struct hci_dev *hdev, const u8 *uuid,
bool enabled, struct sock *skip)
{
struct mgmt_ev_exp_feature_changed ev;
memset(&ev, 0, sizeof(ev));
memcpy(ev.uuid, uuid, 16);
ev.flags = cpu_to_le32(enabled ? BIT(0) : 0);
return mgmt_limited_event(MGMT_EV_EXP_FEATURE_CHANGED, hdev,
&ev, sizeof(ev),
HCI_MGMT_EXP_FEATURE_EVENTS, skip);
}
#define EXP_FEAT(_uuid, _set_func) \
{ \
.uuid = _uuid, \
.set_func = _set_func, \
}
/* The zero key uuid is special. Multiple exp features are set through it. */
static int set_zero_key_func(struct sock *sk, struct hci_dev *hdev,
struct mgmt_cp_set_exp_feature *cp, u16 data_len)
{
struct mgmt_rp_set_exp_feature rp;
memset(rp.uuid, 0, 16);
rp.flags = cpu_to_le32(0);
#ifdef CONFIG_BT_FEATURE_DEBUG
if (!hdev) {
bool changed = bt_dbg_get();
bt_dbg_set(false);
if (changed)
exp_feature_changed(NULL, ZERO_KEY, false, sk);
}
#endif
if (hdev && use_ll_privacy(hdev) && !hdev_is_powered(hdev)) {
bool changed;
changed = hci_dev_test_and_clear_flag(hdev,
HCI_ENABLE_LL_PRIVACY);
if (changed)
exp_feature_changed(hdev, rpa_resolution_uuid, false,
sk);
}
hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
MGMT_OP_SET_EXP_FEATURE, 0,
&rp, sizeof(rp));
}
#ifdef CONFIG_BT_FEATURE_DEBUG
static int set_debug_func(struct sock *sk, struct hci_dev *hdev,
struct mgmt_cp_set_exp_feature *cp, u16 data_len)
{
struct mgmt_rp_set_exp_feature rp;
bool val, changed;
int err;
/* Command requires to use the non-controller index */
if (hdev)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_INDEX);
/* Parameters are limited to a single octet */
if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_PARAMS);
/* Only boolean on/off is supported */
if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_PARAMS);
val = !!cp->param[0];
changed = val ? !bt_dbg_get() : bt_dbg_get();
bt_dbg_set(val);
memcpy(rp.uuid, debug_uuid, 16);
rp.flags = cpu_to_le32(val ? BIT(0) : 0);
hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
MGMT_OP_SET_EXP_FEATURE, 0,
&rp, sizeof(rp));
if (changed)
exp_feature_changed(hdev, debug_uuid, val, sk);
return err;
}
#endif
static int set_mgmt_mesh_func(struct sock *sk, struct hci_dev *hdev,
struct mgmt_cp_set_exp_feature *cp, u16 data_len)
{
struct mgmt_rp_set_exp_feature rp;
bool val, changed;
int err;
/* Command requires to use the controller index */
if (!hdev)
return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_INDEX);
/* Parameters are limited to a single octet */
if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_PARAMS);
/* Only boolean on/off is supported */
if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_PARAMS);
val = !!cp->param[0];
if (val) {
changed = !hci_dev_test_and_set_flag(hdev,
HCI_MESH_EXPERIMENTAL);
} else {
hci_dev_clear_flag(hdev, HCI_MESH);
changed = hci_dev_test_and_clear_flag(hdev,
HCI_MESH_EXPERIMENTAL);
}
memcpy(rp.uuid, mgmt_mesh_uuid, 16);
rp.flags = cpu_to_le32(val ? BIT(0) : 0);
hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE, 0,
&rp, sizeof(rp));
if (changed)
exp_feature_changed(hdev, mgmt_mesh_uuid, val, sk);
return err;
}
static int set_rpa_resolution_func(struct sock *sk, struct hci_dev *hdev,
struct mgmt_cp_set_exp_feature *cp,
u16 data_len)
{
struct mgmt_rp_set_exp_feature rp;
bool val, changed;
int err;
u32 flags;
/* Command requires to use the controller index */
if (!hdev)
return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_INDEX);
/* Changes can only be made when controller is powered down */
if (hdev_is_powered(hdev))
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_REJECTED);
/* Parameters are limited to a single octet */
if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_PARAMS);
/* Only boolean on/off is supported */
if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_PARAMS);
val = !!cp->param[0];
if (val) {
changed = !hci_dev_test_and_set_flag(hdev,
HCI_ENABLE_LL_PRIVACY);
hci_dev_clear_flag(hdev, HCI_ADVERTISING);
/* Enable LL privacy + supported settings changed */
flags = BIT(0) | BIT(1);
} else {
changed = hci_dev_test_and_clear_flag(hdev,
HCI_ENABLE_LL_PRIVACY);
/* Disable LL privacy + supported settings changed */
flags = BIT(1);
}
memcpy(rp.uuid, rpa_resolution_uuid, 16);
rp.flags = cpu_to_le32(flags);
hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE, 0,
&rp, sizeof(rp));
if (changed)
exp_ll_privacy_feature_changed(val, hdev, sk);
return err;
}
static int set_quality_report_func(struct sock *sk, struct hci_dev *hdev,
struct mgmt_cp_set_exp_feature *cp,
u16 data_len)
{
struct mgmt_rp_set_exp_feature rp;
bool val, changed;
int err;
/* Command requires to use a valid controller index */
if (!hdev)
return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_INDEX);
/* Parameters are limited to a single octet */
if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_PARAMS);
/* Only boolean on/off is supported */
if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_PARAMS);
hci_req_sync_lock(hdev);
val = !!cp->param[0];
changed = (val != hci_dev_test_flag(hdev, HCI_QUALITY_REPORT));
if (!aosp_has_quality_report(hdev) && !hdev->set_quality_report) {
err = mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_NOT_SUPPORTED);
goto unlock_quality_report;
}
if (changed) {
if (hdev->set_quality_report)
err = hdev->set_quality_report(hdev, val);
else
err = aosp_set_quality_report(hdev, val);
if (err) {
err = mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_FAILED);
goto unlock_quality_report;
}
if (val)
hci_dev_set_flag(hdev, HCI_QUALITY_REPORT);
else
hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT);
}
bt_dev_dbg(hdev, "quality report enable %d changed %d", val, changed);
memcpy(rp.uuid, quality_report_uuid, 16);
rp.flags = cpu_to_le32(val ? BIT(0) : 0);
hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_EXP_FEATURE, 0,
&rp, sizeof(rp));
if (changed)
exp_feature_changed(hdev, quality_report_uuid, val, sk);
unlock_quality_report:
hci_req_sync_unlock(hdev);
return err;
}
static int set_offload_codec_func(struct sock *sk, struct hci_dev *hdev,
struct mgmt_cp_set_exp_feature *cp,
u16 data_len)
{
bool val, changed;
int err;
struct mgmt_rp_set_exp_feature rp;
/* Command requires to use a valid controller index */
if (!hdev)
return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_INDEX);
/* Parameters are limited to a single octet */
if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_PARAMS);
/* Only boolean on/off is supported */
if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_PARAMS);
val = !!cp->param[0];
changed = (val != hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED));
if (!hdev->get_data_path_id) {
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_NOT_SUPPORTED);
}
if (changed) {
if (val)
hci_dev_set_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED);
else
hci_dev_clear_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED);
}
bt_dev_info(hdev, "offload codecs enable %d changed %d",
val, changed);
memcpy(rp.uuid, offload_codecs_uuid, 16);
rp.flags = cpu_to_le32(val ? BIT(0) : 0);
hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE, 0,
&rp, sizeof(rp));
if (changed)
exp_feature_changed(hdev, offload_codecs_uuid, val, sk);
return err;
}
static int set_le_simultaneous_roles_func(struct sock *sk, struct hci_dev *hdev,
struct mgmt_cp_set_exp_feature *cp,
u16 data_len)
{
bool val, changed;
int err;
struct mgmt_rp_set_exp_feature rp;
/* Command requires to use a valid controller index */
if (!hdev)
return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_INDEX);
/* Parameters are limited to a single octet */
if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_PARAMS);
/* Only boolean on/off is supported */
if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_PARAMS);
val = !!cp->param[0];
changed = (val != hci_dev_test_flag(hdev, HCI_LE_SIMULTANEOUS_ROLES));
if (!hci_dev_le_state_simultaneous(hdev)) {
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_NOT_SUPPORTED);
}
if (changed) {
if (val)
hci_dev_set_flag(hdev, HCI_LE_SIMULTANEOUS_ROLES);
else
hci_dev_clear_flag(hdev, HCI_LE_SIMULTANEOUS_ROLES);
}
bt_dev_info(hdev, "LE simultaneous roles enable %d changed %d",
val, changed);
memcpy(rp.uuid, le_simultaneous_roles_uuid, 16);
rp.flags = cpu_to_le32(val ? BIT(0) : 0);
hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE, 0,
&rp, sizeof(rp));
if (changed)
exp_feature_changed(hdev, le_simultaneous_roles_uuid, val, sk);
return err;
}
#ifdef CONFIG_BT_LE
static int set_iso_socket_func(struct sock *sk, struct hci_dev *hdev,
struct mgmt_cp_set_exp_feature *cp, u16 data_len)
{
struct mgmt_rp_set_exp_feature rp;
bool val, changed = false;
int err;
/* Command requires to use the non-controller index */
if (hdev)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_INDEX);
/* Parameters are limited to a single octet */
if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_PARAMS);
/* Only boolean on/off is supported */
if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_INVALID_PARAMS);
val = cp->param[0] ? true : false;
if (val)
err = iso_init();
else
err = iso_exit();
if (!err)
changed = true;
memcpy(rp.uuid, iso_socket_uuid, 16);
rp.flags = cpu_to_le32(val ? BIT(0) : 0);
hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
MGMT_OP_SET_EXP_FEATURE, 0,
&rp, sizeof(rp));
if (changed)
exp_feature_changed(hdev, iso_socket_uuid, val, sk);
return err;
}
#endif
static const struct mgmt_exp_feature {
const u8 *uuid;
int (*set_func)(struct sock *sk, struct hci_dev *hdev,
struct mgmt_cp_set_exp_feature *cp, u16 data_len);
} exp_features[] = {
EXP_FEAT(ZERO_KEY, set_zero_key_func),
#ifdef CONFIG_BT_FEATURE_DEBUG
EXP_FEAT(debug_uuid, set_debug_func),
#endif
EXP_FEAT(mgmt_mesh_uuid, set_mgmt_mesh_func),
EXP_FEAT(rpa_resolution_uuid, set_rpa_resolution_func),
EXP_FEAT(quality_report_uuid, set_quality_report_func),
EXP_FEAT(offload_codecs_uuid, set_offload_codec_func),
EXP_FEAT(le_simultaneous_roles_uuid, set_le_simultaneous_roles_func),
#ifdef CONFIG_BT_LE
EXP_FEAT(iso_socket_uuid, set_iso_socket_func),
#endif
/* end with a null feature */
EXP_FEAT(NULL, NULL)
};
static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
struct mgmt_cp_set_exp_feature *cp = data;
size_t i = 0;
bt_dev_dbg(hdev, "sock %p", sk);
for (i = 0; exp_features[i].uuid; i++) {
if (!memcmp(cp->uuid, exp_features[i].uuid, 16))
return exp_features[i].set_func(sk, hdev, cp, data_len);
}
return mgmt_cmd_status(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
MGMT_OP_SET_EXP_FEATURE,
MGMT_STATUS_NOT_SUPPORTED);
}
static u32 get_params_flags(struct hci_dev *hdev,
struct hci_conn_params *params)
{
u32 flags = hdev->conn_flags;
/* Devices using RPAs can only be programmed in the acceptlist if
* LL Privacy has been enable otherwise they cannot mark
* HCI_CONN_FLAG_REMOTE_WAKEUP.
*/
if ((flags & HCI_CONN_FLAG_REMOTE_WAKEUP) && !use_ll_privacy(hdev) &&
hci_find_irk_by_addr(hdev, &params->addr, params->addr_type))
flags &= ~HCI_CONN_FLAG_REMOTE_WAKEUP;
return flags;
}
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
static int get_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len)
{
struct mgmt_cp_get_device_flags *cp = data;
struct mgmt_rp_get_device_flags rp;
struct bdaddr_list_with_flags *br_params;
struct hci_conn_params *params;
u32 supported_flags;
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
u32 current_flags = 0;
u8 status = MGMT_STATUS_INVALID_PARAMS;
bt_dev_dbg(hdev, "Get device flags %pMR (type 0x%x)\n",
&cp->addr.bdaddr, cp->addr.type);
hci_dev_lock(hdev);
bluetooth: don't use bitmaps for random flag accesses The bluetooth code uses our bitmap infrastructure for the two bits (!) of connection setup flags, and in the process causes odd problems when it converts between a bitmap and just the regular values of said bits. It's completely pointless to do things like bitmap_to_arr32() to convert a bitmap into a u32. It shoudln't have been a bitmap in the first place. The reason to use bitmaps is if you have arbitrary number of bits you want to manage (not two!), or if you rely on the atomicity guarantees of the bitmap setting and clearing. The code could use an "atomic_t" and use "atomic_or/andnot()" to set and clear the bit values, but considering that it then copies the bitmaps around with "bitmap_to_arr32()" and friends, there clearly cannot be a lot of atomicity requirements. So just use a regular integer. In the process, this avoids the warnings about erroneous use of bitmap_from_u64() which were triggered on 32-bit architectures when conversion from a u64 would access two words (and, surprise, surprise, only one word is needed - and indeed overkill - for a 2-bit bitmap). That was always problematic, but the compiler seems to notice it and warn about the invalid pattern only after commit 0a97953fd221 ("lib: add bitmap_{from,to}_arr64") changed the exact implementation details of 'bitmap_from_u64()', as reported by Sudip Mukherjee and Stephen Rothwell. Fixes: fe92ee6425a2 ("Bluetooth: hci_core: Rework hci_conn_params flags") Link: https://lore.kernel.org/all/YpyJ9qTNHJzz0FHY@debian/ Link: https://lore.kernel.org/all/20220606080631.0c3014f2@canb.auug.org.au/ Link: https://lore.kernel.org/all/20220605162537.1604762-1-yury.norov@gmail.com/ Reported-by: Stephen Rothwell <sfr@canb.auug.org.au> Reported-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Reviewed-by: Yury Norov <yury.norov@gmail.com> Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Cc: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2022-06-05 18:51:48 +00:00
supported_flags = hdev->conn_flags;
memset(&rp, 0, sizeof(rp));
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
if (cp->addr.type == BDADDR_BREDR) {
br_params = hci_bdaddr_list_lookup_with_flags(&hdev->accept_list,
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
&cp->addr.bdaddr,
cp->addr.type);
if (!br_params)
goto done;
bluetooth: don't use bitmaps for random flag accesses The bluetooth code uses our bitmap infrastructure for the two bits (!) of connection setup flags, and in the process causes odd problems when it converts between a bitmap and just the regular values of said bits. It's completely pointless to do things like bitmap_to_arr32() to convert a bitmap into a u32. It shoudln't have been a bitmap in the first place. The reason to use bitmaps is if you have arbitrary number of bits you want to manage (not two!), or if you rely on the atomicity guarantees of the bitmap setting and clearing. The code could use an "atomic_t" and use "atomic_or/andnot()" to set and clear the bit values, but considering that it then copies the bitmaps around with "bitmap_to_arr32()" and friends, there clearly cannot be a lot of atomicity requirements. So just use a regular integer. In the process, this avoids the warnings about erroneous use of bitmap_from_u64() which were triggered on 32-bit architectures when conversion from a u64 would access two words (and, surprise, surprise, only one word is needed - and indeed overkill - for a 2-bit bitmap). That was always problematic, but the compiler seems to notice it and warn about the invalid pattern only after commit 0a97953fd221 ("lib: add bitmap_{from,to}_arr64") changed the exact implementation details of 'bitmap_from_u64()', as reported by Sudip Mukherjee and Stephen Rothwell. Fixes: fe92ee6425a2 ("Bluetooth: hci_core: Rework hci_conn_params flags") Link: https://lore.kernel.org/all/YpyJ9qTNHJzz0FHY@debian/ Link: https://lore.kernel.org/all/20220606080631.0c3014f2@canb.auug.org.au/ Link: https://lore.kernel.org/all/20220605162537.1604762-1-yury.norov@gmail.com/ Reported-by: Stephen Rothwell <sfr@canb.auug.org.au> Reported-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Reviewed-by: Yury Norov <yury.norov@gmail.com> Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Cc: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2022-06-05 18:51:48 +00:00
current_flags = br_params->flags;
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
} else {
params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
le_addr_type(cp->addr.type));
if (!params)
goto done;
supported_flags = get_params_flags(hdev, params);
bluetooth: don't use bitmaps for random flag accesses The bluetooth code uses our bitmap infrastructure for the two bits (!) of connection setup flags, and in the process causes odd problems when it converts between a bitmap and just the regular values of said bits. It's completely pointless to do things like bitmap_to_arr32() to convert a bitmap into a u32. It shoudln't have been a bitmap in the first place. The reason to use bitmaps is if you have arbitrary number of bits you want to manage (not two!), or if you rely on the atomicity guarantees of the bitmap setting and clearing. The code could use an "atomic_t" and use "atomic_or/andnot()" to set and clear the bit values, but considering that it then copies the bitmaps around with "bitmap_to_arr32()" and friends, there clearly cannot be a lot of atomicity requirements. So just use a regular integer. In the process, this avoids the warnings about erroneous use of bitmap_from_u64() which were triggered on 32-bit architectures when conversion from a u64 would access two words (and, surprise, surprise, only one word is needed - and indeed overkill - for a 2-bit bitmap). That was always problematic, but the compiler seems to notice it and warn about the invalid pattern only after commit 0a97953fd221 ("lib: add bitmap_{from,to}_arr64") changed the exact implementation details of 'bitmap_from_u64()', as reported by Sudip Mukherjee and Stephen Rothwell. Fixes: fe92ee6425a2 ("Bluetooth: hci_core: Rework hci_conn_params flags") Link: https://lore.kernel.org/all/YpyJ9qTNHJzz0FHY@debian/ Link: https://lore.kernel.org/all/20220606080631.0c3014f2@canb.auug.org.au/ Link: https://lore.kernel.org/all/20220605162537.1604762-1-yury.norov@gmail.com/ Reported-by: Stephen Rothwell <sfr@canb.auug.org.au> Reported-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Reviewed-by: Yury Norov <yury.norov@gmail.com> Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Cc: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2022-06-05 18:51:48 +00:00
current_flags = params->flags;
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
}
bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
rp.addr.type = cp->addr.type;
rp.supported_flags = cpu_to_le32(supported_flags);
rp.current_flags = cpu_to_le32(current_flags);
status = MGMT_STATUS_SUCCESS;
done:
hci_dev_unlock(hdev);
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_DEVICE_FLAGS, status,
&rp, sizeof(rp));
}
static void device_flags_changed(struct sock *sk, struct hci_dev *hdev,
bdaddr_t *bdaddr, u8 bdaddr_type,
u32 supported_flags, u32 current_flags)
{
struct mgmt_ev_device_flags_changed ev;
bacpy(&ev.addr.bdaddr, bdaddr);
ev.addr.type = bdaddr_type;
ev.supported_flags = cpu_to_le32(supported_flags);
ev.current_flags = cpu_to_le32(current_flags);
mgmt_event(MGMT_EV_DEVICE_FLAGS_CHANGED, hdev, &ev, sizeof(ev), sk);
}
static int set_device_flags(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_set_device_flags *cp = data;
struct bdaddr_list_with_flags *br_params;
struct hci_conn_params *params;
u8 status = MGMT_STATUS_INVALID_PARAMS;
u32 supported_flags;
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
u32 current_flags = __le32_to_cpu(cp->current_flags);
bt_dev_dbg(hdev, "Set device flags %pMR (type 0x%x) = 0x%x",
&cp->addr.bdaddr, cp->addr.type, current_flags);
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
bluetooth: don't use bitmaps for random flag accesses The bluetooth code uses our bitmap infrastructure for the two bits (!) of connection setup flags, and in the process causes odd problems when it converts between a bitmap and just the regular values of said bits. It's completely pointless to do things like bitmap_to_arr32() to convert a bitmap into a u32. It shoudln't have been a bitmap in the first place. The reason to use bitmaps is if you have arbitrary number of bits you want to manage (not two!), or if you rely on the atomicity guarantees of the bitmap setting and clearing. The code could use an "atomic_t" and use "atomic_or/andnot()" to set and clear the bit values, but considering that it then copies the bitmaps around with "bitmap_to_arr32()" and friends, there clearly cannot be a lot of atomicity requirements. So just use a regular integer. In the process, this avoids the warnings about erroneous use of bitmap_from_u64() which were triggered on 32-bit architectures when conversion from a u64 would access two words (and, surprise, surprise, only one word is needed - and indeed overkill - for a 2-bit bitmap). That was always problematic, but the compiler seems to notice it and warn about the invalid pattern only after commit 0a97953fd221 ("lib: add bitmap_{from,to}_arr64") changed the exact implementation details of 'bitmap_from_u64()', as reported by Sudip Mukherjee and Stephen Rothwell. Fixes: fe92ee6425a2 ("Bluetooth: hci_core: Rework hci_conn_params flags") Link: https://lore.kernel.org/all/YpyJ9qTNHJzz0FHY@debian/ Link: https://lore.kernel.org/all/20220606080631.0c3014f2@canb.auug.org.au/ Link: https://lore.kernel.org/all/20220605162537.1604762-1-yury.norov@gmail.com/ Reported-by: Stephen Rothwell <sfr@canb.auug.org.au> Reported-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Reviewed-by: Yury Norov <yury.norov@gmail.com> Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Cc: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2022-06-05 18:51:48 +00:00
// We should take hci_dev_lock() early, I think.. conn_flags can change
supported_flags = hdev->conn_flags;
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
if ((supported_flags | current_flags) != supported_flags) {
bt_dev_warn(hdev, "Bad flag given (0x%x) vs supported (0x%0x)",
current_flags, supported_flags);
goto done;
}
hci_dev_lock(hdev);
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
if (cp->addr.type == BDADDR_BREDR) {
br_params = hci_bdaddr_list_lookup_with_flags(&hdev->accept_list,
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
&cp->addr.bdaddr,
cp->addr.type);
if (br_params) {
bluetooth: don't use bitmaps for random flag accesses The bluetooth code uses our bitmap infrastructure for the two bits (!) of connection setup flags, and in the process causes odd problems when it converts between a bitmap and just the regular values of said bits. It's completely pointless to do things like bitmap_to_arr32() to convert a bitmap into a u32. It shoudln't have been a bitmap in the first place. The reason to use bitmaps is if you have arbitrary number of bits you want to manage (not two!), or if you rely on the atomicity guarantees of the bitmap setting and clearing. The code could use an "atomic_t" and use "atomic_or/andnot()" to set and clear the bit values, but considering that it then copies the bitmaps around with "bitmap_to_arr32()" and friends, there clearly cannot be a lot of atomicity requirements. So just use a regular integer. In the process, this avoids the warnings about erroneous use of bitmap_from_u64() which were triggered on 32-bit architectures when conversion from a u64 would access two words (and, surprise, surprise, only one word is needed - and indeed overkill - for a 2-bit bitmap). That was always problematic, but the compiler seems to notice it and warn about the invalid pattern only after commit 0a97953fd221 ("lib: add bitmap_{from,to}_arr64") changed the exact implementation details of 'bitmap_from_u64()', as reported by Sudip Mukherjee and Stephen Rothwell. Fixes: fe92ee6425a2 ("Bluetooth: hci_core: Rework hci_conn_params flags") Link: https://lore.kernel.org/all/YpyJ9qTNHJzz0FHY@debian/ Link: https://lore.kernel.org/all/20220606080631.0c3014f2@canb.auug.org.au/ Link: https://lore.kernel.org/all/20220605162537.1604762-1-yury.norov@gmail.com/ Reported-by: Stephen Rothwell <sfr@canb.auug.org.au> Reported-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Reviewed-by: Yury Norov <yury.norov@gmail.com> Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Cc: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2022-06-05 18:51:48 +00:00
br_params->flags = current_flags;
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
status = MGMT_STATUS_SUCCESS;
} else {
bt_dev_warn(hdev, "No such BR/EDR device %pMR (0x%x)",
&cp->addr.bdaddr, cp->addr.type);
}
goto unlock;
}
params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
le_addr_type(cp->addr.type));
if (!params) {
bt_dev_warn(hdev, "No such LE device %pMR (0x%x)",
&cp->addr.bdaddr, le_addr_type(cp->addr.type));
goto unlock;
}
supported_flags = get_params_flags(hdev, params);
if ((supported_flags | current_flags) != supported_flags) {
bt_dev_warn(hdev, "Bad flag given (0x%x) vs supported (0x%0x)",
current_flags, supported_flags);
goto unlock;
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
}
Bluetooth: use RCU for hci_conn_params and iterate safely in hci_sync hci_update_accept_list_sync iterates over hdev->pend_le_conns and hdev->pend_le_reports, and waits for controller events in the loop body, without holding hdev lock. Meanwhile, these lists and the items may be modified e.g. by le_scan_cleanup. This can invalidate the list cursor or any other item in the list, resulting to invalid behavior (eg use-after-free). Use RCU for the hci_conn_params action lists. Since the loop bodies in hci_sync block and we cannot use RCU or hdev->lock for the whole loop, copy list items first and then iterate on the copy. Only the flags field is written from elsewhere, so READ_ONCE/WRITE_ONCE should guarantee we read valid values. Free params everywhere with hci_conn_params_free so the cleanup is guaranteed to be done properly. This fixes the following, which can be triggered e.g. by BlueZ new mgmt-tester case "Add + Remove Device Nowait - Success", or by changing hci_le_set_cig_params to always return false, and running iso-tester: ================================================================== BUG: KASAN: slab-use-after-free in hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) Read of size 8 at addr ffff888001265018 by task kworker/u3:0/32 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-1.fc38 04/01/2014 Workqueue: hci0 hci_cmd_sync_work Call Trace: <TASK> dump_stack_lvl (./arch/x86/include/asm/irqflags.h:134 lib/dump_stack.c:107) print_report (mm/kasan/report.c:320 mm/kasan/report.c:430) ? __virt_addr_valid (./include/linux/mmzone.h:1915 ./include/linux/mmzone.h:2011 arch/x86/mm/physaddr.c:65) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) kasan_report (mm/kasan/report.c:538) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) ? __pfx_hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2780) ? mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_unlock (kernel/locking/mutex.c:538) ? __pfx_update_passive_scan_sync (net/bluetooth/hci_sync.c:2861) hci_cmd_sync_work (net/bluetooth/hci_sync.c:306) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) ? __pfx_worker_thread (kernel/workqueue.c:2480) kthread (kernel/kthread.c:376) ? __pfx_kthread (kernel/kthread.c:331) ret_from_fork (arch/x86/entry/entry_64.S:314) </TASK> Allocated by task 31: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) __kasan_kmalloc (mm/kasan/common.c:374 mm/kasan/common.c:383) hci_conn_params_add (./include/linux/slab.h:580 ./include/linux/slab.h:720 net/bluetooth/hci_core.c:2277) hci_connect_le_scan (net/bluetooth/hci_conn.c:1419 net/bluetooth/hci_conn.c:1589) hci_connect_cis (net/bluetooth/hci_conn.c:2266) iso_connect_cis (net/bluetooth/iso.c:390) iso_sock_connect (net/bluetooth/iso.c:899) __sys_connect (net/socket.c:2003 net/socket.c:2020) __x64_sys_connect (net/socket.c:2027) do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) Freed by task 15: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) kasan_save_free_info (mm/kasan/generic.c:523) __kasan_slab_free (mm/kasan/common.c:238 mm/kasan/common.c:200 mm/kasan/common.c:244) __kmem_cache_free (mm/slub.c:1807 mm/slub.c:3787 mm/slub.c:3800) hci_conn_params_del (net/bluetooth/hci_core.c:2323) le_scan_cleanup (net/bluetooth/hci_conn.c:202) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) kthread (kernel/kthread.c:376) ret_from_fork (arch/x86/entry/entry_64.S:314) ================================================================== Fixes: e8907f76544f ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 3") Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-06-18 22:04:31 +00:00
WRITE_ONCE(params->flags, current_flags);
status = MGMT_STATUS_SUCCESS;
/* Update passive scan if HCI_CONN_FLAG_DEVICE_PRIVACY
* has been set.
*/
if (params->flags & HCI_CONN_FLAG_DEVICE_PRIVACY)
hci_update_passive_scan(hdev);
unlock:
hci_dev_unlock(hdev);
done:
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
if (status == MGMT_STATUS_SUCCESS)
device_flags_changed(sk, hdev, &cp->addr.bdaddr, cp->addr.type,
supported_flags, current_flags);
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_FLAGS, status,
&cp->addr, sizeof(cp->addr));
}
static void mgmt_adv_monitor_added(struct sock *sk, struct hci_dev *hdev,
u16 handle)
{
struct mgmt_ev_adv_monitor_added ev;
ev.monitor_handle = cpu_to_le16(handle);
mgmt_event(MGMT_EV_ADV_MONITOR_ADDED, hdev, &ev, sizeof(ev), sk);
}
void mgmt_adv_monitor_removed(struct hci_dev *hdev, u16 handle)
{
struct mgmt_ev_adv_monitor_removed ev;
struct mgmt_pending_cmd *cmd;
struct sock *sk_skip = NULL;
struct mgmt_cp_remove_adv_monitor *cp;
cmd = pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev);
if (cmd) {
cp = cmd->param;
if (cp->monitor_handle)
sk_skip = cmd->sk;
}
ev.monitor_handle = cpu_to_le16(handle);
mgmt_event(MGMT_EV_ADV_MONITOR_REMOVED, hdev, &ev, sizeof(ev), sk_skip);
}
static int read_adv_mon_features(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct adv_monitor *monitor = NULL;
struct mgmt_rp_read_adv_monitor_features *rp = NULL;
int handle, err;
size_t rp_size = 0;
__u32 supported = 0;
__u32 enabled = 0;
__u16 num_handles = 0;
__u16 handles[HCI_MAX_ADV_MONITOR_NUM_HANDLES];
BT_DBG("request for %s", hdev->name);
hci_dev_lock(hdev);
if (msft_monitor_supported(hdev))
supported |= MGMT_ADV_MONITOR_FEATURE_MASK_OR_PATTERNS;
idr_for_each_entry(&hdev->adv_monitors_idr, monitor, handle)
handles[num_handles++] = monitor->handle;
hci_dev_unlock(hdev);
rp_size = sizeof(*rp) + (num_handles * sizeof(u16));
rp = kmalloc(rp_size, GFP_KERNEL);
if (!rp)
return -ENOMEM;
/* All supported features are currently enabled */
enabled = supported;
rp->supported_features = cpu_to_le32(supported);
rp->enabled_features = cpu_to_le32(enabled);
rp->max_num_handles = cpu_to_le16(HCI_MAX_ADV_MONITOR_NUM_HANDLES);
rp->max_num_patterns = HCI_MAX_ADV_MONITOR_NUM_PATTERNS;
rp->num_handles = cpu_to_le16(num_handles);
if (num_handles)
memcpy(&rp->handles, &handles, (num_handles * sizeof(u16)));
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_READ_ADV_MONITOR_FEATURES,
MGMT_STATUS_SUCCESS, rp, rp_size);
kfree(rp);
return err;
}
static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev,
void *data, int status)
{
struct mgmt_rp_add_adv_patterns_monitor rp;
struct mgmt_pending_cmd *cmd = data;
struct adv_monitor *monitor = cmd->user_data;
hci_dev_lock(hdev);
rp.monitor_handle = cpu_to_le16(monitor->handle);
if (!status) {
mgmt_adv_monitor_added(cmd->sk, hdev, monitor->handle);
hdev->adv_monitors_cnt++;
if (monitor->state == ADV_MONITOR_STATE_NOT_REGISTERED)
monitor->state = ADV_MONITOR_STATE_REGISTERED;
hci_update_passive_scan(hdev);
}
mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
mgmt_status(status), &rp, sizeof(rp));
mgmt_pending_remove(cmd);
hci_dev_unlock(hdev);
bt_dev_dbg(hdev, "add monitor %d complete, status %d",
rp.monitor_handle, status);
}
static int mgmt_add_adv_patterns_monitor_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct adv_monitor *monitor = cmd->user_data;
return hci_add_adv_monitor(hdev, monitor);
}
static int __add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
struct adv_monitor *m, u8 status,
void *data, u16 len, u16 op)
{
struct mgmt_pending_cmd *cmd;
int err;
hci_dev_lock(hdev);
if (status)
goto unlock;
if (pending_find(MGMT_OP_SET_LE, hdev) ||
pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) ||
pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev) ||
pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev)) {
status = MGMT_STATUS_BUSY;
goto unlock;
}
cmd = mgmt_pending_add(sk, op, hdev, data, len);
if (!cmd) {
status = MGMT_STATUS_NO_RESOURCES;
goto unlock;
}
Bluetooth: Fix crash in mgmt_add_adv_patterns_monitor_complete If hci_add_adv_monitor is a pending command(e.g. forward to msft_add_monitor_pattern), it is possible that mgmt_add_adv_patterns_monitor_complete gets called before cmd->user_data gets set, which will cause a crash when we try to get the moniter handle through cmd->user_data in mgmt_add_adv_patterns_monitor_complete. This moves the cmd->user_data assignment earlier than hci_add_adv_monitor. RIP: 0010:mgmt_add_adv_patterns_monitor_complete+0x82/0x187 [bluetooth] Code: 1e bf 03 00 00 00 be 52 00 00 00 4c 89 ea e8 9e e4 02 00 49 89 c6 48 85 c0 0f 84 06 01 00 00 48 89 5d b8 4c 89 fb 4d 8b 7e 30 <41> 0f b7 47 18 66 89 45 c0 45 84 e4 75 5a 4d 8b 56 28 48 8d 4d c8 RSP: 0018:ffffae81807dbcb8 EFLAGS: 00010286 RAX: ffff91c4bdf723c0 RBX: 0000000000000000 RCX: ffff91c4e5da5b80 RDX: ffff91c405680000 RSI: 0000000000000052 RDI: ffff91c49d654c00 RBP: ffffae81807dbd00 R08: ffff91c49fb157e0 R09: ffff91c49fb157e0 R10: 000000000002a4f0 R11: ffffffffc0819cfd R12: 0000000000000000 R13: ffff91c405680000 R14: ffff91c4bdf723c0 R15: 0000000000000000 FS: 0000000000000000(0000) GS:ffff91c4ea300000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000018 CR3: 0000000133612002 CR4: 00000000003606e0 Call Trace: ? msft_le_monitor_advertisement_cb+0x111/0x141 [bluetooth] hci_event_packet+0x425e/0x631c [bluetooth] ? printk+0x59/0x73 ? __switch_to_asm+0x41/0x70 ? msft_le_set_advertisement_filter_enable_cb+0xa6/0xa6 [bluetooth] ? bt_dbg+0xb4/0xbb [bluetooth] ? __switch_to_asm+0x41/0x70 hci_rx_work+0x101/0x319 [bluetooth] process_one_work+0x257/0x506 worker_thread+0x10d/0x284 kthread+0x14c/0x154 ? process_one_work+0x506/0x506 ? kthread_blkcg+0x2c/0x2c ret_from_fork+0x1f/0x40 Reviewed-by: Miao-chen Chou <mcchou@chromium.org> Reviewed-by: Manish Mandlik <mmandlik@chromium.org> Reviewed-by: Archie Pusaka <apusaka@chromium.org> Signed-off-by: Howard Chung <howardchung@google.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-02-03 07:09:29 +00:00
cmd->user_data = m;
err = hci_cmd_sync_queue(hdev, mgmt_add_adv_patterns_monitor_sync, cmd,
mgmt_add_adv_patterns_monitor_complete);
if (err) {
if (err == -ENOMEM)
status = MGMT_STATUS_NO_RESOURCES;
else
status = MGMT_STATUS_FAILED;
goto unlock;
}
hci_dev_unlock(hdev);
return 0;
unlock:
hci_free_adv_monitor(hdev, m);
hci_dev_unlock(hdev);
return mgmt_cmd_status(sk, hdev->id, op, status);
}
static void parse_adv_monitor_rssi(struct adv_monitor *m,
struct mgmt_adv_rssi_thresholds *rssi)
{
if (rssi) {
m->rssi.low_threshold = rssi->low_threshold;
m->rssi.low_threshold_timeout =
__le16_to_cpu(rssi->low_threshold_timeout);
m->rssi.high_threshold = rssi->high_threshold;
m->rssi.high_threshold_timeout =
__le16_to_cpu(rssi->high_threshold_timeout);
m->rssi.sampling_period = rssi->sampling_period;
} else {
/* Default values. These numbers are the least constricting
* parameters for MSFT API to work, so it behaves as if there
* are no rssi parameter to consider. May need to be changed
* if other API are to be supported.
*/
m->rssi.low_threshold = -127;
m->rssi.low_threshold_timeout = 60;
m->rssi.high_threshold = -127;
m->rssi.high_threshold_timeout = 0;
m->rssi.sampling_period = 0;
}
}
static u8 parse_adv_monitor_pattern(struct adv_monitor *m, u8 pattern_count,
struct mgmt_adv_pattern *patterns)
{
u8 offset = 0, length = 0;
struct adv_pattern *p = NULL;
int i;
for (i = 0; i < pattern_count; i++) {
offset = patterns[i].offset;
length = patterns[i].length;
if (offset >= HCI_MAX_EXT_AD_LENGTH ||
length > HCI_MAX_EXT_AD_LENGTH ||
(offset + length) > HCI_MAX_EXT_AD_LENGTH)
return MGMT_STATUS_INVALID_PARAMS;
p = kmalloc(sizeof(*p), GFP_KERNEL);
if (!p)
return MGMT_STATUS_NO_RESOURCES;
p->ad_type = patterns[i].ad_type;
p->offset = patterns[i].offset;
p->length = patterns[i].length;
memcpy(p->value, patterns[i].value, p->length);
INIT_LIST_HEAD(&p->list);
list_add(&p->list, &m->patterns);
}
return MGMT_STATUS_SUCCESS;
}
static int add_adv_patterns_monitor(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_cp_add_adv_patterns_monitor *cp = data;
struct adv_monitor *m = NULL;
u8 status = MGMT_STATUS_SUCCESS;
size_t expected_size = sizeof(*cp);
BT_DBG("request for %s", hdev->name);
if (len <= sizeof(*cp)) {
status = MGMT_STATUS_INVALID_PARAMS;
goto done;
}
expected_size += cp->pattern_count * sizeof(struct mgmt_adv_pattern);
if (len != expected_size) {
status = MGMT_STATUS_INVALID_PARAMS;
goto done;
}
m = kzalloc(sizeof(*m), GFP_KERNEL);
if (!m) {
status = MGMT_STATUS_NO_RESOURCES;
goto done;
}
INIT_LIST_HEAD(&m->patterns);
parse_adv_monitor_rssi(m, NULL);
status = parse_adv_monitor_pattern(m, cp->pattern_count, cp->patterns);
done:
return __add_adv_patterns_monitor(sk, hdev, m, status, data, len,
MGMT_OP_ADD_ADV_PATTERNS_MONITOR);
}
static int add_adv_patterns_monitor_rssi(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_cp_add_adv_patterns_monitor_rssi *cp = data;
struct adv_monitor *m = NULL;
u8 status = MGMT_STATUS_SUCCESS;
size_t expected_size = sizeof(*cp);
BT_DBG("request for %s", hdev->name);
if (len <= sizeof(*cp)) {
status = MGMT_STATUS_INVALID_PARAMS;
goto done;
}
expected_size += cp->pattern_count * sizeof(struct mgmt_adv_pattern);
if (len != expected_size) {
status = MGMT_STATUS_INVALID_PARAMS;
goto done;
}
m = kzalloc(sizeof(*m), GFP_KERNEL);
if (!m) {
status = MGMT_STATUS_NO_RESOURCES;
goto done;
}
INIT_LIST_HEAD(&m->patterns);
parse_adv_monitor_rssi(m, &cp->rssi);
status = parse_adv_monitor_pattern(m, cp->pattern_count, cp->patterns);
done:
return __add_adv_patterns_monitor(sk, hdev, m, status, data, len,
MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI);
}
static void mgmt_remove_adv_monitor_complete(struct hci_dev *hdev,
void *data, int status)
{
struct mgmt_rp_remove_adv_monitor rp;
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_remove_adv_monitor *cp = cmd->param;
hci_dev_lock(hdev);
rp.monitor_handle = cp->monitor_handle;
if (!status)
hci_update_passive_scan(hdev);
mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
mgmt_status(status), &rp, sizeof(rp));
mgmt_pending_remove(cmd);
hci_dev_unlock(hdev);
bt_dev_dbg(hdev, "remove monitor %d complete, status %d",
rp.monitor_handle, status);
}
static int mgmt_remove_adv_monitor_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_remove_adv_monitor *cp = cmd->param;
u16 handle = __le16_to_cpu(cp->monitor_handle);
if (!handle)
return hci_remove_all_adv_monitor(hdev);
return hci_remove_single_adv_monitor(hdev, handle);
}
static int remove_adv_monitor(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_pending_cmd *cmd;
int err, status;
hci_dev_lock(hdev);
if (pending_find(MGMT_OP_SET_LE, hdev) ||
pending_find(MGMT_OP_REMOVE_ADV_MONITOR, hdev) ||
pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR, hdev) ||
pending_find(MGMT_OP_ADD_ADV_PATTERNS_MONITOR_RSSI, hdev)) {
status = MGMT_STATUS_BUSY;
goto unlock;
}
cmd = mgmt_pending_add(sk, MGMT_OP_REMOVE_ADV_MONITOR, hdev, data, len);
if (!cmd) {
status = MGMT_STATUS_NO_RESOURCES;
goto unlock;
}
err = hci_cmd_sync_submit(hdev, mgmt_remove_adv_monitor_sync, cmd,
mgmt_remove_adv_monitor_complete);
if (err) {
mgmt_pending_remove(cmd);
if (err == -ENOMEM)
status = MGMT_STATUS_NO_RESOURCES;
else
status = MGMT_STATUS_FAILED;
goto unlock;
}
hci_dev_unlock(hdev);
return 0;
unlock:
hci_dev_unlock(hdev);
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADV_MONITOR,
status);
}
static void read_local_oob_data_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_rp_read_local_oob_data mgmt_rp;
size_t rp_size = sizeof(mgmt_rp);
struct mgmt_pending_cmd *cmd = data;
struct sk_buff *skb = cmd->skb;
u8 status = mgmt_status(err);
if (!status) {
if (!skb)
status = MGMT_STATUS_FAILED;
else if (IS_ERR(skb))
status = mgmt_status(PTR_ERR(skb));
else
status = mgmt_status(skb->data[0]);
}
bt_dev_dbg(hdev, "status %d", status);
if (status) {
mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, status);
goto remove;
}
memset(&mgmt_rp, 0, sizeof(mgmt_rp));
if (!bredr_sc_enabled(hdev)) {
struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
if (skb->len < sizeof(*rp)) {
mgmt_cmd_status(cmd->sk, hdev->id,
MGMT_OP_READ_LOCAL_OOB_DATA,
MGMT_STATUS_FAILED);
goto remove;
}
memcpy(mgmt_rp.hash192, rp->hash, sizeof(rp->hash));
memcpy(mgmt_rp.rand192, rp->rand, sizeof(rp->rand));
rp_size -= sizeof(mgmt_rp.hash256) + sizeof(mgmt_rp.rand256);
} else {
struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data;
if (skb->len < sizeof(*rp)) {
mgmt_cmd_status(cmd->sk, hdev->id,
MGMT_OP_READ_LOCAL_OOB_DATA,
MGMT_STATUS_FAILED);
goto remove;
}
memcpy(mgmt_rp.hash192, rp->hash192, sizeof(rp->hash192));
memcpy(mgmt_rp.rand192, rp->rand192, sizeof(rp->rand192));
memcpy(mgmt_rp.hash256, rp->hash256, sizeof(rp->hash256));
memcpy(mgmt_rp.rand256, rp->rand256, sizeof(rp->rand256));
}
mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
MGMT_STATUS_SUCCESS, &mgmt_rp, rp_size);
remove:
if (skb && !IS_ERR(skb))
kfree_skb(skb);
mgmt_pending_free(cmd);
}
static int read_local_oob_data_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
if (bredr_sc_enabled(hdev))
cmd->skb = hci_read_local_oob_data_sync(hdev, true, cmd->sk);
else
cmd->skb = hci_read_local_oob_data_sync(hdev, false, cmd->sk);
if (IS_ERR(cmd->skb))
return PTR_ERR(cmd->skb);
else
return 0;
}
static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
struct mgmt_pending_cmd *cmd;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
MGMT_STATUS_NOT_POWERED);
goto unlock;
}
if (!lmp_ssp_capable(hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
MGMT_STATUS_NOT_SUPPORTED);
goto unlock;
}
cmd = mgmt_pending_new(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
if (!cmd)
err = -ENOMEM;
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 10:07:26 +00:00
else
err = hci_cmd_sync_queue(hdev, read_local_oob_data_sync, cmd,
read_local_oob_data_complete);
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 10:07:26 +00:00
if (err < 0) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
MGMT_STATUS_FAILED);
if (cmd)
mgmt_pending_free(cmd);
}
unlock:
hci_dev_unlock(hdev);
return err;
}
static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_addr_info *addr = data;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (!bdaddr_type_is_valid(addr->type))
return mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_ADD_REMOTE_OOB_DATA,
MGMT_STATUS_INVALID_PARAMS,
addr, sizeof(*addr));
hci_dev_lock(hdev);
if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) {
struct mgmt_cp_add_remote_oob_data *cp = data;
u8 status;
if (cp->addr.type != BDADDR_BREDR) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_ADD_REMOTE_OOB_DATA,
MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr));
goto unlock;
}
err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
cp->addr.type, cp->hash,
cp->rand, NULL, NULL);
if (err < 0)
status = MGMT_STATUS_FAILED;
else
status = MGMT_STATUS_SUCCESS;
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_ADD_REMOTE_OOB_DATA, status,
&cp->addr, sizeof(cp->addr));
} else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) {
struct mgmt_cp_add_remote_oob_ext_data *cp = data;
u8 *rand192, *hash192, *rand256, *hash256;
u8 status;
if (bdaddr_type_is_le(cp->addr.type)) {
/* Enforce zero-valued 192-bit parameters as
* long as legacy SMP OOB isn't implemented.
*/
if (memcmp(cp->rand192, ZERO_KEY, 16) ||
memcmp(cp->hash192, ZERO_KEY, 16)) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_ADD_REMOTE_OOB_DATA,
MGMT_STATUS_INVALID_PARAMS,
addr, sizeof(*addr));
goto unlock;
}
rand192 = NULL;
hash192 = NULL;
} else {
/* In case one of the P-192 values is set to zero,
* then just disable OOB data for P-192.
*/
if (!memcmp(cp->rand192, ZERO_KEY, 16) ||
!memcmp(cp->hash192, ZERO_KEY, 16)) {
rand192 = NULL;
hash192 = NULL;
} else {
rand192 = cp->rand192;
hash192 = cp->hash192;
}
}
/* In case one of the P-256 values is set to zero, then just
* disable OOB data for P-256.
*/
if (!memcmp(cp->rand256, ZERO_KEY, 16) ||
!memcmp(cp->hash256, ZERO_KEY, 16)) {
rand256 = NULL;
hash256 = NULL;
} else {
rand256 = cp->rand256;
hash256 = cp->hash256;
}
err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr,
cp->addr.type, hash192, rand192,
hash256, rand256);
if (err < 0)
status = MGMT_STATUS_FAILED;
else
status = MGMT_STATUS_SUCCESS;
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_ADD_REMOTE_OOB_DATA,
status, &cp->addr, sizeof(cp->addr));
} else {
bt_dev_err(hdev, "add_remote_oob_data: invalid len of %u bytes",
len);
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA,
MGMT_STATUS_INVALID_PARAMS);
}
unlock:
hci_dev_unlock(hdev);
return err;
}
static int remove_remote_oob_data(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_cp_remove_remote_oob_data *cp = data;
u8 status;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (cp->addr.type != BDADDR_BREDR)
return mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_REMOVE_REMOTE_OOB_DATA,
MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr));
hci_dev_lock(hdev);
if (!bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
hci_remote_oob_data_clear(hdev);
status = MGMT_STATUS_SUCCESS;
goto done;
}
err = hci_remove_remote_oob_data(hdev, &cp->addr.bdaddr, cp->addr.type);
if (err < 0)
status = MGMT_STATUS_INVALID_PARAMS;
else
status = MGMT_STATUS_SUCCESS;
done:
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_REMOTE_OOB_DATA,
status, &cp->addr, sizeof(cp->addr));
hci_dev_unlock(hdev);
return err;
}
void mgmt_start_discovery_complete(struct hci_dev *hdev, u8 status)
{
struct mgmt_pending_cmd *cmd;
bt_dev_dbg(hdev, "status %u", status);
hci_dev_lock(hdev);
cmd = pending_find(MGMT_OP_START_DISCOVERY, hdev);
if (!cmd)
cmd = pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev);
if (!cmd)
cmd = pending_find(MGMT_OP_START_LIMITED_DISCOVERY, hdev);
if (cmd) {
cmd->cmd_complete(cmd, mgmt_status(status));
mgmt_pending_remove(cmd);
}
hci_dev_unlock(hdev);
}
static bool discovery_type_is_valid(struct hci_dev *hdev, uint8_t type,
uint8_t *mgmt_status)
{
switch (type) {
case DISCOV_TYPE_LE:
*mgmt_status = mgmt_le_support(hdev);
if (*mgmt_status)
return false;
break;
case DISCOV_TYPE_INTERLEAVED:
*mgmt_status = mgmt_le_support(hdev);
if (*mgmt_status)
return false;
fallthrough;
case DISCOV_TYPE_BREDR:
*mgmt_status = mgmt_bredr_support(hdev);
if (*mgmt_status)
return false;
break;
default:
*mgmt_status = MGMT_STATUS_INVALID_PARAMS;
return false;
}
return true;
}
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-27 23:58:45 +00:00
static void start_discovery_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_pending_cmd *cmd = data;
if (cmd != pending_find(MGMT_OP_START_DISCOVERY, hdev) &&
cmd != pending_find(MGMT_OP_START_LIMITED_DISCOVERY, hdev) &&
cmd != pending_find(MGMT_OP_START_SERVICE_DISCOVERY, hdev))
return;
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-27 23:58:45 +00:00
bt_dev_dbg(hdev, "err %d", err);
mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err),
cmd->param, 1);
mgmt_pending_remove(cmd);
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-27 23:58:45 +00:00
hci_discovery_set_state(hdev, err ? DISCOVERY_STOPPED:
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-27 23:58:45 +00:00
DISCOVERY_FINDING);
}
static int start_discovery_sync(struct hci_dev *hdev, void *data)
{
return hci_start_discovery_sync(hdev);
}
static int start_discovery_internal(struct sock *sk, struct hci_dev *hdev,
u16 op, void *data, u16 len)
{
struct mgmt_cp_start_discovery *cp = data;
struct mgmt_pending_cmd *cmd;
u8 status;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_complete(sk, hdev->id, op,
MGMT_STATUS_NOT_POWERED,
&cp->type, sizeof(cp->type));
goto failed;
}
if (hdev->discovery.state != DISCOVERY_STOPPED ||
hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
err = mgmt_cmd_complete(sk, hdev->id, op, MGMT_STATUS_BUSY,
&cp->type, sizeof(cp->type));
goto failed;
}
if (!discovery_type_is_valid(hdev, cp->type, &status)) {
err = mgmt_cmd_complete(sk, hdev->id, op, status,
&cp->type, sizeof(cp->type));
goto failed;
}
/* Can't start discovery when it is paused */
if (hdev->discovery_paused) {
err = mgmt_cmd_complete(sk, hdev->id, op, MGMT_STATUS_BUSY,
&cp->type, sizeof(cp->type));
goto failed;
}
/* Clear the discovery filter first to free any previously
* allocated memory for the UUID list.
*/
hci_discovery_filter_clear(hdev);
hdev->discovery.type = cp->type;
hdev->discovery.report_invalid_rssi = false;
if (op == MGMT_OP_START_LIMITED_DISCOVERY)
hdev->discovery.limited = true;
else
hdev->discovery.limited = false;
cmd = mgmt_pending_add(sk, op, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
}
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-27 23:58:45 +00:00
err = hci_cmd_sync_queue(hdev, start_discovery_sync, cmd,
start_discovery_complete);
if (err < 0) {
mgmt_pending_remove(cmd);
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-27 23:58:45 +00:00
goto failed;
}
hci_discovery_set_state(hdev, DISCOVERY_STARTING);
failed:
hci_dev_unlock(hdev);
return err;
}
static int start_discovery(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
return start_discovery_internal(sk, hdev, MGMT_OP_START_DISCOVERY,
data, len);
}
static int start_limited_discovery(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
return start_discovery_internal(sk, hdev,
MGMT_OP_START_LIMITED_DISCOVERY,
data, len);
}
static int start_service_discovery(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_cp_start_service_discovery *cp = data;
struct mgmt_pending_cmd *cmd;
const u16 max_uuid_count = ((U16_MAX - sizeof(*cp)) / 16);
u16 uuid_count, expected_len;
u8 status;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_START_SERVICE_DISCOVERY,
MGMT_STATUS_NOT_POWERED,
&cp->type, sizeof(cp->type));
goto failed;
}
if (hdev->discovery.state != DISCOVERY_STOPPED ||
hci_dev_test_flag(hdev, HCI_PERIODIC_INQ)) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_START_SERVICE_DISCOVERY,
MGMT_STATUS_BUSY, &cp->type,
sizeof(cp->type));
goto failed;
}
if (hdev->discovery_paused) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_START_SERVICE_DISCOVERY,
MGMT_STATUS_BUSY, &cp->type,
sizeof(cp->type));
goto failed;
}
uuid_count = __le16_to_cpu(cp->uuid_count);
if (uuid_count > max_uuid_count) {
bt_dev_err(hdev, "service_discovery: too big uuid_count value %u",
uuid_count);
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_START_SERVICE_DISCOVERY,
MGMT_STATUS_INVALID_PARAMS, &cp->type,
sizeof(cp->type));
goto failed;
}
expected_len = sizeof(*cp) + uuid_count * 16;
if (expected_len != len) {
bt_dev_err(hdev, "service_discovery: expected %u bytes, got %u bytes",
expected_len, len);
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_START_SERVICE_DISCOVERY,
MGMT_STATUS_INVALID_PARAMS, &cp->type,
sizeof(cp->type));
goto failed;
}
if (!discovery_type_is_valid(hdev, cp->type, &status)) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_START_SERVICE_DISCOVERY,
status, &cp->type, sizeof(cp->type));
goto failed;
}
cmd = mgmt_pending_add(sk, MGMT_OP_START_SERVICE_DISCOVERY,
hdev, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
}
/* Clear the discovery filter first to free any previously
* allocated memory for the UUID list.
*/
hci_discovery_filter_clear(hdev);
hdev->discovery.result_filtering = true;
hdev->discovery.type = cp->type;
hdev->discovery.rssi = cp->rssi;
hdev->discovery.uuid_count = uuid_count;
if (uuid_count > 0) {
hdev->discovery.uuids = kmemdup(cp->uuids, uuid_count * 16,
GFP_KERNEL);
if (!hdev->discovery.uuids) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_START_SERVICE_DISCOVERY,
MGMT_STATUS_FAILED,
&cp->type, sizeof(cp->type));
mgmt_pending_remove(cmd);
goto failed;
}
}
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-27 23:58:45 +00:00
err = hci_cmd_sync_queue(hdev, start_discovery_sync, cmd,
start_discovery_complete);
if (err < 0) {
mgmt_pending_remove(cmd);
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-27 23:58:45 +00:00
goto failed;
}
hci_discovery_set_state(hdev, DISCOVERY_STARTING);
failed:
hci_dev_unlock(hdev);
return err;
}
void mgmt_stop_discovery_complete(struct hci_dev *hdev, u8 status)
{
struct mgmt_pending_cmd *cmd;
bt_dev_dbg(hdev, "status %u", status);
hci_dev_lock(hdev);
cmd = pending_find(MGMT_OP_STOP_DISCOVERY, hdev);
if (cmd) {
cmd->cmd_complete(cmd, mgmt_status(status));
mgmt_pending_remove(cmd);
}
hci_dev_unlock(hdev);
}
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-27 23:58:45 +00:00
static void stop_discovery_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_pending_cmd *cmd = data;
if (cmd != pending_find(MGMT_OP_STOP_DISCOVERY, hdev))
return;
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-27 23:58:45 +00:00
bt_dev_dbg(hdev, "err %d", err);
mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(err),
cmd->param, 1);
mgmt_pending_remove(cmd);
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-27 23:58:45 +00:00
if (!err)
hci_discovery_set_state(hdev, DISCOVERY_STOPPED);
}
static int stop_discovery_sync(struct hci_dev *hdev, void *data)
{
return hci_stop_discovery_sync(hdev);
}
static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_stop_discovery *mgmt_cp = data;
struct mgmt_pending_cmd *cmd;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
if (!hci_discovery_active(hdev)) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
MGMT_STATUS_REJECTED, &mgmt_cp->type,
sizeof(mgmt_cp->type));
goto unlock;
}
if (hdev->discovery.type != mgmt_cp->type) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_STOP_DISCOVERY,
MGMT_STATUS_INVALID_PARAMS,
&mgmt_cp->type, sizeof(mgmt_cp->type));
goto unlock;
}
cmd = mgmt_pending_add(sk, MGMT_OP_STOP_DISCOVERY, hdev, data, len);
if (!cmd) {
err = -ENOMEM;
goto unlock;
}
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-27 23:58:45 +00:00
err = hci_cmd_sync_queue(hdev, stop_discovery_sync, cmd,
stop_discovery_complete);
if (err < 0) {
mgmt_pending_remove(cmd);
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-27 23:58:45 +00:00
goto unlock;
}
hci_discovery_set_state(hdev, DISCOVERY_STOPPING);
unlock:
hci_dev_unlock(hdev);
return err;
}
static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_confirm_name *cp = data;
struct inquiry_entry *e;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
if (!hci_discovery_active(hdev)) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
MGMT_STATUS_FAILED, &cp->addr,
sizeof(cp->addr));
goto failed;
}
e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr);
if (!e) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME,
MGMT_STATUS_INVALID_PARAMS, &cp->addr,
sizeof(cp->addr));
goto failed;
}
if (cp->name_known) {
e->name_state = NAME_KNOWN;
list_del(&e->list);
} else {
e->name_state = NAME_NEEDED;
hci_inquiry_cache_update_resolve(hdev, e);
}
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, 0,
&cp->addr, sizeof(cp->addr));
failed:
hci_dev_unlock(hdev);
return err;
}
static int block_device(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_block_device *cp = data;
u8 status;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (!bdaddr_type_is_valid(cp->addr.type))
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr));
hci_dev_lock(hdev);
err = hci_bdaddr_list_add(&hdev->reject_list, &cp->addr.bdaddr,
cp->addr.type);
if (err < 0) {
status = MGMT_STATUS_FAILED;
goto done;
}
mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr),
sk);
status = MGMT_STATUS_SUCCESS;
done:
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status,
&cp->addr, sizeof(cp->addr));
hci_dev_unlock(hdev);
return err;
}
static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_unblock_device *cp = data;
u8 status;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (!bdaddr_type_is_valid(cp->addr.type))
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr));
hci_dev_lock(hdev);
err = hci_bdaddr_list_del(&hdev->reject_list, &cp->addr.bdaddr,
cp->addr.type);
if (err < 0) {
status = MGMT_STATUS_INVALID_PARAMS;
goto done;
}
mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr),
sk);
status = MGMT_STATUS_SUCCESS;
done:
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status,
&cp->addr, sizeof(cp->addr));
hci_dev_unlock(hdev);
return err;
}
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
static int set_device_id_sync(struct hci_dev *hdev, void *data)
{
return hci_update_eir_sync(hdev);
}
static int set_device_id(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_set_device_id *cp = data;
int err;
__u16 source;
bt_dev_dbg(hdev, "sock %p", sk);
source = __le16_to_cpu(cp->source);
if (source > 0x0002)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEVICE_ID,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
hdev->devid_source = source;
hdev->devid_vendor = __le16_to_cpu(cp->vendor);
hdev->devid_product = __le16_to_cpu(cp->product);
hdev->devid_version = __le16_to_cpu(cp->version);
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_DEVICE_ID, 0,
NULL, 0);
Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 1 This make use of hci_cmd_sync_queue for the following MGMT commands: Set Device Class Set Device ID Add UUID Remove UUID tools/mgmt-tester -s "Set Device Class" Test Summary ------------ Set Device Class - Success 1 Passed Set Device Class - Success 2 Passed Set Device Class - Invalid parameters 1 Passed Total: 3, Passed: 3 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0599 seconds tools/mgmt-tester -s "Set Device ID" Test Summary ------------ Set Device ID - Success 1 Passed Set Device ID - Success 2 Passed Set Device ID - Disable Passed Set Device ID - Power off and Power on Passed Set Device ID - SSP off and Power on Passed Set Device ID - Invalid Parameter Passed Total: 6, Passed: 6 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.107 seconds tools/mgmt-tester -s "Add UUID" Test Summary ------------ Add UUID - UUID-16 1 Passed Add UUID - UUID-16 multiple 1 Passed Add UUID - UUID-16 partial 1 Passed Add UUID - UUID-32 1 Passed Add UUID - UUID-32 multiple 1 Passed Add UUID - UUID-32 partial 1 Passed Add UUID - UUID-128 1 Passed Add UUID - UUID-128 multiple 1 Passed Add UUID - UUID-128 partial 1 Passed Add UUID - UUID mix Passed Total: 10, Passed: 10 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.198 seconds tools/mgmt-tester -s "Remove UUID" Test Summary ------------ Remove UUID - Success 1 Passed Remove UUID - All UUID - Success 2 Passed Remove UUID - Power Off - Success 3 Passed Remove UUID - Power Off and On - Success 4 Passed Remove UUID - Not Exist - Invalid Params 1 Passed Total: 5, Passed: 5 (100.0%), Failed: 0, Not Run: 0 Overall execution time: 0.0908 seconds Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-10-27 23:58:39 +00:00
hci_cmd_sync_queue(hdev, set_device_id_sync, NULL, NULL);
hci_dev_unlock(hdev);
return err;
}
static void enable_advertising_instance(struct hci_dev *hdev, int err)
{
if (err)
bt_dev_err(hdev, "failed to re-configure advertising %d", err);
else
bt_dev_dbg(hdev, "status %d", err);
}
static void set_advertising_complete(struct hci_dev *hdev, void *data, int err)
{
struct cmd_lookup match = { NULL, hdev };
u8 instance;
struct adv_info *adv_instance;
u8 status = mgmt_status(err);
Bluetooth: Fix missing hci_dev_lock/unlock in mgmt req_complete() mgmt_pending_remove() should be called with hci_dev_lock protection and currently the rule to take dev lock is that all mgmt req_complete functions should take dev lock. So this patch fixes the same in the missing functions Without this patch there is a chance of invalid memory access while accessing the mgmt_pending list like below bluetoothd: 392] [0] Backtrace: bluetoothd: 392] [0] [<c04ec770>] (pending_eir_or_class+0x0/0x68) from [<c04f1830>] (add_uuid+0x34/0x1c4) bluetoothd: 392] [0] [<c04f17fc>] (add_uuid+0x0/0x1c4) from [<c04f3cc4>] (mgmt_control+0x204/0x274) bluetoothd: 392] [0] [<c04f3ac0>] (mgmt_control+0x0/0x274) from [<c04f609c>] (hci_sock_sendmsg+0x80/0x308) bluetoothd: 392] [0] [<c04f601c>] (hci_sock_sendmsg+0x0/0x308) from [<c03d4d68>] (sock_aio_write+0x144/0x174) bluetoothd: 392] [0] r8:00000000 r7 7c1be90 r6 7c1be18 r5:00000017 r4 a90ea80 bluetoothd: 392] [0] [<c03d4c24>] (sock_aio_write+0x0/0x174) from [<c00e2d4c>] (do_sync_write+0xb0/0xe0) bluetoothd: 392] [0] [<c00e2c9c>] (do_sync_write+0x0/0xe0) from [<c00e371c>] (vfs_write+0x134/0x13c) bluetoothd: 392] [0] r8:00000000 r7 7c1bf70 r6:beeca5c8 r5:00000017 r4 7c05900 bluetoothd: 392] [0] [<c00e35e8>] (vfs_write+0x0/0x13c) from [<c00e3910>] (sys_write+0x44/0x70) bluetoothd: 392] [0] r8:00000000 r7:00000004 r6:00000017 r5:beeca5c8 r4 7c05900 bluetoothd: 392] [0] [<c00e38cc>] (sys_write+0x0/0x70) from [<c000e3c0>] (ret_fast_syscall+0x0/0x30) bluetoothd: 392] [0] r9 7c1a000 r8:c000e568 r6:400b5f10 r5:403896d8 r4:beeca604 bluetoothd: 392] [0] Code: e28cc00c e152000c 0a00000f e3a00001 (e1d210b8) bluetoothd: 392] [0] ---[ end trace 67b6ac67435864c4 ]--- bluetoothd: 392] [0] Kernel panic - not syncing: Fatal exception Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-12-11 06:13:12 +00:00
if (status) {
mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev,
cmd_status_rsp, &status);
return;
}
if (hci_dev_test_flag(hdev, HCI_LE_ADV))
hci_dev_set_flag(hdev, HCI_ADVERTISING);
else
hci_dev_clear_flag(hdev, HCI_ADVERTISING);
mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp,
&match);
new_settings(hdev, match.sk);
if (match.sk)
sock_put(match.sk);
Bluetooth: Fix missing hci_dev_lock/unlock in mgmt req_complete() mgmt_pending_remove() should be called with hci_dev_lock protection and currently the rule to take dev lock is that all mgmt req_complete functions should take dev lock. So this patch fixes the same in the missing functions Without this patch there is a chance of invalid memory access while accessing the mgmt_pending list like below bluetoothd: 392] [0] Backtrace: bluetoothd: 392] [0] [<c04ec770>] (pending_eir_or_class+0x0/0x68) from [<c04f1830>] (add_uuid+0x34/0x1c4) bluetoothd: 392] [0] [<c04f17fc>] (add_uuid+0x0/0x1c4) from [<c04f3cc4>] (mgmt_control+0x204/0x274) bluetoothd: 392] [0] [<c04f3ac0>] (mgmt_control+0x0/0x274) from [<c04f609c>] (hci_sock_sendmsg+0x80/0x308) bluetoothd: 392] [0] [<c04f601c>] (hci_sock_sendmsg+0x0/0x308) from [<c03d4d68>] (sock_aio_write+0x144/0x174) bluetoothd: 392] [0] r8:00000000 r7 7c1be90 r6 7c1be18 r5:00000017 r4 a90ea80 bluetoothd: 392] [0] [<c03d4c24>] (sock_aio_write+0x0/0x174) from [<c00e2d4c>] (do_sync_write+0xb0/0xe0) bluetoothd: 392] [0] [<c00e2c9c>] (do_sync_write+0x0/0xe0) from [<c00e371c>] (vfs_write+0x134/0x13c) bluetoothd: 392] [0] r8:00000000 r7 7c1bf70 r6:beeca5c8 r5:00000017 r4 7c05900 bluetoothd: 392] [0] [<c00e35e8>] (vfs_write+0x0/0x13c) from [<c00e3910>] (sys_write+0x44/0x70) bluetoothd: 392] [0] r8:00000000 r7:00000004 r6:00000017 r5:beeca5c8 r4 7c05900 bluetoothd: 392] [0] [<c00e38cc>] (sys_write+0x0/0x70) from [<c000e3c0>] (ret_fast_syscall+0x0/0x30) bluetoothd: 392] [0] r9 7c1a000 r8:c000e568 r6:400b5f10 r5:403896d8 r4:beeca604 bluetoothd: 392] [0] Code: e28cc00c e152000c 0a00000f e3a00001 (e1d210b8) bluetoothd: 392] [0] ---[ end trace 67b6ac67435864c4 ]--- bluetoothd: 392] [0] Kernel panic - not syncing: Fatal exception Signed-off-by: Jaganath Kanakkassery <jaganath.k@samsung.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2014-12-11 06:13:12 +00:00
/* If "Set Advertising" was just disabled and instance advertising was
* set up earlier, then re-enable multi-instance advertising.
*/
if (hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
list_empty(&hdev->adv_instances))
return;
instance = hdev->cur_adv_instance;
if (!instance) {
adv_instance = list_first_entry_or_null(&hdev->adv_instances,
struct adv_info, list);
if (!adv_instance)
return;
instance = adv_instance->instance;
}
err = hci_schedule_adv_instance_sync(hdev, instance, true);
enable_advertising_instance(hdev, err);
}
static int set_adv_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_mode *cp = cmd->param;
u8 val = !!cp->val;
if (cp->val == 0x02)
hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
else
hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
cancel_adv_timeout(hdev);
if (val) {
/* Switch to instance "0" for the Set Advertising setting.
* We cannot use update_[adv|scan_rsp]_data() here as the
* HCI_ADVERTISING flag is not yet set.
*/
hdev->cur_adv_instance = 0x00;
if (ext_adv_capable(hdev)) {
hci_start_ext_adv_sync(hdev, 0x00);
} else {
hci_update_adv_data_sync(hdev, 0x00);
hci_update_scan_rsp_data_sync(hdev, 0x00);
hci_enable_advertising_sync(hdev);
}
} else {
hci_disable_advertising_sync(hdev);
}
return 0;
}
static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_mode *cp = data;
struct mgmt_pending_cmd *cmd;
u8 val, status;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
status = mgmt_le_support(hdev);
if (status)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
status);
if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
MGMT_STATUS_INVALID_PARAMS);
if (hdev->advertising_paused)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
MGMT_STATUS_BUSY);
hci_dev_lock(hdev);
val = !!cp->val;
/* The following conditions are ones which mean that we should
* not do any HCI communication but directly send a mgmt
* response to user space (after toggling the flag if
* necessary).
*/
if (!hdev_is_powered(hdev) ||
(val == hci_dev_test_flag(hdev, HCI_ADVERTISING) &&
(cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) ||
hci_dev_test_flag(hdev, HCI_MESH) ||
hci_conn_num(hdev, LE_LINK) > 0 ||
(hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
hdev->le_scan_type == LE_SCAN_ACTIVE)) {
bool changed;
if (cp->val) {
hdev->cur_adv_instance = 0x00;
changed = !hci_dev_test_and_set_flag(hdev, HCI_ADVERTISING);
if (cp->val == 0x02)
hci_dev_set_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
else
hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
} else {
changed = hci_dev_test_and_clear_flag(hdev, HCI_ADVERTISING);
hci_dev_clear_flag(hdev, HCI_ADVERTISING_CONNECTABLE);
}
err = send_settings_rsp(sk, MGMT_OP_SET_ADVERTISING, hdev);
if (err < 0)
goto unlock;
if (changed)
err = new_settings(hdev, sk);
goto unlock;
}
if (pending_find(MGMT_OP_SET_ADVERTISING, hdev) ||
pending_find(MGMT_OP_SET_LE, hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_ADVERTISING,
MGMT_STATUS_BUSY);
goto unlock;
}
cmd = mgmt_pending_add(sk, MGMT_OP_SET_ADVERTISING, hdev, data, len);
if (!cmd)
err = -ENOMEM;
else
err = hci_cmd_sync_queue(hdev, set_adv_sync, cmd,
set_advertising_complete);
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 11:39:41 +00:00
if (err < 0 && cmd)
mgmt_pending_remove(cmd);
unlock:
hci_dev_unlock(hdev);
return err;
}
static int set_static_address(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_cp_set_static_address *cp = data;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (!lmp_le_capable(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
MGMT_STATUS_NOT_SUPPORTED);
if (hdev_is_powered(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_STATIC_ADDRESS,
MGMT_STATUS_REJECTED);
if (bacmp(&cp->bdaddr, BDADDR_ANY)) {
if (!bacmp(&cp->bdaddr, BDADDR_NONE))
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_STATIC_ADDRESS,
MGMT_STATUS_INVALID_PARAMS);
/* Two most significant bits shall be set */
if ((cp->bdaddr.b[5] & 0xc0) != 0xc0)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_STATIC_ADDRESS,
MGMT_STATUS_INVALID_PARAMS);
}
hci_dev_lock(hdev);
bacpy(&hdev->static_addr, &cp->bdaddr);
err = send_settings_rsp(sk, MGMT_OP_SET_STATIC_ADDRESS, hdev);
if (err < 0)
goto unlock;
err = new_settings(hdev, sk);
unlock:
hci_dev_unlock(hdev);
return err;
}
static int set_scan_params(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_cp_set_scan_params *cp = data;
__u16 interval, window;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (!lmp_le_capable(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
MGMT_STATUS_NOT_SUPPORTED);
interval = __le16_to_cpu(cp->interval);
if (interval < 0x0004 || interval > 0x4000)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
MGMT_STATUS_INVALID_PARAMS);
window = __le16_to_cpu(cp->window);
if (window < 0x0004 || window > 0x4000)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
MGMT_STATUS_INVALID_PARAMS);
if (window > interval)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
hdev->le_scan_interval = interval;
hdev->le_scan_window = window;
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0,
NULL, 0);
/* If background scan is running, restart it so new parameters are
* loaded.
*/
if (hci_dev_test_flag(hdev, HCI_LE_SCAN) &&
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-27 23:58:45 +00:00
hdev->discovery.state == DISCOVERY_STOPPED)
hci_update_passive_scan(hdev);
hci_dev_unlock(hdev);
return err;
}
static void fast_connectable_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_pending_cmd *cmd = data;
bt_dev_dbg(hdev, "err %d", err);
if (err) {
mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
mgmt_status(err));
} else {
struct mgmt_mode *cp = cmd->param;
if (cp->val)
hci_dev_set_flag(hdev, HCI_FAST_CONNECTABLE);
else
hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
send_settings_rsp(cmd->sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
new_settings(hdev, cmd->sk);
}
mgmt_pending_free(cmd);
}
static int write_fast_connectable_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_mode *cp = cmd->param;
return hci_write_fast_connectable_sync(hdev, cp->val);
}
static int set_fast_connectable(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_mode *cp = data;
struct mgmt_pending_cmd *cmd;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) ||
hdev->hci_ver < BLUETOOTH_VER_1_2)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_FAST_CONNECTABLE,
MGMT_STATUS_NOT_SUPPORTED);
if (cp->val != 0x00 && cp->val != 0x01)
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_SET_FAST_CONNECTABLE,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
if (!!cp->val == hci_dev_test_flag(hdev, HCI_FAST_CONNECTABLE)) {
err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
goto unlock;
}
if (!hdev_is_powered(hdev)) {
hci_dev_change_flag(hdev, HCI_FAST_CONNECTABLE);
err = send_settings_rsp(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev);
new_settings(hdev, sk);
goto unlock;
}
cmd = mgmt_pending_new(sk, MGMT_OP_SET_FAST_CONNECTABLE, hdev, data,
len);
if (!cmd)
err = -ENOMEM;
else
err = hci_cmd_sync_queue(hdev, write_fast_connectable_sync, cmd,
fast_connectable_complete);
if (err < 0) {
mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_FAST_CONNECTABLE,
MGMT_STATUS_FAILED);
if (cmd)
mgmt_pending_free(cmd);
}
unlock:
hci_dev_unlock(hdev);
return err;
}
static void set_bredr_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_pending_cmd *cmd = data;
bt_dev_dbg(hdev, "err %d", err);
if (err) {
u8 mgmt_err = mgmt_status(err);
/* We need to restore the flag if related HCI commands
* failed.
*/
hci_dev_clear_flag(hdev, HCI_BREDR_ENABLED);
mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
} else {
send_settings_rsp(cmd->sk, MGMT_OP_SET_BREDR, hdev);
new_settings(hdev, cmd->sk);
}
mgmt_pending_free(cmd);
}
static int set_bredr_sync(struct hci_dev *hdev, void *data)
{
int status;
status = hci_write_fast_connectable_sync(hdev, false);
if (!status)
status = hci_update_scan_sync(hdev);
/* Since only the advertising data flags will change, there
* is no need to update the scan response data.
*/
if (!status)
status = hci_update_adv_data_sync(hdev, hdev->cur_adv_instance);
return status;
}
static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
{
struct mgmt_mode *cp = data;
struct mgmt_pending_cmd *cmd;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (!lmp_bredr_capable(hdev) || !lmp_le_capable(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
MGMT_STATUS_NOT_SUPPORTED);
if (!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
MGMT_STATUS_REJECTED);
if (cp->val != 0x00 && cp->val != 0x01)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
if (cp->val == hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
goto unlock;
}
if (!hdev_is_powered(hdev)) {
if (!cp->val) {
hci_dev_clear_flag(hdev, HCI_DISCOVERABLE);
hci_dev_clear_flag(hdev, HCI_SSP_ENABLED);
hci_dev_clear_flag(hdev, HCI_LINK_SECURITY);
hci_dev_clear_flag(hdev, HCI_FAST_CONNECTABLE);
}
hci_dev_change_flag(hdev, HCI_BREDR_ENABLED);
err = send_settings_rsp(sk, MGMT_OP_SET_BREDR, hdev);
if (err < 0)
goto unlock;
err = new_settings(hdev, sk);
goto unlock;
}
/* Reject disabling when powered on */
if (!cp->val) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
MGMT_STATUS_REJECTED);
goto unlock;
} else {
/* When configuring a dual-mode controller to operate
* with LE only and using a static address, then switching
* BR/EDR back on is not allowed.
*
* Dual-mode controllers shall operate with the public
* address as its identity address for BR/EDR and LE. So
* reject the attempt to create an invalid configuration.
*
* The same restrictions applies when secure connections
* has been enabled. For BR/EDR this is a controller feature
* while for LE it is a host stack feature. This means that
* switching BR/EDR back on when secure connections has been
* enabled is not a supported transaction.
*/
if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
(bacmp(&hdev->static_addr, BDADDR_ANY) ||
hci_dev_test_flag(hdev, HCI_SC_ENABLED))) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
MGMT_STATUS_REJECTED);
goto unlock;
}
}
cmd = mgmt_pending_new(sk, MGMT_OP_SET_BREDR, hdev, data, len);
if (!cmd)
err = -ENOMEM;
else
err = hci_cmd_sync_queue(hdev, set_bredr_sync, cmd,
set_bredr_complete);
if (err < 0) {
mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BREDR,
MGMT_STATUS_FAILED);
if (cmd)
mgmt_pending_free(cmd);
goto unlock;
}
/* We need to flip the bit already here so that
* hci_req_update_adv_data generates the correct flags.
*/
hci_dev_set_flag(hdev, HCI_BREDR_ENABLED);
unlock:
hci_dev_unlock(hdev);
return err;
}
static void set_secure_conn_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_mode *cp;
bt_dev_dbg(hdev, "err %d", err);
if (err) {
u8 mgmt_err = mgmt_status(err);
mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode, mgmt_err);
goto done;
}
cp = cmd->param;
switch (cp->val) {
case 0x00:
hci_dev_clear_flag(hdev, HCI_SC_ENABLED);
hci_dev_clear_flag(hdev, HCI_SC_ONLY);
break;
case 0x01:
hci_dev_set_flag(hdev, HCI_SC_ENABLED);
hci_dev_clear_flag(hdev, HCI_SC_ONLY);
break;
case 0x02:
hci_dev_set_flag(hdev, HCI_SC_ENABLED);
hci_dev_set_flag(hdev, HCI_SC_ONLY);
break;
}
send_settings_rsp(cmd->sk, cmd->opcode, hdev);
new_settings(hdev, cmd->sk);
done:
mgmt_pending_free(cmd);
}
static int set_secure_conn_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_mode *cp = cmd->param;
u8 val = !!cp->val;
/* Force write of val */
hci_dev_set_flag(hdev, HCI_SC_ENABLED);
return hci_write_sc_support_sync(hdev, val);
}
static int set_secure_conn(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_mode *cp = data;
struct mgmt_pending_cmd *cmd;
u8 val;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (!lmp_sc_capable(hdev) &&
!hci_dev_test_flag(hdev, HCI_LE_ENABLED))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
MGMT_STATUS_NOT_SUPPORTED);
if (hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
lmp_sc_capable(hdev) &&
!hci_dev_test_flag(hdev, HCI_SSP_ENABLED))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
MGMT_STATUS_REJECTED);
if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev) || !lmp_sc_capable(hdev) ||
!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) {
bool changed;
if (cp->val) {
changed = !hci_dev_test_and_set_flag(hdev,
HCI_SC_ENABLED);
if (cp->val == 0x02)
hci_dev_set_flag(hdev, HCI_SC_ONLY);
else
hci_dev_clear_flag(hdev, HCI_SC_ONLY);
} else {
changed = hci_dev_test_and_clear_flag(hdev,
HCI_SC_ENABLED);
hci_dev_clear_flag(hdev, HCI_SC_ONLY);
}
err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
if (err < 0)
goto failed;
if (changed)
err = new_settings(hdev, sk);
goto failed;
}
val = !!cp->val;
if (val == hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
(cp->val == 0x02) == hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev);
goto failed;
}
cmd = mgmt_pending_new(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len);
if (!cmd)
err = -ENOMEM;
else
err = hci_cmd_sync_queue(hdev, set_secure_conn_sync, cmd,
set_secure_conn_complete);
if (err < 0) {
mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN,
MGMT_STATUS_FAILED);
if (cmd)
mgmt_pending_free(cmd);
}
failed:
hci_dev_unlock(hdev);
return err;
}
static int set_debug_keys(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_mode *cp = data;
bool changed, use_changed;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
if (cp->val)
changed = !hci_dev_test_and_set_flag(hdev, HCI_KEEP_DEBUG_KEYS);
else
changed = hci_dev_test_and_clear_flag(hdev,
HCI_KEEP_DEBUG_KEYS);
if (cp->val == 0x02)
use_changed = !hci_dev_test_and_set_flag(hdev,
HCI_USE_DEBUG_KEYS);
else
use_changed = hci_dev_test_and_clear_flag(hdev,
HCI_USE_DEBUG_KEYS);
if (hdev_is_powered(hdev) && use_changed &&
hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
u8 mode = (cp->val == 0x02) ? 0x01 : 0x00;
hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE,
sizeof(mode), &mode);
}
err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev);
if (err < 0)
goto unlock;
if (changed)
err = new_settings(hdev, sk);
unlock:
hci_dev_unlock(hdev);
return err;
}
static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data,
u16 len)
{
struct mgmt_cp_set_privacy *cp = cp_data;
bool changed;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (!lmp_le_capable(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
MGMT_STATUS_NOT_SUPPORTED);
if (cp->privacy != 0x00 && cp->privacy != 0x01 && cp->privacy != 0x02)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
MGMT_STATUS_INVALID_PARAMS);
if (hdev_is_powered(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY,
MGMT_STATUS_REJECTED);
hci_dev_lock(hdev);
/* If user space supports this command it is also expected to
* handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag.
*/
hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
if (cp->privacy) {
changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY);
memcpy(hdev->irk, cp->irk, sizeof(hdev->irk));
hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
hci_adv_instances_set_rpa_expired(hdev, true);
if (cp->privacy == 0x02)
hci_dev_set_flag(hdev, HCI_LIMITED_PRIVACY);
else
hci_dev_clear_flag(hdev, HCI_LIMITED_PRIVACY);
} else {
changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY);
memset(hdev->irk, 0, sizeof(hdev->irk));
hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED);
hci_adv_instances_set_rpa_expired(hdev, false);
hci_dev_clear_flag(hdev, HCI_LIMITED_PRIVACY);
}
err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev);
if (err < 0)
goto unlock;
if (changed)
err = new_settings(hdev, sk);
unlock:
hci_dev_unlock(hdev);
return err;
}
static bool irk_is_valid(struct mgmt_irk_info *irk)
{
switch (irk->addr.type) {
case BDADDR_LE_PUBLIC:
return true;
case BDADDR_LE_RANDOM:
/* Two most significant bits shall be set */
if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0)
return false;
return true;
}
return false;
}
static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
u16 len)
{
struct mgmt_cp_load_irks *cp = cp_data;
const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) /
sizeof(struct mgmt_irk_info));
u16 irk_count, expected_len;
int i, err;
bt_dev_dbg(hdev, "sock %p", sk);
if (!lmp_le_capable(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
MGMT_STATUS_NOT_SUPPORTED);
irk_count = __le16_to_cpu(cp->irk_count);
if (irk_count > max_irk_count) {
bt_dev_err(hdev, "load_irks: too big irk_count value %u",
irk_count);
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
MGMT_STATUS_INVALID_PARAMS);
}
expected_len = struct_size(cp, irks, irk_count);
if (expected_len != len) {
bt_dev_err(hdev, "load_irks: expected %u bytes, got %u bytes",
expected_len, len);
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS,
MGMT_STATUS_INVALID_PARAMS);
}
bt_dev_dbg(hdev, "irk_count %u", irk_count);
for (i = 0; i < irk_count; i++) {
struct mgmt_irk_info *key = &cp->irks[i];
if (!irk_is_valid(key))
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_LOAD_IRKS,
MGMT_STATUS_INVALID_PARAMS);
}
hci_dev_lock(hdev);
hci_smp_irks_clear(hdev);
for (i = 0; i < irk_count; i++) {
struct mgmt_irk_info *irk = &cp->irks[i];
Bluetooth: MGMT/SMP: Fix address type when using SMP over BREDR/LE If two Bluetooth devices both support BR/EDR and BLE, and also support Secure Connections, then they only need to pair once. The LTK generated during the LE pairing process may be converted into a BR/EDR link key for BR/EDR transport, and conversely, a link key generated during the BR/EDR SSP pairing process can be converted into an LTK for LE transport. Hence, the link type of the link key and LTK is not fixed, they can be either an LE LINK or an ACL LINK. Currently, in the mgmt_new_irk/ltk/crsk/link_key functions, the link type is fixed, which could lead to incorrect address types being reported to the application layer. Therefore, it is necessary to add link_type/addr_type to the smp_irk/ltk/crsk and link_key, to ensure the generation of the correct address type. SMP over BREDR: Before Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) After Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) SMP over LE: Before Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5F:5C:07:37:47:D5 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) After Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5E:03:1C:00:38:21 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 Store hint: Yes (0x01) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) Cc: stable@vger.kernel.org Signed-off-by: Xiao Yao <xiaoyao@rock-chips.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-12-11 16:27:18 +00:00
u8 addr_type = le_addr_type(irk->addr.type);
if (hci_is_blocked_key(hdev,
HCI_BLOCKED_KEY_TYPE_IRK,
irk->val)) {
bt_dev_warn(hdev, "Skipping blocked IRK for %pMR",
&irk->addr.bdaddr);
continue;
}
Bluetooth: MGMT/SMP: Fix address type when using SMP over BREDR/LE If two Bluetooth devices both support BR/EDR and BLE, and also support Secure Connections, then they only need to pair once. The LTK generated during the LE pairing process may be converted into a BR/EDR link key for BR/EDR transport, and conversely, a link key generated during the BR/EDR SSP pairing process can be converted into an LTK for LE transport. Hence, the link type of the link key and LTK is not fixed, they can be either an LE LINK or an ACL LINK. Currently, in the mgmt_new_irk/ltk/crsk/link_key functions, the link type is fixed, which could lead to incorrect address types being reported to the application layer. Therefore, it is necessary to add link_type/addr_type to the smp_irk/ltk/crsk and link_key, to ensure the generation of the correct address type. SMP over BREDR: Before Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) After Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) SMP over LE: Before Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5F:5C:07:37:47:D5 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) After Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5E:03:1C:00:38:21 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 Store hint: Yes (0x01) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) Cc: stable@vger.kernel.org Signed-off-by: Xiao Yao <xiaoyao@rock-chips.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-12-11 16:27:18 +00:00
/* When using SMP over BR/EDR, the addr type should be set to BREDR */
if (irk->addr.type == BDADDR_BREDR)
addr_type = BDADDR_BREDR;
hci_add_irk(hdev, &irk->addr.bdaddr,
Bluetooth: MGMT/SMP: Fix address type when using SMP over BREDR/LE If two Bluetooth devices both support BR/EDR and BLE, and also support Secure Connections, then they only need to pair once. The LTK generated during the LE pairing process may be converted into a BR/EDR link key for BR/EDR transport, and conversely, a link key generated during the BR/EDR SSP pairing process can be converted into an LTK for LE transport. Hence, the link type of the link key and LTK is not fixed, they can be either an LE LINK or an ACL LINK. Currently, in the mgmt_new_irk/ltk/crsk/link_key functions, the link type is fixed, which could lead to incorrect address types being reported to the application layer. Therefore, it is necessary to add link_type/addr_type to the smp_irk/ltk/crsk and link_key, to ensure the generation of the correct address type. SMP over BREDR: Before Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) After Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) SMP over LE: Before Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5F:5C:07:37:47:D5 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) After Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5E:03:1C:00:38:21 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 Store hint: Yes (0x01) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) Cc: stable@vger.kernel.org Signed-off-by: Xiao Yao <xiaoyao@rock-chips.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-12-11 16:27:18 +00:00
addr_type, irk->val,
BDADDR_ANY);
}
hci_dev_set_flag(hdev, HCI_RPA_RESOLVING);
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0);
hci_dev_unlock(hdev);
return err;
}
static bool ltk_is_valid(struct mgmt_ltk_info *key)
{
if (key->initiator != 0x00 && key->initiator != 0x01)
return false;
switch (key->addr.type) {
case BDADDR_LE_PUBLIC:
return true;
case BDADDR_LE_RANDOM:
/* Two most significant bits shall be set */
if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0)
return false;
return true;
}
return false;
}
static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
void *cp_data, u16 len)
{
struct mgmt_cp_load_long_term_keys *cp = cp_data;
const u16 max_key_count = ((U16_MAX - sizeof(*cp)) /
sizeof(struct mgmt_ltk_info));
u16 key_count, expected_len;
int i, err;
bt_dev_dbg(hdev, "sock %p", sk);
if (!lmp_le_capable(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
MGMT_STATUS_NOT_SUPPORTED);
key_count = __le16_to_cpu(cp->key_count);
if (key_count > max_key_count) {
bt_dev_err(hdev, "load_ltks: too big key_count value %u",
key_count);
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
MGMT_STATUS_INVALID_PARAMS);
}
expected_len = struct_size(cp, keys, key_count);
if (expected_len != len) {
bt_dev_err(hdev, "load_keys: expected %u bytes, got %u bytes",
expected_len, len);
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS,
MGMT_STATUS_INVALID_PARAMS);
}
bt_dev_dbg(hdev, "key_count %u", key_count);
for (i = 0; i < key_count; i++) {
struct mgmt_ltk_info *key = &cp->keys[i];
if (!ltk_is_valid(key))
return mgmt_cmd_status(sk, hdev->id,
MGMT_OP_LOAD_LONG_TERM_KEYS,
MGMT_STATUS_INVALID_PARAMS);
}
hci_dev_lock(hdev);
hci_smp_ltks_clear(hdev);
for (i = 0; i < key_count; i++) {
struct mgmt_ltk_info *key = &cp->keys[i];
u8 type, authenticated;
Bluetooth: MGMT/SMP: Fix address type when using SMP over BREDR/LE If two Bluetooth devices both support BR/EDR and BLE, and also support Secure Connections, then they only need to pair once. The LTK generated during the LE pairing process may be converted into a BR/EDR link key for BR/EDR transport, and conversely, a link key generated during the BR/EDR SSP pairing process can be converted into an LTK for LE transport. Hence, the link type of the link key and LTK is not fixed, they can be either an LE LINK or an ACL LINK. Currently, in the mgmt_new_irk/ltk/crsk/link_key functions, the link type is fixed, which could lead to incorrect address types being reported to the application layer. Therefore, it is necessary to add link_type/addr_type to the smp_irk/ltk/crsk and link_key, to ensure the generation of the correct address type. SMP over BREDR: Before Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) After Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) SMP over LE: Before Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5F:5C:07:37:47:D5 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) After Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5E:03:1C:00:38:21 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 Store hint: Yes (0x01) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) Cc: stable@vger.kernel.org Signed-off-by: Xiao Yao <xiaoyao@rock-chips.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-12-11 16:27:18 +00:00
u8 addr_type = le_addr_type(key->addr.type);
if (hci_is_blocked_key(hdev,
HCI_BLOCKED_KEY_TYPE_LTK,
key->val)) {
bt_dev_warn(hdev, "Skipping blocked LTK for %pMR",
&key->addr.bdaddr);
continue;
}
switch (key->type) {
case MGMT_LTK_UNAUTHENTICATED:
authenticated = 0x00;
type = key->initiator ? SMP_LTK : SMP_LTK_RESPONDER;
break;
case MGMT_LTK_AUTHENTICATED:
authenticated = 0x01;
type = key->initiator ? SMP_LTK : SMP_LTK_RESPONDER;
break;
case MGMT_LTK_P256_UNAUTH:
authenticated = 0x00;
type = SMP_LTK_P256;
break;
case MGMT_LTK_P256_AUTH:
authenticated = 0x01;
type = SMP_LTK_P256;
break;
case MGMT_LTK_P256_DEBUG:
authenticated = 0x00;
type = SMP_LTK_P256_DEBUG;
fallthrough;
default:
continue;
}
Bluetooth: MGMT/SMP: Fix address type when using SMP over BREDR/LE If two Bluetooth devices both support BR/EDR and BLE, and also support Secure Connections, then they only need to pair once. The LTK generated during the LE pairing process may be converted into a BR/EDR link key for BR/EDR transport, and conversely, a link key generated during the BR/EDR SSP pairing process can be converted into an LTK for LE transport. Hence, the link type of the link key and LTK is not fixed, they can be either an LE LINK or an ACL LINK. Currently, in the mgmt_new_irk/ltk/crsk/link_key functions, the link type is fixed, which could lead to incorrect address types being reported to the application layer. Therefore, it is necessary to add link_type/addr_type to the smp_irk/ltk/crsk and link_key, to ensure the generation of the correct address type. SMP over BREDR: Before Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) After Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) SMP over LE: Before Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5F:5C:07:37:47:D5 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) After Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5E:03:1C:00:38:21 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 Store hint: Yes (0x01) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) Cc: stable@vger.kernel.org Signed-off-by: Xiao Yao <xiaoyao@rock-chips.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-12-11 16:27:18 +00:00
/* When using SMP over BR/EDR, the addr type should be set to BREDR */
if (key->addr.type == BDADDR_BREDR)
addr_type = BDADDR_BREDR;
hci_add_ltk(hdev, &key->addr.bdaddr,
Bluetooth: MGMT/SMP: Fix address type when using SMP over BREDR/LE If two Bluetooth devices both support BR/EDR and BLE, and also support Secure Connections, then they only need to pair once. The LTK generated during the LE pairing process may be converted into a BR/EDR link key for BR/EDR transport, and conversely, a link key generated during the BR/EDR SSP pairing process can be converted into an LTK for LE transport. Hence, the link type of the link key and LTK is not fixed, they can be either an LE LINK or an ACL LINK. Currently, in the mgmt_new_irk/ltk/crsk/link_key functions, the link type is fixed, which could lead to incorrect address types being reported to the application layer. Therefore, it is necessary to add link_type/addr_type to the smp_irk/ltk/crsk and link_key, to ensure the generation of the correct address type. SMP over BREDR: Before Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) After Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) SMP over LE: Before Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5F:5C:07:37:47:D5 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) After Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5E:03:1C:00:38:21 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 Store hint: Yes (0x01) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) Cc: stable@vger.kernel.org Signed-off-by: Xiao Yao <xiaoyao@rock-chips.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-12-11 16:27:18 +00:00
addr_type, type, authenticated,
key->val, key->enc_size, key->ediv, key->rand);
}
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0,
NULL, 0);
hci_dev_unlock(hdev);
return err;
}
static void get_conn_info_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_pending_cmd *cmd = data;
struct hci_conn *conn = cmd->user_data;
struct mgmt_cp_get_conn_info *cp = cmd->param;
struct mgmt_rp_get_conn_info rp;
u8 status;
bt_dev_dbg(hdev, "err %d", err);
memcpy(&rp.addr, &cp->addr, sizeof(rp.addr));
status = mgmt_status(err);
if (status == MGMT_STATUS_SUCCESS) {
rp.rssi = conn->rssi;
rp.tx_power = conn->tx_power;
rp.max_tx_power = conn->max_tx_power;
} else {
rp.rssi = HCI_RSSI_INVALID;
rp.tx_power = HCI_TX_POWER_INVALID;
rp.max_tx_power = HCI_TX_POWER_INVALID;
}
mgmt_cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status,
&rp, sizeof(rp));
mgmt_pending_free(cmd);
}
static int get_conn_info_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_get_conn_info *cp = cmd->param;
struct hci_conn *conn;
int err;
__le16 handle;
/* Make sure we are still connected */
if (cp->addr.type == BDADDR_BREDR)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
&cp->addr.bdaddr);
else
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
if (!conn || conn->state != BT_CONNECTED)
return MGMT_STATUS_NOT_CONNECTED;
cmd->user_data = conn;
handle = cpu_to_le16(conn->handle);
/* Refresh RSSI each time */
err = hci_read_rssi_sync(hdev, handle);
/* For LE links TX power does not change thus we don't need to
* query for it once value is known.
*/
if (!err && (!bdaddr_type_is_le(cp->addr.type) ||
conn->tx_power == HCI_TX_POWER_INVALID))
err = hci_read_tx_power_sync(hdev, handle, 0x00);
/* Max TX power needs to be read only once per connection */
if (!err && conn->max_tx_power == HCI_TX_POWER_INVALID)
err = hci_read_tx_power_sync(hdev, handle, 0x01);
return err;
}
static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_get_conn_info *cp = data;
struct mgmt_rp_get_conn_info rp;
struct hci_conn *conn;
unsigned long conn_info_age;
int err = 0;
bt_dev_dbg(hdev, "sock %p", sk);
memset(&rp, 0, sizeof(rp));
bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
rp.addr.type = cp->addr.type;
if (!bdaddr_type_is_valid(cp->addr.type))
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
MGMT_STATUS_INVALID_PARAMS,
&rp, sizeof(rp));
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
MGMT_STATUS_NOT_POWERED, &rp,
sizeof(rp));
goto unlock;
}
if (cp->addr.type == BDADDR_BREDR)
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
&cp->addr.bdaddr);
else
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr);
if (!conn || conn->state != BT_CONNECTED) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
MGMT_STATUS_NOT_CONNECTED, &rp,
sizeof(rp));
goto unlock;
}
/* To avoid client trying to guess when to poll again for information we
* calculate conn info age as random value between min/max set in hdev.
*/
conn_info_age = get_random_u32_inclusive(hdev->conn_info_min_age,
hdev->conn_info_max_age - 1);
/* Query controller to refresh cached values if they are too old or were
* never read.
*/
if (time_after(jiffies, conn->conn_info_timestamp +
msecs_to_jiffies(conn_info_age)) ||
!conn->conn_info_timestamp) {
struct mgmt_pending_cmd *cmd;
cmd = mgmt_pending_new(sk, MGMT_OP_GET_CONN_INFO, hdev, data,
len);
if (!cmd) {
err = -ENOMEM;
} else {
err = hci_cmd_sync_queue(hdev, get_conn_info_sync,
cmd, get_conn_info_complete);
}
if (err < 0) {
mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
MGMT_STATUS_FAILED, &rp, sizeof(rp));
if (cmd)
mgmt_pending_free(cmd);
goto unlock;
}
conn->conn_info_timestamp = jiffies;
} else {
/* Cache is valid, just reply with values cached in hci_conn */
rp.rssi = conn->rssi;
rp.tx_power = conn->tx_power;
rp.max_tx_power = conn->max_tx_power;
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
}
unlock:
hci_dev_unlock(hdev);
return err;
}
static void get_clock_info_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_get_clock_info *cp = cmd->param;
struct mgmt_rp_get_clock_info rp;
struct hci_conn *conn = cmd->user_data;
u8 status = mgmt_status(err);
bt_dev_dbg(hdev, "err %d", err);
memset(&rp, 0, sizeof(rp));
bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
rp.addr.type = cp->addr.type;
if (err)
goto complete;
rp.local_clock = cpu_to_le32(hdev->clock);
if (conn) {
rp.piconet_clock = cpu_to_le32(conn->clock);
rp.accuracy = cpu_to_le16(conn->clock_accuracy);
}
complete:
mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode, status, &rp,
sizeof(rp));
mgmt_pending_free(cmd);
}
static int get_clock_info_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_get_clock_info *cp = cmd->param;
struct hci_cp_read_clock hci_cp;
struct hci_conn *conn;
memset(&hci_cp, 0, sizeof(hci_cp));
hci_read_clock_sync(hdev, &hci_cp);
/* Make sure connection still exists */
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->addr.bdaddr);
if (!conn || conn->state != BT_CONNECTED)
return MGMT_STATUS_NOT_CONNECTED;
cmd->user_data = conn;
hci_cp.handle = cpu_to_le16(conn->handle);
hci_cp.which = 0x01; /* Piconet clock */
return hci_read_clock_sync(hdev, &hci_cp);
}
static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_get_clock_info *cp = data;
struct mgmt_rp_get_clock_info rp;
struct mgmt_pending_cmd *cmd;
struct hci_conn *conn;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
memset(&rp, 0, sizeof(rp));
bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
rp.addr.type = cp->addr.type;
if (cp->addr.type != BDADDR_BREDR)
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
MGMT_STATUS_INVALID_PARAMS,
&rp, sizeof(rp));
hci_dev_lock(hdev);
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
MGMT_STATUS_NOT_POWERED, &rp,
sizeof(rp));
goto unlock;
}
if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK,
&cp->addr.bdaddr);
if (!conn || conn->state != BT_CONNECTED) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_GET_CLOCK_INFO,
MGMT_STATUS_NOT_CONNECTED,
&rp, sizeof(rp));
goto unlock;
}
} else {
conn = NULL;
}
cmd = mgmt_pending_new(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len);
if (!cmd)
err = -ENOMEM;
else
err = hci_cmd_sync_queue(hdev, get_clock_info_sync, cmd,
get_clock_info_complete);
if (err < 0) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO,
MGMT_STATUS_FAILED, &rp, sizeof(rp));
if (cmd)
mgmt_pending_free(cmd);
}
unlock:
hci_dev_unlock(hdev);
return err;
}
static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type)
{
struct hci_conn *conn;
conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr);
if (!conn)
return false;
if (conn->dst_type != type)
return false;
if (conn->state != BT_CONNECTED)
return false;
return true;
}
/* This function requires the caller holds hdev->lock */
static int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr,
u8 addr_type, u8 auto_connect)
{
struct hci_conn_params *params;
params = hci_conn_params_add(hdev, addr, addr_type);
if (!params)
return -EIO;
if (params->auto_connect == auto_connect)
return 0;
Bluetooth: use RCU for hci_conn_params and iterate safely in hci_sync hci_update_accept_list_sync iterates over hdev->pend_le_conns and hdev->pend_le_reports, and waits for controller events in the loop body, without holding hdev lock. Meanwhile, these lists and the items may be modified e.g. by le_scan_cleanup. This can invalidate the list cursor or any other item in the list, resulting to invalid behavior (eg use-after-free). Use RCU for the hci_conn_params action lists. Since the loop bodies in hci_sync block and we cannot use RCU or hdev->lock for the whole loop, copy list items first and then iterate on the copy. Only the flags field is written from elsewhere, so READ_ONCE/WRITE_ONCE should guarantee we read valid values. Free params everywhere with hci_conn_params_free so the cleanup is guaranteed to be done properly. This fixes the following, which can be triggered e.g. by BlueZ new mgmt-tester case "Add + Remove Device Nowait - Success", or by changing hci_le_set_cig_params to always return false, and running iso-tester: ================================================================== BUG: KASAN: slab-use-after-free in hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) Read of size 8 at addr ffff888001265018 by task kworker/u3:0/32 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-1.fc38 04/01/2014 Workqueue: hci0 hci_cmd_sync_work Call Trace: <TASK> dump_stack_lvl (./arch/x86/include/asm/irqflags.h:134 lib/dump_stack.c:107) print_report (mm/kasan/report.c:320 mm/kasan/report.c:430) ? __virt_addr_valid (./include/linux/mmzone.h:1915 ./include/linux/mmzone.h:2011 arch/x86/mm/physaddr.c:65) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) kasan_report (mm/kasan/report.c:538) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) ? __pfx_hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2780) ? mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_unlock (kernel/locking/mutex.c:538) ? __pfx_update_passive_scan_sync (net/bluetooth/hci_sync.c:2861) hci_cmd_sync_work (net/bluetooth/hci_sync.c:306) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) ? __pfx_worker_thread (kernel/workqueue.c:2480) kthread (kernel/kthread.c:376) ? __pfx_kthread (kernel/kthread.c:331) ret_from_fork (arch/x86/entry/entry_64.S:314) </TASK> Allocated by task 31: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) __kasan_kmalloc (mm/kasan/common.c:374 mm/kasan/common.c:383) hci_conn_params_add (./include/linux/slab.h:580 ./include/linux/slab.h:720 net/bluetooth/hci_core.c:2277) hci_connect_le_scan (net/bluetooth/hci_conn.c:1419 net/bluetooth/hci_conn.c:1589) hci_connect_cis (net/bluetooth/hci_conn.c:2266) iso_connect_cis (net/bluetooth/iso.c:390) iso_sock_connect (net/bluetooth/iso.c:899) __sys_connect (net/socket.c:2003 net/socket.c:2020) __x64_sys_connect (net/socket.c:2027) do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) Freed by task 15: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) kasan_save_free_info (mm/kasan/generic.c:523) __kasan_slab_free (mm/kasan/common.c:238 mm/kasan/common.c:200 mm/kasan/common.c:244) __kmem_cache_free (mm/slub.c:1807 mm/slub.c:3787 mm/slub.c:3800) hci_conn_params_del (net/bluetooth/hci_core.c:2323) le_scan_cleanup (net/bluetooth/hci_conn.c:202) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) kthread (kernel/kthread.c:376) ret_from_fork (arch/x86/entry/entry_64.S:314) ================================================================== Fixes: e8907f76544f ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 3") Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-06-18 22:04:31 +00:00
hci_pend_le_list_del_init(params);
switch (auto_connect) {
case HCI_AUTO_CONN_DISABLED:
case HCI_AUTO_CONN_LINK_LOSS:
/* If auto connect is being disabled when we're trying to
* connect to device, keep connecting.
*/
if (params->explicit_connect)
Bluetooth: use RCU for hci_conn_params and iterate safely in hci_sync hci_update_accept_list_sync iterates over hdev->pend_le_conns and hdev->pend_le_reports, and waits for controller events in the loop body, without holding hdev lock. Meanwhile, these lists and the items may be modified e.g. by le_scan_cleanup. This can invalidate the list cursor or any other item in the list, resulting to invalid behavior (eg use-after-free). Use RCU for the hci_conn_params action lists. Since the loop bodies in hci_sync block and we cannot use RCU or hdev->lock for the whole loop, copy list items first and then iterate on the copy. Only the flags field is written from elsewhere, so READ_ONCE/WRITE_ONCE should guarantee we read valid values. Free params everywhere with hci_conn_params_free so the cleanup is guaranteed to be done properly. This fixes the following, which can be triggered e.g. by BlueZ new mgmt-tester case "Add + Remove Device Nowait - Success", or by changing hci_le_set_cig_params to always return false, and running iso-tester: ================================================================== BUG: KASAN: slab-use-after-free in hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) Read of size 8 at addr ffff888001265018 by task kworker/u3:0/32 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-1.fc38 04/01/2014 Workqueue: hci0 hci_cmd_sync_work Call Trace: <TASK> dump_stack_lvl (./arch/x86/include/asm/irqflags.h:134 lib/dump_stack.c:107) print_report (mm/kasan/report.c:320 mm/kasan/report.c:430) ? __virt_addr_valid (./include/linux/mmzone.h:1915 ./include/linux/mmzone.h:2011 arch/x86/mm/physaddr.c:65) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) kasan_report (mm/kasan/report.c:538) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) ? __pfx_hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2780) ? mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_unlock (kernel/locking/mutex.c:538) ? __pfx_update_passive_scan_sync (net/bluetooth/hci_sync.c:2861) hci_cmd_sync_work (net/bluetooth/hci_sync.c:306) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) ? __pfx_worker_thread (kernel/workqueue.c:2480) kthread (kernel/kthread.c:376) ? __pfx_kthread (kernel/kthread.c:331) ret_from_fork (arch/x86/entry/entry_64.S:314) </TASK> Allocated by task 31: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) __kasan_kmalloc (mm/kasan/common.c:374 mm/kasan/common.c:383) hci_conn_params_add (./include/linux/slab.h:580 ./include/linux/slab.h:720 net/bluetooth/hci_core.c:2277) hci_connect_le_scan (net/bluetooth/hci_conn.c:1419 net/bluetooth/hci_conn.c:1589) hci_connect_cis (net/bluetooth/hci_conn.c:2266) iso_connect_cis (net/bluetooth/iso.c:390) iso_sock_connect (net/bluetooth/iso.c:899) __sys_connect (net/socket.c:2003 net/socket.c:2020) __x64_sys_connect (net/socket.c:2027) do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) Freed by task 15: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) kasan_save_free_info (mm/kasan/generic.c:523) __kasan_slab_free (mm/kasan/common.c:238 mm/kasan/common.c:200 mm/kasan/common.c:244) __kmem_cache_free (mm/slub.c:1807 mm/slub.c:3787 mm/slub.c:3800) hci_conn_params_del (net/bluetooth/hci_core.c:2323) le_scan_cleanup (net/bluetooth/hci_conn.c:202) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) kthread (kernel/kthread.c:376) ret_from_fork (arch/x86/entry/entry_64.S:314) ================================================================== Fixes: e8907f76544f ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 3") Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-06-18 22:04:31 +00:00
hci_pend_le_list_add(params, &hdev->pend_le_conns);
break;
case HCI_AUTO_CONN_REPORT:
if (params->explicit_connect)
Bluetooth: use RCU for hci_conn_params and iterate safely in hci_sync hci_update_accept_list_sync iterates over hdev->pend_le_conns and hdev->pend_le_reports, and waits for controller events in the loop body, without holding hdev lock. Meanwhile, these lists and the items may be modified e.g. by le_scan_cleanup. This can invalidate the list cursor or any other item in the list, resulting to invalid behavior (eg use-after-free). Use RCU for the hci_conn_params action lists. Since the loop bodies in hci_sync block and we cannot use RCU or hdev->lock for the whole loop, copy list items first and then iterate on the copy. Only the flags field is written from elsewhere, so READ_ONCE/WRITE_ONCE should guarantee we read valid values. Free params everywhere with hci_conn_params_free so the cleanup is guaranteed to be done properly. This fixes the following, which can be triggered e.g. by BlueZ new mgmt-tester case "Add + Remove Device Nowait - Success", or by changing hci_le_set_cig_params to always return false, and running iso-tester: ================================================================== BUG: KASAN: slab-use-after-free in hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) Read of size 8 at addr ffff888001265018 by task kworker/u3:0/32 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-1.fc38 04/01/2014 Workqueue: hci0 hci_cmd_sync_work Call Trace: <TASK> dump_stack_lvl (./arch/x86/include/asm/irqflags.h:134 lib/dump_stack.c:107) print_report (mm/kasan/report.c:320 mm/kasan/report.c:430) ? __virt_addr_valid (./include/linux/mmzone.h:1915 ./include/linux/mmzone.h:2011 arch/x86/mm/physaddr.c:65) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) kasan_report (mm/kasan/report.c:538) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) ? __pfx_hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2780) ? mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_unlock (kernel/locking/mutex.c:538) ? __pfx_update_passive_scan_sync (net/bluetooth/hci_sync.c:2861) hci_cmd_sync_work (net/bluetooth/hci_sync.c:306) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) ? __pfx_worker_thread (kernel/workqueue.c:2480) kthread (kernel/kthread.c:376) ? __pfx_kthread (kernel/kthread.c:331) ret_from_fork (arch/x86/entry/entry_64.S:314) </TASK> Allocated by task 31: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) __kasan_kmalloc (mm/kasan/common.c:374 mm/kasan/common.c:383) hci_conn_params_add (./include/linux/slab.h:580 ./include/linux/slab.h:720 net/bluetooth/hci_core.c:2277) hci_connect_le_scan (net/bluetooth/hci_conn.c:1419 net/bluetooth/hci_conn.c:1589) hci_connect_cis (net/bluetooth/hci_conn.c:2266) iso_connect_cis (net/bluetooth/iso.c:390) iso_sock_connect (net/bluetooth/iso.c:899) __sys_connect (net/socket.c:2003 net/socket.c:2020) __x64_sys_connect (net/socket.c:2027) do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) Freed by task 15: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) kasan_save_free_info (mm/kasan/generic.c:523) __kasan_slab_free (mm/kasan/common.c:238 mm/kasan/common.c:200 mm/kasan/common.c:244) __kmem_cache_free (mm/slub.c:1807 mm/slub.c:3787 mm/slub.c:3800) hci_conn_params_del (net/bluetooth/hci_core.c:2323) le_scan_cleanup (net/bluetooth/hci_conn.c:202) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) kthread (kernel/kthread.c:376) ret_from_fork (arch/x86/entry/entry_64.S:314) ================================================================== Fixes: e8907f76544f ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 3") Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-06-18 22:04:31 +00:00
hci_pend_le_list_add(params, &hdev->pend_le_conns);
else
Bluetooth: use RCU for hci_conn_params and iterate safely in hci_sync hci_update_accept_list_sync iterates over hdev->pend_le_conns and hdev->pend_le_reports, and waits for controller events in the loop body, without holding hdev lock. Meanwhile, these lists and the items may be modified e.g. by le_scan_cleanup. This can invalidate the list cursor or any other item in the list, resulting to invalid behavior (eg use-after-free). Use RCU for the hci_conn_params action lists. Since the loop bodies in hci_sync block and we cannot use RCU or hdev->lock for the whole loop, copy list items first and then iterate on the copy. Only the flags field is written from elsewhere, so READ_ONCE/WRITE_ONCE should guarantee we read valid values. Free params everywhere with hci_conn_params_free so the cleanup is guaranteed to be done properly. This fixes the following, which can be triggered e.g. by BlueZ new mgmt-tester case "Add + Remove Device Nowait - Success", or by changing hci_le_set_cig_params to always return false, and running iso-tester: ================================================================== BUG: KASAN: slab-use-after-free in hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) Read of size 8 at addr ffff888001265018 by task kworker/u3:0/32 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-1.fc38 04/01/2014 Workqueue: hci0 hci_cmd_sync_work Call Trace: <TASK> dump_stack_lvl (./arch/x86/include/asm/irqflags.h:134 lib/dump_stack.c:107) print_report (mm/kasan/report.c:320 mm/kasan/report.c:430) ? __virt_addr_valid (./include/linux/mmzone.h:1915 ./include/linux/mmzone.h:2011 arch/x86/mm/physaddr.c:65) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) kasan_report (mm/kasan/report.c:538) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) ? __pfx_hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2780) ? mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_unlock (kernel/locking/mutex.c:538) ? __pfx_update_passive_scan_sync (net/bluetooth/hci_sync.c:2861) hci_cmd_sync_work (net/bluetooth/hci_sync.c:306) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) ? __pfx_worker_thread (kernel/workqueue.c:2480) kthread (kernel/kthread.c:376) ? __pfx_kthread (kernel/kthread.c:331) ret_from_fork (arch/x86/entry/entry_64.S:314) </TASK> Allocated by task 31: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) __kasan_kmalloc (mm/kasan/common.c:374 mm/kasan/common.c:383) hci_conn_params_add (./include/linux/slab.h:580 ./include/linux/slab.h:720 net/bluetooth/hci_core.c:2277) hci_connect_le_scan (net/bluetooth/hci_conn.c:1419 net/bluetooth/hci_conn.c:1589) hci_connect_cis (net/bluetooth/hci_conn.c:2266) iso_connect_cis (net/bluetooth/iso.c:390) iso_sock_connect (net/bluetooth/iso.c:899) __sys_connect (net/socket.c:2003 net/socket.c:2020) __x64_sys_connect (net/socket.c:2027) do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) Freed by task 15: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) kasan_save_free_info (mm/kasan/generic.c:523) __kasan_slab_free (mm/kasan/common.c:238 mm/kasan/common.c:200 mm/kasan/common.c:244) __kmem_cache_free (mm/slub.c:1807 mm/slub.c:3787 mm/slub.c:3800) hci_conn_params_del (net/bluetooth/hci_core.c:2323) le_scan_cleanup (net/bluetooth/hci_conn.c:202) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) kthread (kernel/kthread.c:376) ret_from_fork (arch/x86/entry/entry_64.S:314) ================================================================== Fixes: e8907f76544f ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 3") Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-06-18 22:04:31 +00:00
hci_pend_le_list_add(params, &hdev->pend_le_reports);
break;
case HCI_AUTO_CONN_DIRECT:
case HCI_AUTO_CONN_ALWAYS:
if (!is_connected(hdev, addr, addr_type))
Bluetooth: use RCU for hci_conn_params and iterate safely in hci_sync hci_update_accept_list_sync iterates over hdev->pend_le_conns and hdev->pend_le_reports, and waits for controller events in the loop body, without holding hdev lock. Meanwhile, these lists and the items may be modified e.g. by le_scan_cleanup. This can invalidate the list cursor or any other item in the list, resulting to invalid behavior (eg use-after-free). Use RCU for the hci_conn_params action lists. Since the loop bodies in hci_sync block and we cannot use RCU or hdev->lock for the whole loop, copy list items first and then iterate on the copy. Only the flags field is written from elsewhere, so READ_ONCE/WRITE_ONCE should guarantee we read valid values. Free params everywhere with hci_conn_params_free so the cleanup is guaranteed to be done properly. This fixes the following, which can be triggered e.g. by BlueZ new mgmt-tester case "Add + Remove Device Nowait - Success", or by changing hci_le_set_cig_params to always return false, and running iso-tester: ================================================================== BUG: KASAN: slab-use-after-free in hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) Read of size 8 at addr ffff888001265018 by task kworker/u3:0/32 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-1.fc38 04/01/2014 Workqueue: hci0 hci_cmd_sync_work Call Trace: <TASK> dump_stack_lvl (./arch/x86/include/asm/irqflags.h:134 lib/dump_stack.c:107) print_report (mm/kasan/report.c:320 mm/kasan/report.c:430) ? __virt_addr_valid (./include/linux/mmzone.h:1915 ./include/linux/mmzone.h:2011 arch/x86/mm/physaddr.c:65) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) kasan_report (mm/kasan/report.c:538) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) ? __pfx_hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2780) ? mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_unlock (kernel/locking/mutex.c:538) ? __pfx_update_passive_scan_sync (net/bluetooth/hci_sync.c:2861) hci_cmd_sync_work (net/bluetooth/hci_sync.c:306) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) ? __pfx_worker_thread (kernel/workqueue.c:2480) kthread (kernel/kthread.c:376) ? __pfx_kthread (kernel/kthread.c:331) ret_from_fork (arch/x86/entry/entry_64.S:314) </TASK> Allocated by task 31: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) __kasan_kmalloc (mm/kasan/common.c:374 mm/kasan/common.c:383) hci_conn_params_add (./include/linux/slab.h:580 ./include/linux/slab.h:720 net/bluetooth/hci_core.c:2277) hci_connect_le_scan (net/bluetooth/hci_conn.c:1419 net/bluetooth/hci_conn.c:1589) hci_connect_cis (net/bluetooth/hci_conn.c:2266) iso_connect_cis (net/bluetooth/iso.c:390) iso_sock_connect (net/bluetooth/iso.c:899) __sys_connect (net/socket.c:2003 net/socket.c:2020) __x64_sys_connect (net/socket.c:2027) do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) Freed by task 15: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) kasan_save_free_info (mm/kasan/generic.c:523) __kasan_slab_free (mm/kasan/common.c:238 mm/kasan/common.c:200 mm/kasan/common.c:244) __kmem_cache_free (mm/slub.c:1807 mm/slub.c:3787 mm/slub.c:3800) hci_conn_params_del (net/bluetooth/hci_core.c:2323) le_scan_cleanup (net/bluetooth/hci_conn.c:202) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) kthread (kernel/kthread.c:376) ret_from_fork (arch/x86/entry/entry_64.S:314) ================================================================== Fixes: e8907f76544f ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 3") Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-06-18 22:04:31 +00:00
hci_pend_le_list_add(params, &hdev->pend_le_conns);
break;
}
params->auto_connect = auto_connect;
bt_dev_dbg(hdev, "addr %pMR (type %u) auto_connect %u",
addr, addr_type, auto_connect);
return 0;
}
static void device_added(struct sock *sk, struct hci_dev *hdev,
bdaddr_t *bdaddr, u8 type, u8 action)
{
struct mgmt_ev_device_added ev;
bacpy(&ev.addr.bdaddr, bdaddr);
ev.addr.type = type;
ev.action = action;
mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
}
2021-10-27 23:58:41 +00:00
static int add_device_sync(struct hci_dev *hdev, void *data)
{
return hci_update_passive_scan_sync(hdev);
}
static int add_device(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_cp_add_device *cp = data;
u8 auto_conn, addr_type;
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
struct hci_conn_params *params;
int err;
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
u32 current_flags = 0;
u32 supported_flags;
bt_dev_dbg(hdev, "sock %p", sk);
if (!bdaddr_type_is_valid(cp->addr.type) ||
!bacmp(&cp->addr.bdaddr, BDADDR_ANY))
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr));
if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02)
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr));
hci_dev_lock(hdev);
if (cp->addr.type == BDADDR_BREDR) {
/* Only incoming connections action is supported for now */
if (cp->action != 0x01) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_ADD_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr));
goto unlock;
}
err = hci_bdaddr_list_add_with_flags(&hdev->accept_list,
&cp->addr.bdaddr,
cp->addr.type, 0);
if (err)
goto unlock;
hci_update_scan(hdev);
goto added;
}
addr_type = le_addr_type(cp->addr.type);
if (cp->action == 0x02)
auto_conn = HCI_AUTO_CONN_ALWAYS;
else if (cp->action == 0x01)
auto_conn = HCI_AUTO_CONN_DIRECT;
else
auto_conn = HCI_AUTO_CONN_REPORT;
/* Kernel internally uses conn_params with resolvable private
* address, but Add Device allows only identity addresses.
* Make sure it is enforced before calling
* hci_conn_params_lookup.
*/
if (!hci_is_identity_address(&cp->addr.bdaddr, addr_type)) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr));
goto unlock;
}
/* If the connection parameters don't exist for this device,
* they will be created and configured with defaults.
*/
if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type,
auto_conn) < 0) {
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
MGMT_STATUS_FAILED, &cp->addr,
sizeof(cp->addr));
goto unlock;
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
} else {
params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
addr_type);
if (params)
bluetooth: don't use bitmaps for random flag accesses The bluetooth code uses our bitmap infrastructure for the two bits (!) of connection setup flags, and in the process causes odd problems when it converts between a bitmap and just the regular values of said bits. It's completely pointless to do things like bitmap_to_arr32() to convert a bitmap into a u32. It shoudln't have been a bitmap in the first place. The reason to use bitmaps is if you have arbitrary number of bits you want to manage (not two!), or if you rely on the atomicity guarantees of the bitmap setting and clearing. The code could use an "atomic_t" and use "atomic_or/andnot()" to set and clear the bit values, but considering that it then copies the bitmaps around with "bitmap_to_arr32()" and friends, there clearly cannot be a lot of atomicity requirements. So just use a regular integer. In the process, this avoids the warnings about erroneous use of bitmap_from_u64() which were triggered on 32-bit architectures when conversion from a u64 would access two words (and, surprise, surprise, only one word is needed - and indeed overkill - for a 2-bit bitmap). That was always problematic, but the compiler seems to notice it and warn about the invalid pattern only after commit 0a97953fd221 ("lib: add bitmap_{from,to}_arr64") changed the exact implementation details of 'bitmap_from_u64()', as reported by Sudip Mukherjee and Stephen Rothwell. Fixes: fe92ee6425a2 ("Bluetooth: hci_core: Rework hci_conn_params flags") Link: https://lore.kernel.org/all/YpyJ9qTNHJzz0FHY@debian/ Link: https://lore.kernel.org/all/20220606080631.0c3014f2@canb.auug.org.au/ Link: https://lore.kernel.org/all/20220605162537.1604762-1-yury.norov@gmail.com/ Reported-by: Stephen Rothwell <sfr@canb.auug.org.au> Reported-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Reviewed-by: Yury Norov <yury.norov@gmail.com> Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Cc: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2022-06-05 18:51:48 +00:00
current_flags = params->flags;
}
2021-10-27 23:58:41 +00:00
err = hci_cmd_sync_queue(hdev, add_device_sync, NULL, NULL);
if (err < 0)
goto unlock;
added:
device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
bluetooth: don't use bitmaps for random flag accesses The bluetooth code uses our bitmap infrastructure for the two bits (!) of connection setup flags, and in the process causes odd problems when it converts between a bitmap and just the regular values of said bits. It's completely pointless to do things like bitmap_to_arr32() to convert a bitmap into a u32. It shoudln't have been a bitmap in the first place. The reason to use bitmaps is if you have arbitrary number of bits you want to manage (not two!), or if you rely on the atomicity guarantees of the bitmap setting and clearing. The code could use an "atomic_t" and use "atomic_or/andnot()" to set and clear the bit values, but considering that it then copies the bitmaps around with "bitmap_to_arr32()" and friends, there clearly cannot be a lot of atomicity requirements. So just use a regular integer. In the process, this avoids the warnings about erroneous use of bitmap_from_u64() which were triggered on 32-bit architectures when conversion from a u64 would access two words (and, surprise, surprise, only one word is needed - and indeed overkill - for a 2-bit bitmap). That was always problematic, but the compiler seems to notice it and warn about the invalid pattern only after commit 0a97953fd221 ("lib: add bitmap_{from,to}_arr64") changed the exact implementation details of 'bitmap_from_u64()', as reported by Sudip Mukherjee and Stephen Rothwell. Fixes: fe92ee6425a2 ("Bluetooth: hci_core: Rework hci_conn_params flags") Link: https://lore.kernel.org/all/YpyJ9qTNHJzz0FHY@debian/ Link: https://lore.kernel.org/all/20220606080631.0c3014f2@canb.auug.org.au/ Link: https://lore.kernel.org/all/20220605162537.1604762-1-yury.norov@gmail.com/ Reported-by: Stephen Rothwell <sfr@canb.auug.org.au> Reported-by: Sudip Mukherjee <sudipm.mukherjee@gmail.com> Reviewed-by: Yury Norov <yury.norov@gmail.com> Cc: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Cc: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2022-06-05 18:51:48 +00:00
supported_flags = hdev->conn_flags;
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
device_flags_changed(NULL, hdev, &cp->addr.bdaddr, cp->addr.type,
supported_flags, current_flags);
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
MGMT_STATUS_SUCCESS, &cp->addr,
sizeof(cp->addr));
unlock:
hci_dev_unlock(hdev);
return err;
}
static void device_removed(struct sock *sk, struct hci_dev *hdev,
bdaddr_t *bdaddr, u8 type)
{
struct mgmt_ev_device_removed ev;
bacpy(&ev.addr.bdaddr, bdaddr);
ev.addr.type = type;
mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk);
}
2021-10-27 23:58:41 +00:00
static int remove_device_sync(struct hci_dev *hdev, void *data)
{
return hci_update_passive_scan_sync(hdev);
}
static int remove_device(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_cp_remove_device *cp = data;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) {
struct hci_conn_params *params;
u8 addr_type;
if (!bdaddr_type_is_valid(cp->addr.type)) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_REMOVE_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr));
goto unlock;
}
if (cp->addr.type == BDADDR_BREDR) {
err = hci_bdaddr_list_del(&hdev->accept_list,
&cp->addr.bdaddr,
cp->addr.type);
if (err) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_REMOVE_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&cp->addr,
sizeof(cp->addr));
goto unlock;
}
hci_update_scan(hdev);
device_removed(sk, hdev, &cp->addr.bdaddr,
cp->addr.type);
goto complete;
}
addr_type = le_addr_type(cp->addr.type);
/* Kernel internally uses conn_params with resolvable private
* address, but Remove Device allows only identity addresses.
* Make sure it is enforced before calling
* hci_conn_params_lookup.
*/
if (!hci_is_identity_address(&cp->addr.bdaddr, addr_type)) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_REMOVE_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr));
goto unlock;
}
params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
addr_type);
if (!params) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_REMOVE_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr));
goto unlock;
}
if (params->auto_connect == HCI_AUTO_CONN_DISABLED ||
params->auto_connect == HCI_AUTO_CONN_EXPLICIT) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_REMOVE_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr));
goto unlock;
}
Bluetooth: use RCU for hci_conn_params and iterate safely in hci_sync hci_update_accept_list_sync iterates over hdev->pend_le_conns and hdev->pend_le_reports, and waits for controller events in the loop body, without holding hdev lock. Meanwhile, these lists and the items may be modified e.g. by le_scan_cleanup. This can invalidate the list cursor or any other item in the list, resulting to invalid behavior (eg use-after-free). Use RCU for the hci_conn_params action lists. Since the loop bodies in hci_sync block and we cannot use RCU or hdev->lock for the whole loop, copy list items first and then iterate on the copy. Only the flags field is written from elsewhere, so READ_ONCE/WRITE_ONCE should guarantee we read valid values. Free params everywhere with hci_conn_params_free so the cleanup is guaranteed to be done properly. This fixes the following, which can be triggered e.g. by BlueZ new mgmt-tester case "Add + Remove Device Nowait - Success", or by changing hci_le_set_cig_params to always return false, and running iso-tester: ================================================================== BUG: KASAN: slab-use-after-free in hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) Read of size 8 at addr ffff888001265018 by task kworker/u3:0/32 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-1.fc38 04/01/2014 Workqueue: hci0 hci_cmd_sync_work Call Trace: <TASK> dump_stack_lvl (./arch/x86/include/asm/irqflags.h:134 lib/dump_stack.c:107) print_report (mm/kasan/report.c:320 mm/kasan/report.c:430) ? __virt_addr_valid (./include/linux/mmzone.h:1915 ./include/linux/mmzone.h:2011 arch/x86/mm/physaddr.c:65) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) kasan_report (mm/kasan/report.c:538) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) ? __pfx_hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2780) ? mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_unlock (kernel/locking/mutex.c:538) ? __pfx_update_passive_scan_sync (net/bluetooth/hci_sync.c:2861) hci_cmd_sync_work (net/bluetooth/hci_sync.c:306) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) ? __pfx_worker_thread (kernel/workqueue.c:2480) kthread (kernel/kthread.c:376) ? __pfx_kthread (kernel/kthread.c:331) ret_from_fork (arch/x86/entry/entry_64.S:314) </TASK> Allocated by task 31: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) __kasan_kmalloc (mm/kasan/common.c:374 mm/kasan/common.c:383) hci_conn_params_add (./include/linux/slab.h:580 ./include/linux/slab.h:720 net/bluetooth/hci_core.c:2277) hci_connect_le_scan (net/bluetooth/hci_conn.c:1419 net/bluetooth/hci_conn.c:1589) hci_connect_cis (net/bluetooth/hci_conn.c:2266) iso_connect_cis (net/bluetooth/iso.c:390) iso_sock_connect (net/bluetooth/iso.c:899) __sys_connect (net/socket.c:2003 net/socket.c:2020) __x64_sys_connect (net/socket.c:2027) do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) Freed by task 15: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) kasan_save_free_info (mm/kasan/generic.c:523) __kasan_slab_free (mm/kasan/common.c:238 mm/kasan/common.c:200 mm/kasan/common.c:244) __kmem_cache_free (mm/slub.c:1807 mm/slub.c:3787 mm/slub.c:3800) hci_conn_params_del (net/bluetooth/hci_core.c:2323) le_scan_cleanup (net/bluetooth/hci_conn.c:202) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) kthread (kernel/kthread.c:376) ret_from_fork (arch/x86/entry/entry_64.S:314) ================================================================== Fixes: e8907f76544f ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 3") Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-06-18 22:04:31 +00:00
hci_conn_params_free(params);
device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type);
} else {
struct hci_conn_params *p, *tmp;
struct bdaddr_list *b, *btmp;
if (cp->addr.type) {
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_REMOVE_DEVICE,
MGMT_STATUS_INVALID_PARAMS,
&cp->addr, sizeof(cp->addr));
goto unlock;
}
list_for_each_entry_safe(b, btmp, &hdev->accept_list, list) {
device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type);
list_del(&b->list);
kfree(b);
}
hci_update_scan(hdev);
list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) {
if (p->auto_connect == HCI_AUTO_CONN_DISABLED)
continue;
device_removed(sk, hdev, &p->addr, p->addr_type);
if (p->explicit_connect) {
p->auto_connect = HCI_AUTO_CONN_EXPLICIT;
continue;
}
Bluetooth: use RCU for hci_conn_params and iterate safely in hci_sync hci_update_accept_list_sync iterates over hdev->pend_le_conns and hdev->pend_le_reports, and waits for controller events in the loop body, without holding hdev lock. Meanwhile, these lists and the items may be modified e.g. by le_scan_cleanup. This can invalidate the list cursor or any other item in the list, resulting to invalid behavior (eg use-after-free). Use RCU for the hci_conn_params action lists. Since the loop bodies in hci_sync block and we cannot use RCU or hdev->lock for the whole loop, copy list items first and then iterate on the copy. Only the flags field is written from elsewhere, so READ_ONCE/WRITE_ONCE should guarantee we read valid values. Free params everywhere with hci_conn_params_free so the cleanup is guaranteed to be done properly. This fixes the following, which can be triggered e.g. by BlueZ new mgmt-tester case "Add + Remove Device Nowait - Success", or by changing hci_le_set_cig_params to always return false, and running iso-tester: ================================================================== BUG: KASAN: slab-use-after-free in hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) Read of size 8 at addr ffff888001265018 by task kworker/u3:0/32 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-1.fc38 04/01/2014 Workqueue: hci0 hci_cmd_sync_work Call Trace: <TASK> dump_stack_lvl (./arch/x86/include/asm/irqflags.h:134 lib/dump_stack.c:107) print_report (mm/kasan/report.c:320 mm/kasan/report.c:430) ? __virt_addr_valid (./include/linux/mmzone.h:1915 ./include/linux/mmzone.h:2011 arch/x86/mm/physaddr.c:65) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) kasan_report (mm/kasan/report.c:538) ? hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2536 net/bluetooth/hci_sync.c:2723 net/bluetooth/hci_sync.c:2841) ? __pfx_hci_update_passive_scan_sync (net/bluetooth/hci_sync.c:2780) ? mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_lock (kernel/locking/mutex.c:282) ? __pfx_mutex_unlock (kernel/locking/mutex.c:538) ? __pfx_update_passive_scan_sync (net/bluetooth/hci_sync.c:2861) hci_cmd_sync_work (net/bluetooth/hci_sync.c:306) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) ? __pfx_worker_thread (kernel/workqueue.c:2480) kthread (kernel/kthread.c:376) ? __pfx_kthread (kernel/kthread.c:331) ret_from_fork (arch/x86/entry/entry_64.S:314) </TASK> Allocated by task 31: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) __kasan_kmalloc (mm/kasan/common.c:374 mm/kasan/common.c:383) hci_conn_params_add (./include/linux/slab.h:580 ./include/linux/slab.h:720 net/bluetooth/hci_core.c:2277) hci_connect_le_scan (net/bluetooth/hci_conn.c:1419 net/bluetooth/hci_conn.c:1589) hci_connect_cis (net/bluetooth/hci_conn.c:2266) iso_connect_cis (net/bluetooth/iso.c:390) iso_sock_connect (net/bluetooth/iso.c:899) __sys_connect (net/socket.c:2003 net/socket.c:2020) __x64_sys_connect (net/socket.c:2027) do_syscall_64 (arch/x86/entry/common.c:50 arch/x86/entry/common.c:80) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:120) Freed by task 15: kasan_save_stack (mm/kasan/common.c:46) kasan_set_track (mm/kasan/common.c:52) kasan_save_free_info (mm/kasan/generic.c:523) __kasan_slab_free (mm/kasan/common.c:238 mm/kasan/common.c:200 mm/kasan/common.c:244) __kmem_cache_free (mm/slub.c:1807 mm/slub.c:3787 mm/slub.c:3800) hci_conn_params_del (net/bluetooth/hci_core.c:2323) le_scan_cleanup (net/bluetooth/hci_conn.c:202) process_one_work (./arch/x86/include/asm/preempt.h:27 kernel/workqueue.c:2399) worker_thread (./include/linux/list.h:292 kernel/workqueue.c:2538) kthread (kernel/kthread.c:376) ret_from_fork (arch/x86/entry/entry_64.S:314) ================================================================== Fixes: e8907f76544f ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 3") Signed-off-by: Pauli Virtanen <pav@iki.fi> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-06-18 22:04:31 +00:00
hci_conn_params_free(p);
}
bt_dev_dbg(hdev, "All LE connection parameters were removed");
}
2021-10-27 23:58:41 +00:00
hci_cmd_sync_queue(hdev, remove_device_sync, NULL, NULL);
complete:
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE,
MGMT_STATUS_SUCCESS, &cp->addr,
sizeof(cp->addr));
unlock:
hci_dev_unlock(hdev);
return err;
}
static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_load_conn_param *cp = data;
const u16 max_param_count = ((U16_MAX - sizeof(*cp)) /
sizeof(struct mgmt_conn_param));
u16 param_count, expected_len;
int i;
if (!lmp_le_capable(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
MGMT_STATUS_NOT_SUPPORTED);
param_count = __le16_to_cpu(cp->param_count);
if (param_count > max_param_count) {
bt_dev_err(hdev, "load_conn_param: too big param_count value %u",
param_count);
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
MGMT_STATUS_INVALID_PARAMS);
}
expected_len = struct_size(cp, params, param_count);
if (expected_len != len) {
bt_dev_err(hdev, "load_conn_param: expected %u bytes, got %u bytes",
expected_len, len);
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
MGMT_STATUS_INVALID_PARAMS);
}
bt_dev_dbg(hdev, "param_count %u", param_count);
hci_dev_lock(hdev);
hci_conn_params_clear_disabled(hdev);
for (i = 0; i < param_count; i++) {
struct mgmt_conn_param *param = &cp->params[i];
struct hci_conn_params *hci_param;
u16 min, max, latency, timeout;
u8 addr_type;
bt_dev_dbg(hdev, "Adding %pMR (type %u)", &param->addr.bdaddr,
param->addr.type);
if (param->addr.type == BDADDR_LE_PUBLIC) {
addr_type = ADDR_LE_DEV_PUBLIC;
} else if (param->addr.type == BDADDR_LE_RANDOM) {
addr_type = ADDR_LE_DEV_RANDOM;
} else {
bt_dev_err(hdev, "ignoring invalid connection parameters");
continue;
}
min = le16_to_cpu(param->min_interval);
max = le16_to_cpu(param->max_interval);
latency = le16_to_cpu(param->latency);
timeout = le16_to_cpu(param->timeout);
bt_dev_dbg(hdev, "min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
min, max, latency, timeout);
if (hci_check_conn_params(min, max, latency, timeout) < 0) {
bt_dev_err(hdev, "ignoring invalid connection parameters");
continue;
}
hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
addr_type);
if (!hci_param) {
bt_dev_err(hdev, "failed to add connection parameters");
continue;
}
hci_param->conn_min_interval = min;
hci_param->conn_max_interval = max;
hci_param->conn_latency = latency;
hci_param->supervision_timeout = timeout;
}
hci_dev_unlock(hdev);
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0,
NULL, 0);
}
static int set_external_config(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_cp_set_external_config *cp = data;
bool changed;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (hdev_is_powered(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
MGMT_STATUS_REJECTED);
if (cp->config != 0x00 && cp->config != 0x01)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
MGMT_STATUS_INVALID_PARAMS);
if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG,
MGMT_STATUS_NOT_SUPPORTED);
hci_dev_lock(hdev);
if (cp->config)
changed = !hci_dev_test_and_set_flag(hdev, HCI_EXT_CONFIGURED);
else
changed = hci_dev_test_and_clear_flag(hdev, HCI_EXT_CONFIGURED);
err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev);
if (err < 0)
goto unlock;
if (!changed)
goto unlock;
err = new_options(hdev, sk);
if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED) == is_configured(hdev)) {
mgmt_index_removed(hdev);
if (hci_dev_test_and_change_flag(hdev, HCI_UNCONFIGURED)) {
hci_dev_set_flag(hdev, HCI_CONFIG);
hci_dev_set_flag(hdev, HCI_AUTO_OFF);
queue_work(hdev->req_workqueue, &hdev->power_on);
} else {
set_bit(HCI_RAW, &hdev->flags);
mgmt_index_added(hdev);
}
}
unlock:
hci_dev_unlock(hdev);
return err;
}
static int set_public_address(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
struct mgmt_cp_set_public_address *cp = data;
bool changed;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (hdev_is_powered(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
MGMT_STATUS_REJECTED);
if (!bacmp(&cp->bdaddr, BDADDR_ANY))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
MGMT_STATUS_INVALID_PARAMS);
if (!hdev->set_bdaddr)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS,
MGMT_STATUS_NOT_SUPPORTED);
hci_dev_lock(hdev);
changed = !!bacmp(&hdev->public_addr, &cp->bdaddr);
bacpy(&hdev->public_addr, &cp->bdaddr);
err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev);
if (err < 0)
goto unlock;
if (!changed)
goto unlock;
if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED))
err = new_options(hdev, sk);
if (is_configured(hdev)) {
mgmt_index_removed(hdev);
hci_dev_clear_flag(hdev, HCI_UNCONFIGURED);
hci_dev_set_flag(hdev, HCI_CONFIG);
hci_dev_set_flag(hdev, HCI_AUTO_OFF);
queue_work(hdev->req_workqueue, &hdev->power_on);
}
unlock:
hci_dev_unlock(hdev);
return err;
}
static void read_local_oob_ext_data_complete(struct hci_dev *hdev, void *data,
int err)
{
const struct mgmt_cp_read_local_oob_ext_data *mgmt_cp;
struct mgmt_rp_read_local_oob_ext_data *mgmt_rp;
u8 *h192, *r192, *h256, *r256;
struct mgmt_pending_cmd *cmd = data;
struct sk_buff *skb = cmd->skb;
u8 status = mgmt_status(err);
u16 eir_len;
if (cmd != pending_find(MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev))
return;
if (!status) {
if (!skb)
status = MGMT_STATUS_FAILED;
else if (IS_ERR(skb))
status = mgmt_status(PTR_ERR(skb));
else
status = mgmt_status(skb->data[0]);
}
bt_dev_dbg(hdev, "status %u", status);
mgmt_cp = cmd->param;
if (status) {
status = mgmt_status(status);
eir_len = 0;
h192 = NULL;
r192 = NULL;
h256 = NULL;
r256 = NULL;
} else if (!bredr_sc_enabled(hdev)) {
struct hci_rp_read_local_oob_data *rp;
if (skb->len != sizeof(*rp)) {
status = MGMT_STATUS_FAILED;
eir_len = 0;
} else {
status = MGMT_STATUS_SUCCESS;
rp = (void *)skb->data;
eir_len = 5 + 18 + 18;
h192 = rp->hash;
r192 = rp->rand;
h256 = NULL;
r256 = NULL;
}
} else {
struct hci_rp_read_local_oob_ext_data *rp;
if (skb->len != sizeof(*rp)) {
status = MGMT_STATUS_FAILED;
eir_len = 0;
} else {
status = MGMT_STATUS_SUCCESS;
rp = (void *)skb->data;
if (hci_dev_test_flag(hdev, HCI_SC_ONLY)) {
eir_len = 5 + 18 + 18;
h192 = NULL;
r192 = NULL;
} else {
eir_len = 5 + 18 + 18 + 18 + 18;
h192 = rp->hash192;
r192 = rp->rand192;
}
h256 = rp->hash256;
r256 = rp->rand256;
}
}
mgmt_rp = kmalloc(sizeof(*mgmt_rp) + eir_len, GFP_KERNEL);
if (!mgmt_rp)
goto done;
if (eir_len == 0)
goto send_rsp;
eir_len = eir_append_data(mgmt_rp->eir, 0, EIR_CLASS_OF_DEV,
hdev->dev_class, 3);
if (h192 && r192) {
eir_len = eir_append_data(mgmt_rp->eir, eir_len,
EIR_SSP_HASH_C192, h192, 16);
eir_len = eir_append_data(mgmt_rp->eir, eir_len,
EIR_SSP_RAND_R192, r192, 16);
}
if (h256 && r256) {
eir_len = eir_append_data(mgmt_rp->eir, eir_len,
EIR_SSP_HASH_C256, h256, 16);
eir_len = eir_append_data(mgmt_rp->eir, eir_len,
EIR_SSP_RAND_R256, r256, 16);
}
send_rsp:
mgmt_rp->type = mgmt_cp->type;
mgmt_rp->eir_len = cpu_to_le16(eir_len);
err = mgmt_cmd_complete(cmd->sk, hdev->id,
MGMT_OP_READ_LOCAL_OOB_EXT_DATA, status,
mgmt_rp, sizeof(*mgmt_rp) + eir_len);
if (err < 0 || status)
goto done;
hci_sock_set_flag(cmd->sk, HCI_MGMT_OOB_DATA_EVENTS);
err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
mgmt_rp, sizeof(*mgmt_rp) + eir_len,
HCI_MGMT_OOB_DATA_EVENTS, cmd->sk);
done:
if (skb && !IS_ERR(skb))
kfree_skb(skb);
kfree(mgmt_rp);
mgmt_pending_remove(cmd);
}
static int read_local_ssp_oob_req(struct hci_dev *hdev, struct sock *sk,
struct mgmt_cp_read_local_oob_ext_data *cp)
{
struct mgmt_pending_cmd *cmd;
int err;
cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_EXT_DATA, hdev,
cp, sizeof(*cp));
if (!cmd)
return -ENOMEM;
err = hci_cmd_sync_queue(hdev, read_local_oob_data_sync, cmd,
read_local_oob_ext_data_complete);
if (err < 0) {
mgmt_pending_remove(cmd);
return err;
}
return 0;
}
static int read_local_oob_ext_data(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
struct mgmt_cp_read_local_oob_ext_data *cp = data;
struct mgmt_rp_read_local_oob_ext_data *rp;
size_t rp_len;
u16 eir_len;
u8 status, flags, role, addr[7], hash[16], rand[16];
int err;
bt_dev_dbg(hdev, "sock %p", sk);
if (hdev_is_powered(hdev)) {
switch (cp->type) {
case BIT(BDADDR_BREDR):
status = mgmt_bredr_support(hdev);
if (status)
eir_len = 0;
else
eir_len = 5;
break;
case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
status = mgmt_le_support(hdev);
if (status)
eir_len = 0;
else
eir_len = 9 + 3 + 18 + 18 + 3;
break;
default:
status = MGMT_STATUS_INVALID_PARAMS;
eir_len = 0;
break;
}
} else {
status = MGMT_STATUS_NOT_POWERED;
eir_len = 0;
}
rp_len = sizeof(*rp) + eir_len;
rp = kmalloc(rp_len, GFP_ATOMIC);
if (!rp)
return -ENOMEM;
if (!status && !lmp_ssp_capable(hdev)) {
status = MGMT_STATUS_NOT_SUPPORTED;
eir_len = 0;
}
if (status)
goto complete;
hci_dev_lock(hdev);
eir_len = 0;
switch (cp->type) {
case BIT(BDADDR_BREDR):
if (hci_dev_test_flag(hdev, HCI_SSP_ENABLED)) {
err = read_local_ssp_oob_req(hdev, sk, cp);
hci_dev_unlock(hdev);
if (!err)
goto done;
status = MGMT_STATUS_FAILED;
goto complete;
} else {
eir_len = eir_append_data(rp->eir, eir_len,
EIR_CLASS_OF_DEV,
hdev->dev_class, 3);
}
break;
case (BIT(BDADDR_LE_PUBLIC) | BIT(BDADDR_LE_RANDOM)):
if (hci_dev_test_flag(hdev, HCI_SC_ENABLED) &&
smp_generate_oob(hdev, hash, rand) < 0) {
hci_dev_unlock(hdev);
status = MGMT_STATUS_FAILED;
goto complete;
}
/* This should return the active RPA, but since the RPA
* is only programmed on demand, it is really hard to fill
* this in at the moment. For now disallow retrieving
* local out-of-band data when privacy is in use.
*
* Returning the identity address will not help here since
* pairing happens before the identity resolving key is
* known and thus the connection establishment happens
* based on the RPA and not the identity address.
*/
if (hci_dev_test_flag(hdev, HCI_PRIVACY)) {
hci_dev_unlock(hdev);
status = MGMT_STATUS_REJECTED;
goto complete;
}
if (hci_dev_test_flag(hdev, HCI_FORCE_STATIC_ADDR) ||
!bacmp(&hdev->bdaddr, BDADDR_ANY) ||
(!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED) &&
bacmp(&hdev->static_addr, BDADDR_ANY))) {
memcpy(addr, &hdev->static_addr, 6);
addr[6] = 0x01;
} else {
memcpy(addr, &hdev->bdaddr, 6);
addr[6] = 0x00;
}
eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_BDADDR,
addr, sizeof(addr));
if (hci_dev_test_flag(hdev, HCI_ADVERTISING))
role = 0x02;
else
role = 0x01;
eir_len = eir_append_data(rp->eir, eir_len, EIR_LE_ROLE,
&role, sizeof(role));
if (hci_dev_test_flag(hdev, HCI_SC_ENABLED)) {
eir_len = eir_append_data(rp->eir, eir_len,
EIR_LE_SC_CONFIRM,
hash, sizeof(hash));
eir_len = eir_append_data(rp->eir, eir_len,
EIR_LE_SC_RANDOM,
rand, sizeof(rand));
}
flags = mgmt_get_adv_discov_flags(hdev);
if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED))
flags |= LE_AD_NO_BREDR;
eir_len = eir_append_data(rp->eir, eir_len, EIR_FLAGS,
&flags, sizeof(flags));
break;
}
hci_dev_unlock(hdev);
hci_sock_set_flag(sk, HCI_MGMT_OOB_DATA_EVENTS);
status = MGMT_STATUS_SUCCESS;
complete:
rp->type = cp->type;
rp->eir_len = cpu_to_le16(eir_len);
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_EXT_DATA,
status, rp, sizeof(*rp) + eir_len);
if (err < 0 || status)
goto done;
err = mgmt_limited_event(MGMT_EV_LOCAL_OOB_DATA_UPDATED, hdev,
rp, sizeof(*rp) + eir_len,
HCI_MGMT_OOB_DATA_EVENTS, sk);
done:
kfree(rp);
return err;
}
static u32 get_supported_adv_flags(struct hci_dev *hdev)
{
u32 flags = 0;
flags |= MGMT_ADV_FLAG_CONNECTABLE;
flags |= MGMT_ADV_FLAG_DISCOV;
flags |= MGMT_ADV_FLAG_LIMITED_DISCOV;
flags |= MGMT_ADV_FLAG_MANAGED_FLAGS;
flags |= MGMT_ADV_FLAG_APPEARANCE;
flags |= MGMT_ADV_FLAG_LOCAL_NAME;
flags |= MGMT_ADV_PARAM_DURATION;
flags |= MGMT_ADV_PARAM_TIMEOUT;
flags |= MGMT_ADV_PARAM_INTERVALS;
flags |= MGMT_ADV_PARAM_TX_POWER;
flags |= MGMT_ADV_PARAM_SCAN_RSP;
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 11:39:41 +00:00
/* In extended adv TX_POWER returned from Set Adv Param
* will be always valid.
*/
if (hdev->adv_tx_power != HCI_TX_POWER_INVALID || ext_adv_capable(hdev))
flags |= MGMT_ADV_FLAG_TX_POWER;
if (ext_adv_capable(hdev)) {
flags |= MGMT_ADV_FLAG_SEC_1M;
flags |= MGMT_ADV_FLAG_HW_OFFLOAD;
flags |= MGMT_ADV_FLAG_CAN_SET_TX_POWER;
if (le_2m_capable(hdev))
flags |= MGMT_ADV_FLAG_SEC_2M;
if (le_coded_capable(hdev))
flags |= MGMT_ADV_FLAG_SEC_CODED;
}
return flags;
}
static int read_adv_features(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
struct mgmt_rp_read_adv_features *rp;
size_t rp_len;
int err;
struct adv_info *adv_instance;
u32 supported_flags;
u8 *instance;
bt_dev_dbg(hdev, "sock %p", sk);
if (!lmp_le_capable(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
MGMT_STATUS_REJECTED);
hci_dev_lock(hdev);
rp_len = sizeof(*rp) + hdev->adv_instance_cnt;
rp = kmalloc(rp_len, GFP_ATOMIC);
if (!rp) {
hci_dev_unlock(hdev);
return -ENOMEM;
}
supported_flags = get_supported_adv_flags(hdev);
rp->supported_flags = cpu_to_le32(supported_flags);
rp->max_adv_data_len = max_adv_len(hdev);
rp->max_scan_rsp_len = max_adv_len(hdev);
rp->max_instances = hdev->le_num_of_adv_sets;
rp->num_instances = hdev->adv_instance_cnt;
instance = rp->instance;
list_for_each_entry(adv_instance, &hdev->adv_instances, list) {
/* Only instances 1-le_num_of_adv_sets are externally visible */
if (adv_instance->instance <= hdev->adv_instance_cnt) {
*instance = adv_instance->instance;
instance++;
} else {
rp->num_instances--;
rp_len--;
}
}
hci_dev_unlock(hdev);
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_READ_ADV_FEATURES,
MGMT_STATUS_SUCCESS, rp, rp_len);
kfree(rp);
return err;
}
static u8 calculate_name_len(struct hci_dev *hdev)
{
u8 buf[HCI_MAX_SHORT_NAME_LENGTH + 2]; /* len + type + name */
return eir_append_local_name(hdev, buf, 0);
}
static u8 tlv_data_max_len(struct hci_dev *hdev, u32 adv_flags,
bool is_adv_data)
{
u8 max_len = max_adv_len(hdev);
if (is_adv_data) {
if (adv_flags & (MGMT_ADV_FLAG_DISCOV |
MGMT_ADV_FLAG_LIMITED_DISCOV |
MGMT_ADV_FLAG_MANAGED_FLAGS))
max_len -= 3;
if (adv_flags & MGMT_ADV_FLAG_TX_POWER)
max_len -= 3;
} else {
if (adv_flags & MGMT_ADV_FLAG_LOCAL_NAME)
max_len -= calculate_name_len(hdev);
if (adv_flags & (MGMT_ADV_FLAG_APPEARANCE))
max_len -= 4;
}
return max_len;
}
static bool flags_managed(u32 adv_flags)
{
return adv_flags & (MGMT_ADV_FLAG_DISCOV |
MGMT_ADV_FLAG_LIMITED_DISCOV |
MGMT_ADV_FLAG_MANAGED_FLAGS);
}
static bool tx_power_managed(u32 adv_flags)
{
return adv_flags & MGMT_ADV_FLAG_TX_POWER;
}
static bool name_managed(u32 adv_flags)
{
return adv_flags & MGMT_ADV_FLAG_LOCAL_NAME;
}
static bool appearance_managed(u32 adv_flags)
{
return adv_flags & MGMT_ADV_FLAG_APPEARANCE;
}
static bool tlv_data_is_valid(struct hci_dev *hdev, u32 adv_flags, u8 *data,
u8 len, bool is_adv_data)
{
int i, cur_len;
u8 max_len;
max_len = tlv_data_max_len(hdev, adv_flags, is_adv_data);
if (len > max_len)
return false;
/* Make sure that the data is correctly formatted. */
for (i = 0; i < len; i += (cur_len + 1)) {
cur_len = data[i];
Bluetooth: mgmt: Fix slab-out-of-bounds in tlv_data_is_valid This fixes parsing of LTV entries when the length is 0. Found with: tools/mgmt-tester -s "Add Advertising - Success (ScRsp only)" Add Advertising - Success (ScRsp only) - run Sending Add Advertising (0x003e) Test condition added, total 1 [ 11.004577] ================================================================== [ 11.005292] BUG: KASAN: slab-out-of-bounds in tlv_data_is_valid+0x87/0xe0 [ 11.005984] Read of size 1 at addr ffff888002c695b0 by task mgmt-tester/87 [ 11.006711] [ 11.007176] [ 11.007429] Allocated by task 87: [ 11.008151] [ 11.008438] The buggy address belongs to the object at ffff888002c69580 [ 11.008438] which belongs to the cache kmalloc-64 of size 64 [ 11.010526] The buggy address is located 48 bytes inside of [ 11.010526] 64-byte region [ffff888002c69580, ffff888002c695c0) [ 11.012423] The buggy address belongs to the page: [ 11.013291] [ 11.013544] Memory state around the buggy address: [ 11.014359] ffff888002c69480: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc [ 11.015453] ffff888002c69500: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc [ 11.016232] >ffff888002c69580: 00 00 00 00 00 00 fc fc fc fc fc fc fc fc fc fc [ 11.017010] ^ [ 11.017547] ffff888002c69600: 00 00 00 00 00 00 fc fc fc fc fc fc fc fc fc fc [ 11.018296] ffff888002c69680: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc [ 11.019116] ================================================================== Fixes: 2bb36870e8cb2 ("Bluetooth: Unify advertising instance flags check") Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
2021-05-28 18:45:02 +00:00
if (!cur_len)
continue;
if (data[i + 1] == EIR_FLAGS &&
(!is_adv_data || flags_managed(adv_flags)))
return false;
if (data[i + 1] == EIR_TX_POWER && tx_power_managed(adv_flags))
return false;
if (data[i + 1] == EIR_NAME_COMPLETE && name_managed(adv_flags))
return false;
if (data[i + 1] == EIR_NAME_SHORT && name_managed(adv_flags))
return false;
if (data[i + 1] == EIR_APPEARANCE &&
appearance_managed(adv_flags))
return false;
/* If the current field length would exceed the total data
* length, then it's invalid.
*/
if (i + cur_len >= len)
return false;
}
return true;
}
static bool requested_adv_flags_are_valid(struct hci_dev *hdev, u32 adv_flags)
{
u32 supported_flags, phy_flags;
/* The current implementation only supports a subset of the specified
* flags. Also need to check mutual exclusiveness of sec flags.
*/
supported_flags = get_supported_adv_flags(hdev);
phy_flags = adv_flags & MGMT_ADV_FLAG_SEC_MASK;
if (adv_flags & ~supported_flags ||
((phy_flags && (phy_flags ^ (phy_flags & -phy_flags)))))
return false;
return true;
}
static bool adv_busy(struct hci_dev *hdev)
{
return pending_find(MGMT_OP_SET_LE, hdev);
}
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-27 23:58:40 +00:00
static void add_adv_complete(struct hci_dev *hdev, struct sock *sk, u8 instance,
int err)
{
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-27 23:58:40 +00:00
struct adv_info *adv, *n;
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-27 23:58:40 +00:00
bt_dev_dbg(hdev, "err %d", err);
hci_dev_lock(hdev);
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-27 23:58:40 +00:00
list_for_each_entry_safe(adv, n, &hdev->adv_instances, list) {
u8 instance;
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-27 23:58:40 +00:00
if (!adv->pending)
continue;
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-27 23:58:40 +00:00
if (!err) {
adv->pending = false;
continue;
}
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-27 23:58:40 +00:00
instance = adv->instance;
if (hdev->cur_adv_instance == instance)
cancel_adv_timeout(hdev);
hci_remove_adv_instance(hdev, instance);
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-27 23:58:40 +00:00
mgmt_advertising_removed(sk, hdev, instance);
}
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-27 23:58:40 +00:00
hci_dev_unlock(hdev);
}
static void add_advertising_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_add_advertising *cp = cmd->param;
struct mgmt_rp_add_advertising rp;
memset(&rp, 0, sizeof(rp));
rp.instance = cp->instance;
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-27 23:58:40 +00:00
if (err)
mgmt_cmd_status(cmd->sk, cmd->index, cmd->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-27 23:58:40 +00:00
mgmt_status(err));
else
mgmt_cmd_complete(cmd->sk, cmd->index, cmd->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-27 23:58:40 +00:00
mgmt_status(err), &rp, sizeof(rp));
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-27 23:58:40 +00:00
add_adv_complete(hdev, cmd->sk, cp->instance, err);
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-27 23:58:40 +00:00
mgmt_pending_free(cmd);
}
static int add_advertising_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_add_advertising *cp = cmd->param;
return hci_schedule_adv_instance_sync(hdev, cp->instance, true);
}
static int add_advertising(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
struct mgmt_cp_add_advertising *cp = data;
struct mgmt_rp_add_advertising rp;
u32 flags;
u8 status;
u16 timeout, duration;
unsigned int prev_instance_cnt;
u8 schedule_instance = 0;
Bluetooth: Add initial implementation of BIS connections This adds initial support for BIS/BIG which includes: == Broadcaster role: Setup a periodic advertising and create a BIG == > tools/isotest -s 00:00:00:00:00:00 isotest[63]: Connected [00:00:00:00:00:00] isotest[63]: QoS BIG 0x00 BIS 0x00 Packing 0x00 Framing 0x00] isotest[63]: Output QoS [Interval 10000 us Latency 10 ms SDU 40 PHY 0x02 RTN 2] isotest[63]: Sending ... isotest[63]: Number of packets: 1 isotest[63]: Socket jitter buffer: 80 buffer < HCI Command: LE Set Perio.. (0x08|0x003e) plen 7 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Parameters (0x08|0x003e) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Perio.. (0x08|0x003f) plen 7 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Data (0x08|0x003f) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Perio.. (0x08|0x0040) plen 2 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Enable (0x08|0x0040) ncmd 1 Status: Success (0x00) < HCI Command: LE Create B.. (0x08|0x0068) plen 31 ... > HCI Event: Command Status (0x0f) plen 4 LE Create Broadcast Isochronous Group (0x08|0x0068) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 21 LE Broadcast Isochronous Group Complete (0x1b) ... == Broadcast Receiver role: Create a PA Sync and BIG Sync == > tools/isotest -i hci1 -d 00:AA:01:00:00:00 isotest[66]: Waiting for connection 00:AA:01:00:00:00... < HCI Command: LE Periodic Advert.. (0x08|0x0044) plen 14 ... > HCI Event: Command Status (0x0f) plen 4 LE Periodic Advertising Create Sync (0x08|0x0044) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Extended Sca.. (0x08|0x0041) plen 8 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Parameters (0x08|0x0041) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Extended Sca.. (0x08|0x0042) plen 6 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Enable (0x08|0x0042) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 29 LE Extended Advertising Report (0x0d) ... > HCI Event: LE Meta Event (0x3e) plen 16 LE Periodic Advertising Sync Established (0x0e) ... < HCI Command: LE Broadcast Isoch.. (0x08|0x006b) plen 25 ... > HCI Event: Command Status (0x0f) plen 4 LE Broadcast Isochronous Group Create Sync (0x08|0x006b) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 17 LE Broadcast Isochronous Group Sync Estabilished (0x1d) ... Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2022-03-09 21:22:20 +00:00
struct adv_info *adv, *next_instance;
int err;
struct mgmt_pending_cmd *cmd;
bt_dev_dbg(hdev, "sock %p", sk);
status = mgmt_le_support(hdev);
if (status)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
status);
if (cp->instance < 1 || cp->instance > hdev->le_num_of_adv_sets)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
MGMT_STATUS_INVALID_PARAMS);
if (data_len != sizeof(*cp) + cp->adv_data_len + cp->scan_rsp_len)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
MGMT_STATUS_INVALID_PARAMS);
flags = __le32_to_cpu(cp->flags);
timeout = __le16_to_cpu(cp->timeout);
duration = __le16_to_cpu(cp->duration);
if (!requested_adv_flags_are_valid(hdev, flags))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
if (timeout && !hdev_is_powered(hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
MGMT_STATUS_REJECTED);
goto unlock;
}
if (adv_busy(hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
MGMT_STATUS_BUSY);
goto unlock;
}
if (!tlv_data_is_valid(hdev, flags, cp->data, cp->adv_data_len, true) ||
!tlv_data_is_valid(hdev, flags, cp->data + cp->adv_data_len,
cp->scan_rsp_len, false)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
MGMT_STATUS_INVALID_PARAMS);
goto unlock;
}
prev_instance_cnt = hdev->adv_instance_cnt;
Bluetooth: Add initial implementation of BIS connections This adds initial support for BIS/BIG which includes: == Broadcaster role: Setup a periodic advertising and create a BIG == > tools/isotest -s 00:00:00:00:00:00 isotest[63]: Connected [00:00:00:00:00:00] isotest[63]: QoS BIG 0x00 BIS 0x00 Packing 0x00 Framing 0x00] isotest[63]: Output QoS [Interval 10000 us Latency 10 ms SDU 40 PHY 0x02 RTN 2] isotest[63]: Sending ... isotest[63]: Number of packets: 1 isotest[63]: Socket jitter buffer: 80 buffer < HCI Command: LE Set Perio.. (0x08|0x003e) plen 7 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Parameters (0x08|0x003e) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Perio.. (0x08|0x003f) plen 7 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Data (0x08|0x003f) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Perio.. (0x08|0x0040) plen 2 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Enable (0x08|0x0040) ncmd 1 Status: Success (0x00) < HCI Command: LE Create B.. (0x08|0x0068) plen 31 ... > HCI Event: Command Status (0x0f) plen 4 LE Create Broadcast Isochronous Group (0x08|0x0068) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 21 LE Broadcast Isochronous Group Complete (0x1b) ... == Broadcast Receiver role: Create a PA Sync and BIG Sync == > tools/isotest -i hci1 -d 00:AA:01:00:00:00 isotest[66]: Waiting for connection 00:AA:01:00:00:00... < HCI Command: LE Periodic Advert.. (0x08|0x0044) plen 14 ... > HCI Event: Command Status (0x0f) plen 4 LE Periodic Advertising Create Sync (0x08|0x0044) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Extended Sca.. (0x08|0x0041) plen 8 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Parameters (0x08|0x0041) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Extended Sca.. (0x08|0x0042) plen 6 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Enable (0x08|0x0042) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 29 LE Extended Advertising Report (0x0d) ... > HCI Event: LE Meta Event (0x3e) plen 16 LE Periodic Advertising Sync Established (0x0e) ... < HCI Command: LE Broadcast Isoch.. (0x08|0x006b) plen 25 ... > HCI Event: Command Status (0x0f) plen 4 LE Broadcast Isochronous Group Create Sync (0x08|0x006b) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 17 LE Broadcast Isochronous Group Sync Estabilished (0x1d) ... Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2022-03-09 21:22:20 +00:00
adv = hci_add_adv_instance(hdev, cp->instance, flags,
cp->adv_data_len, cp->data,
cp->scan_rsp_len,
cp->data + cp->adv_data_len,
timeout, duration,
HCI_ADV_TX_POWER_NO_PREFERENCE,
hdev->le_adv_min_interval,
hdev->le_adv_max_interval, 0);
Bluetooth: Add initial implementation of BIS connections This adds initial support for BIS/BIG which includes: == Broadcaster role: Setup a periodic advertising and create a BIG == > tools/isotest -s 00:00:00:00:00:00 isotest[63]: Connected [00:00:00:00:00:00] isotest[63]: QoS BIG 0x00 BIS 0x00 Packing 0x00 Framing 0x00] isotest[63]: Output QoS [Interval 10000 us Latency 10 ms SDU 40 PHY 0x02 RTN 2] isotest[63]: Sending ... isotest[63]: Number of packets: 1 isotest[63]: Socket jitter buffer: 80 buffer < HCI Command: LE Set Perio.. (0x08|0x003e) plen 7 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Parameters (0x08|0x003e) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Perio.. (0x08|0x003f) plen 7 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Data (0x08|0x003f) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Perio.. (0x08|0x0040) plen 2 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Enable (0x08|0x0040) ncmd 1 Status: Success (0x00) < HCI Command: LE Create B.. (0x08|0x0068) plen 31 ... > HCI Event: Command Status (0x0f) plen 4 LE Create Broadcast Isochronous Group (0x08|0x0068) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 21 LE Broadcast Isochronous Group Complete (0x1b) ... == Broadcast Receiver role: Create a PA Sync and BIG Sync == > tools/isotest -i hci1 -d 00:AA:01:00:00:00 isotest[66]: Waiting for connection 00:AA:01:00:00:00... < HCI Command: LE Periodic Advert.. (0x08|0x0044) plen 14 ... > HCI Event: Command Status (0x0f) plen 4 LE Periodic Advertising Create Sync (0x08|0x0044) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Extended Sca.. (0x08|0x0041) plen 8 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Parameters (0x08|0x0041) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Extended Sca.. (0x08|0x0042) plen 6 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Enable (0x08|0x0042) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 29 LE Extended Advertising Report (0x0d) ... > HCI Event: LE Meta Event (0x3e) plen 16 LE Periodic Advertising Sync Established (0x0e) ... < HCI Command: LE Broadcast Isoch.. (0x08|0x006b) plen 25 ... > HCI Event: Command Status (0x0f) plen 4 LE Broadcast Isochronous Group Create Sync (0x08|0x006b) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 17 LE Broadcast Isochronous Group Sync Estabilished (0x1d) ... Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2022-03-09 21:22:20 +00:00
if (IS_ERR(adv)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
MGMT_STATUS_FAILED);
goto unlock;
}
/* Only trigger an advertising added event if a new instance was
* actually added.
*/
if (hdev->adv_instance_cnt > prev_instance_cnt)
mgmt_advertising_added(sk, hdev, cp->instance);
if (hdev->cur_adv_instance == cp->instance) {
/* If the currently advertised instance is being changed then
* cancel the current advertising and schedule the next
* instance. If there is only one instance then the overridden
* advertising data will be visible right away.
*/
cancel_adv_timeout(hdev);
next_instance = hci_get_next_instance(hdev, cp->instance);
if (next_instance)
schedule_instance = next_instance->instance;
} else if (!hdev->adv_instance_timeout) {
/* Immediately advertise the new instance if no other
* instance is currently being advertised.
*/
schedule_instance = cp->instance;
}
/* If the HCI_ADVERTISING flag is set or the device isn't powered or
* there is no instance to be advertised then we have no HCI
* communication to make. Simply return.
*/
if (!hdev_is_powered(hdev) ||
hci_dev_test_flag(hdev, HCI_ADVERTISING) ||
!schedule_instance) {
rp.instance = cp->instance;
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING,
MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
goto unlock;
}
/* We're good to go, update advertising data, parameters, and start
* advertising.
*/
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-27 23:58:40 +00:00
cmd = mgmt_pending_new(sk, MGMT_OP_ADD_ADVERTISING, hdev, data,
data_len);
if (!cmd) {
err = -ENOMEM;
goto unlock;
}
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-27 23:58:40 +00:00
cp->instance = schedule_instance;
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-27 23:58:40 +00:00
err = hci_cmd_sync_queue(hdev, add_advertising_sync, cmd,
add_advertising_complete);
if (err < 0)
mgmt_pending_free(cmd);
unlock:
hci_dev_unlock(hdev);
return err;
}
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-27 23:58:40 +00:00
static void add_ext_adv_params_complete(struct hci_dev *hdev, void *data,
int err)
{
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-27 23:58:40 +00:00
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_add_ext_adv_params *cp = cmd->param;
struct mgmt_rp_add_ext_adv_params rp;
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-27 23:58:40 +00:00
struct adv_info *adv;
u32 flags;
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
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-27 23:58:40 +00:00
adv = hci_find_adv_instance(hdev, cp->instance);
if (!adv)
goto unlock;
rp.instance = cp->instance;
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-27 23:58:40 +00:00
rp.tx_power = adv->tx_power;
/* While we're at it, inform userspace of the available space for this
* advertisement, given the flags that will be used.
*/
flags = __le32_to_cpu(cp->flags);
rp.max_adv_data_len = tlv_data_max_len(hdev, flags, true);
rp.max_scan_rsp_len = tlv_data_max_len(hdev, flags, false);
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-27 23:58:40 +00:00
if (err) {
/* If this advertisement was previously advertising and we
* failed to update it, we signal that it has been removed and
* delete its structure
*/
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-27 23:58:40 +00:00
if (!adv->pending)
mgmt_advertising_removed(cmd->sk, hdev, cp->instance);
hci_remove_adv_instance(hdev, cp->instance);
mgmt_cmd_status(cmd->sk, cmd->index, cmd->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-27 23:58:40 +00:00
mgmt_status(err));
} else {
mgmt_cmd_complete(cmd->sk, cmd->index, cmd->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-27 23:58:40 +00:00
mgmt_status(err), &rp, sizeof(rp));
}
unlock:
mgmt_pending_free(cmd);
hci_dev_unlock(hdev);
}
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-27 23:58:40 +00:00
static int add_ext_adv_params_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_add_ext_adv_params *cp = cmd->param;
return hci_setup_ext_adv_instance_sync(hdev, cp->instance);
}
static int add_ext_adv_params(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
struct mgmt_cp_add_ext_adv_params *cp = data;
struct mgmt_rp_add_ext_adv_params rp;
struct mgmt_pending_cmd *cmd = NULL;
Bluetooth: Add initial implementation of BIS connections This adds initial support for BIS/BIG which includes: == Broadcaster role: Setup a periodic advertising and create a BIG == > tools/isotest -s 00:00:00:00:00:00 isotest[63]: Connected [00:00:00:00:00:00] isotest[63]: QoS BIG 0x00 BIS 0x00 Packing 0x00 Framing 0x00] isotest[63]: Output QoS [Interval 10000 us Latency 10 ms SDU 40 PHY 0x02 RTN 2] isotest[63]: Sending ... isotest[63]: Number of packets: 1 isotest[63]: Socket jitter buffer: 80 buffer < HCI Command: LE Set Perio.. (0x08|0x003e) plen 7 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Parameters (0x08|0x003e) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Perio.. (0x08|0x003f) plen 7 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Data (0x08|0x003f) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Perio.. (0x08|0x0040) plen 2 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Enable (0x08|0x0040) ncmd 1 Status: Success (0x00) < HCI Command: LE Create B.. (0x08|0x0068) plen 31 ... > HCI Event: Command Status (0x0f) plen 4 LE Create Broadcast Isochronous Group (0x08|0x0068) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 21 LE Broadcast Isochronous Group Complete (0x1b) ... == Broadcast Receiver role: Create a PA Sync and BIG Sync == > tools/isotest -i hci1 -d 00:AA:01:00:00:00 isotest[66]: Waiting for connection 00:AA:01:00:00:00... < HCI Command: LE Periodic Advert.. (0x08|0x0044) plen 14 ... > HCI Event: Command Status (0x0f) plen 4 LE Periodic Advertising Create Sync (0x08|0x0044) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Extended Sca.. (0x08|0x0041) plen 8 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Parameters (0x08|0x0041) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Extended Sca.. (0x08|0x0042) plen 6 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Enable (0x08|0x0042) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 29 LE Extended Advertising Report (0x0d) ... > HCI Event: LE Meta Event (0x3e) plen 16 LE Periodic Advertising Sync Established (0x0e) ... < HCI Command: LE Broadcast Isoch.. (0x08|0x006b) plen 25 ... > HCI Event: Command Status (0x0f) plen 4 LE Broadcast Isochronous Group Create Sync (0x08|0x006b) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 17 LE Broadcast Isochronous Group Sync Estabilished (0x1d) ... Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2022-03-09 21:22:20 +00:00
struct adv_info *adv;
u32 flags, min_interval, max_interval;
u16 timeout, duration;
u8 status;
s8 tx_power;
int err;
BT_DBG("%s", hdev->name);
status = mgmt_le_support(hdev);
if (status)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_PARAMS,
status);
if (cp->instance < 1 || cp->instance > hdev->le_num_of_adv_sets)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_PARAMS,
MGMT_STATUS_INVALID_PARAMS);
/* The purpose of breaking add_advertising into two separate MGMT calls
* for params and data is to allow more parameters to be added to this
* structure in the future. For this reason, we verify that we have the
* bare minimum structure we know of when the interface was defined. Any
* extra parameters we don't know about will be ignored in this request.
*/
if (data_len < MGMT_ADD_EXT_ADV_PARAMS_MIN_SIZE)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_PARAMS,
MGMT_STATUS_INVALID_PARAMS);
flags = __le32_to_cpu(cp->flags);
if (!requested_adv_flags_are_valid(hdev, flags))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_PARAMS,
MGMT_STATUS_INVALID_PARAMS);
hci_dev_lock(hdev);
/* In new interface, we require that we are powered to register */
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_PARAMS,
MGMT_STATUS_REJECTED);
goto unlock;
}
if (adv_busy(hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_PARAMS,
MGMT_STATUS_BUSY);
goto unlock;
}
/* Parse defined parameters from request, use defaults otherwise */
timeout = (flags & MGMT_ADV_PARAM_TIMEOUT) ?
__le16_to_cpu(cp->timeout) : 0;
duration = (flags & MGMT_ADV_PARAM_DURATION) ?
__le16_to_cpu(cp->duration) :
hdev->def_multi_adv_rotation_duration;
min_interval = (flags & MGMT_ADV_PARAM_INTERVALS) ?
__le32_to_cpu(cp->min_interval) :
hdev->le_adv_min_interval;
max_interval = (flags & MGMT_ADV_PARAM_INTERVALS) ?
__le32_to_cpu(cp->max_interval) :
hdev->le_adv_max_interval;
tx_power = (flags & MGMT_ADV_PARAM_TX_POWER) ?
cp->tx_power :
HCI_ADV_TX_POWER_NO_PREFERENCE;
/* Create advertising instance with no advertising or response data */
Bluetooth: Add initial implementation of BIS connections This adds initial support for BIS/BIG which includes: == Broadcaster role: Setup a periodic advertising and create a BIG == > tools/isotest -s 00:00:00:00:00:00 isotest[63]: Connected [00:00:00:00:00:00] isotest[63]: QoS BIG 0x00 BIS 0x00 Packing 0x00 Framing 0x00] isotest[63]: Output QoS [Interval 10000 us Latency 10 ms SDU 40 PHY 0x02 RTN 2] isotest[63]: Sending ... isotest[63]: Number of packets: 1 isotest[63]: Socket jitter buffer: 80 buffer < HCI Command: LE Set Perio.. (0x08|0x003e) plen 7 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Parameters (0x08|0x003e) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Perio.. (0x08|0x003f) plen 7 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Data (0x08|0x003f) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Perio.. (0x08|0x0040) plen 2 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Enable (0x08|0x0040) ncmd 1 Status: Success (0x00) < HCI Command: LE Create B.. (0x08|0x0068) plen 31 ... > HCI Event: Command Status (0x0f) plen 4 LE Create Broadcast Isochronous Group (0x08|0x0068) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 21 LE Broadcast Isochronous Group Complete (0x1b) ... == Broadcast Receiver role: Create a PA Sync and BIG Sync == > tools/isotest -i hci1 -d 00:AA:01:00:00:00 isotest[66]: Waiting for connection 00:AA:01:00:00:00... < HCI Command: LE Periodic Advert.. (0x08|0x0044) plen 14 ... > HCI Event: Command Status (0x0f) plen 4 LE Periodic Advertising Create Sync (0x08|0x0044) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Extended Sca.. (0x08|0x0041) plen 8 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Parameters (0x08|0x0041) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Extended Sca.. (0x08|0x0042) plen 6 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Enable (0x08|0x0042) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 29 LE Extended Advertising Report (0x0d) ... > HCI Event: LE Meta Event (0x3e) plen 16 LE Periodic Advertising Sync Established (0x0e) ... < HCI Command: LE Broadcast Isoch.. (0x08|0x006b) plen 25 ... > HCI Event: Command Status (0x0f) plen 4 LE Broadcast Isochronous Group Create Sync (0x08|0x006b) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 17 LE Broadcast Isochronous Group Sync Estabilished (0x1d) ... Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2022-03-09 21:22:20 +00:00
adv = hci_add_adv_instance(hdev, cp->instance, flags, 0, NULL, 0, NULL,
timeout, duration, tx_power, min_interval,
max_interval, 0);
Bluetooth: Add initial implementation of BIS connections This adds initial support for BIS/BIG which includes: == Broadcaster role: Setup a periodic advertising and create a BIG == > tools/isotest -s 00:00:00:00:00:00 isotest[63]: Connected [00:00:00:00:00:00] isotest[63]: QoS BIG 0x00 BIS 0x00 Packing 0x00 Framing 0x00] isotest[63]: Output QoS [Interval 10000 us Latency 10 ms SDU 40 PHY 0x02 RTN 2] isotest[63]: Sending ... isotest[63]: Number of packets: 1 isotest[63]: Socket jitter buffer: 80 buffer < HCI Command: LE Set Perio.. (0x08|0x003e) plen 7 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Parameters (0x08|0x003e) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Perio.. (0x08|0x003f) plen 7 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Data (0x08|0x003f) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Perio.. (0x08|0x0040) plen 2 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Periodic Advertising Enable (0x08|0x0040) ncmd 1 Status: Success (0x00) < HCI Command: LE Create B.. (0x08|0x0068) plen 31 ... > HCI Event: Command Status (0x0f) plen 4 LE Create Broadcast Isochronous Group (0x08|0x0068) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 21 LE Broadcast Isochronous Group Complete (0x1b) ... == Broadcast Receiver role: Create a PA Sync and BIG Sync == > tools/isotest -i hci1 -d 00:AA:01:00:00:00 isotest[66]: Waiting for connection 00:AA:01:00:00:00... < HCI Command: LE Periodic Advert.. (0x08|0x0044) plen 14 ... > HCI Event: Command Status (0x0f) plen 4 LE Periodic Advertising Create Sync (0x08|0x0044) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Extended Sca.. (0x08|0x0041) plen 8 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Parameters (0x08|0x0041) ncmd 1 Status: Success (0x00) < HCI Command: LE Set Extended Sca.. (0x08|0x0042) plen 6 ... > HCI Event: Command Complete (0x0e) plen 4 LE Set Extended Scan Enable (0x08|0x0042) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 29 LE Extended Advertising Report (0x0d) ... > HCI Event: LE Meta Event (0x3e) plen 16 LE Periodic Advertising Sync Established (0x0e) ... < HCI Command: LE Broadcast Isoch.. (0x08|0x006b) plen 25 ... > HCI Event: Command Status (0x0f) plen 4 LE Broadcast Isochronous Group Create Sync (0x08|0x006b) ncmd 1 Status: Success (0x00) > HCI Event: LE Meta Event (0x3e) plen 17 LE Broadcast Isochronous Group Sync Estabilished (0x1d) ... Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2022-03-09 21:22:20 +00:00
if (IS_ERR(adv)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_PARAMS,
MGMT_STATUS_FAILED);
goto unlock;
}
/* Submit request for advertising params if ext adv available */
if (ext_adv_capable(hdev)) {
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-27 23:58:40 +00:00
cmd = mgmt_pending_new(sk, MGMT_OP_ADD_EXT_ADV_PARAMS, hdev,
data, data_len);
if (!cmd) {
err = -ENOMEM;
hci_remove_adv_instance(hdev, cp->instance);
goto unlock;
}
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-27 23:58:40 +00:00
err = hci_cmd_sync_queue(hdev, add_ext_adv_params_sync, cmd,
add_ext_adv_params_complete);
if (err < 0)
mgmt_pending_free(cmd);
} else {
rp.instance = cp->instance;
rp.tx_power = HCI_ADV_TX_POWER_NO_PREFERENCE;
rp.max_adv_data_len = tlv_data_max_len(hdev, flags, true);
rp.max_scan_rsp_len = tlv_data_max_len(hdev, flags, false);
err = mgmt_cmd_complete(sk, hdev->id,
MGMT_OP_ADD_EXT_ADV_PARAMS,
MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
}
unlock:
hci_dev_unlock(hdev);
return err;
}
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-27 23:58:40 +00:00
static void add_ext_adv_data_complete(struct hci_dev *hdev, void *data, int err)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_add_ext_adv_data *cp = cmd->param;
struct mgmt_rp_add_advertising rp;
add_adv_complete(hdev, cmd->sk, cp->instance, err);
memset(&rp, 0, sizeof(rp));
rp.instance = cp->instance;
if (err)
mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
mgmt_status(err));
else
mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
mgmt_status(err), &rp, sizeof(rp));
mgmt_pending_free(cmd);
}
static int add_ext_adv_data_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_add_ext_adv_data *cp = cmd->param;
int err;
if (ext_adv_capable(hdev)) {
err = hci_update_adv_data_sync(hdev, cp->instance);
if (err)
return err;
err = hci_update_scan_rsp_data_sync(hdev, cp->instance);
if (err)
return err;
return hci_enable_ext_advertising_sync(hdev, cp->instance);
}
return hci_schedule_adv_instance_sync(hdev, cp->instance, true);
}
static int add_ext_adv_data(struct sock *sk, struct hci_dev *hdev, void *data,
u16 data_len)
{
struct mgmt_cp_add_ext_adv_data *cp = data;
struct mgmt_rp_add_ext_adv_data rp;
u8 schedule_instance = 0;
struct adv_info *next_instance;
struct adv_info *adv_instance;
int err = 0;
struct mgmt_pending_cmd *cmd;
BT_DBG("%s", hdev->name);
hci_dev_lock(hdev);
adv_instance = hci_find_adv_instance(hdev, cp->instance);
if (!adv_instance) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_DATA,
MGMT_STATUS_INVALID_PARAMS);
goto unlock;
}
/* In new interface, we require that we are powered to register */
if (!hdev_is_powered(hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_DATA,
MGMT_STATUS_REJECTED);
goto clear_new_instance;
}
if (adv_busy(hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_DATA,
MGMT_STATUS_BUSY);
goto clear_new_instance;
}
/* Validate new data */
if (!tlv_data_is_valid(hdev, adv_instance->flags, cp->data,
cp->adv_data_len, true) ||
!tlv_data_is_valid(hdev, adv_instance->flags, cp->data +
cp->adv_data_len, cp->scan_rsp_len, false)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_DATA,
MGMT_STATUS_INVALID_PARAMS);
goto clear_new_instance;
}
/* Set the data in the advertising instance */
hci_set_adv_instance_data(hdev, cp->instance, cp->adv_data_len,
cp->data, cp->scan_rsp_len,
cp->data + cp->adv_data_len);
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-27 23:58:40 +00:00
/* If using software rotation, determine next instance to use */
if (hdev->cur_adv_instance == cp->instance) {
/* If the currently advertised instance is being changed
* then cancel the current advertising and schedule the
* next instance. If there is only one instance then the
* overridden advertising data will be visible right
* away
*/
cancel_adv_timeout(hdev);
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-27 23:58:40 +00:00
next_instance = hci_get_next_instance(hdev, cp->instance);
if (next_instance)
schedule_instance = next_instance->instance;
} else if (!hdev->adv_instance_timeout) {
/* Immediately advertise the new instance if no other
* instance is currently being advertised.
*/
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-27 23:58:40 +00:00
schedule_instance = cp->instance;
}
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-27 23:58:40 +00:00
/* If the HCI_ADVERTISING flag is set or there is no instance to
* be advertised then we have no HCI communication to make.
* Simply return.
*/
if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || !schedule_instance) {
if (adv_instance->pending) {
mgmt_advertising_added(sk, hdev, cp->instance);
adv_instance->pending = false;
}
rp.instance = cp->instance;
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_EXT_ADV_DATA,
MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
goto unlock;
}
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-27 23:58:40 +00:00
cmd = mgmt_pending_new(sk, MGMT_OP_ADD_EXT_ADV_DATA, hdev, data,
data_len);
if (!cmd) {
err = -ENOMEM;
goto clear_new_instance;
}
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-27 23:58:40 +00:00
err = hci_cmd_sync_queue(hdev, add_ext_adv_data_sync, cmd,
add_ext_adv_data_complete);
if (err < 0) {
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-27 23:58:40 +00:00
mgmt_pending_free(cmd);
goto clear_new_instance;
}
/* We were successful in updating data, so trigger advertising_added
* event if this is an instance that wasn't previously advertising. If
* a failure occurs in the requests we initiated, we will remove the
* instance again in add_advertising_complete
*/
if (adv_instance->pending)
mgmt_advertising_added(sk, hdev, cp->instance);
goto unlock;
clear_new_instance:
hci_remove_adv_instance(hdev, cp->instance);
unlock:
hci_dev_unlock(hdev);
return err;
}
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-27 23:58:40 +00:00
static void remove_advertising_complete(struct hci_dev *hdev, void *data,
int err)
{
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-27 23:58:40 +00:00
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_remove_advertising *cp = cmd->param;
struct mgmt_rp_remove_advertising rp;
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-27 23:58:40 +00:00
bt_dev_dbg(hdev, "err %d", err);
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-27 23:58:40 +00:00
memset(&rp, 0, sizeof(rp));
rp.instance = cp->instance;
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-27 23:58:40 +00:00
if (err)
mgmt_cmd_status(cmd->sk, cmd->index, cmd->opcode,
mgmt_status(err));
else
mgmt_cmd_complete(cmd->sk, cmd->index, cmd->opcode,
MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
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-27 23:58:40 +00:00
mgmt_pending_free(cmd);
}
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-27 23:58:40 +00:00
static int remove_advertising_sync(struct hci_dev *hdev, void *data)
{
struct mgmt_pending_cmd *cmd = data;
struct mgmt_cp_remove_advertising *cp = cmd->param;
int err;
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-27 23:58:40 +00:00
err = hci_remove_advertising_sync(hdev, cmd->sk, cp->instance, true);
if (err)
return err;
if (list_empty(&hdev->adv_instances))
err = hci_disable_advertising_sync(hdev);
return err;
}
static int remove_advertising(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
struct mgmt_cp_remove_advertising *cp = data;
struct mgmt_pending_cmd *cmd;
int err;
bt_dev_dbg(hdev, "sock %p", sk);
hci_dev_lock(hdev);
if (cp->instance && !hci_find_adv_instance(hdev, cp->instance)) {
err = mgmt_cmd_status(sk, hdev->id,
MGMT_OP_REMOVE_ADVERTISING,
MGMT_STATUS_INVALID_PARAMS);
goto unlock;
}
if (pending_find(MGMT_OP_SET_LE, hdev)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
MGMT_STATUS_BUSY);
goto unlock;
}
if (list_empty(&hdev->adv_instances)) {
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_REMOVE_ADVERTISING,
MGMT_STATUS_INVALID_PARAMS);
goto unlock;
}
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-27 23:58:40 +00:00
cmd = mgmt_pending_new(sk, MGMT_OP_REMOVE_ADVERTISING, hdev, data,
data_len);
if (!cmd) {
err = -ENOMEM;
goto unlock;
}
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-27 23:58:40 +00:00
err = hci_cmd_sync_queue(hdev, remove_advertising_sync, cmd,
remove_advertising_complete);
if (err < 0)
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-27 23:58:40 +00:00
mgmt_pending_free(cmd);
unlock:
hci_dev_unlock(hdev);
return err;
}
static int get_adv_size_info(struct sock *sk, struct hci_dev *hdev,
void *data, u16 data_len)
{
struct mgmt_cp_get_adv_size_info *cp = data;
struct mgmt_rp_get_adv_size_info rp;
u32 flags, supported_flags;
bt_dev_dbg(hdev, "sock %p", sk);
if (!lmp_le_capable(hdev))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
MGMT_STATUS_REJECTED);
if (cp->instance < 1 || cp->instance > hdev->le_num_of_adv_sets)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
MGMT_STATUS_INVALID_PARAMS);
flags = __le32_to_cpu(cp->flags);
/* The current implementation only supports a subset of the specified
* flags.
*/
supported_flags = get_supported_adv_flags(hdev);
if (flags & ~supported_flags)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
MGMT_STATUS_INVALID_PARAMS);
rp.instance = cp->instance;
rp.flags = cp->flags;
rp.max_adv_data_len = tlv_data_max_len(hdev, flags, true);
rp.max_scan_rsp_len = tlv_data_max_len(hdev, flags, false);
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_ADV_SIZE_INFO,
MGMT_STATUS_SUCCESS, &rp, sizeof(rp));
}
static const struct hci_mgmt_handler mgmt_handlers[] = {
{ NULL }, /* 0x0000 (no command) */
{ read_version, MGMT_READ_VERSION_SIZE,
HCI_MGMT_NO_HDEV |
HCI_MGMT_UNTRUSTED },
{ read_commands, MGMT_READ_COMMANDS_SIZE,
HCI_MGMT_NO_HDEV |
HCI_MGMT_UNTRUSTED },
{ read_index_list, MGMT_READ_INDEX_LIST_SIZE,
HCI_MGMT_NO_HDEV |
HCI_MGMT_UNTRUSTED },
{ read_controller_info, MGMT_READ_INFO_SIZE,
HCI_MGMT_UNTRUSTED },
{ set_powered, MGMT_SETTING_SIZE },
{ set_discoverable, MGMT_SET_DISCOVERABLE_SIZE },
{ set_connectable, MGMT_SETTING_SIZE },
{ set_fast_connectable, MGMT_SETTING_SIZE },
{ set_bondable, MGMT_SETTING_SIZE },
{ set_link_security, MGMT_SETTING_SIZE },
{ set_ssp, MGMT_SETTING_SIZE },
{ set_hs, MGMT_SETTING_SIZE },
{ set_le, MGMT_SETTING_SIZE },
{ set_dev_class, MGMT_SET_DEV_CLASS_SIZE },
{ set_local_name, MGMT_SET_LOCAL_NAME_SIZE },
{ add_uuid, MGMT_ADD_UUID_SIZE },
{ remove_uuid, MGMT_REMOVE_UUID_SIZE },
{ load_link_keys, MGMT_LOAD_LINK_KEYS_SIZE,
HCI_MGMT_VAR_LEN },
{ load_long_term_keys, MGMT_LOAD_LONG_TERM_KEYS_SIZE,
HCI_MGMT_VAR_LEN },
{ disconnect, MGMT_DISCONNECT_SIZE },
{ get_connections, MGMT_GET_CONNECTIONS_SIZE },
{ pin_code_reply, MGMT_PIN_CODE_REPLY_SIZE },
{ pin_code_neg_reply, MGMT_PIN_CODE_NEG_REPLY_SIZE },
{ set_io_capability, MGMT_SET_IO_CAPABILITY_SIZE },
{ pair_device, MGMT_PAIR_DEVICE_SIZE },
{ cancel_pair_device, MGMT_CANCEL_PAIR_DEVICE_SIZE },
{ unpair_device, MGMT_UNPAIR_DEVICE_SIZE },
{ user_confirm_reply, MGMT_USER_CONFIRM_REPLY_SIZE },
{ user_confirm_neg_reply, MGMT_USER_CONFIRM_NEG_REPLY_SIZE },
{ user_passkey_reply, MGMT_USER_PASSKEY_REPLY_SIZE },
{ user_passkey_neg_reply, MGMT_USER_PASSKEY_NEG_REPLY_SIZE },
{ read_local_oob_data, MGMT_READ_LOCAL_OOB_DATA_SIZE },
{ add_remote_oob_data, MGMT_ADD_REMOTE_OOB_DATA_SIZE,
HCI_MGMT_VAR_LEN },
{ remove_remote_oob_data, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE },
{ start_discovery, MGMT_START_DISCOVERY_SIZE },
{ stop_discovery, MGMT_STOP_DISCOVERY_SIZE },
{ confirm_name, MGMT_CONFIRM_NAME_SIZE },
{ block_device, MGMT_BLOCK_DEVICE_SIZE },
{ unblock_device, MGMT_UNBLOCK_DEVICE_SIZE },
{ set_device_id, MGMT_SET_DEVICE_ID_SIZE },
{ set_advertising, MGMT_SETTING_SIZE },
{ set_bredr, MGMT_SETTING_SIZE },
{ set_static_address, MGMT_SET_STATIC_ADDRESS_SIZE },
{ set_scan_params, MGMT_SET_SCAN_PARAMS_SIZE },
{ set_secure_conn, MGMT_SETTING_SIZE },
{ set_debug_keys, MGMT_SETTING_SIZE },
{ set_privacy, MGMT_SET_PRIVACY_SIZE },
{ load_irks, MGMT_LOAD_IRKS_SIZE,
HCI_MGMT_VAR_LEN },
{ get_conn_info, MGMT_GET_CONN_INFO_SIZE },
{ get_clock_info, MGMT_GET_CLOCK_INFO_SIZE },
{ add_device, MGMT_ADD_DEVICE_SIZE },
{ remove_device, MGMT_REMOVE_DEVICE_SIZE },
{ load_conn_param, MGMT_LOAD_CONN_PARAM_SIZE,
HCI_MGMT_VAR_LEN },
{ read_unconf_index_list, MGMT_READ_UNCONF_INDEX_LIST_SIZE,
HCI_MGMT_NO_HDEV |
HCI_MGMT_UNTRUSTED },
{ read_config_info, MGMT_READ_CONFIG_INFO_SIZE,
HCI_MGMT_UNCONFIGURED |
HCI_MGMT_UNTRUSTED },
{ set_external_config, MGMT_SET_EXTERNAL_CONFIG_SIZE,
HCI_MGMT_UNCONFIGURED },
{ set_public_address, MGMT_SET_PUBLIC_ADDRESS_SIZE,
HCI_MGMT_UNCONFIGURED },
{ start_service_discovery, MGMT_START_SERVICE_DISCOVERY_SIZE,
HCI_MGMT_VAR_LEN },
{ read_local_oob_ext_data, MGMT_READ_LOCAL_OOB_EXT_DATA_SIZE },
{ read_ext_index_list, MGMT_READ_EXT_INDEX_LIST_SIZE,
HCI_MGMT_NO_HDEV |
HCI_MGMT_UNTRUSTED },
{ read_adv_features, MGMT_READ_ADV_FEATURES_SIZE },
{ add_advertising, MGMT_ADD_ADVERTISING_SIZE,
HCI_MGMT_VAR_LEN },
{ remove_advertising, MGMT_REMOVE_ADVERTISING_SIZE },
{ get_adv_size_info, MGMT_GET_ADV_SIZE_INFO_SIZE },
{ start_limited_discovery, MGMT_START_DISCOVERY_SIZE },
{ read_ext_controller_info,MGMT_READ_EXT_INFO_SIZE,
HCI_MGMT_UNTRUSTED },
{ set_appearance, MGMT_SET_APPEARANCE_SIZE },
{ get_phy_configuration, MGMT_GET_PHY_CONFIGURATION_SIZE },
{ set_phy_configuration, MGMT_SET_PHY_CONFIGURATION_SIZE },
{ set_blocked_keys, MGMT_OP_SET_BLOCKED_KEYS_SIZE,
HCI_MGMT_VAR_LEN },
{ set_wideband_speech, MGMT_SETTING_SIZE },
{ read_controller_cap, MGMT_READ_CONTROLLER_CAP_SIZE,
HCI_MGMT_UNTRUSTED },
{ read_exp_features_info, MGMT_READ_EXP_FEATURES_INFO_SIZE,
HCI_MGMT_UNTRUSTED |
HCI_MGMT_HDEV_OPTIONAL },
{ set_exp_feature, MGMT_SET_EXP_FEATURE_SIZE,
HCI_MGMT_VAR_LEN |
HCI_MGMT_HDEV_OPTIONAL },
{ read_def_system_config, MGMT_READ_DEF_SYSTEM_CONFIG_SIZE,
HCI_MGMT_UNTRUSTED },
{ set_def_system_config, MGMT_SET_DEF_SYSTEM_CONFIG_SIZE,
HCI_MGMT_VAR_LEN },
{ read_def_runtime_config, MGMT_READ_DEF_RUNTIME_CONFIG_SIZE,
HCI_MGMT_UNTRUSTED },
{ set_def_runtime_config, MGMT_SET_DEF_RUNTIME_CONFIG_SIZE,
HCI_MGMT_VAR_LEN },
Bluetooth: Add get/set device flags mgmt op Add the get device flags and set device flags mgmt ops and the device flags changed event. Their behavior is described in detail in mgmt-api.txt in bluez. Sample btmon trace when a HID device is added (trimmed to 75 chars): @ MGMT Command: Unknown (0x0050) plen 11 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 ........... @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Command Compl.. (0x0001) plen 10 {0x0001} [hci0] 18:06:14.98 Unknown (0x0050) plen 7 Status: Success (0x00) 90 c5 13 cd f3 cd 02 ....... @ MGMT Command: Add Device (0x0033) plen 8 {0x0001} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0004} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0003} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Device Added (0x001a) plen 8 {0x0002} [hci0] 18:06:14.98 LE Address: CD:F3:CD:13:C5:90 (Static) Action: Auto-connect remote device (0x02) @ MGMT Event: Unknown (0x002a) plen 15 {0x0004} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0003} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0002} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... @ MGMT Event: Unknown (0x002a) plen 15 {0x0001} [hci0] 18:06:14.98 90 c5 13 cd f3 cd 02 01 00 00 00 01 00 00 00 ............... Signed-off-by: Abhishek Pandit-Subedi <abhishekpandit@chromium.org> Reviewed-by: Alain Michaud <alainm@chromium.org> Signed-off-by: Marcel Holtmann <marcel@holtmann.org> Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
2020-06-17 14:39:11 +00:00
{ get_device_flags, MGMT_GET_DEVICE_FLAGS_SIZE },
{ set_device_flags, MGMT_SET_DEVICE_FLAGS_SIZE },
{ read_adv_mon_features, MGMT_READ_ADV_MONITOR_FEATURES_SIZE },
{ add_adv_patterns_monitor,MGMT_ADD_ADV_PATTERNS_MONITOR_SIZE,
HCI_MGMT_VAR_LEN },
{ remove_adv_monitor, MGMT_REMOVE_ADV_MONITOR_SIZE },
{ add_ext_adv_params, MGMT_ADD_EXT_ADV_PARAMS_MIN_SIZE,
HCI_MGMT_VAR_LEN },
{ add_ext_adv_data, MGMT_ADD_EXT_ADV_DATA_SIZE,
HCI_MGMT_VAR_LEN },
{ add_adv_patterns_monitor_rssi,
MGMT_ADD_ADV_PATTERNS_MONITOR_RSSI_SIZE,
HCI_MGMT_VAR_LEN },
{ set_mesh, MGMT_SET_MESH_RECEIVER_SIZE,
HCI_MGMT_VAR_LEN },
{ mesh_features, MGMT_MESH_READ_FEATURES_SIZE },
{ mesh_send, MGMT_MESH_SEND_SIZE,
HCI_MGMT_VAR_LEN },
{ mesh_send_cancel, MGMT_MESH_SEND_CANCEL_SIZE },
};
void mgmt_index_added(struct hci_dev *hdev)
{
struct mgmt_ev_ext_index ev;
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
return;
if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
mgmt_index_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0,
HCI_MGMT_UNCONF_INDEX_EVENTS);
ev.type = 0x01;
} else {
mgmt_index_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0,
HCI_MGMT_INDEX_EVENTS);
ev.type = 0x00;
}
ev.bus = hdev->bus;
mgmt_index_event(MGMT_EV_EXT_INDEX_ADDED, hdev, &ev, sizeof(ev),
HCI_MGMT_EXT_INDEX_EVENTS);
}
void mgmt_index_removed(struct hci_dev *hdev)
{
struct mgmt_ev_ext_index ev;
u8 status = MGMT_STATUS_INVALID_INDEX;
if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
return;
mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
if (hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
mgmt_index_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0,
HCI_MGMT_UNCONF_INDEX_EVENTS);
ev.type = 0x01;
} else {
mgmt_index_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0,
HCI_MGMT_INDEX_EVENTS);
ev.type = 0x00;
}
ev.bus = hdev->bus;
mgmt_index_event(MGMT_EV_EXT_INDEX_REMOVED, hdev, &ev, sizeof(ev),
HCI_MGMT_EXT_INDEX_EVENTS);
/* Cancel any remaining timed work */
if (!hci_dev_test_flag(hdev, HCI_MGMT))
return;
cancel_delayed_work_sync(&hdev->discov_off);
cancel_delayed_work_sync(&hdev->service_cache);
cancel_delayed_work_sync(&hdev->rpa_expired);
}
void mgmt_power_on(struct hci_dev *hdev, int err)
{
struct cmd_lookup match = { NULL, hdev };
bt_dev_dbg(hdev, "err %d", err);
hci_dev_lock(hdev);
if (!err) {
restart_le_actions(hdev);
Bluetooth: hci_sync: Enable advertising when LL privacy is enabled This enables advertising when LL privacy is enabled and changes the command sequence when resolving list is updated to also account for when advertising is enabled using the following sequence: If there are devices to scan: Disable Scanning -> Update Accept List -> use_ll_privacy((Disable Advertising) -> Disable Resolving List -> Update Resolving List -> Enable Resolving List -> (Enable Advertising)) -> Enable Scanning Otherwise: Disable Scanning Errors during the Update Accept List stage are handled gracefully by restoring any previous state (e.g. advertising) and disabling the use of accept list as either accept list or resolving list could not be updated. Tested with: mgmt-tester -s "LL Privacy" Test Summary ------------ LL Privacy - Add Device 1 (Add to WL) Passed LL Privacy - Add Device 2 (Add to RL) Passed LL Privacy - Add Device 3 (Enable RL) Passed LL Privacy - Add Device 4 (2 Devices to WL) Passed LL Privacy - Add Device 5 (2 Devices to RL) Passed LL Privacy - Add Device 6 (RL is full) Passed LL Privacy - Add Device 7 (WL is full) Passed LL Privacy - Add Device 8 (Disable Adv) Passed LL Privacy - Add Device 9 (Multi Adv) Passed LL Privacy - Add Device 10 (Multi Dev and Multi Adv) Passed LL Privacy - Remove Device 1 (Remove from WL) Passed LL Privacy - Remove Device 2 (Remove from RL) Passed LL Privacy - Remove Device 3 (Disable RL) Passed LL Privacy - Remove Device 4 (Disable Adv) Passed LL Privacy - Remove Device 5 (Multi Adv) Passed LL Privacy - Start Discovery 1 (Disable RL) Passed LL Privacy - Start Discovery 2 (Disable RL) Passed Total: 18, Passed: 18 (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-27 23:58:42 +00:00
hci_update_passive_scan(hdev);
}
mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
new_settings(hdev, match.sk);
if (match.sk)
sock_put(match.sk);
hci_dev_unlock(hdev);
}
void __mgmt_power_off(struct hci_dev *hdev)
{
struct cmd_lookup match = { NULL, hdev };
u8 status, zero_cod[] = { 0, 0, 0 };
mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match);
/* If the power off is because of hdev unregistration let
* use the appropriate INVALID_INDEX status. Otherwise use
* NOT_POWERED. We cover both scenarios here since later in
* mgmt_index_removed() any hci_conn callbacks will have already
* been triggered, potentially causing misleading DISCONNECTED
* status responses.
*/
if (hci_dev_test_flag(hdev, HCI_UNREGISTER))
status = MGMT_STATUS_INVALID_INDEX;
else
status = MGMT_STATUS_NOT_POWERED;
mgmt_pending_foreach(0, hdev, cmd_complete_rsp, &status);
if (memcmp(hdev->dev_class, zero_cod, sizeof(zero_cod)) != 0) {
mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev,
zero_cod, sizeof(zero_cod),
HCI_MGMT_DEV_CLASS_EVENTS, NULL);
ext_info_changed(hdev, NULL);
}
new_settings(hdev, match.sk);
if (match.sk)
sock_put(match.sk);
}
void mgmt_set_powered_failed(struct hci_dev *hdev, int err)
{
struct mgmt_pending_cmd *cmd;
u8 status;
cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
if (!cmd)
return;
if (err == -ERFKILL)
status = MGMT_STATUS_RFKILLED;
else
status = MGMT_STATUS_FAILED;
mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_POWERED, status);
mgmt_pending_remove(cmd);
}
void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key,
bool persistent)
{
struct mgmt_ev_new_link_key ev;
memset(&ev, 0, sizeof(ev));
ev.store_hint = persistent;
bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Bluetooth: MGMT/SMP: Fix address type when using SMP over BREDR/LE If two Bluetooth devices both support BR/EDR and BLE, and also support Secure Connections, then they only need to pair once. The LTK generated during the LE pairing process may be converted into a BR/EDR link key for BR/EDR transport, and conversely, a link key generated during the BR/EDR SSP pairing process can be converted into an LTK for LE transport. Hence, the link type of the link key and LTK is not fixed, they can be either an LE LINK or an ACL LINK. Currently, in the mgmt_new_irk/ltk/crsk/link_key functions, the link type is fixed, which could lead to incorrect address types being reported to the application layer. Therefore, it is necessary to add link_type/addr_type to the smp_irk/ltk/crsk and link_key, to ensure the generation of the correct address type. SMP over BREDR: Before Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) After Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) SMP over LE: Before Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5F:5C:07:37:47:D5 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) After Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5E:03:1C:00:38:21 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 Store hint: Yes (0x01) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) Cc: stable@vger.kernel.org Signed-off-by: Xiao Yao <xiaoyao@rock-chips.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-12-11 16:27:18 +00:00
ev.key.addr.type = link_to_bdaddr(key->link_type, key->bdaddr_type);
ev.key.type = key->type;
memcpy(ev.key.val, key->val, HCI_LINK_KEY_SIZE);
ev.key.pin_len = key->pin_len;
mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL);
}
static u8 mgmt_ltk_type(struct smp_ltk *ltk)
{
switch (ltk->type) {
case SMP_LTK:
case SMP_LTK_RESPONDER:
if (ltk->authenticated)
return MGMT_LTK_AUTHENTICATED;
return MGMT_LTK_UNAUTHENTICATED;
case SMP_LTK_P256:
if (ltk->authenticated)
return MGMT_LTK_P256_AUTH;
return MGMT_LTK_P256_UNAUTH;
case SMP_LTK_P256_DEBUG:
return MGMT_LTK_P256_DEBUG;
}
return MGMT_LTK_UNAUTHENTICATED;
}
void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent)
{
struct mgmt_ev_new_long_term_key ev;
memset(&ev, 0, sizeof(ev));
/* Devices using resolvable or non-resolvable random addresses
* without providing an identity resolving key don't require
* to store long term keys. Their addresses will change the
* next time around.
*
* Only when a remote device provides an identity address
* make sure the long term key is stored. If the remote
* identity is known, the long term keys are internally
* mapped to the identity address. So allow static random
* and public addresses here.
*/
if (key->bdaddr_type == ADDR_LE_DEV_RANDOM &&
(key->bdaddr.b[5] & 0xc0) != 0xc0)
ev.store_hint = 0x00;
else
ev.store_hint = persistent;
bacpy(&ev.key.addr.bdaddr, &key->bdaddr);
Bluetooth: MGMT/SMP: Fix address type when using SMP over BREDR/LE If two Bluetooth devices both support BR/EDR and BLE, and also support Secure Connections, then they only need to pair once. The LTK generated during the LE pairing process may be converted into a BR/EDR link key for BR/EDR transport, and conversely, a link key generated during the BR/EDR SSP pairing process can be converted into an LTK for LE transport. Hence, the link type of the link key and LTK is not fixed, they can be either an LE LINK or an ACL LINK. Currently, in the mgmt_new_irk/ltk/crsk/link_key functions, the link type is fixed, which could lead to incorrect address types being reported to the application layer. Therefore, it is necessary to add link_type/addr_type to the smp_irk/ltk/crsk and link_key, to ensure the generation of the correct address type. SMP over BREDR: Before Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) After Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) SMP over LE: Before Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5F:5C:07:37:47:D5 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) After Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5E:03:1C:00:38:21 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 Store hint: Yes (0x01) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) Cc: stable@vger.kernel.org Signed-off-by: Xiao Yao <xiaoyao@rock-chips.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-12-11 16:27:18 +00:00
ev.key.addr.type = link_to_bdaddr(key->link_type, key->bdaddr_type);
ev.key.type = mgmt_ltk_type(key);
ev.key.enc_size = key->enc_size;
ev.key.ediv = key->ediv;
ev.key.rand = key->rand;
if (key->type == SMP_LTK)
ev.key.initiator = 1;
/* Make sure we copy only the significant bytes based on the
* encryption key size, and set the rest of the value to zeroes.
*/
memcpy(ev.key.val, key->val, key->enc_size);
memset(ev.key.val + key->enc_size, 0,
sizeof(ev.key.val) - key->enc_size);
mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL);
}
void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk, bool persistent)
{
struct mgmt_ev_new_irk ev;
memset(&ev, 0, sizeof(ev));
ev.store_hint = persistent;
bacpy(&ev.rpa, &irk->rpa);
bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr);
Bluetooth: MGMT/SMP: Fix address type when using SMP over BREDR/LE If two Bluetooth devices both support BR/EDR and BLE, and also support Secure Connections, then they only need to pair once. The LTK generated during the LE pairing process may be converted into a BR/EDR link key for BR/EDR transport, and conversely, a link key generated during the BR/EDR SSP pairing process can be converted into an LTK for LE transport. Hence, the link type of the link key and LTK is not fixed, they can be either an LE LINK or an ACL LINK. Currently, in the mgmt_new_irk/ltk/crsk/link_key functions, the link type is fixed, which could lead to incorrect address types being reported to the application layer. Therefore, it is necessary to add link_type/addr_type to the smp_irk/ltk/crsk and link_key, to ensure the generation of the correct address type. SMP over BREDR: Before Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) After Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) SMP over LE: Before Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5F:5C:07:37:47:D5 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) After Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5E:03:1C:00:38:21 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 Store hint: Yes (0x01) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) Cc: stable@vger.kernel.org Signed-off-by: Xiao Yao <xiaoyao@rock-chips.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-12-11 16:27:18 +00:00
ev.irk.addr.type = link_to_bdaddr(irk->link_type, irk->addr_type);
memcpy(ev.irk.val, irk->val, sizeof(irk->val));
mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL);
}
void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
bool persistent)
{
struct mgmt_ev_new_csrk ev;
memset(&ev, 0, sizeof(ev));
/* Devices using resolvable or non-resolvable random addresses
* without providing an identity resolving key don't require
* to store signature resolving keys. Their addresses will change
* the next time around.
*
* Only when a remote device provides an identity address
* make sure the signature resolving key is stored. So allow
* static random and public addresses here.
*/
if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM &&
(csrk->bdaddr.b[5] & 0xc0) != 0xc0)
ev.store_hint = 0x00;
else
ev.store_hint = persistent;
bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr);
Bluetooth: MGMT/SMP: Fix address type when using SMP over BREDR/LE If two Bluetooth devices both support BR/EDR and BLE, and also support Secure Connections, then they only need to pair once. The LTK generated during the LE pairing process may be converted into a BR/EDR link key for BR/EDR transport, and conversely, a link key generated during the BR/EDR SSP pairing process can be converted into an LTK for LE transport. Hence, the link type of the link key and LTK is not fixed, they can be either an LE LINK or an ACL LINK. Currently, in the mgmt_new_irk/ltk/crsk/link_key functions, the link type is fixed, which could lead to incorrect address types being reported to the application layer. Therefore, it is necessary to add link_type/addr_type to the smp_irk/ltk/crsk and link_key, to ensure the generation of the correct address type. SMP over BREDR: Before Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) After Fix: > ACL Data RX: Handle 11 flags 0x02 dlen 12 BR/EDR SMP: Identity Address Information (0x09) len 7 Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 00:00:00:00:00:00 (Non-Resolvable) BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) SMP over LE: Before Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5F:5C:07:37:47:D5 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 BR/EDR Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) After Fix: @ MGMT Event: New Identity Resolving Key (0x0018) plen 30 Random address: 5E:03:1C:00:38:21 (Resolvable) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) @ MGMT Event: New Long Term Key (0x000a) plen 37 LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated key from P-256 (0x03) @ MGMT Event: New Link Key (0x0009) plen 26 Store hint: Yes (0x01) LE Address: F8:7D:76:F2:12:F3 (OUI F8-7D-76) Key type: Authenticated Combination key from P-256 (0x08) Cc: stable@vger.kernel.org Signed-off-by: Xiao Yao <xiaoyao@rock-chips.com> Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2023-12-11 16:27:18 +00:00
ev.key.addr.type = link_to_bdaddr(csrk->link_type, csrk->bdaddr_type);
ev.key.type = csrk->type;
memcpy(ev.key.val, csrk->val, sizeof(csrk->val));
mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL);
}
void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 bdaddr_type, u8 store_hint, u16 min_interval,
u16 max_interval, u16 latency, u16 timeout)
{
struct mgmt_ev_new_conn_param ev;
if (!hci_is_identity_address(bdaddr, bdaddr_type))
return;
memset(&ev, 0, sizeof(ev));
bacpy(&ev.addr.bdaddr, bdaddr);
ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type);
ev.store_hint = store_hint;
ev.min_interval = cpu_to_le16(min_interval);
ev.max_interval = cpu_to_le16(max_interval);
ev.latency = cpu_to_le16(latency);
ev.timeout = cpu_to_le16(timeout);
mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL);
}
void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn,
u8 *name, u8 name_len)
{
struct sk_buff *skb;
struct mgmt_ev_device_connected *ev;
u16 eir_len = 0;
u32 flags = 0;
if (test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
return;
/* allocate buff for LE or BR/EDR adv */
if (conn->le_adv_data_len > 0)
skb = mgmt_alloc_skb(hdev, MGMT_EV_DEVICE_CONNECTED,
sizeof(*ev) + conn->le_adv_data_len);
else
skb = mgmt_alloc_skb(hdev, MGMT_EV_DEVICE_CONNECTED,
sizeof(*ev) + (name ? eir_precalc_len(name_len) : 0) +
eir_precalc_len(sizeof(conn->dev_class)));
ev = skb_put(skb, sizeof(*ev));
bacpy(&ev->addr.bdaddr, &conn->dst);
ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type);
if (conn->out)
flags |= MGMT_DEV_FOUND_INITIATED_CONN;
ev->flags = __cpu_to_le32(flags);
/* We must ensure that the EIR Data fields are ordered and
* unique. Keep it simple for now and avoid the problem by not
* adding any BR/EDR data to the LE adv.
*/
if (conn->le_adv_data_len > 0) {
skb_put_data(skb, conn->le_adv_data, conn->le_adv_data_len);
eir_len = conn->le_adv_data_len;
} else {
if (name)
eir_len += eir_skb_put_data(skb, EIR_NAME_COMPLETE, name, name_len);
if (memcmp(conn->dev_class, "\0\0\0", sizeof(conn->dev_class)))
eir_len += eir_skb_put_data(skb, EIR_CLASS_OF_DEV,
conn->dev_class, sizeof(conn->dev_class));
}
ev->eir_len = cpu_to_le16(eir_len);
mgmt_event_skb(skb, NULL);
}
static void disconnect_rsp(struct mgmt_pending_cmd *cmd, void *data)
{
struct sock **sk = data;
cmd->cmd_complete(cmd, 0);
*sk = cmd->sk;
sock_hold(*sk);
mgmt_pending_remove(cmd);
}
static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data)
{
struct hci_dev *hdev = data;
struct mgmt_cp_unpair_device *cp = cmd->param;
device_unpaired(hdev, &cp->addr.bdaddr, cp->addr.type, cmd->sk);
cmd->cmd_complete(cmd, 0);
mgmt_pending_remove(cmd);
}
bool mgmt_powering_down(struct hci_dev *hdev)
{
struct mgmt_pending_cmd *cmd;
struct mgmt_mode *cp;
if (hci_dev_test_flag(hdev, HCI_POWERING_DOWN))
return true;
cmd = pending_find(MGMT_OP_SET_POWERED, hdev);
if (!cmd)
return false;
cp = cmd->param;
if (!cp->val)
return true;
return false;
}
void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u8 reason,
bool mgmt_connected)
{
struct mgmt_ev_device_disconnected ev;
struct sock *sk = NULL;
if (!mgmt_connected)
return;
if (link_type != ACL_LINK && link_type != LE_LINK)
return;
mgmt_pending_foreach(MGMT_OP_DISCONNECT, hdev, disconnect_rsp, &sk);
bacpy(&ev.addr.bdaddr, bdaddr);
ev.addr.type = link_to_bdaddr(link_type, addr_type);
ev.reason = reason;
/* Report disconnects due to suspend */
if (hdev->suspended)
ev.reason = MGMT_DEV_DISCONN_LOCAL_HOST_SUSPEND;
mgmt_event(MGMT_EV_DEVICE_DISCONNECTED, hdev, &ev, sizeof(ev), sk);
if (sk)
sock_put(sk);
mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
hdev);
}
void mgmt_disconnect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u8 status)
{
u8 bdaddr_type = link_to_bdaddr(link_type, addr_type);
struct mgmt_cp_disconnect *cp;
struct mgmt_pending_cmd *cmd;
mgmt_pending_foreach(MGMT_OP_UNPAIR_DEVICE, hdev, unpair_device_rsp,
hdev);
cmd = pending_find(MGMT_OP_DISCONNECT, hdev);
if (!cmd)
return;
cp = cmd->param;
if (bacmp(bdaddr, &cp->addr.bdaddr))
return;
if (cp->addr.type != bdaddr_type)
return;
cmd->cmd_complete(cmd, mgmt_status(status));
mgmt_pending_remove(cmd);
}
void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 status)
{
struct mgmt_ev_connect_failed ev;
bacpy(&ev.addr.bdaddr, bdaddr);
ev.addr.type = link_to_bdaddr(link_type, addr_type);
ev.status = mgmt_status(status);
mgmt_event(MGMT_EV_CONNECT_FAILED, hdev, &ev, sizeof(ev), NULL);
}
void mgmt_pin_code_request(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 secure)
{
struct mgmt_ev_pin_code_request ev;
bacpy(&ev.addr.bdaddr, bdaddr);
ev.addr.type = BDADDR_BREDR;
ev.secure = secure;
mgmt_event(MGMT_EV_PIN_CODE_REQUEST, hdev, &ev, sizeof(ev), NULL);
}
void mgmt_pin_code_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 status)
{
struct mgmt_pending_cmd *cmd;
cmd = pending_find(MGMT_OP_PIN_CODE_REPLY, hdev);
if (!cmd)
return;
cmd->cmd_complete(cmd, mgmt_status(status));
mgmt_pending_remove(cmd);
}
void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 status)
{
struct mgmt_pending_cmd *cmd;
cmd = pending_find(MGMT_OP_PIN_CODE_NEG_REPLY, hdev);
if (!cmd)
return;
cmd->cmd_complete(cmd, mgmt_status(status));
mgmt_pending_remove(cmd);
}
int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u32 value,
u8 confirm_hint)
{
struct mgmt_ev_user_confirm_request ev;
bt_dev_dbg(hdev, "bdaddr %pMR", bdaddr);
bacpy(&ev.addr.bdaddr, bdaddr);
ev.addr.type = link_to_bdaddr(link_type, addr_type);
ev.confirm_hint = confirm_hint;
ev.value = cpu_to_le32(value);
return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev),
NULL);
}
int mgmt_user_passkey_request(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type)
{
struct mgmt_ev_user_passkey_request ev;
bt_dev_dbg(hdev, "bdaddr %pMR", bdaddr);
bacpy(&ev.addr.bdaddr, bdaddr);
ev.addr.type = link_to_bdaddr(link_type, addr_type);
return mgmt_event(MGMT_EV_USER_PASSKEY_REQUEST, hdev, &ev, sizeof(ev),
NULL);
}
static int user_pairing_resp_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u8 status,
u8 opcode)
{
struct mgmt_pending_cmd *cmd;
cmd = pending_find(opcode, hdev);
if (!cmd)
return -ENOENT;
cmd->cmd_complete(cmd, mgmt_status(status));
mgmt_pending_remove(cmd);
return 0;
}
int mgmt_user_confirm_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u8 status)
{
return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
status, MGMT_OP_USER_CONFIRM_REPLY);
}
int mgmt_user_confirm_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u8 status)
{
return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
status,
MGMT_OP_USER_CONFIRM_NEG_REPLY);
}
int mgmt_user_passkey_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u8 status)
{
return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
status, MGMT_OP_USER_PASSKEY_REPLY);
}
int mgmt_user_passkey_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u8 status)
{
return user_pairing_resp_complete(hdev, bdaddr, link_type, addr_type,
status,
MGMT_OP_USER_PASSKEY_NEG_REPLY);
}
int mgmt_user_passkey_notify(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 link_type, u8 addr_type, u32 passkey,
u8 entered)
{
struct mgmt_ev_passkey_notify ev;
bt_dev_dbg(hdev, "bdaddr %pMR", bdaddr);
bacpy(&ev.addr.bdaddr, bdaddr);
ev.addr.type = link_to_bdaddr(link_type, addr_type);
ev.passkey = __cpu_to_le32(passkey);
ev.entered = entered;
return mgmt_event(MGMT_EV_PASSKEY_NOTIFY, hdev, &ev, sizeof(ev), NULL);
}
void mgmt_auth_failed(struct hci_conn *conn, u8 hci_status)
{
struct mgmt_ev_auth_failed ev;
struct mgmt_pending_cmd *cmd;
u8 status = mgmt_status(hci_status);
bacpy(&ev.addr.bdaddr, &conn->dst);
ev.addr.type = link_to_bdaddr(conn->type, conn->dst_type);
ev.status = status;
cmd = find_pairing(conn);
mgmt_event(MGMT_EV_AUTH_FAILED, conn->hdev, &ev, sizeof(ev),
cmd ? cmd->sk : NULL);
if (cmd) {
cmd->cmd_complete(cmd, status);
mgmt_pending_remove(cmd);
}
}
void mgmt_auth_enable_complete(struct hci_dev *hdev, u8 status)
{
struct cmd_lookup match = { NULL, hdev };
bool changed;
if (status) {
u8 mgmt_err = mgmt_status(status);
mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev,
cmd_status_rsp, &mgmt_err);
return;
}
if (test_bit(HCI_AUTH, &hdev->flags))
changed = !hci_dev_test_and_set_flag(hdev, HCI_LINK_SECURITY);
else
changed = hci_dev_test_and_clear_flag(hdev, HCI_LINK_SECURITY);
mgmt_pending_foreach(MGMT_OP_SET_LINK_SECURITY, hdev, settings_rsp,
&match);
if (changed)
new_settings(hdev, match.sk);
if (match.sk)
sock_put(match.sk);
}
static void sk_lookup(struct mgmt_pending_cmd *cmd, void *data)
{
struct cmd_lookup *match = data;
if (match->sk == NULL) {
match->sk = cmd->sk;
sock_hold(match->sk);
}
}
void mgmt_set_class_of_dev_complete(struct hci_dev *hdev, u8 *dev_class,
u8 status)
{
struct cmd_lookup match = { NULL, hdev, mgmt_status(status) };
mgmt_pending_foreach(MGMT_OP_SET_DEV_CLASS, hdev, sk_lookup, &match);
mgmt_pending_foreach(MGMT_OP_ADD_UUID, hdev, sk_lookup, &match);
mgmt_pending_foreach(MGMT_OP_REMOVE_UUID, hdev, sk_lookup, &match);
if (!status) {
mgmt_limited_event(MGMT_EV_CLASS_OF_DEV_CHANGED, hdev, dev_class,
3, HCI_MGMT_DEV_CLASS_EVENTS, NULL);
ext_info_changed(hdev, NULL);
}
if (match.sk)
sock_put(match.sk);
}
void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status)
{
struct mgmt_cp_set_local_name ev;
struct mgmt_pending_cmd *cmd;
if (status)
return;
memset(&ev, 0, sizeof(ev));
memcpy(ev.name, name, HCI_MAX_NAME_LENGTH);
memcpy(ev.short_name, hdev->short_name, HCI_MAX_SHORT_NAME_LENGTH);
cmd = pending_find(MGMT_OP_SET_LOCAL_NAME, hdev);
if (!cmd) {
memcpy(hdev->dev_name, name, sizeof(hdev->dev_name));
/* If this is a HCI command related to powering on the
* HCI dev don't send any mgmt signals.
*/
if (hci_dev_test_flag(hdev, HCI_POWERING_DOWN))
return;
if (pending_find(MGMT_OP_SET_POWERED, hdev))
return;
}
mgmt_limited_event(MGMT_EV_LOCAL_NAME_CHANGED, hdev, &ev, sizeof(ev),
HCI_MGMT_LOCAL_NAME_EVENTS, cmd ? cmd->sk : NULL);
ext_info_changed(hdev, cmd ? cmd->sk : NULL);
}
static inline bool has_uuid(u8 *uuid, u16 uuid_count, u8 (*uuids)[16])
{
int i;
for (i = 0; i < uuid_count; i++) {
if (!memcmp(uuid, uuids[i], 16))
return true;
}
return false;
}
static bool eir_has_uuids(u8 *eir, u16 eir_len, u16 uuid_count, u8 (*uuids)[16])
{
u16 parsed = 0;
while (parsed < eir_len) {
u8 field_len = eir[0];
u8 uuid[16];
int i;
if (field_len == 0)
break;
if (eir_len - parsed < field_len + 1)
break;
switch (eir[1]) {
case EIR_UUID16_ALL:
case EIR_UUID16_SOME:
for (i = 0; i + 3 <= field_len; i += 2) {
memcpy(uuid, bluetooth_base_uuid, 16);
uuid[13] = eir[i + 3];
uuid[12] = eir[i + 2];
if (has_uuid(uuid, uuid_count, uuids))
return true;
}
break;
case EIR_UUID32_ALL:
case EIR_UUID32_SOME:
for (i = 0; i + 5 <= field_len; i += 4) {
memcpy(uuid, bluetooth_base_uuid, 16);
uuid[15] = eir[i + 5];
uuid[14] = eir[i + 4];
uuid[13] = eir[i + 3];
uuid[12] = eir[i + 2];
if (has_uuid(uuid, uuid_count, uuids))
return true;
}
break;
case EIR_UUID128_ALL:
case EIR_UUID128_SOME:
for (i = 0; i + 17 <= field_len; i += 16) {
memcpy(uuid, eir + i + 2, 16);
if (has_uuid(uuid, uuid_count, uuids))
return true;
}
break;
}
parsed += field_len + 1;
eir += field_len + 1;
}
return false;
}
static bool is_filter_match(struct hci_dev *hdev, s8 rssi, u8 *eir,
u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len)
{
/* If a RSSI threshold has been specified, and
* HCI_QUIRK_STRICT_DUPLICATE_FILTER is not set, then all results with
* a RSSI smaller than the RSSI threshold will be dropped. If the quirk
* is set, let it through for further processing, as we might need to
* restart the scan.
*
* For BR/EDR devices (pre 1.2) providing no RSSI during inquiry,
* the results are also dropped.
*/
if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
(rssi == HCI_RSSI_INVALID ||
(rssi < hdev->discovery.rssi &&
!test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks))))
return false;
if (hdev->discovery.uuid_count != 0) {
/* If a list of UUIDs is provided in filter, results with no
* matching UUID should be dropped.
*/
if (!eir_has_uuids(eir, eir_len, hdev->discovery.uuid_count,
hdev->discovery.uuids) &&
!eir_has_uuids(scan_rsp, scan_rsp_len,
hdev->discovery.uuid_count,
hdev->discovery.uuids))
return false;
}
/* If duplicate filtering does not report RSSI changes, then restart
* scanning to ensure updated result with updated RSSI values.
*/
if (test_bit(HCI_QUIRK_STRICT_DUPLICATE_FILTER, &hdev->quirks)) {
/* Validate RSSI value against the RSSI threshold once more. */
if (hdev->discovery.rssi != HCI_RSSI_INVALID &&
rssi < hdev->discovery.rssi)
return false;
}
return true;
}
void mgmt_adv_monitor_device_lost(struct hci_dev *hdev, u16 handle,
bdaddr_t *bdaddr, u8 addr_type)
{
struct mgmt_ev_adv_monitor_device_lost ev;
ev.monitor_handle = cpu_to_le16(handle);
bacpy(&ev.addr.bdaddr, bdaddr);
ev.addr.type = addr_type;
mgmt_event(MGMT_EV_ADV_MONITOR_DEVICE_LOST, hdev, &ev, sizeof(ev),
NULL);
}
static void mgmt_send_adv_monitor_device_found(struct hci_dev *hdev,
struct sk_buff *skb,
struct sock *skip_sk,
u16 handle)
{
struct sk_buff *advmon_skb;
size_t advmon_skb_len;
__le16 *monitor_handle;
if (!skb)
return;
advmon_skb_len = (sizeof(struct mgmt_ev_adv_monitor_device_found) -
sizeof(struct mgmt_ev_device_found)) + skb->len;
advmon_skb = mgmt_alloc_skb(hdev, MGMT_EV_ADV_MONITOR_DEVICE_FOUND,
advmon_skb_len);
if (!advmon_skb)
return;
/* ADV_MONITOR_DEVICE_FOUND is similar to DEVICE_FOUND event except
* that it also has 'monitor_handle'. Make a copy of DEVICE_FOUND and
* store monitor_handle of the matched monitor.
*/
monitor_handle = skb_put(advmon_skb, sizeof(*monitor_handle));
*monitor_handle = cpu_to_le16(handle);
skb_put_data(advmon_skb, skb->data, skb->len);
mgmt_event_skb(advmon_skb, skip_sk);
}
static void mgmt_adv_monitor_device_found(struct hci_dev *hdev,
bdaddr_t *bdaddr, bool report_device,
struct sk_buff *skb,
struct sock *skip_sk)
{
struct monitored_device *dev, *tmp;
bool matched = false;
bool notified = false;
/* We have received the Advertisement Report because:
* 1. the kernel has initiated active discovery
* 2. if not, we have pend_le_reports > 0 in which case we are doing
* passive scanning
* 3. if none of the above is true, we have one or more active
* Advertisement Monitor
*
* For case 1 and 2, report all advertisements via MGMT_EV_DEVICE_FOUND
* and report ONLY one advertisement per device for the matched Monitor
* via MGMT_EV_ADV_MONITOR_DEVICE_FOUND event.
*
* For case 3, since we are not active scanning and all advertisements
* received are due to a matched Advertisement Monitor, report all
* advertisements ONLY via MGMT_EV_ADV_MONITOR_DEVICE_FOUND event.
*/
if (report_device && !hdev->advmon_pend_notify) {
mgmt_event_skb(skb, skip_sk);
return;
}
hdev->advmon_pend_notify = false;
list_for_each_entry_safe(dev, tmp, &hdev->monitored_devices, list) {
if (!bacmp(&dev->bdaddr, bdaddr)) {
matched = true;
if (!dev->notified) {
mgmt_send_adv_monitor_device_found(hdev, skb,
skip_sk,
dev->handle);
notified = true;
dev->notified = true;
}
}
if (!dev->notified)
hdev->advmon_pend_notify = true;
}
if (!report_device &&
((matched && !notified) || !msft_monitor_supported(hdev))) {
/* Handle 0 indicates that we are not active scanning and this
* is a subsequent advertisement report for an already matched
* Advertisement Monitor or the controller offloading support
* is not available.
*/
mgmt_send_adv_monitor_device_found(hdev, skb, skip_sk, 0);
}
if (report_device)
mgmt_event_skb(skb, skip_sk);
else
kfree_skb(skb);
}
static void mesh_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type, s8 rssi, u32 flags, u8 *eir,
u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len,
u64 instant)
{
struct sk_buff *skb;
struct mgmt_ev_mesh_device_found *ev;
int i, j;
if (!hdev->mesh_ad_types[0])
goto accepted;
/* Scan for requested AD types */
if (eir_len > 0) {
for (i = 0; i + 1 < eir_len; i += eir[i] + 1) {
for (j = 0; j < sizeof(hdev->mesh_ad_types); j++) {
if (!hdev->mesh_ad_types[j])
break;
if (hdev->mesh_ad_types[j] == eir[i + 1])
goto accepted;
}
}
}
if (scan_rsp_len > 0) {
for (i = 0; i + 1 < scan_rsp_len; i += scan_rsp[i] + 1) {
for (j = 0; j < sizeof(hdev->mesh_ad_types); j++) {
if (!hdev->mesh_ad_types[j])
break;
if (hdev->mesh_ad_types[j] == scan_rsp[i + 1])
goto accepted;
}
}
}
return;
accepted:
skb = mgmt_alloc_skb(hdev, MGMT_EV_MESH_DEVICE_FOUND,
sizeof(*ev) + eir_len + scan_rsp_len);
if (!skb)
return;
ev = skb_put(skb, sizeof(*ev));
bacpy(&ev->addr.bdaddr, bdaddr);
ev->addr.type = link_to_bdaddr(LE_LINK, addr_type);
ev->rssi = rssi;
ev->flags = cpu_to_le32(flags);
ev->instant = cpu_to_le64(instant);
if (eir_len > 0)
/* Copy EIR or advertising data into event */
skb_put_data(skb, eir, eir_len);
if (scan_rsp_len > 0)
/* Append scan response data to event */
skb_put_data(skb, scan_rsp, scan_rsp_len);
ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
mgmt_event_skb(skb, NULL);
}
void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, u8 *dev_class, s8 rssi, u32 flags,
u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len,
u64 instant)
{
struct sk_buff *skb;
struct mgmt_ev_device_found *ev;
bool report_device = hci_discovery_active(hdev);
if (hci_dev_test_flag(hdev, HCI_MESH) && link_type == LE_LINK)
mesh_device_found(hdev, bdaddr, addr_type, rssi, flags,
eir, eir_len, scan_rsp, scan_rsp_len,
instant);
/* Don't send events for a non-kernel initiated discovery. With
* LE one exception is if we have pend_le_reports > 0 in which
* case we're doing passive scanning and want these events.
*/
if (!hci_discovery_active(hdev)) {
if (link_type == ACL_LINK)
return;
if (link_type == LE_LINK && !list_empty(&hdev->pend_le_reports))
report_device = true;
else if (!hci_is_adv_monitoring(hdev))
return;
}
if (hdev->discovery.result_filtering) {
/* We are using service discovery */
if (!is_filter_match(hdev, rssi, eir, eir_len, scan_rsp,
scan_rsp_len))
return;
}
if (hdev->discovery.limited) {
/* Check for limited discoverable bit */
if (dev_class) {
if (!(dev_class[1] & 0x20))
return;
} else {
u8 *flags = eir_get_data(eir, eir_len, EIR_FLAGS, NULL);
if (!flags || !(flags[0] & LE_AD_LIMITED))
return;
}
}
/* Allocate skb. The 5 extra bytes are for the potential CoD field */
skb = mgmt_alloc_skb(hdev, MGMT_EV_DEVICE_FOUND,
sizeof(*ev) + eir_len + scan_rsp_len + 5);
if (!skb)
return;
ev = skb_put(skb, sizeof(*ev));
/* In case of device discovery with BR/EDR devices (pre 1.2), the
* RSSI value was reported as 0 when not available. This behavior
* is kept when using device discovery. This is required for full
* backwards compatibility with the API.
*
* However when using service discovery, the value 127 will be
* returned when the RSSI is not available.
*/
if (rssi == HCI_RSSI_INVALID && !hdev->discovery.report_invalid_rssi &&
link_type == ACL_LINK)
rssi = 0;
bacpy(&ev->addr.bdaddr, bdaddr);
ev->addr.type = link_to_bdaddr(link_type, addr_type);
ev->rssi = rssi;
ev->flags = cpu_to_le32(flags);
if (eir_len > 0)
/* Copy EIR or advertising data into event */
skb_put_data(skb, eir, eir_len);
if (dev_class && !eir_get_data(eir, eir_len, EIR_CLASS_OF_DEV, NULL)) {
u8 eir_cod[5];
eir_len += eir_append_data(eir_cod, 0, EIR_CLASS_OF_DEV,
dev_class, 3);
skb_put_data(skb, eir_cod, sizeof(eir_cod));
}
if (scan_rsp_len > 0)
/* Append scan response data to event */
skb_put_data(skb, scan_rsp, scan_rsp_len);
ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len);
mgmt_adv_monitor_device_found(hdev, bdaddr, report_device, skb, NULL);
}
void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
u8 addr_type, s8 rssi, u8 *name, u8 name_len)
{
struct sk_buff *skb;
struct mgmt_ev_device_found *ev;
u16 eir_len = 0;
u32 flags = 0;
skb = mgmt_alloc_skb(hdev, MGMT_EV_DEVICE_FOUND,
sizeof(*ev) + (name ? eir_precalc_len(name_len) : 0));
ev = skb_put(skb, sizeof(*ev));
bacpy(&ev->addr.bdaddr, bdaddr);
ev->addr.type = link_to_bdaddr(link_type, addr_type);
ev->rssi = rssi;
if (name)
eir_len += eir_skb_put_data(skb, EIR_NAME_COMPLETE, name, name_len);
else
flags = MGMT_DEV_FOUND_NAME_REQUEST_FAILED;
ev->eir_len = cpu_to_le16(eir_len);
ev->flags = cpu_to_le32(flags);
mgmt_event_skb(skb, NULL);
}
void mgmt_discovering(struct hci_dev *hdev, u8 discovering)
{
struct mgmt_ev_discovering ev;
bt_dev_dbg(hdev, "discovering %u", discovering);
memset(&ev, 0, sizeof(ev));
ev.type = hdev->discovery.type;
ev.discovering = discovering;
mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL);
}
void mgmt_suspending(struct hci_dev *hdev, u8 state)
{
struct mgmt_ev_controller_suspend ev;
ev.suspend_state = state;
mgmt_event(MGMT_EV_CONTROLLER_SUSPEND, hdev, &ev, sizeof(ev), NULL);
}
void mgmt_resuming(struct hci_dev *hdev, u8 reason, bdaddr_t *bdaddr,
u8 addr_type)
{
struct mgmt_ev_controller_resume ev;
ev.wake_reason = reason;
if (bdaddr) {
bacpy(&ev.addr.bdaddr, bdaddr);
ev.addr.type = addr_type;
} else {
memset(&ev.addr, 0, sizeof(ev.addr));
}
mgmt_event(MGMT_EV_CONTROLLER_RESUME, hdev, &ev, sizeof(ev), NULL);
}
static struct hci_mgmt_chan chan = {
.channel = HCI_CHANNEL_CONTROL,
.handler_count = ARRAY_SIZE(mgmt_handlers),
.handlers = mgmt_handlers,
.hdev_init = mgmt_init_hdev,
};
int mgmt_init(void)
{
return hci_mgmt_chan_register(&chan);
}
void mgmt_exit(void)
{
hci_mgmt_chan_unregister(&chan);
}
void mgmt_cleanup(struct sock *sk)
{
struct mgmt_mesh_tx *mesh_tx;
struct hci_dev *hdev;
read_lock(&hci_dev_list_lock);
list_for_each_entry(hdev, &hci_dev_list, list) {
do {
mesh_tx = mgmt_mesh_next(hdev, sk);
if (mesh_tx)
mesh_send_complete(hdev, mesh_tx, true);
} while (mesh_tx);
}
read_unlock(&hci_dev_list_lock);
}