Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 02350a72 authored by Johan Hedberg's avatar Johan Hedberg
Browse files

Bluetooth: Add support for custom event terminated commands



This patch adds support for having commands within HCI requests that do
not result in a command complete but some other event. This is at least
needed for some vendor specific commands to be issued in the
hdev->setup() procecure, but might also be useful for other commands.

The way that the support is implemented is by extending the skb control
buffer to have a field to indicate that the command is expected to
terminate with a special event. After sending the command each received
event can then be compared against this field through hdev->sent_cmd.

Signed-off-by: default avatarJohan Hedberg <johan.hedberg@intel.com>
Acked-by: default avatarMarcel Holtmann <marcel@holtmann.org>
parent 75e84b7c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -266,6 +266,7 @@ typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status);

struct hci_req_ctrl {
	bool			start;
	u8			event;
	hci_req_complete_t	complete;
};

+2 −0
Original line number Diff line number Diff line
@@ -1055,6 +1055,8 @@ struct hci_request {
void hci_req_init(struct hci_request *req, struct hci_dev *hdev);
int hci_req_run(struct hci_request *req, hci_req_complete_t complete);
void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param);
void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void *param,
		    u8 event);
void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status);

struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
+9 −1
Original line number Diff line number Diff line
@@ -2645,7 +2645,8 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param)
}

/* Queue a command to an asynchronous HCI request */
void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param)
void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void *param,
		    u8 event)
{
	struct hci_dev *hdev = req->hdev;
	struct sk_buff *skb;
@@ -2669,9 +2670,16 @@ void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param)
	if (skb_queue_empty(&req->cmd_q))
		bt_cb(skb)->req.start = true;

	bt_cb(skb)->req.event = event;

	skb_queue_tail(&req->cmd_q, skb);
}

void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param)
{
	hci_req_add_ev(req, opcode, plen, param, 0);
}

/* Get data from the previously sent command */
void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode)
{
+10 −1
Original line number Diff line number Diff line
@@ -2463,6 +2463,8 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
	if (opcode != HCI_OP_NOP)
		del_timer(&hdev->cmd_timer);

	if (ev->status ||
	    (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event))
		hci_req_cmd_complete(hdev, opcode, ev->status);

	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
@@ -3713,6 +3715,13 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)

	skb_pull(skb, HCI_EVENT_HDR_SIZE);

	if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) {
		struct hci_command_hdr *hdr = (void *) hdev->sent_cmd->data;
		u16 opcode = __le16_to_cpu(hdr->opcode);

		hci_req_cmd_complete(hdev, opcode, 0);
	}

	switch (event) {
	case HCI_EV_INQUIRY_COMPLETE:
		hci_inquiry_complete_evt(hdev, skb);