aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/mgmt.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-12-05 06:42:57 -0500
committerMarcel Holtmann <marcel@holtmann.org>2014-12-05 06:46:28 -0500
commit9981bdb05a220d8c58ec47357d0423d0f07f6089 (patch)
tree1385c00cee8206716cca14dc819521c4f58ea1f7 /net/bluetooth/mgmt.c
parentebf86aa3aeaa4e9f434dacdd0a1d851a6c0332f8 (diff)
Bluetooth: Fix Get Conn Info to use cmd_complete callback
This patch fixes the Get Connection Information mgmt command to take advantage of the new cmd_complete callback. This allows for great simplifications in the logic for constructing the cmd_complete event. Signed-off-by: Johan Hedberg <johan.hedberg@intel.com> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/mgmt.c')
-rw-r--r--net/bluetooth/mgmt.c84
1 files changed, 33 insertions, 51 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 8467d3552aa9..61a04a3de7ad 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -5074,67 +5074,42 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
5074 return err; 5074 return err;
5075} 5075}
5076 5076
5077struct cmd_conn_lookup { 5077static void conn_info_cmd_complete(struct pending_cmd *cmd, u8 status)
5078 struct hci_conn *conn;
5079 bool valid_tx_power;
5080 u8 mgmt_status;
5081};
5082
5083static void get_conn_info_complete(struct pending_cmd *cmd, void *data)
5084{ 5078{
5085 struct cmd_conn_lookup *match = data;
5086 struct mgmt_cp_get_conn_info *cp;
5087 struct mgmt_rp_get_conn_info rp;
5088 struct hci_conn *conn = cmd->user_data; 5079 struct hci_conn *conn = cmd->user_data;
5080 struct mgmt_rp_get_conn_info rp;
5089 5081
5090 if (conn != match->conn) 5082 memcpy(&rp.addr, cmd->param, sizeof(rp.addr));
5091 return;
5092
5093 cp = (struct mgmt_cp_get_conn_info *) cmd->param;
5094 5083
5095 memset(&rp, 0, sizeof(rp)); 5084 if (status == MGMT_STATUS_SUCCESS) {
5096 bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr);
5097 rp.addr.type = cp->addr.type;
5098
5099 if (!match->mgmt_status) {
5100 rp.rssi = conn->rssi; 5085 rp.rssi = conn->rssi;
5101 5086 rp.tx_power = conn->tx_power;
5102 if (match->valid_tx_power) { 5087 rp.max_tx_power = conn->max_tx_power;
5103 rp.tx_power = conn->tx_power; 5088 } else {
5104 rp.max_tx_power = conn->max_tx_power; 5089 rp.rssi = HCI_RSSI_INVALID;
5105 } else { 5090 rp.tx_power = HCI_TX_POWER_INVALID;
5106 rp.tx_power = HCI_TX_POWER_INVALID; 5091 rp.max_tx_power = HCI_TX_POWER_INVALID;
5107 rp.max_tx_power = HCI_TX_POWER_INVALID;
5108 }
5109 } 5092 }
5110 5093
5111 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, 5094 cmd_complete(cmd->sk, cmd->index, MGMT_OP_GET_CONN_INFO, status,
5112 match->mgmt_status, &rp, sizeof(rp)); 5095 &rp, sizeof(rp));
5113 5096
5114 hci_conn_drop(conn); 5097 hci_conn_drop(conn);
5115 hci_conn_put(conn); 5098 hci_conn_put(conn);
5116
5117 mgmt_pending_remove(cmd);
5118} 5099}
5119 5100
5120static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status) 5101static void conn_info_refresh_complete(struct hci_dev *hdev, u8 hci_status)
5121{ 5102{
5122 struct hci_cp_read_rssi *cp; 5103 struct hci_cp_read_rssi *cp;
5104 struct pending_cmd *cmd;
5123 struct hci_conn *conn; 5105 struct hci_conn *conn;
5124 struct cmd_conn_lookup match;
5125 u16 handle; 5106 u16 handle;
5107 u8 status;
5126 5108
5127 BT_DBG("status 0x%02x", status); 5109 BT_DBG("status 0x%02x", hci_status);
5128 5110
5129 hci_dev_lock(hdev); 5111 hci_dev_lock(hdev);
5130 5112
5131 /* TX power data is valid in case request completed successfully,
5132 * otherwise we assume it's not valid. At the moment we assume that
5133 * either both or none of current and max values are valid to keep code
5134 * simple.
5135 */
5136 match.valid_tx_power = !status;
5137
5138 /* Commands sent in request are either Read RSSI or Read Transmit Power 5113 /* Commands sent in request are either Read RSSI or Read Transmit Power
5139 * Level so we check which one was last sent to retrieve connection 5114 * Level so we check which one was last sent to retrieve connection
5140 * handle. Both commands have handle as first parameter so it's safe to 5115 * handle. Both commands have handle as first parameter so it's safe to
@@ -5147,29 +5122,29 @@ static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status)
5147 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI); 5122 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_RSSI);
5148 if (!cp) { 5123 if (!cp) {
5149 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER); 5124 cp = hci_sent_cmd_data(hdev, HCI_OP_READ_TX_POWER);
5150 status = 0; 5125 status = MGMT_STATUS_SUCCESS;
5126 } else {
5127 status = mgmt_status(hci_status);
5151 } 5128 }
5152 5129
5153 if (!cp) { 5130 if (!cp) {
5154 BT_ERR("invalid sent_cmd in response"); 5131 BT_ERR("invalid sent_cmd in conn_info response");
5155 goto unlock; 5132 goto unlock;
5156 } 5133 }
5157 5134
5158 handle = __le16_to_cpu(cp->handle); 5135 handle = __le16_to_cpu(cp->handle);
5159 conn = hci_conn_hash_lookup_handle(hdev, handle); 5136 conn = hci_conn_hash_lookup_handle(hdev, handle);
5160 if (!conn) { 5137 if (!conn) {
5161 BT_ERR("unknown handle (%d) in response", handle); 5138 BT_ERR("unknown handle (%d) in conn_info response", handle);
5162 goto unlock; 5139 goto unlock;
5163 } 5140 }
5164 5141
5165 match.conn = conn; 5142 cmd = mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn);
5166 match.mgmt_status = mgmt_status(status); 5143 if (!cmd)
5144 goto unlock;
5167 5145
5168 /* Cache refresh is complete, now reply for mgmt request for given 5146 cmd->cmd_complete(cmd, status);
5169 * connection only. 5147 mgmt_pending_remove(cmd);
5170 */
5171 mgmt_pending_foreach(MGMT_OP_GET_CONN_INFO, hdev,
5172 get_conn_info_complete, &match);
5173 5148
5174unlock: 5149unlock:
5175 hci_dev_unlock(hdev); 5150 hci_dev_unlock(hdev);
@@ -5215,6 +5190,12 @@ static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5215 goto unlock; 5190 goto unlock;
5216 } 5191 }
5217 5192
5193 if (mgmt_pending_find_data(MGMT_OP_GET_CONN_INFO, hdev, conn)) {
5194 err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CONN_INFO,
5195 MGMT_STATUS_BUSY, &rp, sizeof(rp));
5196 goto unlock;
5197 }
5198
5218 /* To avoid client trying to guess when to poll again for information we 5199 /* To avoid client trying to guess when to poll again for information we
5219 * calculate conn info age as random value between min/max set in hdev. 5200 * calculate conn info age as random value between min/max set in hdev.
5220 */ 5201 */
@@ -5270,6 +5251,7 @@ static int get_conn_info(struct sock *sk, struct hci_dev *hdev, void *data,
5270 5251
5271 hci_conn_hold(conn); 5252 hci_conn_hold(conn);
5272 cmd->user_data = hci_conn_get(conn); 5253 cmd->user_data = hci_conn_get(conn);
5254 cmd->cmd_complete = conn_info_cmd_complete;
5273 5255
5274 conn->conn_info_timestamp = jiffies; 5256 conn->conn_info_timestamp = jiffies;
5275 } else { 5257 } else {