From 4d1e4223f4c5ad4b87f9bb2ec19bdbe25d2a4249 Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 8 Sep 2016 10:56:15 +0530 Subject: [PATCH 01/16] Bluetooth: Add LE vendor specific event handler This patch adds the vendor specific LE meta event handler. It handles the vendor specific handles like, LE_MULTI_ADV_STATE_CHANGE_SUB_EVENT, LE_RSSI_LINK_ALERT. Change-Id: I1f344a31e36f9c7442fe0bd8b598e67d9f5fb9bf Signed-off-by: Sudha Bheemanna [divide hci vendor speicif group event function] Signed-off-by: Seung-Woo Kim Signed-off-by: Amit Purwar --- include/net/bluetooth/hci.h | 19 +++++++++++++++++ net/bluetooth/hci_event.c | 50 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 5ce0292..d45f7ee 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1920,6 +1920,25 @@ struct hci_ev_sync_train_complete { #define HCI_EV_SLAVE_PAGE_RESP_TIMEOUT 0x54 +#ifdef TIZEN_BT +/* + * Vendor Specific HCI Event + * Vendor: Broadcom + * Purpose: This HCI Event gives RSSI Alerts for monitored LE Link + */ +#define HCI_EV_VENDOR_SPECIFIC 0xFF +struct hci_ev_vendor_specific { + __u8 event_sub_code; +} __packed; + +#define LE_META_VENDOR_SPECIFIC_GROUP_EVENT 0xE9 +struct hci_ev_ext_vendor_specific { + __u8 event_le_ext_sub_code; +} __packed; + +#define LE_RSSI_LINK_ALERT 0x02 +#endif + #define HCI_EV_LE_CONN_COMPLETE 0x01 struct hci_ev_le_conn_complete { __u8 status; diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0b179ea..e8ef30e 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1418,6 +1418,50 @@ static void hci_cc_get_raw_rssi(struct hci_dev *hdev, mgmt_raw_rssi_response(hdev, rp, rp->status); } + +static void hci_vendor_specific_group_ext_evt(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_ev_ext_vendor_specific *ev = (void *)skb->data; + __u8 event_le_ext_sub_code; + + BT_DBG("RSSI event LE_META_VENDOR_SPECIFIC_GROUP_EVENT: %X", + LE_META_VENDOR_SPECIFIC_GROUP_EVENT); + + skb_pull(skb, sizeof(*ev)); + event_le_ext_sub_code = ev->event_le_ext_sub_code; + + switch (event_le_ext_sub_code) { + case LE_RSSI_LINK_ALERT: + BT_DBG("RSSI event LE_RSSI_LINK_ALERT %X", + LE_RSSI_LINK_ALERT); + mgmt_rssi_alert_evt(hdev, skb); + break; + + default: + break; + } +} + +static void hci_vendor_specific_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + struct hci_ev_vendor_specific *ev = (void *)skb->data; + __u8 event_sub_code; + + BT_DBG("hci_vendor_specific_evt"); + + skb_pull(skb, sizeof(*ev)); + event_sub_code = ev->event_sub_code; + + switch (event_sub_code) { + case LE_META_VENDOR_SPECIFIC_GROUP_EVENT: + hci_vendor_specific_group_ext_evt(hdev, skb); + break; + + default: + break; + } +} #endif static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb) @@ -5519,6 +5563,12 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) hci_num_comp_blocks_evt(hdev, skb); break; +#ifdef TIZEN_BT + case HCI_EV_VENDOR_SPECIFIC: + hci_vendor_specific_evt(hdev, skb); + break; +#endif + default: BT_DBG("%s event 0x%2.2x", hdev->name, event); break; -- 2.7.4 From 68a00598e885e9db4c339fee50c9f29a0d694b36 Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Wed, 7 Sep 2016 15:42:22 +0530 Subject: [PATCH 02/16] Bluetooth: Add hardware error MGMT event Add code to handle hardware error MGMT event. Change-Id: I5875ea2aeae7aba95c1f8e15b456704dc6bcdee4 Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- include/net/bluetooth/hci_core.h | 1 + include/net/bluetooth/mgmt_tizen.h | 7 +++++++ net/bluetooth/hci_event.c | 5 +++++ net/bluetooth/mgmt.c | 8 ++++++++ 4 files changed, 21 insertions(+) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 7e36431..3d9278e 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1654,6 +1654,7 @@ int mgmt_le_conn_updated(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, u16 supervision_timeout); int mgmt_le_conn_update_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 status); +void mgmt_hardware_error(struct hci_dev *hdev, u8 err_code); #endif u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency, diff --git a/include/net/bluetooth/mgmt_tizen.h b/include/net/bluetooth/mgmt_tizen.h index 4c2e9d0..680ad8b 100644 --- a/include/net/bluetooth/mgmt_tizen.h +++ b/include/net/bluetooth/mgmt_tizen.h @@ -162,6 +162,13 @@ struct mgmt_ev_device_name_update { } __packed; /* Device name update changes */ +/* For handling of hardware error event */ +#define MGMT_EV_HARDWARE_ERROR (TIZEN_EV_BASE + 0x02) +struct mgmt_ev_hardware_error { + __u8 error_code; +} __packed; +/* handling of hardware error event */ + /* For handling of RSSI Events */ #define MGMT_EV_RSSI_ALERT (TIZEN_EV_BASE + 0x04) struct mgmt_ev_vendor_specific_rssi_alert { diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index e8ef30e..63890dc 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -3246,6 +3246,11 @@ static void hci_hardware_error_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_hardware_error *ev = (void *) skb->data; +#ifdef TIZEN_BT + hci_dev_lock(hdev); + mgmt_hardware_error(hdev, ev->code); + hci_dev_unlock(hdev); +#endif hdev->hw_error_code = ev->code; queue_work(hdev->req_workqueue, &hdev->error_reset); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 3023f9a..0d6829a 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -6384,6 +6384,14 @@ static int le_set_scan_params(struct sock *sk, struct hci_dev *hdev, return err; } + +void mgmt_hardware_error(struct hci_dev *hdev, u8 err_code) +{ + struct mgmt_ev_hardware_error ev; + + ev.error_code = err_code; + mgmt_event(MGMT_EV_HARDWARE_ERROR, hdev, &ev, sizeof(ev), NULL); +} #endif /* TIZEN_BT */ static bool ltk_is_valid(struct mgmt_ltk_info *key) -- 2.7.4 From 4510f6ad92d59933ecfd2f83d65a7b48708266fc Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Wed, 7 Sep 2016 16:47:58 +0530 Subject: [PATCH 03/16] Bluetooth: Add H/W TX timeout error MGMT event This patch sends the H/W TX timeout error MGMT event if HCI command timeout occurs after sending HCI commands. Change-Id: I5eb593f2fe4d31c404dd94ef582790e47d03b10a Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- include/net/bluetooth/hci.h | 4 ++++ include/net/bluetooth/hci_core.h | 1 + include/net/bluetooth/mgmt_tizen.h | 4 ++++ net/bluetooth/hci_core.c | 11 +++++++++++ net/bluetooth/mgmt.c | 5 +++++ 5 files changed, 25 insertions(+) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index d45f7ee..9f3948e 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -268,7 +268,11 @@ enum { #define HCI_DISCONN_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ #define HCI_PAIRING_TIMEOUT msecs_to_jiffies(60000) /* 60 seconds */ #define HCI_INIT_TIMEOUT msecs_to_jiffies(10000) /* 10 seconds */ +#ifdef TIZEN_BT +#define HCI_CMD_TIMEOUT msecs_to_jiffies(5000) /* 5 seconds */ +#else #define HCI_CMD_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ +#endif #define HCI_ACL_TX_TIMEOUT msecs_to_jiffies(45000) /* 45 seconds */ #define HCI_AUTO_OFF_TIMEOUT msecs_to_jiffies(2000) /* 2 seconds */ #define HCI_POWER_OFF_TIMEOUT msecs_to_jiffies(5000) /* 5 seconds */ diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 3d9278e..b38f811 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1655,6 +1655,7 @@ int mgmt_le_conn_updated(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type, int mgmt_le_conn_update_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 status); void mgmt_hardware_error(struct hci_dev *hdev, u8 err_code); +void mgmt_tx_timeout_error(struct hci_dev *hdev); #endif u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency, diff --git a/include/net/bluetooth/mgmt_tizen.h b/include/net/bluetooth/mgmt_tizen.h index 680ad8b..fd5a9fe 100644 --- a/include/net/bluetooth/mgmt_tizen.h +++ b/include/net/bluetooth/mgmt_tizen.h @@ -169,6 +169,10 @@ struct mgmt_ev_hardware_error { } __packed; /* handling of hardware error event */ +/* For HCI TX Timeout Error */ +#define MGMT_EV_TX_TIMEOUT_ERROR (TIZEN_EV_BASE + 0x03) +/* HCI TX Timeout Error */ + /* For handling of RSSI Events */ #define MGMT_EV_RSSI_ALERT (TIZEN_EV_BASE + 0x04) struct mgmt_ev_vendor_specific_rssi_alert { diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index ae9d874..301b1e0 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1036,6 +1036,13 @@ void hci_le_discovery_set_state(struct hci_dev *hdev, int state) hdev->le_discovery.state = state; } + +static void hci_tx_timeout_error_evt(struct hci_dev *hdev) +{ + BT_ERR("%s H/W TX Timeout error", hdev->name); + + mgmt_tx_timeout_error(hdev); +} #endif void hci_inquiry_cache_flush(struct hci_dev *hdev) @@ -2538,6 +2545,10 @@ static void hci_cmd_timeout(struct work_struct *work) BT_ERR("%s command tx timeout", hdev->name); } +#ifdef TIZEN_BT + hci_tx_timeout_error_evt(hdev); +#endif + atomic_set(&hdev->cmd_cnt, 1); queue_work(hdev->workqueue, &hdev->cmd_work); } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 0d6829a..aaa3bf2 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -6392,6 +6392,11 @@ void mgmt_hardware_error(struct hci_dev *hdev, u8 err_code) ev.error_code = err_code; mgmt_event(MGMT_EV_HARDWARE_ERROR, hdev, &ev, sizeof(ev), NULL); } + +void mgmt_tx_timeout_error(struct hci_dev *hdev) +{ + mgmt_event(MGMT_EV_TX_TIMEOUT_ERROR, hdev, NULL, 0, NULL); +} #endif /* TIZEN_BT */ static bool ltk_is_valid(struct mgmt_ltk_info *key) -- 2.7.4 From 4546c992ef84c989d31bc49e84253a5d4f7d91db Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Thu, 29 Sep 2016 01:59:05 +0900 Subject: [PATCH 04/16] Bluetooth: fix vendor ext rssi link alert event This patch fixes style for rssi link alert event from vendor specific group ext. Change-Id: I0e7003e417c5f5a590cce8264caccad515dd3c10 Signed-off-by: Seung-Woo Kim Signed-off-by: Amit Purwar --- include/net/bluetooth/hci.h | 11 +++++------ include/net/bluetooth/hci_core.h | 3 ++- net/bluetooth/hci_event.c | 15 ++++++++++++--- net/bluetooth/mgmt.c | 12 ++++++------ 4 files changed, 25 insertions(+), 16 deletions(-) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 9f3948e..9af1803 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1532,12 +1532,6 @@ struct hci_cc_rsp_enable_rssi { __u8 le_ext_opcode; } __packed; -struct hci_ev_vendor_specific_rssi_alert { - __le16 conn_handle; - __s8 alert_type; - __s8 rssi_dbm; -} __packed; - /* * Vendor Specific HCI Command * Vendor: Broadcom @@ -1941,6 +1935,11 @@ struct hci_ev_ext_vendor_specific { } __packed; #define LE_RSSI_LINK_ALERT 0x02 +struct hci_ev_vendor_specific_rssi_alert { + __le16 conn_handle; + __s8 alert_type; + __s8 rssi_dbm; +} __packed; #endif #define HCI_EV_LE_CONN_COMPLETE 0x01 diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index b38f811..b503f05 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1642,7 +1642,8 @@ void mgmt_rssi_disable_success(struct sock *sk, struct hci_dev *hdev, void *data, struct hci_cc_rsp_enable_rssi *rp, int success); int mgmt_set_rssi_threshold(struct sock *sk, struct hci_dev *hdev, void *data, u16 len); -void mgmt_rssi_alert_evt(struct hci_dev *hdev, struct sk_buff *skb); +void mgmt_rssi_alert_evt(struct hci_dev *hdev, u16 conn_handle, + s8 alert_type, s8 rssi_dbm); void mgmt_raw_rssi_response(struct hci_dev *hdev, struct hci_cc_rp_get_raw_rssi *rp, int success); void mgmt_enable_rssi_cc(struct hci_dev *hdev, void *response, u8 status); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 63890dc..8f12f09 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1419,6 +1419,17 @@ static void hci_cc_get_raw_rssi(struct hci_dev *hdev, mgmt_raw_rssi_response(hdev, rp, rp->status); } +static void hci_vendor_ext_rssi_link_alert_evt(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_ev_vendor_specific_rssi_alert *ev = (void *)skb->data; + + BT_DBG("RSSI event LE_RSSI_LINK_ALERT %X", LE_RSSI_LINK_ALERT); + + mgmt_rssi_alert_evt(hdev, ev->conn_handle, ev->alert_type, + ev->rssi_dbm); +} + static void hci_vendor_specific_group_ext_evt(struct hci_dev *hdev, struct sk_buff *skb) { @@ -1433,9 +1444,7 @@ static void hci_vendor_specific_group_ext_evt(struct hci_dev *hdev, switch (event_le_ext_sub_code) { case LE_RSSI_LINK_ALERT: - BT_DBG("RSSI event LE_RSSI_LINK_ALERT %X", - LE_RSSI_LINK_ALERT); - mgmt_rssi_alert_evt(hdev, skb); + hci_vendor_ext_rssi_link_alert_evt(hdev, skb); break; default: diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index aaa3bf2..b0e2ee4 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -5823,16 +5823,16 @@ unlocked: return err; } -void mgmt_rssi_alert_evt(struct hci_dev *hdev, struct sk_buff *skb) +void mgmt_rssi_alert_evt(struct hci_dev *hdev, u16 conn_handle, + s8 alert_type, s8 rssi_dbm) { - struct hci_ev_vendor_specific_rssi_alert *ev = (void *)skb->data; struct mgmt_ev_vendor_specific_rssi_alert mgmt_ev; struct hci_conn *conn; BT_DBG("RSSI alert [%2.2X %2.2X %2.2X]", - ev->conn_handle, ev->alert_type, ev->rssi_dbm); + conn_handle, alert_type, rssi_dbm); - conn = hci_conn_hash_lookup_handle(hdev, ev->conn_handle); + conn = hci_conn_hash_lookup_handle(hdev, conn_handle); if (!conn) { BT_ERR("RSSI alert Error: Device not found for handle"); @@ -5845,8 +5845,8 @@ void mgmt_rssi_alert_evt(struct hci_dev *hdev, struct sk_buff *skb) else mgmt_ev.link_type = 0x00; - mgmt_ev.alert_type = ev->alert_type; - mgmt_ev.rssi_dbm = ev->rssi_dbm; + mgmt_ev.alert_type = alert_type; + mgmt_ev.rssi_dbm = rssi_dbm; mgmt_event(MGMT_EV_RSSI_ALERT, hdev, &mgmt_ev, sizeof(struct mgmt_ev_vendor_specific_rssi_alert), -- 2.7.4 From 36dd935a9149ed0dd4705adc1692f18c03bab74b Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 8 Sep 2016 10:10:03 +0530 Subject: [PATCH 05/16] Bluetooth: Add LE device found MGMT event This patch adds new MGMT event for LE device discovery and allows the handling of all advertisement packets in platform. Change-Id: I1927acb75eff0b60a5899898c6d7a000e1a108ef Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- include/net/bluetooth/hci.h | 7 +++++++ include/net/bluetooth/hci_core.h | 6 ++++++ include/net/bluetooth/mgmt_tizen.h | 22 ++++++++++++++++++++ net/bluetooth/hci_event.c | 20 ++++++++++++++++++ net/bluetooth/mgmt.c | 42 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 97 insertions(+) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 9af1803..7e14055 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1940,6 +1940,13 @@ struct hci_ev_vendor_specific_rssi_alert { __s8 alert_type; __s8 rssi_dbm; } __packed; + +#define LE_MULTI_ADV_STATE_CHANGE_SUB_EVENT 0x55 +struct hci_ev_vendor_specific_multi_adv_state { + __u8 adv_instance; + __u8 state_change_reason; + __le16 connection_handle; +} __packed; #endif #define HCI_EV_LE_CONN_COMPLETE 0x01 diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index b503f05..b645066 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1657,6 +1657,12 @@ int mgmt_le_conn_update_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, u8 status); void mgmt_hardware_error(struct hci_dev *hdev, u8 err_code); void mgmt_tx_timeout_error(struct hci_dev *hdev); +/* Pass adv type in the le device found */ +void mgmt_le_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, + u8 addr_type, u8 *dev_class, s8 rssi, u32 flags, u8 *eir, + u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len, u8 adv_type); +void mgmt_multi_adv_state_change_evt(struct hci_dev *hdev, u8 adv_instance, + u8 state_change_reason, u16 connection_handle); #endif u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency, diff --git a/include/net/bluetooth/mgmt_tizen.h b/include/net/bluetooth/mgmt_tizen.h index fd5a9fe..504c2d4 100644 --- a/include/net/bluetooth/mgmt_tizen.h +++ b/include/net/bluetooth/mgmt_tizen.h @@ -211,4 +211,26 @@ struct mgmt_ev_conn_update_failed { } __packed; /* Add LE connection update Events */ +/* For LE device found event */ +#define MGMT_EV_LE_DEVICE_FOUND (TIZEN_EV_BASE + 0x0a) +struct mgmt_ev_le_device_found { + struct mgmt_addr_info addr; + __s8 rssi; + __le32 flags; + __s8 adv_type; + __le16 eir_len; + __u8 eir[0]; +} __packed; +/* LE device found event */ + +/* For LE advertisement state changed event */ +#define MGMT_EV_MULTI_ADV_STATE_CHANGED (TIZEN_EV_BASE + 0x0b) +struct mgmt_ev_vendor_specific_multi_adv_state_changed { + __u8 adv_instance; + __u8 state_change_reason; + __le16 connection_handle; +} __packed; +/* LE advertisement state changed event */ + + #endif /* __MGMT_TIZEN_H */ diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 8f12f09..53c5285 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1127,6 +1127,7 @@ static void clear_pending_adv_report(struct hci_dev *hdev) d->last_adv_data_len = 0; } +#ifndef TIZEN_BT static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type, s8 rssi, u32 flags, u8 *data, u8 len) @@ -1143,6 +1144,7 @@ static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr, memcpy(d->last_adv_data, data, len); d->last_adv_data_len = len; } +#endif static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) @@ -4854,10 +4856,14 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, u8 bdaddr_type, bdaddr_t *direct_addr, u8 direct_addr_type, s8 rssi, u8 *data, u8 len) { +#ifndef TIZEN_BT struct discovery_state *d = &hdev->discovery; +#endif struct smp_irk *irk; struct hci_conn *conn; +#ifndef TIZEN_BT bool match; +#endif u32 flags; u8 *ptr, real_len; @@ -4955,16 +4961,24 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, if (type == LE_ADV_DIRECT_IND) return; +#ifndef TIZEN_BT + /* Handle all adv packet in platform */ if (!hci_pend_le_action_lookup(&hdev->pend_le_reports, bdaddr, bdaddr_type)) return; +#endif if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND) flags = MGMT_DEV_FOUND_NOT_CONNECTABLE; else flags = 0; +#ifdef TIZEN_BT + mgmt_le_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, + rssi, flags, data, len, NULL, 0, type); +#else mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, rssi, flags, data, len, NULL, 0); +#endif return; } @@ -4989,6 +5003,11 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, else flags = 0; +#ifdef TIZEN_BT + /* Disable adv ind and scan rsp merging */ + mgmt_le_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, + rssi, flags, data, len, NULL, 0, type); +#else /* If there's nothing pending either store the data from this * event or send an immediate device found event if the data * should not be stored for later. @@ -5051,6 +5070,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, d->last_adv_addr_type, NULL, rssi, d->last_adv_flags, d->last_adv_data, d->last_adv_data_len, data, len); clear_pending_adv_report(hdev); +#endif } static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index b0e2ee4..1cc3663 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -7397,6 +7397,48 @@ int mgmt_le_conn_updated(struct hci_dev *hdev, bdaddr_t *bdaddr, return mgmt_event(MGMT_EV_CONN_UPDATED, hdev, &ev, sizeof(ev), NULL); } + +/* le device found event - Pass adv type */ +void mgmt_le_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, + u8 addr_type, u8 *dev_class, s8 rssi, u32 flags, u8 *eir, + u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len, u8 adv_type) +{ + char buf[512]; + struct mgmt_ev_le_device_found *ev = (void *)buf; + size_t ev_size; + + if (!hci_discovery_active(hdev) && !hci_le_discovery_active(hdev)) + return; + + /* Make sure that the buffer is big enough. The 5 extra bytes + * are for the potential CoD field. + */ + if (sizeof(*ev) + eir_len + scan_rsp_len + 5 > sizeof(buf)) + return; + + memset(buf, 0, sizeof(buf)); + + bacpy(&ev->addr.bdaddr, bdaddr); + ev->addr.type = link_to_bdaddr(link_type, addr_type); + ev->rssi = rssi; + ev->flags = cpu_to_le32(flags); + ev->adv_type = adv_type; + + if (eir_len > 0) + memcpy(ev->eir, eir, eir_len); + + if (dev_class && !eir_get_data(ev->eir, eir_len, EIR_CLASS_OF_DEV, NULL)) + eir_len = eir_append_data(ev->eir, eir_len, EIR_CLASS_OF_DEV, + dev_class, 3); + + if (scan_rsp_len > 0) + memcpy(ev->eir + eir_len, scan_rsp, scan_rsp_len); + + ev->eir_len = cpu_to_le16(eir_len + scan_rsp_len); + ev_size = sizeof(*ev) + eir_len + scan_rsp_len; + + mgmt_event(MGMT_EV_LE_DEVICE_FOUND, hdev, ev, ev_size, NULL); +} #endif static void read_local_oob_ext_data_complete(struct hci_dev *hdev, u8 status, -- 2.7.4 From 15d3a04ebf39f5bd6b4b0560ab502ffb1124d5b2 Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 8 Sep 2016 10:31:17 +0530 Subject: [PATCH 06/16] Bluetooth: Add multiple LE advertise state change event This patch adds code for providing multiple LE advertisement state changed event to upper layer. Change-Id: I58fb8044e74402376ec30b121081edce7c8709d1 Signed-off-by: Sudha Bheemanna [divide hci_vendor_mutli_adv_state_change_evt and remove hci event structure from mgmt] Signed-off-by: Seung-Woo Kim Signed-off-by: Amit Purwar --- net/bluetooth/hci_event.c | 16 ++++++++++++++++ net/bluetooth/mgmt.c | 17 +++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 53c5285..17a734c 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1454,6 +1454,18 @@ static void hci_vendor_specific_group_ext_evt(struct hci_dev *hdev, } } +static void hci_vendor_multi_adv_state_change_evt(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_ev_vendor_specific_multi_adv_state *ev = (void *)skb->data; + + BT_DBG("LE_MULTI_ADV_STATE_CHANGE_SUB_EVENT"); + + mgmt_multi_adv_state_change_evt(hdev, ev->adv_instance, + ev->state_change_reason, + ev->connection_handle); +} + static void hci_vendor_specific_evt(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_ev_vendor_specific *ev = (void *)skb->data; @@ -1469,6 +1481,10 @@ static void hci_vendor_specific_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_vendor_specific_group_ext_evt(hdev, skb); break; + case LE_MULTI_ADV_STATE_CHANGE_SUB_EVENT: + hci_vendor_multi_adv_state_change_evt(hdev, skb); + break; + default: break; } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 1cc3663..8b498f2 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -6397,6 +6397,23 @@ void mgmt_tx_timeout_error(struct hci_dev *hdev) { mgmt_event(MGMT_EV_TX_TIMEOUT_ERROR, hdev, NULL, 0, NULL); } + +void mgmt_multi_adv_state_change_evt(struct hci_dev *hdev, u8 adv_instance, + u8 state_change_reason, u16 connection_handle) +{ + struct mgmt_ev_vendor_specific_multi_adv_state_changed mgmt_ev; + + BT_DBG("Multi adv state changed [%2.2X %2.2X %2.2X]", + adv_instance, state_change_reason, connection_handle); + + mgmt_ev.adv_instance = adv_instance; + mgmt_ev.state_change_reason = state_change_reason; + mgmt_ev.connection_handle = connection_handle; + + mgmt_event(MGMT_EV_MULTI_ADV_STATE_CHANGED, hdev, &mgmt_ev, + sizeof(struct mgmt_ev_vendor_specific_multi_adv_state_changed), + NULL); +} #endif /* TIZEN_BT */ static bool ltk_is_valid(struct mgmt_ltk_info *key) -- 2.7.4 From 2bcbbea6106ff9e804c0053fa8d715d039906024 Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Tue, 6 Sep 2016 16:38:36 +0530 Subject: [PATCH 07/16] Bluetooth: Add MGMT command to set SCO settings Added code to set sco settings. Change-Id: I37aa572436241b06e00d1e9e75964aac747eeba5 Signed-off-by: Sudha Bheemanna [remove sco link policy part] Signed-off-by: Seung-Woo Kim Signed-off-by: Amit Purwar --- include/net/bluetooth/hci.h | 23 +++++ include/net/bluetooth/hci_core.h | 19 ++++ include/net/bluetooth/mgmt_tizen.h | 10 ++ include/net/bluetooth/sco.h | 7 ++ net/bluetooth/hci_conn.c | 19 ++++ net/bluetooth/mgmt.c | 57 ++++++++++++ net/bluetooth/sco.c | 182 +++++++++++++++++++++++++++++++++++++ 7 files changed, 317 insertions(+) diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 7e14055..3fdc0c0 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -1548,6 +1548,29 @@ struct hci_cc_rp_get_raw_rssi { __le16 conn_handle; __s8 rssi_dbm; } __packed; + +#define HCI_BCM_ENABLE_WBS_REQ 0xfc7e +struct hci_cp_bcm_wbs_req { + __u8 role; + __le16 pkt_type; +} __packed; + +#define HCI_BCM_I2C_PCM_REQ 0xfc6d +struct hci_cp_i2c_pcm_req { + __u8 i2c_enable; + __u8 is_master; + __u8 pcm_rate; + __u8 clock_rate; +} __packed; + +#define HCI_BCM_SCO_PCM_REQ 0xfc1c +struct hci_cp_sco_pcm_req { + __u8 sco_routing; + __u8 pcm_rate; + __u8 frame_type; + __u8 sync_mode; + __u8 clock_mode; +} __packed; #endif /* ---- HCI Events ---- */ diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index b645066..3ddbdbc 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -514,6 +514,8 @@ struct hci_conn { #ifdef TIZEN_BT bool rssi_monitored; + __u8 sco_role; + __u16 voice_setting; #endif struct hci_conn *link; @@ -958,6 +960,23 @@ static inline int hci_conn_hash_lookup_rssi_count(struct hci_dev *hdev) bool hci_le_discovery_active(struct hci_dev *hdev); void hci_le_discovery_set_state(struct hci_dev *hdev, int state); + +static inline struct hci_conn *hci_conn_hash_lookup_sco(struct hci_dev *hdev) +{ + struct hci_conn_hash *h = &hdev->conn_hash; + struct hci_conn *c; + + rcu_read_lock(); + list_for_each_entry_rcu(c, &h->list, list) { + if (c->type == SCO_LINK || c->type == ESCO_LINK) { + rcu_read_unlock(); + return c; + } + } + rcu_read_unlock(); + + return NULL; +} #endif int hci_disconnect(struct hci_conn *conn, __u8 reason); diff --git a/include/net/bluetooth/mgmt_tizen.h b/include/net/bluetooth/mgmt_tizen.h index 504c2d4..4eaa867 100644 --- a/include/net/bluetooth/mgmt_tizen.h +++ b/include/net/bluetooth/mgmt_tizen.h @@ -151,6 +151,16 @@ struct mgmt_cp_le_set_scan_params { } __packed; #define MGMT_LE_SET_SCAN_PARAMS_SIZE 5 +#define MGMT_SCO_ROLE_HANDSFREE 0x00 +#define MGMT_SCO_ROLE_AUDIO_GATEWAY 0x01 +#define MGMT_OP_SET_VOICE_SETTING (TIZEN_OP_CODE_BASE + 0x10) +struct mgmt_cp_set_voice_setting { + bdaddr_t bdaddr; + uint8_t sco_role; + uint16_t voice_setting; +} __packed; +#define MGMT_SET_VOICE_SETTING_SIZE 9 + /* EVENTS */ /* For device name update changes */ diff --git a/include/net/bluetooth/sco.h b/include/net/bluetooth/sco.h index f40ddb4..bca05bf 100644 --- a/include/net/bluetooth/sco.h +++ b/include/net/bluetooth/sco.h @@ -46,4 +46,11 @@ struct sco_conninfo { __u8 dev_class[3]; }; +#ifdef TIZEN_BT +void sco_connect_set_gw_nbc(struct hci_dev *hdev); +void sco_connect_set_gw_wbc(struct hci_dev *hdev); +void sco_connect_set_nbc(struct hci_dev *hdev); +void sco_connect_set_wbc(struct hci_dev *hdev); +#endif + #endif /* __SCO_H */ diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index e3cd81c..074c8f1 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -41,6 +41,16 @@ struct sco_param { u8 retrans_effort; }; +#ifdef TIZEN_BT +static const struct sco_param esco_param_cvsd[] = { + { (EDR_ESCO_MASK & ~ESCO_2EV3) | SCO_ESCO_MASK | ESCO_EV3, + 0x000a, 0x01 }, /* S3 */ + { EDR_ESCO_MASK & ~ESCO_2EV3, 0x0007, 0x01 }, /* S2 */ + { EDR_ESCO_MASK | ESCO_EV3, 0x0007, 0x01 }, /* S1 */ + { EDR_ESCO_MASK | ESCO_HV3, 0xffff, 0x01 }, /* D1 */ + { EDR_ESCO_MASK | ESCO_HV1, 0xffff, 0x01 }, /* D0 */ +}; +#else static const struct sco_param esco_param_cvsd[] = { { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000a, 0x01 }, /* S3 */ { EDR_ESCO_MASK & ~ESCO_2EV3, 0x0007, 0x01 }, /* S2 */ @@ -48,16 +58,25 @@ static const struct sco_param esco_param_cvsd[] = { { EDR_ESCO_MASK | ESCO_HV3, 0xffff, 0x01 }, /* D1 */ { EDR_ESCO_MASK | ESCO_HV1, 0xffff, 0x01 }, /* D0 */ }; +#endif static const struct sco_param sco_param_cvsd[] = { { EDR_ESCO_MASK | ESCO_HV3, 0xffff, 0xff }, /* D1 */ { EDR_ESCO_MASK | ESCO_HV1, 0xffff, 0xff }, /* D0 */ }; +#ifdef TIZEN_BT +static const struct sco_param esco_param_msbc[] = { + { (EDR_ESCO_MASK & ~ESCO_2EV3) | ESCO_EV3, + 0x000d, 0x02 }, /* T2 */ + { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000d, 0x02 }, /* T2 */ +}; +#else static const struct sco_param esco_param_msbc[] = { { EDR_ESCO_MASK & ~ESCO_2EV3, 0x000d, 0x02 }, /* T2 */ { EDR_ESCO_MASK | ESCO_EV3, 0x0008, 0x02 }, /* T1 */ }; +#endif /* This function requires the caller holds hdev->lock */ static void hci_connect_le_scan_cleanup(struct hci_conn *conn) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 8b498f2..0c8bec1 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -34,6 +34,7 @@ #include #ifdef TIZEN_BT #include +#include #endif #include "hci_request.h" @@ -6385,6 +6386,61 @@ static int le_set_scan_params(struct sock *sk, struct hci_dev *hdev, return err; } +static int set_voice_setting(struct sock *sk, struct hci_dev *hdev, + void *data, u16 len) +{ + struct mgmt_cp_set_voice_setting *cp = data; + struct hci_conn *conn; + struct hci_conn *sco_conn; + + int err; + + BT_DBG("%s", hdev->name); + + if (!lmp_bredr_capable(hdev)) { + return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_VOICE_SETTING, + MGMT_STATUS_NOT_SUPPORTED); + } + + hci_dev_lock(hdev); + + conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); + if (!conn) { + err = mgmt_cmd_complete(sk, hdev->id, + MGMT_OP_SET_VOICE_SETTING, 0, NULL, 0); + goto unlock; + } + + conn->voice_setting = cp->voice_setting; + conn->sco_role = cp->sco_role; + + sco_conn = hci_conn_hash_lookup_sco(hdev); + if (sco_conn && bacmp(&sco_conn->dst, &cp->bdaddr) != 0) { + BT_ERR("There is other SCO connection."); + goto done; + } + + if (conn->sco_role == MGMT_SCO_ROLE_HANDSFREE) { + if (conn->voice_setting == 0x0063) + sco_connect_set_wbc(hdev); + else + sco_connect_set_nbc(hdev); + } else { + if (conn->voice_setting == 0x0063) + sco_connect_set_gw_wbc(hdev); + else + sco_connect_set_gw_nbc(hdev); + } + +done: + err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_VOICE_SETTING, 0, + cp, sizeof(cp)); + +unlock: + hci_dev_unlock(hdev); + return err; +} + void mgmt_hardware_error(struct hci_dev *hdev, u8 err_code) { struct mgmt_ev_hardware_error ev; @@ -8362,6 +8418,7 @@ static const struct hci_mgmt_handler tizen_mgmt_handlers[] = { { le_conn_update, MGMT_LE_CONN_UPDATE_SIZE }, { set_manufacturer_data, MGMT_SET_MANUFACTURER_DATA_SIZE }, { le_set_scan_params, MGMT_LE_SET_SCAN_PARAMS_SIZE }, + { set_voice_setting, MGMT_SET_VOICE_SETTING_SIZE }, }; #endif diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 95fd7a8..c665a5e 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -32,6 +32,11 @@ #include #include +#ifdef TIZEN_BT +#include +#include +#endif + static bool disable_esco; static const struct proto_ops sco_sock_ops; @@ -839,8 +844,15 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, } /* Explicitly check for these values */ +#ifdef TIZEN_BT + /* Codec defer accept */ + if (voice.setting != (BT_VOICE_TRANSPARENT | + BT_VOICE_CVSD_16BIT) && + voice.setting != BT_VOICE_CVSD_16BIT) { +#else if (voice.setting != BT_VOICE_TRANSPARENT && voice.setting != BT_VOICE_CVSD_16BIT) { +#endif err = -EINVAL; break; } @@ -1016,6 +1028,10 @@ static int sco_sock_release(struct socket *sock) release_sock(sk); } +#ifdef TIZEN_BT + /* SCO kernel panic fix */ + bt_sock_unlink(&sco_sk_list, sk); +#endif sock_orphan(sk); sco_sock_kill(sk); return err; @@ -1042,7 +1058,12 @@ static void sco_conn_ready(struct sco_conn *conn) return; } +#ifdef TIZEN_BT + /* Multiple SCO accept feature */ + parent = sco_get_sock_listen(&conn->hcon->dst); +#else parent = sco_get_sock_listen(&conn->hcon->src); +#endif if (!parent) { sco_conn_unlock(conn); return; @@ -1080,6 +1101,131 @@ static void sco_conn_ready(struct sco_conn *conn) } } +#ifdef TIZEN_BT +/* WBC/NBC feature */ +void sco_connect_set_gw_nbc(struct hci_dev *hdev) +{ + struct hci_cp_write_voice_setting cp1; + struct hci_cp_bcm_wbs_req cp2; + struct hci_cp_i2c_pcm_req cp3; + struct hci_cp_sco_pcm_req cp4; + + BT_DBG("Setting the NBC params, hdev = %p", hdev); + + cp1.voice_setting = cpu_to_le16(0x0060); + hci_send_cmd(hdev, HCI_OP_WRITE_VOICE_SETTING, sizeof(cp1), &cp1); + hdev->voice_setting = cpu_to_le16(0x0060); + + cp2.role = 0x00; /* WbDisable */ + cp2.pkt_type = cpu_to_le16(0x0002); + hci_send_cmd(hdev, HCI_BCM_ENABLE_WBS_REQ, sizeof(cp2), &cp2); + + cp3.i2c_enable = 0x01; + cp3.is_master = 0x00; + cp3.pcm_rate = 0x00; + cp3.clock_rate = 0x01; + hci_send_cmd(hdev, HCI_BCM_I2C_PCM_REQ, sizeof(cp3), &cp3); + + cp4.sco_routing = 0x00; + cp4.pcm_rate = 0x01; + cp4.frame_type = 0x00; + cp4.sync_mode = 0x00; + cp4.clock_mode = 0x00; + hci_send_cmd(hdev, HCI_BCM_SCO_PCM_REQ, sizeof(cp4), &cp4); +} + +void sco_connect_set_gw_wbc(struct hci_dev *hdev) +{ + struct hci_cp_write_voice_setting cp1; + struct hci_cp_bcm_wbs_req cp2; + struct hci_cp_i2c_pcm_req cp3; + struct hci_cp_sco_pcm_req cp4; + + BT_DBG("Setting the WBC params, hdev = %p", hdev); + cp1.voice_setting = cpu_to_le16(0x0003 | 0x0060); + hci_send_cmd(hdev, HCI_OP_WRITE_VOICE_SETTING, sizeof(cp1), &cp1); + hdev->voice_setting = cpu_to_le16(0x0003 | 0x0060); + + cp2.role = 0x01; /* Enable */ + cp2.pkt_type = cpu_to_le16(0x0002); + hci_send_cmd(hdev, HCI_BCM_ENABLE_WBS_REQ, sizeof(cp2), &cp2); + + cp3.i2c_enable = 0x00; + cp3.is_master = 0x00; + cp3.pcm_rate = 0x01; + cp3.clock_rate = 0x02; + hci_send_cmd(hdev, HCI_BCM_I2C_PCM_REQ, sizeof(cp3), &cp3); + + cp4.sco_routing = 0x00; + cp4.pcm_rate = 0x00; + cp4.frame_type = 0x00; + cp4.sync_mode = 0x00; + cp4.clock_mode = 0x00; + hci_send_cmd(hdev, HCI_BCM_SCO_PCM_REQ, sizeof(cp4), &cp4); +} + +void sco_connect_set_nbc(struct hci_dev *hdev) +{ + struct hci_cp_write_voice_setting cp1; + struct hci_cp_bcm_wbs_req cp2; + struct hci_cp_i2c_pcm_req cp3; + struct hci_cp_sco_pcm_req cp4; + + BT_DBG("Setting the NBC params, hdev = %p", hdev); + + cp1.voice_setting = cpu_to_le16(0x0060); + hci_send_cmd(hdev, HCI_OP_WRITE_VOICE_SETTING, sizeof(cp1), &cp1); + hdev->voice_setting = cpu_to_le16(0x0060); + + cp2.role = 0x00; /* WbDisable */ + cp2.pkt_type = cpu_to_le16(0x0002); + hci_send_cmd(hdev, HCI_BCM_ENABLE_WBS_REQ, sizeof(cp2), &cp2); + + cp3.i2c_enable = 0x00; + cp3.is_master = 0x00; + cp3.pcm_rate = 0x00; + cp3.clock_rate = 0x04; + hci_send_cmd(hdev, HCI_BCM_I2C_PCM_REQ, sizeof(cp3), &cp3); + + cp4.sco_routing = 0x00; + cp4.pcm_rate = 0x04; + cp4.frame_type = 0x00; + cp4.sync_mode = 0x00; + cp4.clock_mode = 0x00; + hci_send_cmd(hdev, HCI_BCM_SCO_PCM_REQ, sizeof(cp4), &cp4); +} + +void sco_connect_set_wbc(struct hci_dev *hdev) +{ + struct hci_cp_write_voice_setting cp1; + struct hci_cp_bcm_wbs_req cp2; + struct hci_cp_i2c_pcm_req cp3; + struct hci_cp_sco_pcm_req cp4; + + BT_DBG("Setting the WBC params, hdev = %p", hdev); + cp1.voice_setting = cpu_to_le16(0x0003 | 0x0060); + hci_send_cmd(hdev, HCI_OP_WRITE_VOICE_SETTING, sizeof(cp1), &cp1); + hdev->voice_setting = cpu_to_le16(0x0003 | 0x0060); + + cp2.role = 0x01; /* Enable */ + cp2.pkt_type = cpu_to_le16(0x0002); + hci_send_cmd(hdev, HCI_BCM_ENABLE_WBS_REQ, sizeof(cp2), &cp2); + + cp3.i2c_enable = 0x00; + cp3.is_master = 0x00; + cp3.pcm_rate = 0x01; + cp3.clock_rate = 0x04; + hci_send_cmd(hdev, HCI_BCM_I2C_PCM_REQ, sizeof(cp3), &cp3); + + cp4.sco_routing = 0x00; + cp4.pcm_rate = 0x04; + cp4.frame_type = 0x00; + cp4.sync_mode = 0x00; + cp4.clock_mode = 0x00; + hci_send_cmd(hdev, HCI_BCM_SCO_PCM_REQ, sizeof(cp4), &cp4); +} +#endif + /* ----- SCO interface with lower layer (HCI) ----- */ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) { @@ -1094,8 +1240,14 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) if (sk->sk_state != BT_LISTEN) continue; +#ifdef TIZEN_BT + /* Multiple SCO accept feature */ + if (!bacmp(&sco_pi(sk)->src, bdaddr) || + !bacmp(&sco_pi(sk)->src, BDADDR_ANY)) { +#else if (!bacmp(&sco_pi(sk)->src, &hdev->bdaddr) || !bacmp(&sco_pi(sk)->src, BDADDR_ANY)) { +#endif lm |= HCI_LM_ACCEPT; if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) @@ -1105,6 +1257,36 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) } read_unlock(&sco_sk_list.lock); +#ifdef TIZEN_BT + /* WBC/NBC feature */ + if ((lm & HCI_LM_ACCEPT) && !hci_conn_hash_lookup_sco(hdev)) { + struct hci_conn *hcon_acl; + + hcon_acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, bdaddr); + if (!hcon_acl) { + BT_ERR("ACL doesn't alive. Use 0x%X", + hdev->voice_setting); + + if (hdev->voice_setting == 0x0063) + sco_connect_set_wbc(hdev); + else + sco_connect_set_nbc(hdev); + } else if (hcon_acl->sco_role == MGMT_SCO_ROLE_HANDSFREE) { + BT_DBG("Handsfree SCO 0x%X", hcon_acl->voice_setting); + if (hcon_acl->voice_setting == 0x0063) + sco_connect_set_wbc(hdev); + else + sco_connect_set_nbc(hdev); + } else { + BT_DBG("Gateway SCO 0x%X", hcon_acl->voice_setting); + if (hcon_acl->voice_setting == 0x0063) + sco_connect_set_gw_wbc(hdev); + else + sco_connect_set_gw_nbc(hdev); + } + } +#endif + return lm; } -- 2.7.4 From f09ac1d2189035c556c1ca14144b831b6f0b453b Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 8 Sep 2016 12:37:45 +0530 Subject: [PATCH 08/16] Bluetooth: Set the link for SCO connection This patch sets the link policy for SCO/eSCO connection. Change-Id: I71caef5a3887f73a10329b6886c8cf52b80e8d37 Signed-off-by: Sudha Bheemanna [add link policy setting in sco connection] Signed-off-by: Seung-Woo Kim Signed-off-by: Amit Purwar --- net/bluetooth/hci_event.c | 29 +++++++++++++++++++++++++++++ net/bluetooth/sco.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 17a734c..aff1855 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -156,6 +156,10 @@ static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) struct hci_rp_write_link_policy *rp = (void *) skb->data; struct hci_conn *conn; void *sent; +#ifdef TIZEN_BT + struct hci_cp_write_link_policy cp; + struct hci_conn *sco_conn; +#endif BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); @@ -172,6 +176,17 @@ static void hci_cc_write_link_policy(struct hci_dev *hdev, struct sk_buff *skb) if (conn) conn->link_policy = get_unaligned_le16(sent + 2); +#ifdef TIZEN_BT + sco_conn = hci_conn_hash_lookup_sco(hdev); + if (sco_conn && bacmp(&sco_conn->dst, &conn->dst) == 0 && + conn->link_policy & HCI_LP_SNIFF) { + BT_ERR("SNIFF is not allowed during sco connection"); + cp.handle = __cpu_to_le16(conn->handle); + cp.policy = __cpu_to_le16(conn->link_policy & ~HCI_LP_SNIFF); + hci_send_cmd(hdev, HCI_OP_WRITE_LINK_POLICY, sizeof(cp), &cp); + } +#endif + hci_dev_unlock(hdev); } @@ -2390,6 +2405,20 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) if (ie) memcpy(ie->data.dev_class, ev->dev_class, 3); +#ifdef TIZEN_BT + if ((ev->link_type == SCO_LINK || ev->link_type == ESCO_LINK) && + hci_conn_hash_lookup_sco(hdev)) { + struct hci_cp_reject_conn_req cp; + + bacpy(&cp.bdaddr, &ev->bdaddr); + cp.reason = HCI_ERROR_REJ_LIMITED_RESOURCES; + hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, + sizeof(cp), &cp); + hci_dev_unlock(hdev); + return; + } +#endif + conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); if (!conn) { diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index c665a5e..2d5ba2d 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -1102,6 +1102,29 @@ static void sco_conn_ready(struct sco_conn *conn) } #ifdef TIZEN_BT +/* Link policy */ +static int hci_write_acl_link_policy(struct hci_conn *hcon, uint16_t policy) +{ + struct hci_conn *hcon_acl; + struct hci_cp_write_link_policy cp; + + BT_DBG("Write link Policy %d", policy); + + hcon_acl = hci_conn_hash_lookup_ba(hcon->hdev, ACL_LINK, &hcon->dst); + if (!hcon_acl) { + BT_ERR("ACL does not alive"); + return -1; + } + + memset(&cp, 0, sizeof(cp)); + cp.handle = __cpu_to_le16(hcon_acl->handle); + cp.policy = __cpu_to_le16(policy); + + hci_send_cmd(hcon_acl->hdev, HCI_OP_WRITE_LINK_POLICY, sizeof(cp), &cp); + + return 0; +} + /* WBC/NBC feature */ void sco_connect_set_gw_nbc(struct hci_dev *hdev) { @@ -1303,6 +1326,11 @@ static void sco_connect_cfm(struct hci_conn *hcon, __u8 status) conn = sco_conn_add(hcon); if (conn) sco_conn_ready(conn); + +#ifdef TIZEN_BT + /* Link policy */ + hci_write_acl_link_policy(hcon, HCI_LP_RSWITCH); +#endif } else sco_conn_del(hcon, bt_to_errno(status)); } @@ -1314,6 +1342,11 @@ static void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) BT_DBG("hcon %p reason %d", hcon, reason); +#ifdef TIZEN_BT + /* Link policy */ + hci_write_acl_link_policy(hcon, HCI_LP_SNIFF | HCI_LP_RSWITCH); +#endif + sco_conn_del(hcon, bt_to_errno(reason)); } -- 2.7.4 From d0bce3e55edf845f61a2c9b593f8fab4096617e7 Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Wed, 7 Sep 2016 15:22:08 +0530 Subject: [PATCH 09/16] Bluetooth: Get Advertising TX power This patch adds MGMT command to read the advertising TX power. Change-Id: Ide9e5d332f034928d2eae2cbd68a025a0d42be1b Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- include/net/bluetooth/mgmt_tizen.h | 6 ++++++ net/bluetooth/mgmt.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/include/net/bluetooth/mgmt_tizen.h b/include/net/bluetooth/mgmt_tizen.h index 4eaa867..982c00d 100644 --- a/include/net/bluetooth/mgmt_tizen.h +++ b/include/net/bluetooth/mgmt_tizen.h @@ -161,6 +161,12 @@ struct mgmt_cp_set_voice_setting { } __packed; #define MGMT_SET_VOICE_SETTING_SIZE 9 +#define MGMT_OP_GET_ADV_TX_POWER (TIZEN_OP_CODE_BASE + 0x11) +#define MGMT_GET_ADV_TX_POWER_SIZE 0 +struct mgmt_rp_get_adv_tx_power { + __s8 adv_tx_power; +} __packed; + /* EVENTS */ /* For device name update changes */ diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 0c8bec1..25be8b3 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -6441,6 +6441,37 @@ unlock: return err; } +static int get_adv_tx_power(struct sock *sk, struct hci_dev *hdev, + void *data, u16 len) +{ + struct mgmt_rp_get_adv_tx_power *rp; + size_t rp_len; + int err; + + BT_DBG("%s", hdev->name); + + hci_dev_lock(hdev); + + rp_len = sizeof(*rp); + rp = kmalloc(rp_len, GFP_KERNEL); + if (!rp) { + err = -ENOMEM; + goto unlock; + } + + rp->adv_tx_power = hdev->adv_tx_power; + + err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_GET_ADV_TX_POWER, 0, rp, + rp_len); + + kfree(rp); + +unlock: + hci_dev_unlock(hdev); + + return err; +} + void mgmt_hardware_error(struct hci_dev *hdev, u8 err_code) { struct mgmt_ev_hardware_error ev; @@ -8419,6 +8450,7 @@ static const struct hci_mgmt_handler tizen_mgmt_handlers[] = { { set_manufacturer_data, MGMT_SET_MANUFACTURER_DATA_SIZE }, { le_set_scan_params, MGMT_LE_SET_SCAN_PARAMS_SIZE }, { set_voice_setting, MGMT_SET_VOICE_SETTING_SIZE }, + { get_adv_tx_power, MGMT_GET_ADV_TX_POWER_SIZE }, }; #endif -- 2.7.4 From 6a2c6ccbe3c6f97b1c91b9581fa0bbed2d371dba Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 8 Sep 2016 11:21:06 +0530 Subject: [PATCH 10/16] Bluetooth: Set filter policy for LE connection This patch sets the filter policy to a default value 0x01 during LE auto connection if the destination address is not set. And it updates the destination address once the LE connection complete event is recieved during LE auto connection. And for it checks valid destination address before cancelling LE connection when connection timeout occurs. Change-Id: I9877556c0b0ab4826f5f4934ead4d85b7837036d Signed-off-by: Sudha Bheemanna [squash patches, LE connection policy, set dest address and check dest address before cancelling connection] Signed-off-by: Seung-Woo Kim Signed-off-by: Amit Purwar --- net/bluetooth/hci_conn.c | 8 ++++++++ net/bluetooth/hci_event.c | 4 ++++ net/bluetooth/hci_request.c | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 074c8f1..76fd976 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -802,7 +802,15 @@ static void hci_req_add_le_create_conn(struct hci_request *req, cp.scan_interval = cpu_to_le16(hdev->le_scan_interval); cp.scan_window = cp.scan_interval; +#ifdef TIZEN_BT + /* LE auto connect */ + if (!bacmp(&conn->dst, BDADDR_ANY)) + cp.filter_policy = 0x1; + else + bacpy(&cp.peer_addr, &conn->dst); +#else bacpy(&cp.peer_addr, &conn->dst); +#endif cp.peer_addr_type = conn->dst_type; cp.own_address_type = own_addr_type; cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval); diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index aff1855..f4c3676 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -4657,6 +4657,10 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) } } } else { +#ifdef TIZEN_BT + /* LE auto connect */ + bacpy(&conn->dst, &ev->bdaddr); +#endif cancel_delayed_work(&conn->le_conn_timeout); } diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 3c4ca4b..876363f8 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c @@ -1751,7 +1751,11 @@ void __hci_abort_conn(struct hci_request *req, struct hci_conn *conn, break; case BT_CONNECT: +#ifdef TIZEN_BT + if (conn->type == LE_LINK && bacmp(&conn->dst, BDADDR_ANY)) { +#else if (conn->type == LE_LINK) { +#endif if (test_bit(HCI_CONN_SCANNING, &conn->flags)) break; hci_req_add(req, HCI_OP_LE_CREATE_CONN_CANCEL, -- 2.7.4 From 0b1d08db7298185dfec22ae597dcd1c65d35a6bc Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 8 Sep 2016 12:24:43 +0530 Subject: [PATCH 11/16] Bluetooth: Set link Supervision timeout for a connection This patch allows to set the supervision timeout for a connection if the device role is master. Change-Id: I7897167ec07803f3059f2ab4d3314b0b7a951533 Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- include/net/bluetooth/bluetooth.h | 7 +++++++ include/net/bluetooth/hci.h | 15 +++++++++++++++ include/net/bluetooth/hci_core.h | 8 ++++++++ net/bluetooth/hci_conn.c | 27 +++++++++++++++++++++++++++ net/bluetooth/hci_core.c | 8 +++++++- net/bluetooth/hci_event.c | 10 ++++++++++ 6 files changed, 74 insertions(+), 1 deletion(-) diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h index ca445d6..69f3947 100644 --- a/include/net/bluetooth/bluetooth.h +++ b/include/net/bluetooth/bluetooth.h @@ -195,6 +195,13 @@ typedef struct { __u8 b[6]; } __packed bdaddr_t; +#ifdef TIZEN_BT +/* Automatically enable sniff mode for connection. + * In case of normal phone this timeout would be 5 seconds + */ +#define TIZEN_SNIFF_TIMEOUT 5 /* 5 seconds */ +#endif + /* BD Address type */ #define BDADDR_BREDR 0x00 #define BDADDR_LE_PUBLIC 0x01 diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 3fdc0c0..663b23e 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -987,6 +987,21 @@ struct hci_cp_host_buffer_size { __le16 sco_max_pkt; } __packed; +#ifdef TIZEN_BT +/* Set Link supervision timeout */ +#define HCI_OP_WRITE_LINK_SUPERVISION_TIMEOUT 0x0c37 +struct hci_cp_write_link_supervision_timeout { + __le16 handle; + __le16 timeout; +} __packed; + +struct hci_rp_write_link_supervision_timeout { + __u8 status; + __le16 handle; +} __packed; +/* Set Link supervision timeout */ +#endif /* TIZEN_BT */ + #define HCI_OP_READ_NUM_SUPPORTED_IAC 0x0c38 struct hci_rp_read_num_supported_iac { __u8 status; diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 3ddbdbc..1b5d6e2 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -658,6 +658,10 @@ u32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, void hci_inquiry_cache_flush(struct hci_dev *hdev); /* ----- HCI Connections ----- */ +#ifdef TIZEN_BT +#define LINK_SUPERVISION_TIMEOUT 0x1F40 /* n * 0.625 = 5 seconds */ +#endif /* TIZEN_BT */ + enum { HCI_CONN_AUTH_PEND, HCI_CONN_REAUTH_PEND, @@ -958,6 +962,7 @@ static inline int hci_conn_hash_lookup_rssi_count(struct hci_dev *hdev) return count; } +int hci_conn_change_supervision_timeout(struct hci_conn *conn, __u16 timeout); bool hci_le_discovery_active(struct hci_dev *hdev); void hci_le_discovery_set_state(struct hci_dev *hdev, int state); @@ -1148,6 +1153,9 @@ int hci_get_dev_info(void __user *arg); int hci_get_conn_list(void __user *arg); int hci_get_conn_info(struct hci_dev *hdev, void __user *arg); int hci_get_auth_info(struct hci_dev *hdev, void __user *arg); +#ifdef TIZEN_BT +u32 get_link_mode(struct hci_conn *conn); +#endif int hci_inquiry(void __user *arg); struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *list, diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 76fd976..d4f5829 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -1381,6 +1381,29 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role) } EXPORT_SYMBOL(hci_conn_switch_role); +#ifdef TIZEN_BT +int hci_conn_change_supervision_timeout(struct hci_conn *conn, __u16 timeout) +{ + struct hci_cp_write_link_supervision_timeout cp; + + if (!((get_link_mode(conn)) & HCI_LM_MASTER)) + return 1; + + if (conn->handle == 0) + return 1; + + memset(&cp, 0, sizeof(cp)); + cp.handle = cpu_to_le16(conn->handle); + cp.timeout = cpu_to_le16(timeout); + + if (hci_send_cmd(conn->hdev, HCI_OP_WRITE_LINK_SUPERVISION_TIMEOUT, + sizeof(cp), &cp) < 0) + BT_ERR("HCI_OP_WRITE_LINK_SUPERVISION_TIMEOUT is failed"); + + return 0; +} +#endif + /* Enter active mode */ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active) { @@ -1438,7 +1461,11 @@ void hci_conn_check_pending(struct hci_dev *hdev) hci_dev_unlock(hdev); } +#ifndef TIZEN_BT static u32 get_link_mode(struct hci_conn *conn) +#else +u32 get_link_mode(struct hci_conn *conn) +#endif { u32 link_mode = 0; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 301b1e0..c371595 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -3012,12 +3012,18 @@ struct hci_dev *hci_alloc_dev(void) hdev->adv_instance_timeout = 0; hdev->sniff_max_interval = 800; +#ifdef TIZEN_BT + hdev->sniff_min_interval = 400; +#else hdev->sniff_min_interval = 80; - +#endif hdev->le_adv_channel_map = 0x07; hdev->le_adv_min_interval = 0x0800; hdev->le_adv_max_interval = 0x0800; #ifdef TIZEN_BT + /* automatically enable sniff mode for connection */ + hdev->idle_timeout = TIZEN_SNIFF_TIMEOUT * 1000; + hdev->adv_filter_policy = 0x00; hdev->adv_type = 0x00; #endif diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index f4c3676..c4ceb47 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2329,6 +2329,11 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) hci_send_cmd(hdev, HCI_OP_CHANGE_CONN_PTYPE, sizeof(cp), &cp); } +#ifdef TIZEN_BT + if (get_link_mode(conn) & HCI_LM_MASTER) + hci_conn_change_supervision_timeout(conn, + LINK_SUPERVISION_TIMEOUT); +#endif } else { conn->state = BT_CLOSED; if (conn->type == ACL_LINK) @@ -3329,6 +3334,11 @@ static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); hci_role_switch_cfm(conn, ev->status, ev->role); +#ifdef TIZEN_BT + if (!ev->status && (get_link_mode(conn) & HCI_LM_MASTER)) + hci_conn_change_supervision_timeout(conn, + LINK_SUPERVISION_TIMEOUT); +#endif } hci_dev_unlock(hdev); -- 2.7.4 From 0d12fa7a9652394ee2930c0e948e5e61faabe76c Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 8 Sep 2016 13:04:11 +0530 Subject: [PATCH 12/16] Bluetooth: Change authentication requirement. This patch updates the authentication requirement to general MITM if local and remote device IO capabilities are not NO_INPUT_NO_OUTPUT. Change-Id: Ie3955c3f8287418e74af20d40bdf30d0f1963e31 Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- net/bluetooth/hci_event.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index c4ceb47..6d16935 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -4078,6 +4078,14 @@ unlock: static u8 hci_get_auth_req(struct hci_conn *conn) { +#ifdef TIZEN_BT + if (conn->remote_auth == HCI_AT_GENERAL_BONDING_MITM) { + if (conn->remote_cap != HCI_IO_NO_INPUT_OUTPUT && + conn->io_capability != HCI_IO_NO_INPUT_OUTPUT) + return HCI_AT_GENERAL_BONDING_MITM; + } +#endif + /* If remote requests no-bonding follow that lead */ if (conn->remote_auth == HCI_AT_NO_BONDING || conn->remote_auth == HCI_AT_NO_BONDING_MITM) -- 2.7.4 From a3e73b2a6ebce11b43021a95532ace0f558a2b90 Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 8 Sep 2016 14:54:54 +0530 Subject: [PATCH 13/16] Bluetooth: Enable inquiry and page scan This patch enables the inquiry and page scan after ACL disconnection with one device and if there are no other devices connected. Change-Id: Ifb28be7d23f237d35112b2e0739ed55169baacf7 Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- net/bluetooth/hci_event.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 6d16935..b1001fe 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2570,6 +2570,22 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) if (type == LE_LINK) hci_req_reenable_advertising(hdev); +#ifdef TIZEN_BT + if (type == ACL_LINK && !hci_conn_num(hdev, ACL_LINK)) { + int iscan; + int pscan; + + iscan = test_bit(HCI_ISCAN, &hdev->flags); + pscan = test_bit(HCI_PSCAN, &hdev->flags); + if (!iscan && !pscan) { + u8 scan_enable = SCAN_PAGE; + + hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, + sizeof(scan_enable), &scan_enable); + } + } +#endif + unlock: hci_dev_unlock(hdev); } -- 2.7.4 From 444222275b48c8dc73d0601fba13ba84c67d9347 Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 8 Sep 2016 15:11:28 +0530 Subject: [PATCH 14/16] Bluetooth: Send Authentication Request command on pairing failure This patch allows to send HCI_OP_AUTH_REQUESTED command to the remote device if pairing failure happens because of pin or key missing error. Change-Id: I9c28394dc06b22fd5fe9e58ac0b7d728c086bde4 Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- net/bluetooth/hci_event.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index b1001fe..feb1d7e 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -2603,6 +2603,24 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) if (!conn) goto unlock; +#ifdef TIZEN_BT + /* PIN or Key Missing patch */ + BT_DBG("remote_auth %x, remote_cap %x, auth_type %x, io_capability %x", + conn->remote_auth, conn->remote_cap, + conn->auth_type, conn->io_capability); + + if (ev->status == 0x06 && hci_conn_ssp_enabled(conn)) { + struct hci_cp_auth_requested cp; + + BT_DBG("Pin or key missing"); + hci_remove_link_key(hdev, &conn->dst); + cp.handle = cpu_to_le16(conn->handle); + hci_send_cmd(conn->hdev, HCI_OP_AUTH_REQUESTED, + sizeof(cp), &cp); + goto unlock; + } +#endif + if (!ev->status) { clear_bit(HCI_CONN_AUTH_FAILURE, &conn->flags); -- 2.7.4 From 44b396e62f133eacb9eb9080bcfc99b1844102e1 Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 8 Sep 2016 16:01:23 +0530 Subject: [PATCH 15/16] Bluetooth: Modify fast connectable type. This patch modifies the fast connectable function to just set the type. Change-Id: I0cce96f85d823f9798ae7f147c4e33ce7b18e0e3 Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- net/bluetooth/hci_request.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 876363f8..79443bb 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c @@ -352,7 +352,9 @@ void hci_req_add(struct hci_request *req, u16 opcode, u32 plen, void __hci_req_write_fast_connectable(struct hci_request *req, bool enable) { struct hci_dev *hdev = req->hdev; +#ifndef TIZEN_BT struct hci_cp_write_page_scan_activity acp; +#endif u8 type; if (!hci_dev_test_flag(hdev, HCI_BREDR_ENABLED)) @@ -361,6 +363,12 @@ void __hci_req_write_fast_connectable(struct hci_request *req, bool enable) if (hdev->hci_ver < BLUETOOTH_VER_1_2) return; +#ifdef TIZEN_BT + if (enable) + type = PAGE_SCAN_TYPE_INTERLACED; + else + type = PAGE_SCAN_TYPE_STANDARD; /* default */ +#else if (enable) { type = PAGE_SCAN_TYPE_INTERLACED; @@ -379,6 +387,7 @@ void __hci_req_write_fast_connectable(struct hci_request *req, bool enable) __cpu_to_le16(hdev->page_scan_window) != acp.window) hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_ACTIVITY, sizeof(acp), &acp); +#endif if (hdev->page_scan_type != type) hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); -- 2.7.4 From 9f61ee597cc495bf1956fc36b2fa8a56307a43c0 Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 8 Sep 2016 16:40:50 +0530 Subject: [PATCH 16/16] Bluetooth: Enable sniff mode for incoming connection Add provision to set the link poilicy to enable sniff mode for incoming connection. Change-Id: Ifff9e9f0838f26a6c96d81f4cbaae43429aa231f Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- net/bluetooth/hci_conn.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index d4f5829..2a3b3b8 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -536,6 +536,11 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, conn->tx_power = HCI_TX_POWER_INVALID; conn->max_tx_power = HCI_TX_POWER_INVALID; +#ifdef TIZEN_BT + /* enable sniff mode for incoming connection */ + conn->link_policy = hdev->link_policy; +#endif + set_bit(HCI_CONN_POWER_SAVE, &conn->flags); conn->disc_timeout = HCI_DISCONN_TIMEOUT; -- 2.7.4