diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/hci_event.c | 33 | ||||
-rw-r--r-- | net/bluetooth/mgmt.c | 686 |
2 files changed, 719 insertions, 0 deletions
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 7b61be73650f..987b9db6f958 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -1423,6 +1423,30 @@ static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, amp_write_rem_assoc_continue(hdev, rp->phy_handle); } +#ifdef TIZEN_BT +static void hci_cc_enable_rssi(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_cc_rsp_enable_rssi *rp = (void *)skb->data; + + BT_DBG("hci_cc_enable_rssi - %s status 0x%2.2x Event_LE_ext_Opcode 0x%2.2x", + hdev->name, rp->status, rp->le_ext_opcode); + + mgmt_enable_rssi_cc(hdev, rp, rp->status); +} + +static void hci_cc_get_raw_rssi(struct hci_dev *hdev, + struct sk_buff *skb) +{ + struct hci_cc_rp_get_raw_rssi *rp = (void *)skb->data; + + BT_DBG("hci_cc_get_raw_rssi- %s Get Raw Rssi Response[%2.2x %4.4x %2.2X]", + hdev->name, rp->status, rp->conn_handle, rp->rssi_dbm); + + mgmt_raw_rssi_response(hdev, rp, rp->status); +} +#endif + static void hci_cc_read_rssi(struct hci_dev *hdev, struct sk_buff *skb) { struct hci_rp_read_rssi *rp = (void *) skb->data; @@ -3036,6 +3060,15 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb, hci_cc_write_ssp_debug_mode(hdev, skb); break; +#ifdef TIZEN_BT + case HCI_OP_ENABLE_RSSI: + hci_cc_enable_rssi(hdev, skb); + break; + + case HCI_OP_GET_RAW_RSSI: + hci_cc_get_raw_rssi(hdev, skb); + break; +#endif default: BT_DBG("%s opcode 0x%4.4x", hdev->name, *opcode); break; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index c0c6b62fd826..28da6d31f80d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -5948,6 +5948,689 @@ unlocked: return err; } + +static void set_rssi_threshold_complete(struct hci_dev *hdev, + u8 status, u16 opcode) +{ + struct mgmt_pending_cmd *cmd; + + BT_DBG("status 0x%02x", status); + + hci_dev_lock(hdev); + + cmd = pending_find(MGMT_OP_SET_RSSI_ENABLE, hdev); + if (!cmd) + goto unlock; + + if (status) + mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_RSSI_ENABLE, + mgmt_status(status)); + else + mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_RSSI_ENABLE, 0, + NULL, 0); + + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock(hdev); +} + +static void set_rssi_disable_complete(struct hci_dev *hdev, + u8 status, u16 opcode) +{ + struct mgmt_pending_cmd *cmd; + + BT_DBG("status 0x%02x", status); + + hci_dev_lock(hdev); + + cmd = pending_find(MGMT_OP_SET_RSSI_DISABLE, hdev); + if (!cmd) + goto unlock; + + if (status) + mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_RSSI_DISABLE, + mgmt_status(status)); + else + mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_RSSI_DISABLE, + 0, NULL, 0); + + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock(hdev); +} + +int mgmt_set_rssi_threshold(struct sock *sk, struct hci_dev *hdev, + void *data, u16 len) +{ + int err = 0; + struct hci_cp_set_rssi_threshold th = { 0, }; + struct mgmt_cp_set_enable_rssi *cp = data; + struct hci_conn *conn; + struct mgmt_pending_cmd *cmd; + struct hci_request req; + __u8 dest_type; + + hci_dev_lock(hdev); + + cmd = pending_find(MGMT_OP_SET_RSSI_ENABLE, hdev); + if (!cmd) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_RSSI_ENABLE, + MGMT_STATUS_FAILED); + goto unlocked; + } + + if (!lmp_le_capable(hdev)) { + mgmt_pending_remove(cmd); + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_RSSI_ENABLE, + MGMT_STATUS_NOT_SUPPORTED); + goto unlocked; + } + + if (!hdev_is_powered(hdev)) { + BT_DBG("%s", hdev->name); + mgmt_pending_remove(cmd); + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_RSSI_ENABLE, + MGMT_STATUS_NOT_POWERED); + goto unlocked; + } + + if (cp->link_type == 0x01) + dest_type = LE_LINK; + else + dest_type = ACL_LINK; + + /* Get LE/ACL link handle info */ + conn = hci_conn_hash_lookup_ba(hdev, + dest_type, &cp->bdaddr); + + if (!conn) { + err = mgmt_cmd_complete(sk, hdev->id, + MGMT_OP_SET_RSSI_ENABLE, 1, NULL, 0); + mgmt_pending_remove(cmd); + goto unlocked; + } + + hci_req_init(&req, hdev); + + th.hci_le_ext_opcode = 0x0B; + th.mode = 0x01; + th.conn_handle = conn->handle; + th.alert_mask = 0x07; + th.low_th = cp->low_th; + th.in_range_th = cp->in_range_th; + th.high_th = cp->high_th; + + hci_req_add(&req, HCI_OP_ENABLE_RSSI, sizeof(th), &th); + err = hci_req_run(&req, set_rssi_threshold_complete); + + if (err < 0) { + mgmt_pending_remove(cmd); + BT_ERR("Error in requesting hci_req_run"); + goto unlocked; + } + +unlocked: + hci_dev_unlock(hdev); + return err; +} + +void mgmt_rssi_enable_success(struct sock *sk, struct hci_dev *hdev, + void *data, struct hci_cc_rsp_enable_rssi *rp, int success) +{ + struct mgmt_cc_rsp_enable_rssi mgmt_rp = { 0, }; + struct mgmt_cp_set_enable_rssi *cp = data; + struct mgmt_pending_cmd *cmd; + + if (!cp || !rp) + goto remove_cmd; + + mgmt_rp.status = rp->status; + mgmt_rp.le_ext_opcode = rp->le_ext_opcode; + mgmt_rp.bt_address = cp->bdaddr; + mgmt_rp.link_type = cp->link_type; + + mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_RSSI_ENABLE, + MGMT_STATUS_SUCCESS, &mgmt_rp, + sizeof(struct mgmt_cc_rsp_enable_rssi)); + + mgmt_event(MGMT_EV_RSSI_ENABLED, hdev, &mgmt_rp, + sizeof(struct mgmt_cc_rsp_enable_rssi), NULL); + + hci_conn_rssi_unset_all(hdev, mgmt_rp.link_type); + hci_conn_rssi_state_set(hdev, mgmt_rp.link_type, + &mgmt_rp.bt_address, true); + +remove_cmd: + hci_dev_lock(hdev); + cmd = pending_find(MGMT_OP_SET_RSSI_ENABLE, hdev); + if (cmd) + mgmt_pending_remove(cmd); + + hci_dev_unlock(hdev); +} + +void mgmt_rssi_disable_success(struct sock *sk, struct hci_dev *hdev, + void *data, struct hci_cc_rsp_enable_rssi *rp, int success) +{ + struct mgmt_cc_rp_disable_rssi mgmt_rp = { 0, }; + struct mgmt_cp_disable_rssi *cp = data; + struct mgmt_pending_cmd *cmd; + + if (!cp || !rp) + goto remove_cmd; + + mgmt_rp.status = rp->status; + mgmt_rp.le_ext_opcode = rp->le_ext_opcode; + mgmt_rp.bt_address = cp->bdaddr; + mgmt_rp.link_type = cp->link_type; + + mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_RSSI_DISABLE, + MGMT_STATUS_SUCCESS, &mgmt_rp, + sizeof(struct mgmt_cc_rsp_enable_rssi)); + + mgmt_event(MGMT_EV_RSSI_DISABLED, hdev, &mgmt_rp, + sizeof(struct mgmt_cc_rsp_enable_rssi), NULL); + + hci_conn_rssi_state_set(hdev, mgmt_rp.link_type, + &mgmt_rp.bt_address, false); + +remove_cmd: + hci_dev_lock(hdev); + cmd = pending_find(MGMT_OP_SET_RSSI_DISABLE, hdev); + if (cmd) + mgmt_pending_remove(cmd); + + hci_dev_unlock(hdev); +} + +static int mgmt_set_disable_rssi(struct sock *sk, struct hci_dev *hdev, + void *data, u16 len) +{ + struct mgmt_pending_cmd *cmd; + struct hci_request req; + struct hci_cp_set_enable_rssi cp_en = { 0, }; + int err; + + BT_DBG("Set Disable RSSI."); + + cp_en.hci_le_ext_opcode = 0x01; + cp_en.le_enable_cs_Features = 0x00; + cp_en.data[0] = 0x00; + cp_en.data[1] = 0x00; + cp_en.data[2] = 0x00; + + hci_dev_lock(hdev); + + cmd = pending_find(MGMT_OP_SET_RSSI_DISABLE, hdev); + if (!cmd) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_RSSI_DISABLE, + MGMT_STATUS_FAILED); + goto unlocked; + } + + if (!lmp_le_capable(hdev)) { + mgmt_pending_remove(cmd); + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_RSSI_DISABLE, + MGMT_STATUS_NOT_SUPPORTED); + goto unlocked; + } + + if (!hdev_is_powered(hdev)) { + BT_DBG("%s", hdev->name); + mgmt_pending_remove(cmd); + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_RSSI_DISABLE, + MGMT_STATUS_NOT_POWERED); + goto unlocked; + } + + hci_req_init(&req, hdev); + + BT_DBG("Enable Len: %zu [%2.2X %2.2X %2.2X %2.2X %2.2X]", + sizeof(struct hci_cp_set_enable_rssi), + cp_en.hci_le_ext_opcode, cp_en.le_enable_cs_Features, + cp_en.data[0], cp_en.data[1], cp_en.data[2]); + + hci_req_add(&req, HCI_OP_ENABLE_RSSI, sizeof(cp_en), &cp_en); + err = hci_req_run(&req, set_rssi_disable_complete); + + if (err < 0) { + mgmt_pending_remove(cmd); + BT_ERR("Error in requesting hci_req_run"); + goto unlocked; + } + +unlocked: + hci_dev_unlock(hdev); + return err; +} + +void mgmt_enable_rssi_cc(struct hci_dev *hdev, void *response, u8 status) +{ + struct hci_cc_rsp_enable_rssi *rp = response; + struct mgmt_pending_cmd *cmd_enable = NULL; + struct mgmt_pending_cmd *cmd_disable = NULL; + struct mgmt_cp_set_enable_rssi *cp_en; + struct mgmt_cp_disable_rssi *cp_dis; + + hci_dev_lock(hdev); + cmd_enable = pending_find(MGMT_OP_SET_RSSI_ENABLE, hdev); + cmd_disable = pending_find(MGMT_OP_SET_RSSI_DISABLE, hdev); + hci_dev_unlock(hdev); + + if (cmd_enable) + BT_DBG("Enable Request"); + + if (cmd_disable) + BT_DBG("Disable Request"); + + if (cmd_enable) { + cp_en = cmd_enable->param; + + if (status != 0x00) + return; + + switch (rp->le_ext_opcode) { + case 0x01: + BT_DBG("RSSI enabled.. Setting Threshold..."); + mgmt_set_rssi_threshold(cmd_enable->sk, hdev, + cp_en, sizeof(*cp_en)); + break; + + case 0x0B: + BT_DBG("Sending RSSI enable success"); + mgmt_rssi_enable_success(cmd_enable->sk, hdev, + cp_en, rp, rp->status); + break; + } + + } else if (cmd_disable) { + cp_dis = cmd_disable->param; + + if (status != 0x00) + return; + + switch (rp->le_ext_opcode) { + case 0x01: + BT_DBG("Sending RSSI disable success"); + mgmt_rssi_disable_success(cmd_disable->sk, hdev, + cp_dis, rp, rp->status); + break; + + case 0x0B: + /* + * Only unset RSSI Threshold values for the Link if + * RSSI is monitored for other BREDR or LE Links + */ + if (hci_conn_hash_lookup_rssi_count(hdev) > 1) { + BT_DBG("Unset Threshold. Other links being monitored"); + mgmt_rssi_disable_success(cmd_disable->sk, hdev, + cp_dis, rp, rp->status); + } else { + BT_DBG("Unset Threshold. Disabling..."); + mgmt_set_disable_rssi(cmd_disable->sk, hdev, + cp_dis, sizeof(*cp_dis)); + } + break; + } + } +} + +static void set_rssi_enable_complete(struct hci_dev *hdev, u8 status, + u16 opcode) +{ + struct mgmt_pending_cmd *cmd; + + BT_DBG("status 0x%02x", status); + + hci_dev_lock(hdev); + + cmd = pending_find(MGMT_OP_SET_RSSI_ENABLE, hdev); + if (!cmd) + goto unlock; + + if (status) + mgmt_cmd_status(cmd->sk, hdev->id, MGMT_OP_SET_RSSI_ENABLE, + mgmt_status(status)); + else + mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_RSSI_ENABLE, 0, + NULL, 0); + + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock(hdev); +} + +static int set_enable_rssi(struct sock *sk, struct hci_dev *hdev, + void *data, u16 len) +{ + struct mgmt_pending_cmd *cmd; + struct hci_request req; + struct mgmt_cp_set_enable_rssi *cp = data; + struct hci_cp_set_enable_rssi cp_en = { 0, }; + int err; + + BT_DBG("Set Enable RSSI."); + + cp_en.hci_le_ext_opcode = 0x01; + cp_en.le_enable_cs_Features = 0x04; + cp_en.data[0] = 0x00; + cp_en.data[1] = 0x00; + cp_en.data[2] = 0x00; + + hci_dev_lock(hdev); + + if (!lmp_le_capable(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_RSSI_ENABLE, + MGMT_STATUS_NOT_SUPPORTED); + goto unlocked; + } + + if (!hdev_is_powered(hdev)) { + BT_DBG("%s", hdev->name); + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_RSSI_ENABLE, + MGMT_STATUS_NOT_POWERED); + goto unlocked; + } + + if (pending_find(MGMT_OP_SET_RSSI_ENABLE, hdev)) { + BT_DBG("%s", hdev->name); + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_RSSI_ENABLE, + MGMT_STATUS_BUSY); + goto unlocked; + } + + cmd = mgmt_pending_add(sk, MGMT_OP_SET_RSSI_ENABLE, hdev, cp, + sizeof(*cp)); + if (!cmd) { + BT_DBG("%s", hdev->name); + err = -ENOMEM; + goto unlocked; + } + + /* If RSSI is already enabled directly set Threshold values */ + if (hci_conn_hash_lookup_rssi_count(hdev) > 0) { + hci_dev_unlock(hdev); + BT_DBG("RSSI Enabled. Directly set Threshold"); + err = mgmt_set_rssi_threshold(sk, hdev, cp, sizeof(*cp)); + return err; + } + + hci_req_init(&req, hdev); + + BT_DBG("Enable Len: %zu [%2.2X %2.2X %2.2X %2.2X %2.2X]", + sizeof(struct hci_cp_set_enable_rssi), + cp_en.hci_le_ext_opcode, cp_en.le_enable_cs_Features, + cp_en.data[0], cp_en.data[1], cp_en.data[2]); + + hci_req_add(&req, HCI_OP_ENABLE_RSSI, sizeof(cp_en), &cp_en); + err = hci_req_run(&req, set_rssi_enable_complete); + + if (err < 0) { + mgmt_pending_remove(cmd); + BT_ERR("Error in requesting hci_req_run"); + goto unlocked; + } + +unlocked: + hci_dev_unlock(hdev); + + return err; +} + +static void get_raw_rssi_complete(struct hci_dev *hdev, u8 status, u16 opcode) +{ + struct mgmt_pending_cmd *cmd; + + BT_DBG("status 0x%02x", status); + + hci_dev_lock(hdev); + + cmd = pending_find(MGMT_OP_GET_RAW_RSSI, hdev); + if (!cmd) + goto unlock; + + mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_GET_RAW_RSSI, + MGMT_STATUS_SUCCESS, &status, 1); + + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock(hdev); +} + +static int get_raw_rssi(struct sock *sk, struct hci_dev *hdev, void *data, + u16 len) +{ + struct mgmt_pending_cmd *cmd; + struct hci_request req; + struct mgmt_cp_get_raw_rssi *cp = data; + struct hci_cp_get_raw_rssi hci_cp; + + struct hci_conn *conn; + int err; + __u8 dest_type; + + BT_DBG("Get Raw RSSI."); + + hci_dev_lock(hdev); + + if (!lmp_le_capable(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_RAW_RSSI, + MGMT_STATUS_NOT_SUPPORTED); + goto unlocked; + } + + if (cp->link_type == 0x01) + dest_type = LE_LINK; + else + dest_type = ACL_LINK; + + /* Get LE/BREDR link handle info */ + conn = hci_conn_hash_lookup_ba(hdev, + dest_type, &cp->bt_address); + if (!conn) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_RAW_RSSI, + MGMT_STATUS_NOT_CONNECTED); + goto unlocked; + } + hci_cp.conn_handle = conn->handle; + + if (!hdev_is_powered(hdev)) { + BT_DBG("%s", hdev->name); + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_RAW_RSSI, + MGMT_STATUS_NOT_POWERED); + goto unlocked; + } + + if (pending_find(MGMT_OP_GET_RAW_RSSI, hdev)) { + BT_DBG("%s", hdev->name); + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_GET_RAW_RSSI, + MGMT_STATUS_BUSY); + goto unlocked; + } + + cmd = mgmt_pending_add(sk, MGMT_OP_GET_RAW_RSSI, hdev, data, len); + if (!cmd) { + BT_DBG("%s", hdev->name); + err = -ENOMEM; + goto unlocked; + } + + hci_req_init(&req, hdev); + + BT_DBG("Connection Handle [%d]", hci_cp.conn_handle); + hci_req_add(&req, HCI_OP_GET_RAW_RSSI, sizeof(hci_cp), &hci_cp); + err = hci_req_run(&req, get_raw_rssi_complete); + + if (err < 0) { + mgmt_pending_remove(cmd); + BT_ERR("Error in requesting hci_req_run"); + } + +unlocked: + hci_dev_unlock(hdev); + + return err; +} + +void mgmt_raw_rssi_response(struct hci_dev *hdev, + struct hci_cc_rp_get_raw_rssi *rp, int success) +{ + struct mgmt_cc_rp_get_raw_rssi mgmt_rp = { 0, }; + struct hci_conn *conn; + + mgmt_rp.status = rp->status; + mgmt_rp.rssi_dbm = rp->rssi_dbm; + + conn = hci_conn_hash_lookup_handle(hdev, rp->conn_handle); + if (!conn) + return; + + bacpy(&mgmt_rp.bt_address, &conn->dst); + if (conn->type == LE_LINK) + mgmt_rp.link_type = 0x01; + else + mgmt_rp.link_type = 0x00; + + mgmt_event(MGMT_EV_RAW_RSSI, hdev, &mgmt_rp, + sizeof(struct mgmt_cc_rp_get_raw_rssi), NULL); +} + +static void set_disable_threshold_complete(struct hci_dev *hdev, + u8 status, u16 opcode) +{ + struct mgmt_pending_cmd *cmd; + + BT_DBG("status 0x%02x", status); + + hci_dev_lock(hdev); + + cmd = pending_find(MGMT_OP_SET_RSSI_DISABLE, hdev); + if (!cmd) + goto unlock; + + mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_SET_RSSI_DISABLE, + MGMT_STATUS_SUCCESS, &status, 1); + + mgmt_pending_remove(cmd); + +unlock: + hci_dev_unlock(hdev); +} + +/** Removes monitoring for a link*/ +static int set_disable_threshold(struct sock *sk, struct hci_dev *hdev, + void *data, u16 len) +{ + int err = 0; + struct hci_cp_set_rssi_threshold th = { 0, }; + struct mgmt_cp_disable_rssi *cp = data; + struct hci_conn *conn; + struct mgmt_pending_cmd *cmd; + struct hci_request req; + __u8 dest_type; + + BT_DBG("Set Disable RSSI."); + + hci_dev_lock(hdev); + + if (!lmp_le_capable(hdev)) { + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_RSSI_DISABLE, + MGMT_STATUS_NOT_SUPPORTED); + goto unlocked; + } + + /* Get LE/ACL link handle info*/ + if (cp->link_type == 0x01) + dest_type = LE_LINK; + else + dest_type = ACL_LINK; + + conn = hci_conn_hash_lookup_ba(hdev, dest_type, &cp->bdaddr); + if (!conn) { + err = mgmt_cmd_complete(sk, hdev->id, + MGMT_OP_SET_RSSI_DISABLE, 1, NULL, 0); + goto unlocked; + } + + th.hci_le_ext_opcode = 0x0B; + th.mode = 0x01; + th.conn_handle = conn->handle; + th.alert_mask = 0x00; + th.low_th = 0x00; + th.in_range_th = 0x00; + th.high_th = 0x00; + + if (!hdev_is_powered(hdev)) { + BT_DBG("%s", hdev->name); + err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_RSSI_DISABLE, + 0, data, len); + goto unlocked; + } + + if (pending_find(MGMT_OP_SET_RSSI_DISABLE, hdev)) { + BT_DBG("%s", hdev->name); + err = mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_RSSI_DISABLE, + MGMT_STATUS_BUSY); + goto unlocked; + } + + cmd = mgmt_pending_add(sk, MGMT_OP_SET_RSSI_DISABLE, hdev, cp, + sizeof(*cp)); + if (!cmd) { + BT_DBG("%s", hdev->name); + err = -ENOMEM; + goto unlocked; + } + + hci_req_init(&req, hdev); + + hci_req_add(&req, HCI_OP_ENABLE_RSSI, sizeof(th), &th); + err = hci_req_run(&req, set_disable_threshold_complete); + if (err < 0) { + mgmt_pending_remove(cmd); + BT_ERR("Error in requesting hci_req_run"); + goto unlocked; + } + +unlocked: + hci_dev_unlock(hdev); + + return err; +} + +void mgmt_rssi_alert_evt(struct hci_dev *hdev, struct sk_buff *skb) +{ + 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 = hci_conn_hash_lookup_handle(hdev, ev->conn_handle); + + if (!conn) { + BT_ERR("RSSI alert Error: Device not found for handle"); + return; + } + bacpy(&mgmt_ev.bdaddr, &conn->dst); + + if (conn->type == LE_LINK) + mgmt_ev.link_type = 0x01; + else + mgmt_ev.link_type = 0x00; + + mgmt_ev.alert_type = ev->alert_type; + mgmt_ev.rssi_dbm = ev->rssi_dbm; + + mgmt_event(MGMT_EV_RSSI_ALERT, hdev, &mgmt_ev, + sizeof(struct mgmt_ev_vendor_specific_rssi_alert), + NULL); +} #endif /* TIZEN_BT */ static bool ltk_is_valid(struct mgmt_ltk_info *key) @@ -7732,6 +8415,9 @@ static const struct hci_mgmt_handler tizen_mgmt_handlers[] = { { add_white_list, MGMT_ADD_DEV_WHITE_LIST_SIZE }, { remove_from_white_list, MGMT_REMOVE_DEV_FROM_WHITE_LIST_SIZE }, { clear_white_list, MGMT_OP_CLEAR_DEV_WHITE_LIST_SIZE }, + { set_enable_rssi, MGMT_SET_RSSI_ENABLE_SIZE }, + { get_raw_rssi, MGMT_GET_RAW_RSSI_SIZE }, + { set_disable_threshold, MGMT_SET_RSSI_DISABLE_SIZE }, }; #endif |