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 | |
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>
-rw-r--r-- | include/net/bluetooth/bluetooth.h | 1 | ||||
-rw-r--r-- | include/net/bluetooth/hci_core.h | 2 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 10 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 11 |
4 files changed, 22 insertions, 2 deletions
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index ed6e9552252e..591fee7d0060 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h | |||
@@ -266,6 +266,7 @@ typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status); | |||
266 | 266 | ||
267 | struct hci_req_ctrl { | 267 | struct hci_req_ctrl { |
268 | bool start; | 268 | bool start; |
269 | u8 event; | ||
269 | hci_req_complete_t complete; | 270 | hci_req_complete_t complete; |
270 | }; | 271 | }; |
271 | 272 | ||
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 755743d508aa..b85eefb230fd 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -1055,6 +1055,8 @@ struct hci_request { | |||
1055 | void hci_req_init(struct hci_request *req, struct hci_dev *hdev); | 1055 | void hci_req_init(struct hci_request *req, struct hci_dev *hdev); |
1056 | int hci_req_run(struct hci_request *req, hci_req_complete_t complete); | 1056 | int hci_req_run(struct hci_request *req, hci_req_complete_t complete); |
1057 | void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param); | 1057 | void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param); |
1058 | void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen, void *param, | ||
1059 | u8 event); | ||
1058 | void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status); | 1060 | void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status); |
1059 | 1061 | ||
1060 | struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen, | 1062 | struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen, |
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); |