Skip to content

Commit e621448

Browse files
Johan Hedbergholtmann
authored andcommitted
Bluetooth: Add second hci_request callback option for full skb
This patch adds a second possible callback for HCI requests where the callback will receive the full skb of the last successfully completed HCI command. This API is useful for cases where we want to use a request to read some data and the existing hci_event.c handlers do not store it e.g. in the hci_dev struct. The reason the patch is a bit bigger than just adding the new API is because the hci_req_cmd_complete() functions required some refactoring to enable it: now hci_req_cmd_complete() is simply used to request the callback pointers if any, and the actual calling of them happens from a single place at the end of hci_event_packet(). The reason for this is that we need to pass the original skb (without any skb_pull, etc modifications done to it) and it's simplest to keep track of it within the hci_event_packet() function. Signed-off-by: Johan Hedberg <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]>
1 parent 444c6dd commit e621448

File tree

5 files changed

+84
-44
lines changed

5 files changed

+84
-44
lines changed

include/net/bluetooth/bluetooth.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,11 +277,14 @@ struct l2cap_ctrl {
277277
struct hci_dev;
278278

279279
typedef void (*hci_req_complete_t)(struct hci_dev *hdev, u8 status, u16 opcode);
280+
typedef void (*hci_req_complete_skb_t)(struct hci_dev *hdev, u8 status,
281+
u16 opcode, struct sk_buff *skb);
280282

281283
struct req_ctrl {
282284
bool start;
283285
u8 event;
284286
hci_req_complete_t complete;
287+
hci_req_complete_skb_t complete_skb;
285288
};
286289

287290
struct bt_skb_cb {

net/bluetooth/hci_core.c

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4288,9 +4288,10 @@ static void hci_resend_last(struct hci_dev *hdev)
42884288
queue_work(hdev->workqueue, &hdev->cmd_work);
42894289
}
42904290

4291-
void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status)
4291+
void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status,
4292+
hci_req_complete_t *req_complete,
4293+
hci_req_complete_skb_t *req_complete_skb)
42924294
{
4293-
hci_req_complete_t req_complete = NULL;
42944295
struct sk_buff *skb;
42954296
unsigned long flags;
42964297

@@ -4322,18 +4323,14 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status)
43224323
* callback would be found in hdev->sent_cmd instead of the
43234324
* command queue (hdev->cmd_q).
43244325
*/
4325-
if (hdev->sent_cmd) {
4326-
req_complete = bt_cb(hdev->sent_cmd)->req.complete;
4327-
4328-
if (req_complete) {
4329-
/* We must set the complete callback to NULL to
4330-
* avoid calling the callback more than once if
4331-
* this function gets called again.
4332-
*/
4333-
bt_cb(hdev->sent_cmd)->req.complete = NULL;
4326+
if (bt_cb(hdev->sent_cmd)->req.complete) {
4327+
*req_complete = bt_cb(hdev->sent_cmd)->req.complete;
4328+
return;
4329+
}
43344330

4335-
goto call_complete;
4336-
}
4331+
if (bt_cb(hdev->sent_cmd)->req.complete_skb) {
4332+
*req_complete_skb = bt_cb(hdev->sent_cmd)->req.complete_skb;
4333+
return;
43374334
}
43384335

43394336
/* Remove all pending commands belonging to this request */
@@ -4344,14 +4341,11 @@ void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status)
43444341
break;
43454342
}
43464343

4347-
req_complete = bt_cb(skb)->req.complete;
4344+
*req_complete = bt_cb(skb)->req.complete;
4345+
*req_complete_skb = bt_cb(skb)->req.complete_skb;
43484346
kfree_skb(skb);
43494347
}
43504348
spin_unlock_irqrestore(&hdev->cmd_q.lock, flags);
4351-
4352-
call_complete:
4353-
if (req_complete)
4354-
req_complete(hdev, status, status ? opcode : HCI_OP_NOP);
43554349
}
43564350

43574351
static void hci_rx_work(struct work_struct *work)

net/bluetooth/hci_event.c

Lines changed: 52 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2731,17 +2731,19 @@ static void hci_remote_features_evt(struct hci_dev *hdev,
27312731
hci_dev_unlock(hdev);
27322732
}
27332733

2734-
static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
2734+
static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb,
2735+
u16 *opcode, u8 *status,
2736+
hci_req_complete_t *req_complete,
2737+
hci_req_complete_skb_t *req_complete_skb)
27352738
{
27362739
struct hci_ev_cmd_complete *ev = (void *) skb->data;
2737-
u8 status = skb->data[sizeof(*ev)];
2738-
__u16 opcode;
27392740

2740-
skb_pull(skb, sizeof(*ev));
2741+
*opcode = __le16_to_cpu(ev->opcode);
2742+
*status = skb->data[sizeof(*ev)];
27412743

2742-
opcode = __le16_to_cpu(ev->opcode);
2744+
skb_pull(skb, sizeof(*ev));
27432745

2744-
switch (opcode) {
2746+
switch (*opcode) {
27452747
case HCI_OP_INQUIRY_CANCEL:
27462748
hci_cc_inquiry_cancel(hdev, skb);
27472749
break;
@@ -3019,32 +3021,36 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb)
30193021
break;
30203022

30213023
default:
3022-
BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
3024+
BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
30233025
break;
30243026
}
30253027

3026-
if (opcode != HCI_OP_NOP)
3028+
if (*opcode != HCI_OP_NOP)
30273029
cancel_delayed_work(&hdev->cmd_timer);
30283030

30293031
if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags))
30303032
atomic_set(&hdev->cmd_cnt, 1);
30313033

3032-
hci_req_cmd_complete(hdev, opcode, status);
3034+
hci_req_cmd_complete(hdev, *opcode, *status, req_complete,
3035+
req_complete_skb);
30333036

30343037
if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
30353038
queue_work(hdev->workqueue, &hdev->cmd_work);
30363039
}
30373040

3038-
static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
3041+
static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb,
3042+
u16 *opcode, u8 *status,
3043+
hci_req_complete_t *req_complete,
3044+
hci_req_complete_skb_t *req_complete_skb)
30393045
{
30403046
struct hci_ev_cmd_status *ev = (void *) skb->data;
3041-
__u16 opcode;
30423047

30433048
skb_pull(skb, sizeof(*ev));
30443049

3045-
opcode = __le16_to_cpu(ev->opcode);
3050+
*opcode = __le16_to_cpu(ev->opcode);
3051+
*status = ev->status;
30463052

3047-
switch (opcode) {
3053+
switch (*opcode) {
30483054
case HCI_OP_INQUIRY:
30493055
hci_cs_inquiry(hdev, ev->status);
30503056
break;
@@ -3114,11 +3120,11 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
31143120
break;
31153121

31163122
default:
3117-
BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode);
3123+
BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode);
31183124
break;
31193125
}
31203126

3121-
if (opcode != HCI_OP_NOP)
3127+
if (*opcode != HCI_OP_NOP)
31223128
cancel_delayed_work(&hdev->cmd_timer);
31233129

31243130
if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags))
@@ -3132,7 +3138,8 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb)
31323138
*/
31333139
if (ev->status ||
31343140
(hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event))
3135-
hci_req_cmd_complete(hdev, opcode, ev->status);
3141+
hci_req_cmd_complete(hdev, *opcode, ev->status, req_complete,
3142+
req_complete_skb);
31363143

31373144
if (atomic_read(&hdev->cmd_cnt) && !skb_queue_empty(&hdev->cmd_q))
31383145
queue_work(hdev->workqueue, &hdev->cmd_work);
@@ -5039,7 +5046,11 @@ static void hci_chan_selected_evt(struct hci_dev *hdev, struct sk_buff *skb)
50395046
void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
50405047
{
50415048
struct hci_event_hdr *hdr = (void *) skb->data;
5042-
__u8 event = hdr->evt;
5049+
hci_req_complete_t req_complete = NULL;
5050+
hci_req_complete_skb_t req_complete_skb = NULL;
5051+
struct sk_buff *orig_skb = NULL;
5052+
u8 status = 0, event = hdr->evt;
5053+
u16 opcode = HCI_OP_NOP;
50435054

50445055
hci_dev_lock(hdev);
50455056

@@ -5053,15 +5064,24 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
50535064

50545065
hci_dev_unlock(hdev);
50555066

5056-
skb_pull(skb, HCI_EVENT_HDR_SIZE);
5057-
50585067
if (hdev->sent_cmd && bt_cb(hdev->sent_cmd)->req.event == event) {
50595068
struct hci_command_hdr *cmd_hdr = (void *) hdev->sent_cmd->data;
5060-
u16 opcode = __le16_to_cpu(cmd_hdr->opcode);
5061-
5062-
hci_req_cmd_complete(hdev, opcode, 0);
5069+
opcode = __le16_to_cpu(cmd_hdr->opcode);
5070+
hci_req_cmd_complete(hdev, opcode, status, &req_complete,
5071+
&req_complete_skb);
50635072
}
50645073

5074+
/* If it looks like we might end up having to call
5075+
* req_complete_skb, store a pristine copy of the skb since the
5076+
* various handlers may modify the original one through
5077+
* skb_pull() calls, etc.
5078+
*/
5079+
if (req_complete_skb || event == HCI_EV_CMD_STATUS ||
5080+
event == HCI_EV_CMD_COMPLETE)
5081+
orig_skb = skb_clone(skb, GFP_KERNEL);
5082+
5083+
skb_pull(skb, HCI_EVENT_HDR_SIZE);
5084+
50655085
switch (event) {
50665086
case HCI_EV_INQUIRY_COMPLETE:
50675087
hci_inquiry_complete_evt(hdev, skb);
@@ -5104,11 +5124,13 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
51045124
break;
51055125

51065126
case HCI_EV_CMD_COMPLETE:
5107-
hci_cmd_complete_evt(hdev, skb);
5127+
hci_cmd_complete_evt(hdev, skb, &opcode, &status,
5128+
&req_complete, &req_complete_skb);
51085129
break;
51095130

51105131
case HCI_EV_CMD_STATUS:
5111-
hci_cmd_status_evt(hdev, skb);
5132+
hci_cmd_status_evt(hdev, skb, &opcode, &status, &req_complete,
5133+
&req_complete_skb);
51125134
break;
51135135

51145136
case HCI_EV_HARDWARE_ERROR:
@@ -5240,6 +5262,12 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb)
52405262
break;
52415263
}
52425264

5265+
if (req_complete)
5266+
req_complete(hdev, status, opcode);
5267+
else if (req_complete_skb)
5268+
req_complete_skb(hdev, status, opcode, orig_skb);
5269+
5270+
kfree_skb(orig_skb);
52435271
kfree_skb(skb);
52445272
hdev->stat.evt_rx++;
52455273
}

net/bluetooth/hci_request.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ void hci_req_init(struct hci_request *req, struct hci_dev *hdev)
3434
req->err = 0;
3535
}
3636

37-
int hci_req_run(struct hci_request *req, hci_req_complete_t complete)
37+
static int req_run(struct hci_request *req, hci_req_complete_t complete,
38+
hci_req_complete_skb_t complete_skb)
3839
{
3940
struct hci_dev *hdev = req->hdev;
4041
struct sk_buff *skb;
@@ -56,6 +57,7 @@ int hci_req_run(struct hci_request *req, hci_req_complete_t complete)
5657

5758
skb = skb_peek_tail(&req->cmd_q);
5859
bt_cb(skb)->req.complete = complete;
60+
bt_cb(skb)->req.complete_skb = complete_skb;
5961

6062
spin_lock_irqsave(&hdev->cmd_q.lock, flags);
6163
skb_queue_splice_tail(&req->cmd_q, &hdev->cmd_q);
@@ -66,6 +68,16 @@ int hci_req_run(struct hci_request *req, hci_req_complete_t complete)
6668
return 0;
6769
}
6870

71+
int hci_req_run(struct hci_request *req, hci_req_complete_t complete)
72+
{
73+
return req_run(req, complete, NULL);
74+
}
75+
76+
int hci_req_run_skb(struct hci_request *req, hci_req_complete_skb_t complete)
77+
{
78+
return req_run(req, NULL, complete);
79+
}
80+
6981
struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen,
7082
const void *param)
7183
{

net/bluetooth/hci_request.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,14 @@ struct hci_request {
3232

3333
void hci_req_init(struct hci_request *req, struct hci_dev *hdev);
3434
int hci_req_run(struct hci_request *req, hci_req_complete_t complete);
35+
int hci_req_run_skb(struct hci_request *req, hci_req_complete_skb_t complete);
3536
void hci_req_add(struct hci_request *req, u16 opcode, u32 plen,
3637
const void *param);
3738
void hci_req_add_ev(struct hci_request *req, u16 opcode, u32 plen,
3839
const void *param, u8 event);
39-
void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status);
40+
void hci_req_cmd_complete(struct hci_dev *hdev, u16 opcode, u8 status,
41+
hci_req_complete_t *req_complete,
42+
hci_req_complete_skb_t *req_complete_skb);
4043

4144
struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen,
4245
const void *param);

0 commit comments

Comments
 (0)