aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth/mgmt.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-07-02 10:37:29 -0400
committerMarcel Holtmann <marcel@holtmann.org>2014-07-03 11:42:57 -0400
commita26f3dcff2cf5890f33d883c98d90cdfa51ed460 (patch)
treef9149c17177f5e56b5fef11856c2ed51791ef509 /net/bluetooth/mgmt.c
parentc71593dd34ae1fd46777662a522a32cfde86f073 (diff)
Bluetooth: Add Load Connection Parameters command
This patch implements the new Load Connection Parameters mgmt command that's intended to load the desired connection parameters for LE devices. 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.c79
1 files changed, 79 insertions, 0 deletions
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 574dd9f7c39e..59bf1ac41429 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -88,6 +88,7 @@ static const u16 mgmt_commands[] = {
88 MGMT_OP_GET_CLOCK_INFO, 88 MGMT_OP_GET_CLOCK_INFO,
89 MGMT_OP_ADD_DEVICE, 89 MGMT_OP_ADD_DEVICE,
90 MGMT_OP_REMOVE_DEVICE, 90 MGMT_OP_REMOVE_DEVICE,
91 MGMT_OP_LOAD_CONN_PARAM,
91}; 92};
92 93
93static const u16 mgmt_events[] = { 94static const u16 mgmt_events[] = {
@@ -5134,6 +5135,83 @@ unlock:
5134 return err; 5135 return err;
5135} 5136}
5136 5137
5138static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data,
5139 u16 len)
5140{
5141 struct mgmt_cp_load_conn_param *cp = data;
5142 u16 param_count, expected_len;
5143 int i;
5144
5145 if (!lmp_le_capable(hdev))
5146 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5147 MGMT_STATUS_NOT_SUPPORTED);
5148
5149 param_count = __le16_to_cpu(cp->param_count);
5150
5151 expected_len = sizeof(*cp) + param_count *
5152 sizeof(struct mgmt_conn_param);
5153 if (expected_len != len) {
5154 BT_ERR("load_conn_param: expected %u bytes, got %u bytes",
5155 expected_len, len);
5156 return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM,
5157 MGMT_STATUS_INVALID_PARAMS);
5158 }
5159
5160 BT_DBG("%s param_count %u", hdev->name, param_count);
5161
5162 hci_dev_lock(hdev);
5163
5164 hci_conn_params_clear_disabled(hdev);
5165
5166 for (i = 0; i < param_count; i++) {
5167 struct mgmt_conn_param *param = &cp->params[i];
5168 struct hci_conn_params *hci_param;
5169 u16 min, max, latency, timeout;
5170 u8 addr_type;
5171
5172 BT_DBG("Adding %pMR (type %u)", &param->addr.bdaddr,
5173 param->addr.type);
5174
5175 if (param->addr.type == BDADDR_LE_PUBLIC) {
5176 addr_type = ADDR_LE_DEV_PUBLIC;
5177 } else if (param->addr.type == BDADDR_LE_RANDOM) {
5178 addr_type = ADDR_LE_DEV_RANDOM;
5179 } else {
5180 BT_ERR("Ignoring invalid connection parameters");
5181 continue;
5182 }
5183
5184 min = le16_to_cpu(param->min_interval);
5185 max = le16_to_cpu(param->max_interval);
5186 latency = le16_to_cpu(param->latency);
5187 timeout = le16_to_cpu(param->timeout);
5188
5189 BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x",
5190 min, max, latency, timeout);
5191
5192 if (hci_check_conn_params(min, max, latency, timeout) < 0) {
5193 BT_ERR("Ignoring invalid connection parameters");
5194 continue;
5195 }
5196
5197 hci_param = hci_conn_params_add(hdev, &param->addr.bdaddr,
5198 addr_type);
5199 if (!hci_param) {
5200 BT_ERR("Failed to add connection parameters");
5201 continue;
5202 }
5203
5204 hci_param->conn_min_interval = min;
5205 hci_param->conn_max_interval = max;
5206 hci_param->conn_latency = latency;
5207 hci_param->supervision_timeout = timeout;
5208 }
5209
5210 hci_dev_unlock(hdev);
5211
5212 return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0);
5213}
5214
5137static const struct mgmt_handler { 5215static const struct mgmt_handler {
5138 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data, 5216 int (*func) (struct sock *sk, struct hci_dev *hdev, void *data,
5139 u16 data_len); 5217 u16 data_len);
@@ -5193,6 +5271,7 @@ static const struct mgmt_handler {
5193 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE }, 5271 { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE },
5194 { add_device, false, MGMT_ADD_DEVICE_SIZE }, 5272 { add_device, false, MGMT_ADD_DEVICE_SIZE },
5195 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE }, 5273 { remove_device, false, MGMT_REMOVE_DEVICE_SIZE },
5274 { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE },
5196}; 5275};
5197 5276
5198int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) 5277int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)