Skip to content

Commit f8e802a

Browse files
committed
Bluetooth: MGMT: Add initial implementation of MGMT_OP_HCI_CMD_SYNC
This adds the initial implementation of MGMT_OP_HCI_CMD_SYNC as documented in mgmt-api (BlueZ tree): Send HCI command and wait for event Command =========================================== Command Code: 0x005B Controller Index: <controller id> Command Parameters: Opcode (2 Octets) Event (1 Octet) Timeout (1 Octet) Parameter Length (2 Octets) Parameter (variable) Return Parameters: Response (1-variable Octets) This command may be used to send a HCI command and wait for an (optional) event. The HCI command is specified by the Opcode, any arbitrary is supported including vendor commands, but contrary to the like of Raw/User channel it is run as an HCI command send by the kernel since it uses its command synchronization thus it is possible to wait for a specific event as a response. Setting event to 0x00 will cause the command to wait for either HCI Command Status or HCI Command Complete. Timeout is specified in seconds, setting it to 0 will cause the default timeout to be used. Possible errors: Failed Invalid Parameters Signed-off-by: Luiz Augusto von Dentz <[email protected]>
1 parent 2918697 commit f8e802a

File tree

2 files changed

+70
-0
lines changed

2 files changed

+70
-0
lines changed

include/net/bluetooth/mgmt.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,16 @@ struct mgmt_cp_mesh_send_cancel {
878878
} __packed;
879879
#define MGMT_MESH_SEND_CANCEL_SIZE 1
880880

881+
#define MGMT_OP_HCI_CMD_SYNC 0x005B
882+
struct mgmt_cp_hci_cmd_sync {
883+
__le16 opcode;
884+
__u8 event;
885+
__u8 timeout;
886+
__le16 params_len;
887+
__u8 params[];
888+
} __packed;
889+
#define MGMT_HCI_CMD_SYNC_SIZE 6
890+
881891
#define MGMT_EV_CMD_COMPLETE 0x0001
882892
struct mgmt_ev_cmd_complete {
883893
__le16 opcode;

net/bluetooth/mgmt.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ static const u16 mgmt_commands[] = {
132132
MGMT_OP_MESH_READ_FEATURES,
133133
MGMT_OP_MESH_SEND,
134134
MGMT_OP_MESH_SEND_CANCEL,
135+
MGMT_OP_HCI_CMD_SYNC,
135136
};
136137

137138
static const u16 mgmt_events[] = {
@@ -2515,6 +2516,64 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)
25152516
return err;
25162517
}
25172518

2519+
static int send_hci_cmd_sync(struct hci_dev *hdev, void *data)
2520+
{
2521+
struct mgmt_pending_cmd *cmd = data;
2522+
struct mgmt_cp_hci_cmd_sync *cp = cmd->param;
2523+
struct sk_buff *skb;
2524+
2525+
skb = __hci_cmd_sync_ev(hdev, le16_to_cpu(cp->opcode),
2526+
le16_to_cpu(cp->params_len), cp->params,
2527+
cp->event, cp->timeout ?
2528+
msecs_to_jiffies(cp->timeout * 1000) :
2529+
HCI_CMD_TIMEOUT);
2530+
if (IS_ERR(skb)) {
2531+
mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_HCI_CMD_SYNC,
2532+
mgmt_status(PTR_ERR(skb)));
2533+
goto done;
2534+
}
2535+
2536+
mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_HCI_CMD_SYNC, 0,
2537+
skb->data, skb->len);
2538+
2539+
kfree_skb(skb);
2540+
2541+
done:
2542+
mgmt_pending_free(cmd);
2543+
2544+
return 0;
2545+
}
2546+
2547+
static int mgmt_hci_cmd_sync(struct sock *sk, struct hci_dev *hdev,
2548+
void *data, u16 len)
2549+
{
2550+
struct mgmt_cp_hci_cmd_sync *cp = data;
2551+
struct mgmt_pending_cmd *cmd;
2552+
int err;
2553+
2554+
if (len < sizeof(*cp))
2555+
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_HCI_CMD_SYNC,
2556+
MGMT_STATUS_INVALID_PARAMS);
2557+
2558+
hci_dev_lock(hdev);
2559+
cmd = mgmt_pending_new(sk, MGMT_OP_HCI_CMD_SYNC, hdev, data, len);
2560+
if (!cmd)
2561+
err = -ENOMEM;
2562+
else
2563+
err = hci_cmd_sync_queue(hdev, send_hci_cmd_sync, cmd, NULL);
2564+
2565+
if (err < 0) {
2566+
err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_HCI_CMD_SYNC,
2567+
MGMT_STATUS_FAILED);
2568+
2569+
if (cmd)
2570+
mgmt_pending_free(cmd);
2571+
}
2572+
2573+
hci_dev_unlock(hdev);
2574+
return err;
2575+
}
2576+
25182577
/* This is a helper function to test for pending mgmt commands that can
25192578
* cause CoD or EIR HCI commands. We can only allow one such pending
25202579
* mgmt command at a time since otherwise we cannot easily track what
@@ -9371,6 +9430,7 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
93719430
{ mesh_send, MGMT_MESH_SEND_SIZE,
93729431
HCI_MGMT_VAR_LEN },
93739432
{ mesh_send_cancel, MGMT_MESH_SEND_CANCEL_SIZE },
9433+
{ mgmt_hci_cmd_sync, MGMT_HCI_CMD_SYNC_SIZE, HCI_MGMT_VAR_LEN },
93749434
};
93759435

93769436
void mgmt_index_added(struct hci_dev *hdev)

0 commit comments

Comments
 (0)