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>
This commit is contained in:
Родитель
a1fc7535ec
Коммит
4c54bf2b09
|
@ -720,6 +720,27 @@ struct mgmt_rp_set_exp_feature {
|
|||
#define MGMT_OP_SET_DEF_RUNTIME_CONFIG 0x004e
|
||||
#define MGMT_SET_DEF_RUNTIME_CONFIG_SIZE 0
|
||||
|
||||
#define MGMT_OP_GET_DEVICE_FLAGS 0x004F
|
||||
#define MGMT_GET_DEVICE_FLAGS_SIZE 7
|
||||
struct mgmt_cp_get_device_flags {
|
||||
struct mgmt_addr_info addr;
|
||||
} __packed;
|
||||
struct mgmt_rp_get_device_flags {
|
||||
struct mgmt_addr_info addr;
|
||||
__le32 supported_flags;
|
||||
__le32 current_flags;
|
||||
} __packed;
|
||||
|
||||
#define MGMT_OP_SET_DEVICE_FLAGS 0x0050
|
||||
#define MGMT_SET_DEVICE_FLAGS_SIZE 11
|
||||
struct mgmt_cp_set_device_flags {
|
||||
struct mgmt_addr_info addr;
|
||||
__le32 current_flags;
|
||||
} __packed;
|
||||
struct mgmt_rp_set_device_flags {
|
||||
struct mgmt_addr_info addr;
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_CMD_COMPLETE 0x0001
|
||||
struct mgmt_ev_cmd_complete {
|
||||
__le16 opcode;
|
||||
|
@ -951,3 +972,10 @@ struct mgmt_ev_exp_feature_changed {
|
|||
__u8 uuid[16];
|
||||
__le32 flags;
|
||||
} __packed;
|
||||
|
||||
#define MGMT_EV_DEVICE_FLAGS_CHANGED 0x002a
|
||||
struct mgmt_ev_device_flags_changed {
|
||||
struct mgmt_addr_info addr;
|
||||
__le32 supported_flags;
|
||||
__le32 current_flags;
|
||||
} __packed;
|
||||
|
|
|
@ -116,6 +116,8 @@ static const u16 mgmt_commands[] = {
|
|||
MGMT_OP_SET_DEF_SYSTEM_CONFIG,
|
||||
MGMT_OP_READ_DEF_RUNTIME_CONFIG,
|
||||
MGMT_OP_SET_DEF_RUNTIME_CONFIG,
|
||||
MGMT_OP_GET_DEVICE_FLAGS,
|
||||
MGMT_OP_SET_DEVICE_FLAGS,
|
||||
};
|
||||
|
||||
static const u16 mgmt_events[] = {
|
||||
|
@ -156,6 +158,7 @@ static const u16 mgmt_events[] = {
|
|||
MGMT_EV_EXT_INFO_CHANGED,
|
||||
MGMT_EV_PHY_CONFIGURATION_CHANGED,
|
||||
MGMT_EV_EXP_FEATURE_CHANGED,
|
||||
MGMT_EV_DEVICE_FLAGS_CHANGED,
|
||||
};
|
||||
|
||||
static const u16 mgmt_untrusted_commands[] = {
|
||||
|
@ -3856,6 +3859,120 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
|
|||
MGMT_STATUS_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
#define SUPPORTED_DEVICE_FLAGS() ((1U << HCI_CONN_FLAG_MAX) - 1)
|
||||
|
||||
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 = SUPPORTED_DEVICE_FLAGS();
|
||||
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);
|
||||
|
||||
if (cp->addr.type == BDADDR_BREDR) {
|
||||
br_params = hci_bdaddr_list_lookup_with_flags(&hdev->whitelist,
|
||||
&cp->addr.bdaddr,
|
||||
cp->addr.type);
|
||||
if (!br_params)
|
||||
goto done;
|
||||
|
||||
current_flags = br_params->current_flags;
|
||||
} else {
|
||||
params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
|
||||
le_addr_type(cp->addr.type));
|
||||
|
||||
if (!params)
|
||||
goto done;
|
||||
|
||||
current_flags = params->current_flags;
|
||||
}
|
||||
|
||||
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:
|
||||
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 = SUPPORTED_DEVICE_FLAGS();
|
||||
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,
|
||||
__le32_to_cpu(current_flags));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (cp->addr.type == BDADDR_BREDR) {
|
||||
br_params = hci_bdaddr_list_lookup_with_flags(&hdev->whitelist,
|
||||
&cp->addr.bdaddr,
|
||||
cp->addr.type);
|
||||
|
||||
if (br_params) {
|
||||
br_params->current_flags = current_flags;
|
||||
status = MGMT_STATUS_SUCCESS;
|
||||
} else {
|
||||
bt_dev_warn(hdev, "No such BR/EDR device %pMR (0x%x)",
|
||||
&cp->addr.bdaddr, cp->addr.type);
|
||||
}
|
||||
} else {
|
||||
params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
|
||||
le_addr_type(cp->addr.type));
|
||||
if (params) {
|
||||
params->current_flags = current_flags;
|
||||
status = MGMT_STATUS_SUCCESS;
|
||||
} else {
|
||||
bt_dev_warn(hdev, "No such LE device %pMR (0x%x)",
|
||||
&cp->addr.bdaddr,
|
||||
le_addr_type(cp->addr.type));
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
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 read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
|
||||
u16 opcode, struct sk_buff *skb)
|
||||
{
|
||||
|
@ -5973,7 +6090,9 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
|
|||
{
|
||||
struct mgmt_cp_add_device *cp = data;
|
||||
u8 auto_conn, addr_type;
|
||||
struct hci_conn_params *params;
|
||||
int err;
|
||||
u32 current_flags = 0;
|
||||
|
||||
bt_dev_dbg(hdev, "sock %p", sk);
|
||||
|
||||
|
@ -6041,12 +6160,19 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
|
|||
MGMT_STATUS_FAILED, &cp->addr,
|
||||
sizeof(cp->addr));
|
||||
goto unlock;
|
||||
} else {
|
||||
params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr,
|
||||
addr_type);
|
||||
if (params)
|
||||
current_flags = params->current_flags;
|
||||
}
|
||||
|
||||
hci_update_background_scan(hdev);
|
||||
|
||||
added:
|
||||
device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
|
||||
device_flags_changed(NULL, hdev, &cp->addr.bdaddr, cp->addr.type,
|
||||
SUPPORTED_DEVICE_FLAGS(), current_flags);
|
||||
|
||||
err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
|
||||
MGMT_STATUS_SUCCESS, &cp->addr,
|
||||
|
@ -7313,6 +7439,8 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
|
|||
HCI_MGMT_UNTRUSTED },
|
||||
{ set_def_runtime_config, MGMT_SET_DEF_RUNTIME_CONFIG_SIZE,
|
||||
HCI_MGMT_VAR_LEN },
|
||||
{ get_device_flags, MGMT_GET_DEVICE_FLAGS_SIZE },
|
||||
{ set_device_flags, MGMT_SET_DEVICE_FLAGS_SIZE },
|
||||
};
|
||||
|
||||
void mgmt_index_added(struct hci_dev *hdev)
|
||||
|
|
Загрузка…
Ссылка в новой задаче