diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2012-10-19 13:57:45 -0400 |
---|---|---|
committer | Gustavo Padovan <gustavo.padovan@collabora.co.uk> | 2012-10-24 09:11:04 -0400 |
commit | e1171e8d9c50c38a9adba72bb23949d9b975335c (patch) | |
tree | ba32884946ac9cad44ebee3664e0da89d09301df | |
parent | 2ad8f54bc86809c2a8de3830e3ed275fcc6401ed (diff) |
Bluetooth: Add initial support for LE-only controllers
This patch splits off most the HCI init sequence commands from a fixed
set into a conditional one that is sent once the HCI_Read_Local_Features
and HCI_Read_Local_Version_Information commands complete. This is
necessary since many of the current fixed commands are not allowed for
LE-only controllers.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Acked-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
-rw-r--r-- | net/bluetooth/hci_core.c | 47 | ||||
-rw-r--r-- | net/bluetooth/hci_event.c | 58 |
2 files changed, 53 insertions, 52 deletions
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 5a3f941b610f..854202679c49 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -178,48 +178,13 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt) | |||
178 | 178 | ||
179 | static void bredr_init(struct hci_dev *hdev) | 179 | static void bredr_init(struct hci_dev *hdev) |
180 | { | 180 | { |
181 | struct hci_cp_delete_stored_link_key cp; | ||
182 | __le16 param; | ||
183 | __u8 flt_type; | ||
184 | |||
185 | hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED; | 181 | hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED; |
186 | 182 | ||
187 | /* Mandatory initialization */ | ||
188 | |||
189 | /* Read Local Supported Features */ | 183 | /* Read Local Supported Features */ |
190 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); | 184 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL); |
191 | 185 | ||
192 | /* Read Local Version */ | 186 | /* Read Local Version */ |
193 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL); | 187 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL); |
194 | |||
195 | /* Read Buffer Size (ACL mtu, max pkt, etc.) */ | ||
196 | hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL); | ||
197 | |||
198 | /* Read BD Address */ | ||
199 | hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL); | ||
200 | |||
201 | /* Read Class of Device */ | ||
202 | hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL); | ||
203 | |||
204 | /* Read Local Name */ | ||
205 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL); | ||
206 | |||
207 | /* Read Voice Setting */ | ||
208 | hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL); | ||
209 | |||
210 | /* Optional initialization */ | ||
211 | |||
212 | /* Clear Event Filters */ | ||
213 | flt_type = HCI_FLT_CLEAR_ALL; | ||
214 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type); | ||
215 | |||
216 | /* Connection accept timeout ~20 secs */ | ||
217 | param = __constant_cpu_to_le16(0x7d00); | ||
218 | hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); | ||
219 | |||
220 | bacpy(&cp.bdaddr, BDADDR_ANY); | ||
221 | cp.delete_all = 1; | ||
222 | hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp); | ||
223 | } | 188 | } |
224 | 189 | ||
225 | static void amp_init(struct hci_dev *hdev) | 190 | static void amp_init(struct hci_dev *hdev) |
@@ -273,14 +238,6 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt) | |||
273 | } | 238 | } |
274 | } | 239 | } |
275 | 240 | ||
276 | static void hci_le_init_req(struct hci_dev *hdev, unsigned long opt) | ||
277 | { | ||
278 | BT_DBG("%s", hdev->name); | ||
279 | |||
280 | /* Read LE buffer size */ | ||
281 | hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); | ||
282 | } | ||
283 | |||
284 | static void hci_scan_req(struct hci_dev *hdev, unsigned long opt) | 241 | static void hci_scan_req(struct hci_dev *hdev, unsigned long opt) |
285 | { | 242 | { |
286 | __u8 scan = opt; | 243 | __u8 scan = opt; |
@@ -687,10 +644,6 @@ int hci_dev_open(__u16 dev) | |||
687 | 644 | ||
688 | ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT); | 645 | ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT); |
689 | 646 | ||
690 | if (lmp_host_le_capable(hdev)) | ||
691 | ret = __hci_request(hdev, hci_le_init_req, 0, | ||
692 | HCI_INIT_TIMEOUT); | ||
693 | |||
694 | clear_bit(HCI_INIT, &hdev->flags); | 647 | clear_bit(HCI_INIT, &hdev->flags); |
695 | } | 648 | } |
696 | 649 | ||
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0383635f91fb..f4f0b8bfdee6 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -507,11 +507,13 @@ static void hci_setup_event_mask(struct hci_dev *hdev) | |||
507 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) | 507 | if (hdev->hci_ver < BLUETOOTH_VER_1_2) |
508 | return; | 508 | return; |
509 | 509 | ||
510 | events[4] |= 0x01; /* Flow Specification Complete */ | 510 | if (lmp_bredr_capable(hdev)) { |
511 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | 511 | events[4] |= 0x01; /* Flow Specification Complete */ |
512 | events[4] |= 0x04; /* Read Remote Extended Features Complete */ | 512 | events[4] |= 0x02; /* Inquiry Result with RSSI */ |
513 | events[5] |= 0x08; /* Synchronous Connection Complete */ | 513 | events[4] |= 0x04; /* Read Remote Extended Features Complete */ |
514 | events[5] |= 0x10; /* Synchronous Connection Changed */ | 514 | events[5] |= 0x08; /* Synchronous Connection Complete */ |
515 | events[5] |= 0x10; /* Synchronous Connection Changed */ | ||
516 | } | ||
515 | 517 | ||
516 | if (hdev->features[3] & LMP_RSSI_INQ) | 518 | if (hdev->features[3] & LMP_RSSI_INQ) |
517 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | 519 | events[4] |= 0x02; /* Inquiry Result with RSSI */ |
@@ -550,11 +552,57 @@ static void hci_setup_event_mask(struct hci_dev *hdev) | |||
550 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); | 552 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); |
551 | } | 553 | } |
552 | 554 | ||
555 | static void bredr_init(struct hci_dev *hdev) | ||
556 | { | ||
557 | struct hci_cp_delete_stored_link_key cp; | ||
558 | __le16 param; | ||
559 | __u8 flt_type; | ||
560 | |||
561 | /* Read Buffer Size (ACL mtu, max pkt, etc.) */ | ||
562 | hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL); | ||
563 | |||
564 | /* Read Class of Device */ | ||
565 | hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL); | ||
566 | |||
567 | /* Read Local Name */ | ||
568 | hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL); | ||
569 | |||
570 | /* Read Voice Setting */ | ||
571 | hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL); | ||
572 | |||
573 | /* Clear Event Filters */ | ||
574 | flt_type = HCI_FLT_CLEAR_ALL; | ||
575 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type); | ||
576 | |||
577 | /* Connection accept timeout ~20 secs */ | ||
578 | param = __constant_cpu_to_le16(0x7d00); | ||
579 | hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); | ||
580 | |||
581 | bacpy(&cp.bdaddr, BDADDR_ANY); | ||
582 | cp.delete_all = 1; | ||
583 | hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp); | ||
584 | } | ||
585 | |||
586 | static void le_init(struct hci_dev *hdev) | ||
587 | { | ||
588 | /* Read LE Buffer Size */ | ||
589 | hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL); | ||
590 | } | ||
591 | |||
553 | static void hci_setup(struct hci_dev *hdev) | 592 | static void hci_setup(struct hci_dev *hdev) |
554 | { | 593 | { |
555 | if (hdev->dev_type != HCI_BREDR) | 594 | if (hdev->dev_type != HCI_BREDR) |
556 | return; | 595 | return; |
557 | 596 | ||
597 | /* Read BD Address */ | ||
598 | hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL); | ||
599 | |||
600 | if (lmp_bredr_capable(hdev)) | ||
601 | bredr_init(hdev); | ||
602 | |||
603 | if (lmp_le_capable(hdev)) | ||
604 | le_init(hdev); | ||
605 | |||
558 | hci_setup_event_mask(hdev); | 606 | hci_setup_event_mask(hdev); |
559 | 607 | ||
560 | if (hdev->hci_ver > BLUETOOTH_VER_1_1) | 608 | if (hdev->hci_ver > BLUETOOTH_VER_1_1) |