diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2013-04-03 14:50:29 -0400 |
---|---|---|
committer | Johan Hedberg <johan.hedberg@intel.com> | 2013-04-04 12:16:08 -0400 |
commit | 02350a725f5bc44490c30a10e7e04a12a5ecd406 (patch) | |
tree | 243d09f74edf36d79d50db5d470d340c733f38b1 /net | |
parent | 75e84b7c522c6e07964cd1f5bf28535768a1e9fa (diff) |
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: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/hci_core.c | 10 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 11 |
2 files changed, 19 insertions, 2 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 8b2d543fb143..7f1413cae2cb 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -2645,7 +2645,8 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param) | |||
2645 | } | 2645 | } |
2646 | 2646 | ||
2647 | /* Queue a command to an asynchronous HCI request */ | 2647 | /* Queue a command to an asynchronous HCI request */ |
2648 | void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param) | 2648 | void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void *param, |
2649 | u8 event) | ||
2649 | { | 2650 | { |
2650 | struct hci_dev *hdev = req->hdev; | 2651 | struct hci_dev *hdev = req->hdev; |
2651 | struct sk_buff *skb; | 2652 | struct sk_buff *skb; |
@@ -2669,9 +2670,16 @@ void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param) | |||
2669 | if (skb_queue_empty(&req->cmd_q)) | 2670 | if (skb_queue_empty(&req->cmd_q)) |
2670 | bt_cb(skb)->req.start = true; | 2671 | bt_cb(skb)->req.start = true; |
2671 | 2672 | ||
2673 | bt_cb(skb)->req.event = event; | ||
2674 | |||
2672 | skb_queue_tail(&req->cmd_q, skb); | 2675 | skb_queue_tail(&req->cmd_q, skb); |
2673 | } | 2676 | } |
2674 | 2677 | ||
2678 | void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param) | ||
2679 | { | ||
2680 | hci_req_add_ev(req, opcode, plen, param, 0); | ||
2681 | } | ||
2682 | |||
2675 | /* Get data from the previously sent command */ | 2683 | /* Get data from the previously sent command */ |
2676 | void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode) | 2684 | void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode) |
2677 | { | 2685 | { |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index ed0efb7255b0..0a2b128d2cc9 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -2463,7 +2463,9 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2463 | if (opcode != HCI_OP_NOP) | 2463 | if (opcode != HCI_OP_NOP) |
2464 | del_timer(&hdev->cmd_timer); | 2464 | del_timer(&hdev->cmd_timer); |
2465 | 2465 | ||
2466 | hci_req_cmd_complete(hdev, opcode, ev->status); | 2466 | if (ev->status || |
2467 | (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event)) | ||
2468 | hci_req_cmd_complete(hdev, opcode, ev->status); | ||
2467 | 2469 | ||
2468 | if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { | 2470 | if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) { |
2469 | atomic_set(&hdev->cmd_cnt, 1); | 2471 | atomic_set(&hdev->cmd_cnt, 1); |
@@ -3713,6 +3715,13 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
3713 | 3715 | ||
3714 | skb_pull(skb, HCI_EVENT_HDR_SIZE); | 3716 | skb_pull(skb, HCI_EVENT_HDR_SIZE); |
3715 | 3717 | ||
3718 | if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) { | ||
3719 | struct hci_command_hdr *hdr = (void *) hdev->sent_cmd->data; | ||
3720 | u16 opcode = __le16_to_cpu(hdr->opcode); | ||
3721 | |||
3722 | hci_req_cmd_complete(hdev, opcode, 0); | ||
3723 | } | ||
3724 | |||
3716 | switch (event) { | 3725 | switch (event) { |
3717 | case HCI_EV_INQUIRY_COMPLETE: | 3726 | case HCI_EV_INQUIRY_COMPLETE: |
3718 | hci_inquiry_complete_evt(hdev, skb); | 3727 | hci_inquiry_complete_evt(hdev, skb); |