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/bluetooth/hci_event.c | |
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/bluetooth/hci_event.c')
-rw-r--r-- | net/bluetooth/hci_event.c | 11 |
1 files changed, 10 insertions, 1 deletions
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); |