From 0d12fa7a9652394ee2930c0e948e5e61faabe76c Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 8 Sep 2016 13:04:11 +0530 Subject: [PATCH 01/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 02/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 03/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 04/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 05/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 From f596367819a6b2d66ccf83f0ead6465b07810f64 Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 8 Sep 2016 17:01:39 +0530 Subject: [PATCH 06/16] Bluetooth: Cancel the Sniff timer This patch adds code to cancel the sniff timer. Change-Id: I756d3b08acf6462044d1fb204064fe12ce1238c1 Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- net/bluetooth/hci_conn.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 2a3b3b8..e64f0b3 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -1429,9 +1429,18 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active) } timer: +#ifdef TIZEN_BT + if (hdev->idle_timeout > 0) { + /* Sniff timer cancel */ + cancel_delayed_work(&conn->idle_work); + queue_delayed_work(hdev->workqueue, &conn->idle_work, + msecs_to_jiffies(hdev->idle_timeout)); + } +#else if (hdev->idle_timeout > 0) queue_delayed_work(hdev->workqueue, &conn->idle_work, msecs_to_jiffies(hdev->idle_timeout)); +#endif } /* Drop all connection on the device */ -- 2.7.4 From 3374963e76ae60c9398f0018c88c8b9199076a28 Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Mon, 12 Sep 2016 12:46:44 +0530 Subject: [PATCH 07/16] Bluetooth: Store the key if auth type is P192 This patch allows to store the key after authentication if auth type is "HCI_LK_AUTH_COMBINATION_P192" Change-Id: Ie44dbe7dfec361edab61aceaf9b2ca4057b88fa5 Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- net/bluetooth/hci_core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index c371595..b1d98ee 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2266,6 +2266,14 @@ static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, if (conn->remote_auth == 0x02 || conn->remote_auth == 0x03) return true; +#ifdef TIZEN_BT + /* In case of auth_type '0x01', it is authenticated by MITM. + * So store it. + */ + if (key_type == HCI_LK_AUTH_COMBINATION_P192) + return true; +#endif + /* If none of the above criteria match, then don't store the key * persistently */ return false; -- 2.7.4 From 547f8992e9bf4260cf0bcb0f5b550d0e14af0387 Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 8 Sep 2016 16:21:01 +0530 Subject: [PATCH 08/16] Bluetooth: Fix issue in the Set LE privacy function. This patch fixes not to check the hdev power before setting LE Privacy. Change-Id: I344ea13b1d90527e3e7554ec616cdc640b85159c Signed-off-by: Sudha Bheemanna Signed-off-by: Seung-Woo Kim Signed-off-by: Amit Purwar --- net/bluetooth/mgmt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 25be8b3..b67650b 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -4599,9 +4599,14 @@ static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, MGMT_STATUS_INVALID_PARAMS); +#ifndef TIZEN_BT + /* commenting out since set privacy command is always rejected + * if this condition is enabled. + */ if (hdev_is_powered(hdev)) return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, MGMT_STATUS_REJECTED); +#endif hci_dev_lock(hdev); -- 2.7.4 From 2d9d4b3a28bed8976867354e146ee08d895a7a3e Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 15 Sep 2016 10:12:09 +0530 Subject: [PATCH 09/16] Bluetooth: Add support to enable/disable IPSP This patch supports MGMT commands and code to enable or disable IPSP 6LowPan features. Change-Id: Ia866ecfa517c7d7e4320f17d94d80dfeb9261e59 Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- include/net/bluetooth/l2cap.h | 11 +++++++++++ include/net/bluetooth/mgmt_tizen.h | 6 ++++++ net/bluetooth/6lowpan.c | 34 ++++++++++++++++++++++++++++++++++ net/bluetooth/mgmt.c | 35 +++++++++++++++++++++++++++++++++++ 4 files changed, 86 insertions(+) diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index 9c50d45..c7abda1 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -950,4 +950,15 @@ void l2cap_conn_put(struct l2cap_conn *conn); int l2cap_register_user(struct l2cap_conn *conn, struct l2cap_user *user); void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user); +#ifdef TIZEN_BT +#ifdef CONFIG_BT_6LOWPAN +/* IPSP : initialize/deinitialize 6lowpan */ +void bt_6lowpan_enable(void); +void bt_6lowpan_disable(void); +#else +static inline void bt_6lowpan_enable(void) { } +static inline void bt_6lowpan_disable(void) { } +#endif +#endif /* TIZEN_BT */ + #endif /* __L2CAP_H */ diff --git a/include/net/bluetooth/mgmt_tizen.h b/include/net/bluetooth/mgmt_tizen.h index 982c00d..6549be1 100644 --- a/include/net/bluetooth/mgmt_tizen.h +++ b/include/net/bluetooth/mgmt_tizen.h @@ -167,6 +167,12 @@ struct mgmt_rp_get_adv_tx_power { __s8 adv_tx_power; } __packed; +#define MGMT_OP_ENABLE_6LOWPAN (TIZEN_OP_CODE_BASE + 0x12) +struct mgmt_cp_enable_6lowpan { + __u8 enable_6lowpan; +} __packed; +#define MGMT_ENABLE_BT_6LOWPAN_SIZE 1 + /* EVENTS */ /* For device name update changes */ diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 3bfd747..b336725 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c @@ -1404,6 +1404,40 @@ static int __init bt_6lowpan_init(void) return register_netdevice_notifier(&bt_6lowpan_dev_notifier); } +#ifdef TIZEN_BT +void bt_6lowpan_enable(void) +{ + if (!enable_6lowpan) { + disconnect_all_peers(); + + enable_6lowpan = true; + + if (listen_chan) { + l2cap_chan_close(listen_chan, 0); + l2cap_chan_put(listen_chan); + } + + listen_chan = bt_6lowpan_listen(); + + register_netdevice_notifier(&bt_6lowpan_dev_notifier); + } +} + +void bt_6lowpan_disable(void) +{ + if (enable_6lowpan) { + if (listen_chan) { + l2cap_chan_close(listen_chan, 0); + l2cap_chan_put(listen_chan); + listen_chan = NULL; + } + disconnect_devices(); + unregister_netdevice_notifier(&bt_6lowpan_dev_notifier); + enable_6lowpan = false; + } +} +#endif + static void __exit bt_6lowpan_exit(void) { debugfs_remove(lowpan_enable_debugfs); diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index b67650b..bb4e312 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -6506,6 +6506,40 @@ void mgmt_multi_adv_state_change_evt(struct hci_dev *hdev, u8 adv_instance, sizeof(struct mgmt_ev_vendor_specific_multi_adv_state_changed), NULL); } + +static int enable_bt_6lowpan(struct sock *sk, struct hci_dev *hdev, + void *data, u16 len) +{ + int err; + struct mgmt_cp_enable_6lowpan *cp = data; + + BT_DBG("%s", hdev->name); + + hci_dev_lock(hdev); + + if (!hdev_is_powered(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ENABLE_6LOWPAN, + MGMT_STATUS_NOT_POWERED); + goto unlocked; + } + + if (!lmp_le_capable(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_ENABLE_6LOWPAN, + MGMT_STATUS_NOT_SUPPORTED); + goto unlocked; + } + + if (cp->enable_6lowpan) + bt_6lowpan_enable(); + else + bt_6lowpan_disable(); + + err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ENABLE_6LOWPAN, + MGMT_STATUS_SUCCESS, NULL, 0); +unlocked: + hci_dev_unlock(hdev); + return err; +} #endif /* TIZEN_BT */ static bool ltk_is_valid(struct mgmt_ltk_info *key) @@ -8456,6 +8490,7 @@ static const struct hci_mgmt_handler tizen_mgmt_handlers[] = { { 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 }, + { enable_bt_6lowpan, MGMT_ENABLE_BT_6LOWPAN_SIZE }, }; #endif -- 2.7.4 From 34f06a0722cdf8abcb86fcfb430bf0976096f76f Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Thu, 15 Sep 2016 12:53:03 +0530 Subject: [PATCH 10/16] Bluetooth: IPSP Connect/Disconnect apis This patch adds MGMT code to support IPSP connect and disconnect apis and handle connection state changed event. Change-Id: I1c41ec4f38cf9a108e443def3bc23c1b964e2985 Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- include/net/bluetooth/hci_core.h | 2 + include/net/bluetooth/l2cap.h | 5 ++ include/net/bluetooth/mgmt_tizen.h | 18 +++++ net/bluetooth/6lowpan.c | 16 ++++ net/bluetooth/mgmt.c | 150 +++++++++++++++++++++++++++++++++++++ 5 files changed, 191 insertions(+) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 1b5d6e2..ee6d95e 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1690,6 +1690,8 @@ void mgmt_le_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, 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); +void mgmt_6lowpan_conn_changed(struct hci_dev *hdev, char if_name[16], + bdaddr_t *bdaddr, u8 addr_type, bool connected); #endif u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency, diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index c7abda1..312ff74 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -955,9 +955,14 @@ void l2cap_unregister_user(struct l2cap_conn *conn, struct l2cap_user *user); /* IPSP : initialize/deinitialize 6lowpan */ void bt_6lowpan_enable(void); void bt_6lowpan_disable(void); +/* IPSP: Connect and Disconnect */ +int _bt_6lowpan_connect(bdaddr_t *addr, u8 dst_type); +int _bt_6lowpan_disconnect(struct l2cap_conn *conn, u8 dst_type); #else static inline void bt_6lowpan_enable(void) { } static inline void bt_6lowpan_disable(void) { } +static inline int _bt_6lowpan_connect(bdaddr_t *addr, u8 dst_type) { return -ENODEV; } +static inline int _bt_6lowpan_disconnect(struct l2cap_conn *conn, u8 dst_type) { return -ENODEV; } #endif #endif /* TIZEN_BT */ diff --git a/include/net/bluetooth/mgmt_tizen.h b/include/net/bluetooth/mgmt_tizen.h index 6549be1..52a36f9 100644 --- a/include/net/bluetooth/mgmt_tizen.h +++ b/include/net/bluetooth/mgmt_tizen.h @@ -173,6 +173,18 @@ struct mgmt_cp_enable_6lowpan { } __packed; #define MGMT_ENABLE_BT_6LOWPAN_SIZE 1 +#define MGMT_OP_CONNECT_6LOWPAN (TIZEN_OP_CODE_BASE + 0x13) +struct mgmt_cp_connect_6lowpan { + struct mgmt_addr_info addr; +} __packed; +#define MGMT_CONNECT_6LOWPAN_SIZE 7 + +#define MGMT_OP_DISCONNECT_6LOWPAN (TIZEN_OP_CODE_BASE + 0x14) +struct mgmt_cp_disconnect_6lowpan { + struct mgmt_addr_info addr; +} __packed; +#define MGMT_DISCONNECT_6LOWPAN_SIZE 7 + /* EVENTS */ /* For device name update changes */ @@ -254,5 +266,11 @@ struct mgmt_ev_vendor_specific_multi_adv_state_changed { } __packed; /* LE advertisement state changed event */ +#define MGMT_EV_6LOWPAN_CONN_STATE_CHANGED (TIZEN_EV_BASE + 0x0c) +struct mgmt_ev_6lowpan_conn_state_changed { + struct mgmt_addr_info addr; + __u8 connected; + __u8 ifname[16]; +} __packed; #endif /* __MGMT_TIZEN_H */ diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index b336725..9bd9efd 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c @@ -871,6 +871,12 @@ static inline void chan_ready_cb(struct l2cap_chan *chan) add_peer_chan(chan, dev, new_netdev); ifup(dev->netdev); + +#ifdef TIZEN_BT + /* IPSP: Send connection changed state info to bluez */ + mgmt_6lowpan_conn_changed(dev->hdev, dev->netdev->name, &chan->dst, + chan->dst_type, true); +#endif } static inline struct l2cap_chan *chan_new_conn_cb(struct l2cap_chan *pchan) @@ -1436,6 +1442,16 @@ void bt_6lowpan_disable(void) enable_6lowpan = false; } } + +int _bt_6lowpan_connect(bdaddr_t *addr, u8 dst_type) +{ + return bt_6lowpan_connect(addr, dst_type); +} + +int _bt_6lowpan_disconnect(struct l2cap_conn *conn, u8 dst_type) +{ + return bt_6lowpan_disconnect(conn, dst_type); +} #endif static void __exit bt_6lowpan_exit(void) diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index bb4e312..279cb97 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -6540,6 +6540,154 @@ unlocked: hci_dev_unlock(hdev); return err; } + +static int connect_bt_6lowpan(struct sock *sk, struct hci_dev *hdev, + void *data, u16 len) +{ + struct mgmt_cp_connect_6lowpan *cp = data; + __u8 addr_type = ADDR_LE_DEV_PUBLIC; + int err; + + BT_DBG("%s", hdev->name); + + hci_dev_lock(hdev); + + if (!lmp_le_capable(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CONNECT_6LOWPAN, + MGMT_STATUS_NOT_SUPPORTED); + goto unlocked; + } + + if (!hdev_is_powered(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_CONNECT_6LOWPAN, + MGMT_STATUS_REJECTED); + goto unlocked; + } + + if (bdaddr_type_is_le(cp->addr.type)) { + if (cp->addr.type == BDADDR_LE_PUBLIC) + addr_type = ADDR_LE_DEV_PUBLIC; + else + addr_type = ADDR_LE_DEV_RANDOM; + } else { + err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONNECT_6LOWPAN, + MGMT_STATUS_INVALID_PARAMS, NULL, 0); + goto unlocked; + } + + hci_dev_unlock(hdev); + + /* 6lowpan Connect */ + err = _bt_6lowpan_connect(&cp->addr.bdaddr, cp->addr.type); + + hci_dev_lock(hdev); + + if (err < 0) { + err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONNECT_6LOWPAN, + MGMT_STATUS_REJECTED, NULL, 0); + + goto unlocked; + } + + err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONNECT_6LOWPAN, 0, + NULL, 0); +unlocked: + hci_dev_unlock(hdev); + return err; +} + +static int disconnect_bt_6lowpan(struct sock *sk, struct hci_dev *hdev, + void *data, u16 len) +{ + struct mgmt_cp_disconnect_6lowpan *cp = data; + struct hci_conn *conn = NULL; + __u8 addr_type = ADDR_LE_DEV_PUBLIC; + int err; + + BT_DBG("%s", hdev->name); + + hci_dev_lock(hdev); + + if (!lmp_le_capable(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT_6LOWPAN, + MGMT_STATUS_NOT_SUPPORTED); + goto unlocked; + } + + if (!hdev_is_powered(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_DISCONNECT_6LOWPAN, + MGMT_STATUS_REJECTED); + goto unlocked; + } + + if (bdaddr_type_is_le(cp->addr.type)) { + if (cp->addr.type == BDADDR_LE_PUBLIC) + addr_type = ADDR_LE_DEV_PUBLIC; + else + addr_type = ADDR_LE_DEV_RANDOM; + } else { + err = mgmt_cmd_complete(sk, hdev->id, + MGMT_OP_DISCONNECT_6LOWPAN, + MGMT_STATUS_INVALID_PARAMS, NULL, 0); + goto unlocked; + } + + conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->addr.bdaddr); + if (!conn) { + err = mgmt_cmd_complete(sk, hdev->id, + MGMT_OP_DISCONNECT_6LOWPAN, + MGMT_STATUS_NOT_CONNECTED, NULL, 0); + goto unlocked; + } + + if (conn->dst_type != addr_type) { + err = mgmt_cmd_complete(sk, hdev->id, + MGMT_OP_DISCONNECT_6LOWPAN, + MGMT_STATUS_INVALID_PARAMS, NULL, 0); + goto unlocked; + } + + if (conn->state != BT_CONNECTED) { + err = mgmt_cmd_complete(sk, hdev->id, + MGMT_OP_DISCONNECT_6LOWPAN, + MGMT_STATUS_NOT_CONNECTED, NULL, 0); + goto unlocked; + } + + /* 6lowpan Disconnect */ + err = _bt_6lowpan_disconnect(conn->l2cap_data, cp->addr.type); + if (err < 0) { + err = mgmt_cmd_complete(sk, hdev->id, + MGMT_OP_DISCONNECT_6LOWPAN, + MGMT_STATUS_REJECTED, NULL, 0); + goto unlocked; + } + + err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_CONNECT_6LOWPAN, 0, + NULL, 0); + +unlocked: + hci_dev_unlock(hdev); + return err; +} + +void mgmt_6lowpan_conn_changed(struct hci_dev *hdev, char if_name[16], + bdaddr_t *bdaddr, u8 addr_type, bool connected) +{ + char buf[512]; + struct mgmt_ev_6lowpan_conn_state_changed *ev = (void *)buf; + size_t ev_size; + + memset(buf, 0, sizeof(buf)); + bacpy(&ev->addr.bdaddr, bdaddr); + ev->addr.type = addr_type; + ev->connected = connected; + memcpy(ev->ifname, (__u8 *)if_name, 16); + + ev_size = sizeof(*ev); + + mgmt_event(MGMT_EV_6LOWPAN_CONN_STATE_CHANGED, hdev, ev, ev_size, NULL); +} #endif /* TIZEN_BT */ static bool ltk_is_valid(struct mgmt_ltk_info *key) @@ -8491,6 +8639,8 @@ static const struct hci_mgmt_handler tizen_mgmt_handlers[] = { { set_voice_setting, MGMT_SET_VOICE_SETTING_SIZE }, { get_adv_tx_power, MGMT_GET_ADV_TX_POWER_SIZE }, { enable_bt_6lowpan, MGMT_ENABLE_BT_6LOWPAN_SIZE }, + { connect_bt_6lowpan, MGMT_CONNECT_6LOWPAN_SIZE }, + { disconnect_bt_6lowpan, MGMT_DISCONNECT_6LOWPAN_SIZE }, }; #endif -- 2.7.4 From 833c0356e813e29aefeb55b2584b4bbbdfce71fc Mon Sep 17 00:00:00 2001 From: "h.sandeep" Date: Fri, 16 Sep 2016 14:45:24 +0530 Subject: [PATCH 11/16] Bluetooth: Fix IPSP connection callback event issue. This patch fixes the IPSP connection callback event issue between kernel and bluez layer. Change-Id: Ia4d625aa8a6dbc9da89a7d9f12308af9c90d0594 Signed-off-by: h.sandeep Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- net/bluetooth/l2cap_core.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b96818c..c7ce0d5 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -1262,8 +1262,23 @@ static void l2cap_chan_ready(struct l2cap_chan *chan) * case of receiving data before the L2CAP info req/rsp * procedure is complete. */ +#ifndef TIZEN_BT if (chan->state == BT_CONNECTED) return; +#else + if (chan->state == BT_CONNECTED) { + if (chan->psm == L2CAP_PSM_IPSP) { + struct l2cap_conn *conn = chan->conn; + + if (conn->hcon->out) + return; + else if (conn->hcon->type != LE_LINK) + return; + } else { + return; + } + } +#endif /* This clears all conf flags, including CONF_NOT_COMPLETE */ chan->conf_state = 0; @@ -6894,8 +6909,23 @@ static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, * procdure is done simply assume that the channel is supported * and mark it as ready. */ +#ifndef TIZEN_BT if (chan->chan_type == L2CAP_CHAN_FIXED) l2cap_chan_ready(chan); +#else + if (chan->chan_type == L2CAP_CHAN_FIXED) { + if (chan->psm == L2CAP_PSM_IPSP) { + struct l2cap_conn *conn = chan->conn; + + if (conn->hcon->out) + l2cap_chan_ready(chan); + else if (conn->hcon->type != LE_LINK) + l2cap_chan_ready(chan); + } else { + l2cap_chan_ready(chan); + } + } +#endif if (chan->state != BT_CONNECTED) goto drop; -- 2.7.4 From 8fc9276a1e356610e2df9fbd565338522cc0694f Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Fri, 16 Sep 2016 10:38:30 +0530 Subject: [PATCH 12/16] Bluetooth: Read LE Max data length command This patch adds the MGMT command and code to support reading the maximum data length supported command for LE. Change-Id: I4dc0041f2070de2ccb6a4164c8823612863c941e Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- include/net/bluetooth/hci_core.h | 2 + include/net/bluetooth/mgmt_tizen.h | 9 +++++ net/bluetooth/hci_event.c | 9 +++++ net/bluetooth/mgmt.c | 79 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 99 insertions(+) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index ee6d95e..4fc5f3e 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1692,6 +1692,8 @@ void mgmt_multi_adv_state_change_evt(struct hci_dev *hdev, u8 adv_instance, u8 state_change_reason, u16 connection_handle); void mgmt_6lowpan_conn_changed(struct hci_dev *hdev, char if_name[16], bdaddr_t *bdaddr, u8 addr_type, bool connected); +void mgmt_le_read_maximum_data_length_complete(struct hci_dev *hdev, + u8 status); #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 52a36f9..444d793 100644 --- a/include/net/bluetooth/mgmt_tizen.h +++ b/include/net/bluetooth/mgmt_tizen.h @@ -185,6 +185,15 @@ struct mgmt_cp_disconnect_6lowpan { } __packed; #define MGMT_DISCONNECT_6LOWPAN_SIZE 7 +#define MGMT_OP_LE_READ_MAXIMUM_DATA_LENGTH (TIZEN_OP_CODE_BASE + 0x15) +struct mgmt_rp_le_read_maximum_data_length { + __le16 max_tx_octets; + __le16 max_tx_time; + __le16 max_rx_octets; + __le16 max_rx_time; +} __packed; +#define MGMT_LE_READ_MAXIMUM_DATA_LENGTH_SIZE 0 + /* EVENTS */ /* For device name update changes */ diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index feb1d7e..40dbcdd 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1351,13 +1351,22 @@ static void hci_cc_le_read_max_data_len(struct hci_dev *hdev, BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); +#ifndef TIZEN_BT if (rp->status) return; +#else + hci_dev_lock(hdev); +#endif hdev->le_max_tx_len = le16_to_cpu(rp->tx_len); hdev->le_max_tx_time = le16_to_cpu(rp->tx_time); hdev->le_max_rx_len = le16_to_cpu(rp->rx_len); hdev->le_max_rx_time = le16_to_cpu(rp->rx_time); + +#ifdef TIZEN_BT + mgmt_le_read_maximum_data_length_complete(hdev, rp->status); + hci_dev_unlock(hdev); +#endif } static void hci_cc_write_le_host_supported(struct hci_dev *hdev, diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 279cb97..366c1ce 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -6688,6 +6688,83 @@ void mgmt_6lowpan_conn_changed(struct hci_dev *hdev, char if_name[16], mgmt_event(MGMT_EV_6LOWPAN_CONN_STATE_CHANGED, hdev, ev, ev_size, NULL); } + +void mgmt_le_read_maximum_data_length_complete(struct hci_dev *hdev, u8 status) +{ + struct mgmt_pending_cmd *cmd; + struct mgmt_rp_le_read_maximum_data_length rp; + + BT_DBG("%s status %u", hdev->name, status); + + cmd = pending_find(MGMT_OP_LE_READ_MAXIMUM_DATA_LENGTH, hdev); + if (!cmd) + return; + + if (status) + mgmt_cmd_status(cmd->sk, hdev->id, + MGMT_OP_LE_READ_MAXIMUM_DATA_LENGTH, + mgmt_status(status)); + + memset(&rp, 0, sizeof(rp)); + + rp.max_tx_octets = cpu_to_le16(hdev->le_max_tx_len); + rp.max_tx_time = cpu_to_le16(hdev->le_max_tx_time); + rp.max_rx_octets = cpu_to_le16(hdev->le_max_rx_len); + rp.max_rx_time = cpu_to_le16(hdev->le_max_rx_time); + + mgmt_cmd_complete(cmd->sk, hdev->id, + MGMT_OP_LE_READ_MAXIMUM_DATA_LENGTH, 0, + &rp, sizeof(rp)); + + mgmt_pending_remove(cmd); +} + +static int read_maximum_le_data_length(struct sock *sk, + struct hci_dev *hdev, void *data, u16 len) +{ + struct mgmt_pending_cmd *cmd; + int err; + + BT_DBG("read_maximum_le_data_length %s", hdev->name); + + hci_dev_lock(hdev); + + if (!hdev_is_powered(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, + MGMT_OP_LE_READ_MAXIMUM_DATA_LENGTH, + MGMT_STATUS_NOT_POWERED); + goto unlock; + } + + if (!lmp_le_capable(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, + MGMT_OP_LE_READ_MAXIMUM_DATA_LENGTH, + MGMT_STATUS_NOT_SUPPORTED); + goto unlock; + } + + if (pending_find(MGMT_OP_LE_READ_MAXIMUM_DATA_LENGTH, hdev)) { + err = mgmt_cmd_status(sk, hdev->id, + MGMT_OP_LE_READ_MAXIMUM_DATA_LENGTH, + MGMT_STATUS_BUSY); + goto unlock; + } + + cmd = mgmt_pending_add(sk, MGMT_OP_LE_READ_MAXIMUM_DATA_LENGTH, + hdev, data, len); + if (!cmd) { + err = -ENOMEM; + goto unlock; + } + + err = hci_send_cmd(hdev, HCI_OP_LE_READ_MAX_DATA_LEN, 0, NULL); + if (err < 0) + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock(hdev); + return err; +} #endif /* TIZEN_BT */ static bool ltk_is_valid(struct mgmt_ltk_info *key) @@ -8641,6 +8718,8 @@ static const struct hci_mgmt_handler tizen_mgmt_handlers[] = { { enable_bt_6lowpan, MGMT_ENABLE_BT_6LOWPAN_SIZE }, { connect_bt_6lowpan, MGMT_CONNECT_6LOWPAN_SIZE }, { disconnect_bt_6lowpan, MGMT_DISCONNECT_6LOWPAN_SIZE }, + { read_maximum_le_data_length, + MGMT_LE_READ_MAXIMUM_DATA_LENGTH_SIZE }, }; #endif -- 2.7.4 From 07a3271b1bf9882d9841d4fcdae3852758377aa1 Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Fri, 16 Sep 2016 12:09:57 +0530 Subject: [PATCH 13/16] Bluetooth: Write host suggested default le data length This patch adds MGMT command and code for supporting write default le data length command to the controller. Change-Id: I3d2c8b622b7913a3ed542342e3ba8076c30dc279 Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- include/net/bluetooth/hci_core.h | 2 + include/net/bluetooth/mgmt_tizen.h | 7 ++++ net/bluetooth/hci_event.c | 13 ++++++ net/bluetooth/mgmt.c | 86 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index 4fc5f3e..bc05106 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1694,6 +1694,8 @@ void mgmt_6lowpan_conn_changed(struct hci_dev *hdev, char if_name[16], bdaddr_t *bdaddr, u8 addr_type, bool connected); void mgmt_le_read_maximum_data_length_complete(struct hci_dev *hdev, u8 status); +void mgmt_le_write_host_suggested_data_length_complete(struct hci_dev *hdev, + u8 status); #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 444d793..0f36ecd 100644 --- a/include/net/bluetooth/mgmt_tizen.h +++ b/include/net/bluetooth/mgmt_tizen.h @@ -194,6 +194,13 @@ struct mgmt_rp_le_read_maximum_data_length { } __packed; #define MGMT_LE_READ_MAXIMUM_DATA_LENGTH_SIZE 0 +#define MGMT_OP_LE_WRITE_HOST_SUGGESTED_DATA_LENGTH (TIZEN_OP_CODE_BASE + 0x16) +struct mgmt_cp_le_write_host_suggested_data_length { + __le16 def_tx_octets; + __le16 def_tx_time; +} __packed; +#define MGMT_LE_WRITE_HOST_SUGGESTED_DATA_LENGTH_SIZE 4 + /* EVENTS */ /* For device name update changes */ diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 40dbcdd..0649dc1 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1334,14 +1334,27 @@ static void hci_cc_le_write_def_data_len(struct hci_dev *hdev, BT_DBG("%s status 0x%2.2x", hdev->name, status); if (status) +#ifndef TIZEN_BT return; +#else + goto unblock; +#endif sent = hci_sent_cmd_data(hdev, HCI_OP_LE_WRITE_DEF_DATA_LEN); if (!sent) +#ifndef TIZEN_BT return; +#else + goto unblock; +#endif hdev->le_def_tx_len = le16_to_cpu(sent->tx_len); hdev->le_def_tx_time = le16_to_cpu(sent->tx_time); + +#ifdef TIZEN_BT +unblock: + mgmt_le_write_host_suggested_data_length_complete(hdev, status); +#endif } static void hci_cc_le_read_max_data_len(struct hci_dev *hdev, diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 366c1ce..fbe2b96 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -6765,6 +6765,90 @@ unlock: hci_dev_unlock(hdev); return err; } + +void mgmt_le_write_host_suggested_data_length_complete(struct hci_dev *hdev, + u8 status) +{ + struct mgmt_pending_cmd *cmd; + + BT_DBG("status 0x%02x", status); + + hci_dev_lock(hdev); + + cmd = pending_find(MGMT_OP_LE_WRITE_HOST_SUGGESTED_DATA_LENGTH, hdev); + if (!cmd) { + BT_ERR("cmd not found in the pending list"); + goto unlock; + } + + if (status) + mgmt_cmd_status(cmd->sk, hdev->id, + MGMT_OP_LE_WRITE_HOST_SUGGESTED_DATA_LENGTH, + mgmt_status(status)); + else + mgmt_cmd_complete(cmd->sk, hdev->id, + MGMT_OP_LE_WRITE_HOST_SUGGESTED_DATA_LENGTH, + 0, NULL, 0); + + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock(hdev); +} + +static int write_host_suggested_le_data_length(struct sock *sk, + struct hci_dev *hdev, void *data, u16 len) +{ + struct mgmt_pending_cmd *cmd; + struct mgmt_cp_le_write_host_suggested_data_length *cp = data; + struct hci_cp_le_write_def_data_len hci_data; + int err = 0; + + BT_DBG("Write host suggested data length request for %s", hdev->name); + + hci_dev_lock(hdev); + + if (!hdev_is_powered(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, + MGMT_OP_LE_WRITE_HOST_SUGGESTED_DATA_LENGTH, + MGMT_STATUS_NOT_POWERED); + goto unlock; + } + + if (!lmp_le_capable(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, + MGMT_OP_LE_WRITE_HOST_SUGGESTED_DATA_LENGTH, + MGMT_STATUS_NOT_SUPPORTED); + goto unlock; + } + + if (pending_find(MGMT_OP_LE_WRITE_HOST_SUGGESTED_DATA_LENGTH, hdev)) { + err = mgmt_cmd_status(sk, hdev->id, + MGMT_OP_LE_WRITE_HOST_SUGGESTED_DATA_LENGTH, + MGMT_STATUS_BUSY); + goto unlock; + } + + cmd = mgmt_pending_add(sk, MGMT_OP_LE_WRITE_HOST_SUGGESTED_DATA_LENGTH, + hdev, data, len); + if (!cmd) { + err = -ENOMEM; + goto unlock; + } + + hci_data.tx_len = cp->def_tx_octets; + hci_data.tx_time = cp->def_tx_time; + + err = hci_send_cmd(hdev, HCI_OP_LE_WRITE_DEF_DATA_LEN, + sizeof(hci_data), &hci_data); + if (err < 0) + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock(hdev); + + return err; +} #endif /* TIZEN_BT */ static bool ltk_is_valid(struct mgmt_ltk_info *key) @@ -8720,6 +8804,8 @@ static const struct hci_mgmt_handler tizen_mgmt_handlers[] = { { disconnect_bt_6lowpan, MGMT_DISCONNECT_6LOWPAN_SIZE }, { read_maximum_le_data_length, MGMT_LE_READ_MAXIMUM_DATA_LENGTH_SIZE }, + { write_host_suggested_le_data_length, + MGMT_LE_WRITE_HOST_SUGGESTED_DATA_LENGTH_SIZE }, }; #endif -- 2.7.4 From 61562387b732862d01b3070ec6faffac145ba85d Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Fri, 16 Sep 2016 12:54:31 +0530 Subject: [PATCH 14/16] Bluetooth: Read host suggested default le data length This patch adds MGMT command and code for supporting reading default le data length value set at the controller. Change-Id: I2b81982dc26ed5af4a8f8a3d3913db5d64625260 Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- include/net/bluetooth/hci_core.h | 2 + include/net/bluetooth/mgmt_tizen.h | 7 ++++ net/bluetooth/hci_event.c | 10 +++++ net/bluetooth/mgmt.c | 81 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 100 insertions(+) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index bc05106..a00527c 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -1696,6 +1696,8 @@ void mgmt_le_read_maximum_data_length_complete(struct hci_dev *hdev, u8 status); void mgmt_le_write_host_suggested_data_length_complete(struct hci_dev *hdev, u8 status); +void mgmt_le_read_host_suggested_data_length_complete(struct hci_dev *hdev, + u8 status); #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 0f36ecd..2d11d5b 100644 --- a/include/net/bluetooth/mgmt_tizen.h +++ b/include/net/bluetooth/mgmt_tizen.h @@ -201,6 +201,13 @@ struct mgmt_cp_le_write_host_suggested_data_length { } __packed; #define MGMT_LE_WRITE_HOST_SUGGESTED_DATA_LENGTH_SIZE 4 +#define MGMT_OP_LE_READ_HOST_SUGGESTED_DATA_LENGTH (TIZEN_OP_CODE_BASE + 0x17) +struct mgmt_rp_le_read_host_suggested_data_length { + __le16 def_tx_octets; + __le16 def_tx_time; +} __packed; +#define MGMT_LE_READ_HOST_SUGGESTED_DATA_LENGTH_SIZE 0 + /* EVENTS */ /* For device name update changes */ diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 0649dc1..5418481 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1318,11 +1318,21 @@ static void hci_cc_le_read_def_data_len(struct hci_dev *hdev, BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); +#ifdef TIZEN_BT + hci_dev_lock(hdev); +#else if (rp->status) return; +#endif hdev->le_def_tx_len = le16_to_cpu(rp->tx_len); hdev->le_def_tx_time = le16_to_cpu(rp->tx_time); + +#ifdef TIZEN_BT + mgmt_le_read_host_suggested_data_length_complete(hdev, rp->status); + + hci_dev_unlock(hdev); +#endif } static void hci_cc_le_write_def_data_len(struct hci_dev *hdev, diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index fbe2b96..2609b95 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -6849,6 +6849,85 @@ unlock: return err; } + +void mgmt_le_read_host_suggested_data_length_complete(struct hci_dev *hdev, + u8 status) +{ + struct mgmt_pending_cmd *cmd; + struct mgmt_rp_le_read_host_suggested_data_length rp; + + BT_DBG("%s status %u", hdev->name, status); + + cmd = pending_find(MGMT_OP_LE_READ_HOST_SUGGESTED_DATA_LENGTH, hdev); + if (!cmd) { + BT_ERR("cmd not found in the pending list"); + return; + } + + if (status) + mgmt_cmd_status(cmd->sk, hdev->id, + MGMT_OP_LE_READ_HOST_SUGGESTED_DATA_LENGTH, + mgmt_status(status)); + + memset(&rp, 0, sizeof(rp)); + + rp.def_tx_octets = cpu_to_le16(hdev->le_def_tx_len); + rp.def_tx_time = cpu_to_le16(hdev->le_def_tx_time); + + mgmt_cmd_complete(cmd->sk, hdev->id, + MGMT_OP_LE_READ_HOST_SUGGESTED_DATA_LENGTH, 0, + &rp, sizeof(rp)); + + mgmt_pending_remove(cmd); +} + +static int read_host_suggested_data_length(struct sock *sk, + struct hci_dev *hdev, void *data, u16 len) +{ + struct mgmt_pending_cmd *cmd; + int err; + + BT_DBG("read_host_suggested_data_length %s", hdev->name); + + hci_dev_lock(hdev); + + if (!hdev_is_powered(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, + MGMT_OP_LE_READ_HOST_SUGGESTED_DATA_LENGTH, + MGMT_STATUS_NOT_POWERED); + goto unlock; + } + + if (!lmp_le_capable(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, + MGMT_OP_LE_READ_HOST_SUGGESTED_DATA_LENGTH, + MGMT_STATUS_NOT_SUPPORTED); + goto unlock; + } + + if (pending_find(MGMT_OP_LE_READ_HOST_SUGGESTED_DATA_LENGTH, hdev)) { + err = mgmt_cmd_status(sk, hdev->id, + MGMT_OP_LE_READ_HOST_SUGGESTED_DATA_LENGTH, + MGMT_STATUS_BUSY); + goto unlock; + } + + cmd = mgmt_pending_add(sk, MGMT_OP_LE_READ_HOST_SUGGESTED_DATA_LENGTH, + hdev, data, len); + if (!cmd) { + err = -ENOMEM; + goto unlock; + } + + err = hci_send_cmd(hdev, HCI_OP_LE_READ_DEF_DATA_LEN, 0, NULL); + if (err < 0) + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock(hdev); + + return err; +} #endif /* TIZEN_BT */ static bool ltk_is_valid(struct mgmt_ltk_info *key) @@ -8806,6 +8885,8 @@ static const struct hci_mgmt_handler tizen_mgmt_handlers[] = { MGMT_LE_READ_MAXIMUM_DATA_LENGTH_SIZE }, { write_host_suggested_le_data_length, MGMT_LE_WRITE_HOST_SUGGESTED_DATA_LENGTH_SIZE }, + { read_host_suggested_data_length, + MGMT_LE_READ_HOST_SUGGESTED_DATA_LENGTH_SIZE }, }; #endif -- 2.7.4 From ace75290740e921b99ded4ad3f865f5f510dea0b Mon Sep 17 00:00:00 2001 From: Sudha Bheemanna Date: Fri, 16 Sep 2016 15:37:22 +0530 Subject: [PATCH 15/16] Bluetooth: Set le data length command and event Sets the data length for the le data packet with in the advised limits. MGMT command and event are added to handle the setting of data length. Change-Id: Ia5c2167743cc9a29190e5631973e9d52d41caa1d Signed-off-by: Sudha Bheemanna Signed-off-by: Amit Purwar --- include/net/bluetooth/hci_core.h | 14 ++++++ include/net/bluetooth/mgmt_tizen.h | 23 +++++++++ net/bluetooth/hci_conn.c | 29 ++++++++++++ net/bluetooth/hci_event.c | 31 ++++++++++++- net/bluetooth/mgmt.c | 95 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 191 insertions(+), 1 deletion(-) diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h index a00527c..b51a31a 100644 --- a/include/net/bluetooth/hci_core.h +++ b/include/net/bluetooth/hci_core.h @@ -494,6 +494,12 @@ struct hci_conn { __u8 remote_id; unsigned int sent; +#ifdef TIZEN_BT + __u16 tx_len; + __u16 tx_time; + __u16 rx_len; + __u16 rx_time; +#endif struct sk_buff_head data_q; struct list_head chan_list; @@ -545,6 +551,10 @@ struct hci_conn_params { u16 conn_latency; u16 supervision_timeout; +#ifdef TIZEN_BT + u16 max_tx_octets; + u16 max_tx_time; +#endif enum { HCI_AUTO_CONN_DISABLED, HCI_AUTO_CONN_REPORT, @@ -1698,6 +1708,10 @@ void mgmt_le_write_host_suggested_data_length_complete(struct hci_dev *hdev, u8 status); void mgmt_le_read_host_suggested_data_length_complete(struct hci_dev *hdev, u8 status); +void mgmt_le_data_length_change_complete(struct hci_dev *hdev, + bdaddr_t *bdaddr, u16 tx_octets, u16 tx_time, + u16 rx_octets, u16 rx_time); +int hci_le_set_data_length(struct hci_conn *conn, u16 tx_octets, u16 tx_time); #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 2d11d5b..cfb9d50 100644 --- a/include/net/bluetooth/mgmt_tizen.h +++ b/include/net/bluetooth/mgmt_tizen.h @@ -208,6 +208,20 @@ struct mgmt_rp_le_read_host_suggested_data_length { } __packed; #define MGMT_LE_READ_HOST_SUGGESTED_DATA_LENGTH_SIZE 0 +#define MGMT_OP_LE_SET_DATA_LENGTH (TIZEN_OP_CODE_BASE + 0x18) +struct mgmt_cp_le_set_data_length { + bdaddr_t bdaddr; + __le16 max_tx_octets; + __le16 max_tx_time; +} __packed; +#define MGMT_LE_SET_DATA_LENGTH_SIZE 10 + +struct mgmt_rp_le_set_data_length { + __u8 status; + __le16 handle; +} __packed; +#define MGMT_LE_SET_DATA_LENGTH_RSP_SIZE 3 + /* EVENTS */ /* For device name update changes */ @@ -296,4 +310,13 @@ struct mgmt_ev_6lowpan_conn_state_changed { __u8 ifname[16]; } __packed; +#define MGMT_EV_LE_DATA_LENGTH_CHANGED (TIZEN_EV_BASE + 0x0d) +struct mgmt_ev_le_data_length_changed { + struct mgmt_addr_info addr; + __le16 max_tx_octets; + __le16 max_tx_time; + __le16 max_rx_octets; + __le16 max_rx_time; +} __packed; + #endif /* __MGMT_TIZEN_H */ diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index e64f0b3..ea94d77 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -1407,6 +1407,35 @@ int hci_conn_change_supervision_timeout(struct hci_conn *conn, __u16 timeout) return 0; } + +int hci_le_set_data_length(struct hci_conn *conn, u16 tx_octets, u16 tx_time) +{ + struct hci_dev *hdev = conn->hdev; + struct hci_conn_params *params; + struct hci_cp_le_set_data_len cp; + + hci_dev_lock(hdev); + + params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); + if (params) { + params->max_tx_octets = tx_octets; + params->max_tx_time = tx_time; + } + + hci_dev_unlock(hdev); + + memset(&cp, 0, sizeof(cp)); + cp.handle = cpu_to_le16(conn->handle); + cp.tx_len = cpu_to_le16(tx_octets); + cp.tx_time = cpu_to_le16(tx_time); + + hci_send_cmd(hdev, HCI_OP_LE_SET_DATA_LEN, sizeof(cp), &cp); + + if (params) + return 0x01; + + return 0x00; +} #endif /* Enter active mode */ diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 5418481..051f77b 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1536,6 +1536,31 @@ static void hci_vendor_specific_evt(struct hci_dev *hdev, struct sk_buff *skb) break; } } + +static void hci_le_data_length_changed_complete_evt(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_ev_le_data_len_change *ev = (void *)skb->data; + struct hci_conn *conn; + + BT_DBG("%s status", hdev->name); + + hci_dev_lock(hdev); + + conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); + if (conn) { + conn->tx_len = le16_to_cpu(ev->tx_len); + conn->tx_time = le16_to_cpu(ev->tx_time); + conn->rx_len = le16_to_cpu(ev->rx_len); + conn->rx_time = le16_to_cpu(ev->rx_time); + + mgmt_le_data_length_change_complete(hdev, &conn->dst, + conn->tx_len, conn->tx_time, + conn->rx_len, conn->rx_time); + } + + hci_dev_unlock(hdev); +} #endif static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb) @@ -5463,7 +5488,11 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) case HCI_EV_LE_DIRECT_ADV_REPORT: hci_le_direct_adv_report_evt(hdev, skb); break; - +#ifdef TIZEN_BT + case HCI_EV_LE_DATA_LEN_CHANGE: + hci_le_data_length_changed_complete_evt(hdev, skb); + break; +#endif default: break; } diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 2609b95..7a398d9 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -6928,6 +6928,99 @@ unlock: return err; } + +static int set_le_data_length_params(struct sock *sk, struct hci_dev *hdev, + void *data, u16 len) +{ + struct mgmt_cp_le_set_data_length *cp = data; + struct mgmt_rp_le_set_data_length *rp; + struct mgmt_pending_cmd *cmd; + struct hci_conn *conn; + int err = 0; + u16 max_tx_octets, max_tx_time; + size_t rp_len; + + BT_INFO("Set Data length for the device %s", hdev->name); + + hci_dev_lock(hdev); + + rp_len = sizeof(*rp); + rp = kmalloc(rp_len, GFP_KERNEL); + if (!rp) { + err = -ENOMEM; + goto unlock; + } + + if (!hdev_is_powered(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_LE_SET_DATA_LENGTH, + MGMT_STATUS_NOT_POWERED); + goto unlock; + } + + if (!lmp_le_capable(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_LE_SET_DATA_LENGTH, + MGMT_STATUS_NOT_SUPPORTED); + goto unlock; + } + + if (pending_find(MGMT_OP_LE_SET_DATA_LENGTH, hdev)) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_LE_SET_DATA_LENGTH, + MGMT_STATUS_BUSY); + goto unlock; + } + + cmd = mgmt_pending_add(sk, MGMT_OP_LE_SET_DATA_LENGTH, hdev, data, len); + if (!cmd) { + err = -ENOMEM; + goto unlock; + } + + max_tx_octets = __le16_to_cpu(cp->max_tx_octets); + max_tx_time = __le16_to_cpu(cp->max_tx_time); + + BT_DBG("max_tx_octets 0x%4.4x max_tx_time 0x%4.4x latency", + max_tx_octets, max_tx_time); + + conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->bdaddr); + if (!conn) { + mgmt_cmd_status(sk, hdev->id, MGMT_OP_LE_SET_DATA_LENGTH, + MGMT_STATUS_NOT_CONNECTED); + goto unlock; + } + + hci_dev_unlock(hdev); + + err = hci_le_set_data_length(conn, max_tx_octets, max_tx_time); + if (err < 0) + mgmt_pending_remove(cmd); + + rp->handle = conn->handle; + rp->status = 0; + + hci_dev_lock(hdev); + err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_LE_SET_DATA_LENGTH, 0, + rp, rp_len); +unlock: + kfree(rp); + hci_dev_unlock(hdev); + + return err; +} + +void mgmt_le_data_length_change_complete(struct hci_dev *hdev, + bdaddr_t *bdaddr, u16 tx_octets, u16 tx_time, + u16 rx_octets, u16 rx_time) +{ + struct mgmt_ev_le_data_length_changed ev; + + bacpy(&ev.addr.bdaddr, bdaddr); + ev.max_tx_octets = tx_octets; + ev.max_tx_time = tx_time; + ev.max_rx_octets = rx_octets; + ev.max_rx_time = rx_time; + + mgmt_event(MGMT_EV_LE_DATA_LENGTH_CHANGED, hdev, &ev, sizeof(ev), NULL); +} #endif /* TIZEN_BT */ static bool ltk_is_valid(struct mgmt_ltk_info *key) @@ -8887,6 +8980,8 @@ static const struct hci_mgmt_handler tizen_mgmt_handlers[] = { MGMT_LE_WRITE_HOST_SUGGESTED_DATA_LENGTH_SIZE }, { read_host_suggested_data_length, MGMT_LE_READ_HOST_SUGGESTED_DATA_LENGTH_SIZE }, + { set_le_data_length_params, + MGMT_LE_SET_DATA_LENGTH_SIZE }, }; #endif -- 2.7.4 From 95ec7e188c0e37c8d0565a354dcbf8a9fe3b1751 Mon Sep 17 00:00:00 2001 From: Jaehoon Chung Date: Tue, 16 Nov 2021 12:54:43 +0900 Subject: [PATCH 16/16] ARM: defconfig: disable ANDROID_LOGGER Disable ANDROID_LOGGER. Change-Id: I0fa79d5f7829f59eb8467f4daa8e81a390ec57fa Signed-off-by: Jaehoon Chung --- arch/arm64/configs/tizen_kvims_defconfig | 1 - arch/arm64/configs/tizen_odroidg12_defconfig | 1 - 2 files changed, 2 deletions(-) diff --git a/arch/arm64/configs/tizen_kvims_defconfig b/arch/arm64/configs/tizen_kvims_defconfig index ac53cee..5305de38 100644 --- a/arch/arm64/configs/tizen_kvims_defconfig +++ b/arch/arm64/configs/tizen_kvims_defconfig @@ -608,7 +608,6 @@ CONFIG_UIO=y CONFIG_UIO_PDRV_GENIRQ=y CONFIG_VIRTIO_MMIO=y CONFIG_STAGING=y -CONFIG_ANDROID_LOGGER=y CONFIG_TIZEN=y CONFIG_PM_DEVFREQ=y CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y diff --git a/arch/arm64/configs/tizen_odroidg12_defconfig b/arch/arm64/configs/tizen_odroidg12_defconfig index 2ee8981..941383a 100644 --- a/arch/arm64/configs/tizen_odroidg12_defconfig +++ b/arch/arm64/configs/tizen_odroidg12_defconfig @@ -680,7 +680,6 @@ CONFIG_R8712U=y CONFIG_STAGING_MEDIA=y CONFIG_LIRC_STAGING=y CONFIG_LIRC_ODROID=m -CONFIG_ANDROID_LOGGER=y CONFIG_TIZEN=y CONFIG_PM_DEVFREQ=y CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=y -- 2.7.4