diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2014-12-05 06:42:57 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2014-12-05 06:46:28 -0500 |
commit | 9981bdb05a220d8c58ec47357d0423d0f07f6089 (patch) | |
tree | 1385c00cee8206716cca14dc819521c4f58ea1f7 /net/bluetooth/mgmt.c | |
parent | ebf86aa3aeaa4e9f434dacdd0a1d851a6c0332f8 (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.c | 84 |
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 | ||
5077 | struct cmd_conn_lookup { | 5077 | static 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 | |||
5083 | static 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 | ||
5120 | static void conn_info_refresh_complete(struct hci_dev *hdev, u8 status) | 5101 | static 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 | ||
5174 | unlock: | 5149 | unlock: |
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 { |