aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2013-04-03 14:50:29 -0400
committerJohan Hedberg <johan.hedberg@intel.com>2013-04-04 12:16:08 -0400
commit02350a725f5bc44490c30a10e7e04a12a5ecd406 (patch)
tree243d09f74edf36d79d50db5d470d340c733f38b1 /net
parent75e84b7c522c6e07964cd1f5bf28535768a1e9fa (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.c10
-rw-r--r--net/bluetooth/hci_event.c11
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 */
2648void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void *param) 2648void 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
2678void 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 */
2676void *hci_sent_cmd_data(struct hci_dev *hdev, __u16 opcode) 2684void *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);