diff options
author | Johan Hedberg <johan.hedberg@nokia.com> | 2011-01-10 06:28:59 -0500 |
---|---|---|
committer | Gustavo F. Padovan <padovan@profusion.mobi> | 2011-02-07 22:40:06 -0500 |
commit | a5040efa2017f3e4f1b4d5f40fd989567f3994c1 (patch) | |
tree | 451984186e4504665bff2ed0b74a9510a0d32d13 | |
parent | 03b555e119de8288a16e086e1fbd223d9b429d3d (diff) |
Bluetooth: Add special handling with __hci_request and HCI_INIT
To support a more dynamic HCI initialization sequence the __hci_request
behavior requires some more changes. Particularly, the init sequence
should be able to have conditionals in it (sending some HCI commands
depending on the outcome of a previous command) instead of being a fixed
list as it is right now.
The reasons for these additional requirements are the moving all
previously user space driven initialization commands to the kernel side
as well as the support the Low Energy controllers.
To fulfull these requirements the init sequence is made the only special
case for multi-command requests and req_last_cmd is renamed to
init_last_cmd. The hci_send_cmd function is changed to update
init_last_cmd as long as the HCI_INIT flag is set.
Signed-off-by: Johan Hedberg <johan.hedberg@nokia.com>
Signed-off-by: Gustavo F. Padovan <padovan@profusion.mobi>
-rw-r--r-- | include/net/bluetooth/hci_core.h | 3 | ||||
-rw-r--r-- | net/bluetooth/hci_core.c | 17 |
2 files changed, 11 insertions, 9 deletions
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index dc8084a139ed..0dbdcc5f44e4 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h | |||
@@ -139,7 +139,8 @@ struct hci_dev { | |||
139 | wait_queue_head_t req_wait_q; | 139 | wait_queue_head_t req_wait_q; |
140 | __u32 req_status; | 140 | __u32 req_status; |
141 | __u32 req_result; | 141 | __u32 req_result; |
142 | __u16 req_last_cmd; | 142 | |
143 | __u16 init_last_cmd; | ||
143 | 144 | ||
144 | struct inquiry_cache inq_cache; | 145 | struct inquiry_cache inq_cache; |
145 | struct hci_conn_hash conn_hash; | 146 | struct hci_conn_hash conn_hash; |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index b99248d4a5b2..183ce81f7a5c 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -97,11 +97,10 @@ void hci_req_complete(struct hci_dev *hdev, __u16 cmd, int result) | |||
97 | { | 97 | { |
98 | BT_DBG("%s command 0x%04x result 0x%2.2x", hdev->name, cmd, result); | 98 | BT_DBG("%s command 0x%04x result 0x%2.2x", hdev->name, cmd, result); |
99 | 99 | ||
100 | /* If the request has set req_last_cmd (typical for multi-HCI | 100 | /* If this is the init phase check if the completed command matches |
101 | * command requests) check if the completed command matches | 101 | * the last init command, and if not just return. |
102 | * this, and if not just return. Single HCI command requests | 102 | */ |
103 | * typically leave req_last_cmd as 0 */ | 103 | if (test_bit(HCI_INIT, &hdev->flags) && hdev->init_last_cmd != cmd) |
104 | if (hdev->req_last_cmd && cmd != hdev->req_last_cmd) | ||
105 | return; | 104 | return; |
106 | 105 | ||
107 | if (hdev->req_status == HCI_REQ_PEND) { | 106 | if (hdev->req_status == HCI_REQ_PEND) { |
@@ -158,7 +157,7 @@ static int __hci_request(struct hci_dev *hdev, void (*req)(struct hci_dev *hdev, | |||
158 | break; | 157 | break; |
159 | } | 158 | } |
160 | 159 | ||
161 | hdev->req_last_cmd = hdev->req_status = hdev->req_result = 0; | 160 | hdev->req_status = hdev->req_result = 0; |
162 | 161 | ||
163 | BT_DBG("%s end: err %d", hdev->name, err); | 162 | BT_DBG("%s end: err %d", hdev->name, err); |
164 | 163 | ||
@@ -261,8 +260,6 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) | |||
261 | /* Connection accept timeout ~20 secs */ | 260 | /* Connection accept timeout ~20 secs */ |
262 | param = cpu_to_le16(0x7d00); | 261 | param = cpu_to_le16(0x7d00); |
263 | hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); | 262 | hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); |
264 | |||
265 | hdev->req_last_cmd = HCI_OP_WRITE_CA_TIMEOUT; | ||
266 | } | 263 | } |
267 | 264 | ||
268 | static void hci_scan_req(struct hci_dev *hdev, unsigned long opt) | 265 | static void hci_scan_req(struct hci_dev *hdev, unsigned long opt) |
@@ -523,6 +520,7 @@ int hci_dev_open(__u16 dev) | |||
523 | if (!test_bit(HCI_RAW, &hdev->flags)) { | 520 | if (!test_bit(HCI_RAW, &hdev->flags)) { |
524 | atomic_set(&hdev->cmd_cnt, 1); | 521 | atomic_set(&hdev->cmd_cnt, 1); |
525 | set_bit(HCI_INIT, &hdev->flags); | 522 | set_bit(HCI_INIT, &hdev->flags); |
523 | hdev->init_last_cmd = 0; | ||
526 | 524 | ||
527 | //__hci_request(hdev, hci_reset_req, 0, HZ); | 525 | //__hci_request(hdev, hci_reset_req, 0, HZ); |
528 | ret = __hci_request(hdev, hci_init_req, 0, | 526 | ret = __hci_request(hdev, hci_init_req, 0, |
@@ -1442,6 +1440,9 @@ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, void *param) | |||
1442 | bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; | 1440 | bt_cb(skb)->pkt_type = HCI_COMMAND_PKT; |
1443 | skb->dev = (void *) hdev; | 1441 | skb->dev = (void *) hdev; |
1444 | 1442 | ||
1443 | if (test_bit(HCI_INIT, &hdev->flags)) | ||
1444 | hdev->init_last_cmd = opcode; | ||
1445 | |||
1445 | skb_queue_tail(&hdev->cmd_q, skb); | 1446 | skb_queue_tail(&hdev->cmd_q, skb); |
1446 | tasklet_schedule(&hdev->cmd_task); | 1447 | tasklet_schedule(&hdev->cmd_task); |
1447 | 1448 | ||