mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-12 08:00:09 +00:00
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>
This commit is contained in:
parent
2ad8f54bc8
commit
e1171e8d9c
@ -178,48 +178,13 @@ static void hci_reset_req(struct hci_dev *hdev, unsigned long opt)
|
|||||||
|
|
||||||
static void bredr_init(struct hci_dev *hdev)
|
static void bredr_init(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
struct hci_cp_delete_stored_link_key cp;
|
|
||||||
__le16 param;
|
|
||||||
__u8 flt_type;
|
|
||||||
|
|
||||||
hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED;
|
hdev->flow_ctl_mode = HCI_FLOW_CTL_MODE_PACKET_BASED;
|
||||||
|
|
||||||
/* Mandatory initialization */
|
|
||||||
|
|
||||||
/* Read Local Supported Features */
|
/* Read Local Supported Features */
|
||||||
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
|
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_FEATURES, 0, NULL);
|
||||||
|
|
||||||
/* Read Local Version */
|
/* Read Local Version */
|
||||||
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
|
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_VERSION, 0, NULL);
|
||||||
|
|
||||||
/* Read Buffer Size (ACL mtu, max pkt, etc.) */
|
|
||||||
hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
|
|
||||||
|
|
||||||
/* Read BD Address */
|
|
||||||
hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
|
|
||||||
|
|
||||||
/* Read Class of Device */
|
|
||||||
hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
|
|
||||||
|
|
||||||
/* Read Local Name */
|
|
||||||
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
|
|
||||||
|
|
||||||
/* Read Voice Setting */
|
|
||||||
hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
|
|
||||||
|
|
||||||
/* Optional initialization */
|
|
||||||
|
|
||||||
/* Clear Event Filters */
|
|
||||||
flt_type = HCI_FLT_CLEAR_ALL;
|
|
||||||
hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
|
|
||||||
|
|
||||||
/* Connection accept timeout ~20 secs */
|
|
||||||
param = __constant_cpu_to_le16(0x7d00);
|
|
||||||
hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m);
|
|
||||||
|
|
||||||
bacpy(&cp.bdaddr, BDADDR_ANY);
|
|
||||||
cp.delete_all = 1;
|
|
||||||
hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void amp_init(struct hci_dev *hdev)
|
static void amp_init(struct hci_dev *hdev)
|
||||||
@ -273,14 +238,6 @@ static void hci_init_req(struct hci_dev *hdev, unsigned long opt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hci_le_init_req(struct hci_dev *hdev, unsigned long opt)
|
|
||||||
{
|
|
||||||
BT_DBG("%s", hdev->name);
|
|
||||||
|
|
||||||
/* Read LE buffer size */
|
|
||||||
hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
|
static void hci_scan_req(struct hci_dev *hdev, unsigned long opt)
|
||||||
{
|
{
|
||||||
__u8 scan = opt;
|
__u8 scan = opt;
|
||||||
@ -687,10 +644,6 @@ int hci_dev_open(__u16 dev)
|
|||||||
|
|
||||||
ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT);
|
ret = __hci_request(hdev, hci_init_req, 0, HCI_INIT_TIMEOUT);
|
||||||
|
|
||||||
if (lmp_host_le_capable(hdev))
|
|
||||||
ret = __hci_request(hdev, hci_le_init_req, 0,
|
|
||||||
HCI_INIT_TIMEOUT);
|
|
||||||
|
|
||||||
clear_bit(HCI_INIT, &hdev->flags);
|
clear_bit(HCI_INIT, &hdev->flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -507,11 +507,13 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
|
|||||||
if (hdev->hci_ver < BLUETOOTH_VER_1_2)
|
if (hdev->hci_ver < BLUETOOTH_VER_1_2)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
events[4] |= 0x01; /* Flow Specification Complete */
|
if (lmp_bredr_capable(hdev)) {
|
||||||
events[4] |= 0x02; /* Inquiry Result with RSSI */
|
events[4] |= 0x01; /* Flow Specification Complete */
|
||||||
events[4] |= 0x04; /* Read Remote Extended Features Complete */
|
events[4] |= 0x02; /* Inquiry Result with RSSI */
|
||||||
events[5] |= 0x08; /* Synchronous Connection Complete */
|
events[4] |= 0x04; /* Read Remote Extended Features Complete */
|
||||||
events[5] |= 0x10; /* Synchronous Connection Changed */
|
events[5] |= 0x08; /* Synchronous Connection Complete */
|
||||||
|
events[5] |= 0x10; /* Synchronous Connection Changed */
|
||||||
|
}
|
||||||
|
|
||||||
if (hdev->features[3] & LMP_RSSI_INQ)
|
if (hdev->features[3] & LMP_RSSI_INQ)
|
||||||
events[4] |= 0x02; /* Inquiry Result with RSSI */
|
events[4] |= 0x02; /* Inquiry Result with RSSI */
|
||||||
@ -550,11 +552,57 @@ static void hci_setup_event_mask(struct hci_dev *hdev)
|
|||||||
hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
|
hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void bredr_init(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
struct hci_cp_delete_stored_link_key cp;
|
||||||
|
__le16 param;
|
||||||
|
__u8 flt_type;
|
||||||
|
|
||||||
|
/* Read Buffer Size (ACL mtu, max pkt, etc.) */
|
||||||
|
hci_send_cmd(hdev, HCI_OP_READ_BUFFER_SIZE, 0, NULL);
|
||||||
|
|
||||||
|
/* Read Class of Device */
|
||||||
|
hci_send_cmd(hdev, HCI_OP_READ_CLASS_OF_DEV, 0, NULL);
|
||||||
|
|
||||||
|
/* Read Local Name */
|
||||||
|
hci_send_cmd(hdev, HCI_OP_READ_LOCAL_NAME, 0, NULL);
|
||||||
|
|
||||||
|
/* Read Voice Setting */
|
||||||
|
hci_send_cmd(hdev, HCI_OP_READ_VOICE_SETTING, 0, NULL);
|
||||||
|
|
||||||
|
/* Clear Event Filters */
|
||||||
|
flt_type = HCI_FLT_CLEAR_ALL;
|
||||||
|
hci_send_cmd(hdev, HCI_OP_SET_EVENT_FLT, 1, &flt_type);
|
||||||
|
|
||||||
|
/* Connection accept timeout ~20 secs */
|
||||||
|
param = __constant_cpu_to_le16(0x7d00);
|
||||||
|
hci_send_cmd(hdev, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m);
|
||||||
|
|
||||||
|
bacpy(&cp.bdaddr, BDADDR_ANY);
|
||||||
|
cp.delete_all = 1;
|
||||||
|
hci_send_cmd(hdev, HCI_OP_DELETE_STORED_LINK_KEY, sizeof(cp), &cp);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void le_init(struct hci_dev *hdev)
|
||||||
|
{
|
||||||
|
/* Read LE Buffer Size */
|
||||||
|
hci_send_cmd(hdev, HCI_OP_LE_READ_BUFFER_SIZE, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static void hci_setup(struct hci_dev *hdev)
|
static void hci_setup(struct hci_dev *hdev)
|
||||||
{
|
{
|
||||||
if (hdev->dev_type != HCI_BREDR)
|
if (hdev->dev_type != HCI_BREDR)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
/* Read BD Address */
|
||||||
|
hci_send_cmd(hdev, HCI_OP_READ_BD_ADDR, 0, NULL);
|
||||||
|
|
||||||
|
if (lmp_bredr_capable(hdev))
|
||||||
|
bredr_init(hdev);
|
||||||
|
|
||||||
|
if (lmp_le_capable(hdev))
|
||||||
|
le_init(hdev);
|
||||||
|
|
||||||
hci_setup_event_mask(hdev);
|
hci_setup_event_mask(hdev);
|
||||||
|
|
||||||
if (hdev->hci_ver > BLUETOOTH_VER_1_1)
|
if (hdev->hci_ver > BLUETOOTH_VER_1_1)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user