* [PATCH 1/2] Bluetooth: Add support for custom event terminated commands
2013-04-03 19:11 [PATCH 0/2] Bluetooth: Add custom HCI command termination support Johan Hedberg
@ 2013-04-03 19:11 ` Johan Hedberg
2013-04-03 19:25 ` Anderson Lizardo
2013-04-03 19:11 ` [PATCH 2/2] Bluetooth: Add __hci_cmd_sync_ev function Johan Hedberg
1 sibling, 1 reply; 5+ messages in thread
From: Johan Hedberg @ 2013-04-03 19:11 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
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.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/bluetooth.h | 1 +
include/net/bluetooth/hci_core.h | 2 ++
net/bluetooth/hci_core.c | 10 +++++++++-
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 ed6e955..591fee7 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);
struct hci_req_ctrl {
bool start;
+ u8 event;
hci_req_complete_t complete;
};
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 064b057..8ee1381 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -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,
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 689c959..6f71e4c 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2622,7 +2622,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;
@@ -2646,9 +2647,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)
{
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 24906fb..5b922a0 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)
if (opcode != HCI_OP_NOP)
del_timer(&hdev->cmd_timer);
- hci_req_cmd_complete(hdev, opcode, ev->status);
+ 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)) {
atomic_set(&hdev->cmd_cnt, 1);
@@ -3709,6 +3711,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);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH 2/2] Bluetooth: Add __hci_cmd_sync_ev function
2013-04-03 19:11 [PATCH 0/2] Bluetooth: Add custom HCI command termination support Johan Hedberg
2013-04-03 19:11 ` [PATCH 1/2] Bluetooth: Add support for custom event terminated commands Johan Hedberg
@ 2013-04-03 19:11 ` Johan Hedberg
1 sibling, 0 replies; 5+ messages in thread
From: Johan Hedberg @ 2013-04-03 19:11 UTC (permalink / raw)
To: linux-bluetooth
From: Johan Hedberg <johan.hedberg@intel.com>
This patch adds a __hci_cmd_sync_ev function, analogous to
__hci_cmd_sync except that it also takes an event parameter to indicate
that the command completes with a special event instead of command
complete. Internally this new function takes advantage of the
hci_req_add_ev function introduced in the previous patch.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
---
include/net/bluetooth/hci_core.h | 2 ++
net/bluetooth/hci_core.c | 22 +++++++++++++++++-----
2 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 8ee1381..be695e6 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1061,6 +1061,8 @@ 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,
void *param, u32 timeout);
+struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
+ void *param, u8 event, u32 timeout);
int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param);
void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags);
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 6f71e4c..d181992 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -79,7 +79,7 @@ static void hci_req_cancel(struct hci_dev *hdev, int err)
}
}
-struct sk_buff *hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode)
+struct sk_buff *hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 event)
{
struct hci_ev_cmd_complete *ev;
struct hci_event_hdr *hdr;
@@ -100,6 +100,12 @@ struct sk_buff *hci_get_cmd_complete(struct hci_dev *hdev, u16 opcode)
hdr = (void *) skb->data;
skb_pull(skb, HCI_EVENT_HDR_SIZE);
+ if (event) {
+ if (hdr->evt != event)
+ goto failed;
+ return skb;
+ }
+
if (hdr->evt != HCI_EV_CMD_COMPLETE) {
BT_DBG("Last event is not cmd complete (0x%2.2x)", hdr->evt);
goto failed;
@@ -119,8 +125,8 @@ failed:
return ERR_PTR(-ENODATA);
}
-struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
- void *param, u32 timeout)
+struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
+ void *param, u8 event, u32 timeout)
{
DECLARE_WAITQUEUE(wait, current);
struct hci_request req;
@@ -130,7 +136,7 @@ struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
hci_req_init(&req, hdev);
- hci_req_add(&req, opcode, plen, param);
+ hci_req_add_ev(&req, opcode, plen, param, event);
hdev->req_status = HCI_REQ_PEND;
@@ -169,7 +175,13 @@ struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
if (err < 0)
return ERR_PTR(err);
- return hci_get_cmd_complete(hdev, opcode);
+ return hci_get_cmd_complete(hdev, opcode, event);
+}
+
+struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
+ void *param, u32 timeout)
+{
+ return __hci_cmd_sync_ev(hdev, opcode, plen, param, 0, timeout);
}
/* Execute request and wait for completion. */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 5+ messages in thread