Skip to content

Commit

Permalink
Bluetooth: Configure codec for HFP offload use case
Browse files Browse the repository at this point in the history
For HFP offload use case, codec needs to be configured
before opening SCO connection. This patch sends
HCI_CONFIGURE_DATA_PATH command to configure doec before
opening SCO connection.

Signed-off-by: Kiran K <kiran.k@intel.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
  • Loading branch information
Kiran K authored and Luiz Augusto von Dentz committed Sep 7, 2021
1 parent b2af264 commit 9798fbd
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 0 deletions.
8 changes: 8 additions & 0 deletions include/net/bluetooth/hci.h
Original file line number Diff line number Diff line change
Expand Up @@ -1286,6 +1286,14 @@ struct hci_rp_read_local_oob_ext_data {
__u8 rand256[16];
} __packed;

#define HCI_CONFIGURE_DATA_PATH 0x0c83
struct hci_op_configure_data_path {
__u8 direction;
__u8 data_path_id;
__u8 vnd_len;
__u8 vnd_data[];
} __packed;

#define HCI_OP_READ_LOCAL_VERSION 0x1001
struct hci_rp_read_local_version {
__u8 status;
Expand Down
3 changes: 3 additions & 0 deletions include/net/bluetooth/hci_core.h
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,9 @@ struct hci_dev {
bool (*prevent_wake)(struct hci_dev *hdev);
int (*set_quality_report)(struct hci_dev *hdev, bool enable);
int (*get_data_path_id)(struct hci_dev *hdev, __u8 *data_path);
int (*get_codec_config_data)(struct hci_dev *hdev, __u8 type,
struct bt_codec *codec, __u8 *vnd_len,
__u8 **vnd_data);
};

#define HCI_PHY_HANDLE(handle) (handle & 0xff)
Expand Down
4 changes: 4 additions & 0 deletions net/bluetooth/hci_conn.c
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,10 @@ static bool hci_enhanced_setup_sync_conn(struct hci_conn *conn, __u16 handle)

bt_dev_dbg(hdev, "hcon %p", conn);

/* for offload use case, codec needs to configured before opening SCO */
if (conn->codec.data_path)
hci_req_configure_datapath(hdev, &conn->codec);

conn->state = BT_CONNECT;
conn->out = true;

Expand Down
47 changes: 47 additions & 0 deletions net/bluetooth/hci_request.c
Original file line number Diff line number Diff line change
Expand Up @@ -3327,6 +3327,53 @@ bool hci_req_stop_discovery(struct hci_request *req)
return ret;
}

static void config_data_path_complete(struct hci_dev *hdev, u8 status,
u16 opcode)
{
bt_dev_dbg(hdev, "status %u", status);
}

int hci_req_configure_datapath(struct hci_dev *hdev, struct bt_codec *codec)
{
struct hci_request req;
int err;
__u8 vnd_len, *vnd_data = NULL;
struct hci_op_configure_data_path *cmd = NULL;

hci_req_init(&req, hdev);

err = hdev->get_codec_config_data(hdev, ESCO_LINK, codec, &vnd_len,
&vnd_data);
if (err < 0)
goto error;

cmd = kzalloc(sizeof(*cmd) + vnd_len, GFP_KERNEL);
if (!cmd) {
err = -ENOMEM;
goto error;
}

err = hdev->get_data_path_id(hdev, &cmd->data_path_id);
if (err < 0)
goto error;

cmd->vnd_len = vnd_len;
memcpy(cmd->vnd_data, vnd_data, vnd_len);

cmd->direction = 0x00;
hci_req_add(&req, HCI_CONFIGURE_DATA_PATH, sizeof(*cmd) + vnd_len, cmd);

cmd->direction = 0x01;
hci_req_add(&req, HCI_CONFIGURE_DATA_PATH, sizeof(*cmd) + vnd_len, cmd);

err = hci_req_run(&req, config_data_path_complete);
error:

kfree(cmd);
kfree(vnd_data);
return err;
}

static int stop_discovery(struct hci_request *req, unsigned long opt)
{
hci_dev_lock(req->hdev);
Expand Down
2 changes: 2 additions & 0 deletions net/bluetooth/hci_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ void __hci_req_update_class(struct hci_request *req);
/* Returns true if HCI commands were queued */
bool hci_req_stop_discovery(struct hci_request *req);

int hci_req_configure_datapath(struct hci_dev *hdev, struct bt_codec *codec);

static inline void hci_req_update_scan(struct hci_dev *hdev)
{
queue_work(hdev->req_workqueue, &hdev->scan_update);
Expand Down

0 comments on commit 9798fbd

Please sign in to comment.