forked from Minki/linux
Bluetooth: hci_sync: Convert MGMT_OP_READ_LOCAL_OOB_DATA
New functions: hci_read_local_oob_data_sync This function requires all of the data from the cmd cmplt event to be passed up to the caller via the skb. mgmt-tester paths: Read Local OOB Data - Not powered Read Local OOB Data - Legacy pairing Read Local OOB Data - Success SSP Read Local OOB Data - Success SC Signed-off-by: Brian Gix <brian.gix@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
d81a494c43
commit
f892244b05
@ -78,6 +78,8 @@ int hci_update_scan_sync(struct hci_dev *hdev);
|
||||
int hci_write_le_host_supported_sync(struct hci_dev *hdev, u8 le, u8 simul);
|
||||
int hci_remove_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance,
|
||||
struct sock *sk);
|
||||
struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev, bool ext,
|
||||
struct sock *sk);
|
||||
|
||||
int hci_dev_open_sync(struct hci_dev *hdev);
|
||||
int hci_dev_close_sync(struct hci_dev *hdev);
|
||||
|
@ -1703,6 +1703,15 @@ static int hci_resume_advertising_sync(struct hci_dev *hdev)
|
||||
return err;
|
||||
}
|
||||
|
||||
struct sk_buff *hci_read_local_oob_data_sync(struct hci_dev *hdev,
|
||||
bool extended, struct sock *sk)
|
||||
{
|
||||
u16 opcode = extended ? HCI_OP_READ_LOCAL_OOB_EXT_DATA :
|
||||
HCI_OP_READ_LOCAL_OOB_DATA;
|
||||
|
||||
return __hci_cmd_sync_sk(hdev, opcode, 0, NULL, 0, HCI_CMD_TIMEOUT, sk);
|
||||
}
|
||||
|
||||
/* Device must not be scanning when updating the accept list.
|
||||
*
|
||||
* Update is done using the following sequence:
|
||||
|
@ -4793,28 +4793,33 @@ unlock:
|
||||
status);
|
||||
}
|
||||
|
||||
static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
|
||||
u16 opcode, struct sk_buff *skb)
|
||||
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;
|
||||
struct mgmt_pending_cmd *cmd = data;
|
||||
struct sk_buff *skb = cmd->skb;
|
||||
u8 status = mgmt_status(err);
|
||||
|
||||
bt_dev_dbg(hdev, "status %u", status);
|
||||
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]);
|
||||
}
|
||||
|
||||
cmd = pending_find(MGMT_OP_READ_LOCAL_OOB_DATA, hdev);
|
||||
if (!cmd)
|
||||
return;
|
||||
bt_dev_dbg(hdev, "status %d", status);
|
||||
|
||||
if (status || !skb) {
|
||||
mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA,
|
||||
status ? mgmt_status(status) : MGMT_STATUS_FAILED);
|
||||
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 (opcode == HCI_OP_READ_LOCAL_OOB_DATA) {
|
||||
if (!bredr_sc_enabled(hdev)) {
|
||||
struct hci_rp_read_local_oob_data *rp = (void *) skb->data;
|
||||
|
||||
if (skb->len < sizeof(*rp)) {
|
||||
@ -4849,14 +4854,31 @@ static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
|
||||
MGMT_STATUS_SUCCESS, &mgmt_rp, rp_size);
|
||||
|
||||
remove:
|
||||
mgmt_pending_remove(cmd);
|
||||
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;
|
||||
struct hci_request req;
|
||||
int err;
|
||||
|
||||
bt_dev_dbg(hdev, "sock %p", sk);
|
||||
@ -4881,22 +4903,20 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev,
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
cmd = mgmt_pending_add(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
|
||||
if (!cmd) {
|
||||
cmd = mgmt_pending_new(sk, MGMT_OP_READ_LOCAL_OOB_DATA, hdev, NULL, 0);
|
||||
if (!cmd)
|
||||
err = -ENOMEM;
|
||||
goto unlock;
|
||||
}
|
||||
|
||||
hci_req_init(&req, hdev);
|
||||
|
||||
if (bredr_sc_enabled(hdev))
|
||||
hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_EXT_DATA, 0, NULL);
|
||||
else
|
||||
hci_req_add(&req, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL);
|
||||
err = hci_cmd_sync_queue(hdev, read_local_oob_data_sync, cmd,
|
||||
read_local_oob_data_complete);
|
||||
|
||||
err = hci_req_run_skb(&req, read_local_oob_data_complete);
|
||||
if (err < 0)
|
||||
mgmt_pending_remove(cmd);
|
||||
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);
|
||||
|
@ -27,6 +27,7 @@ struct mgmt_pending_cmd {
|
||||
void *param;
|
||||
size_t param_len;
|
||||
struct sock *sk;
|
||||
struct sk_buff *skb;
|
||||
void *user_data;
|
||||
int (*cmd_complete)(struct mgmt_pending_cmd *cmd, u8 status);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user