1 /* 2 * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /** 19 * DOC: wlan_hdd_sysfs_motion_detection.c 20 * 21 * implementation for creating sysfs file motion_detection 22 */ 23 24 #include <wlan_hdd_includes.h> 25 #include <wlan_hdd_main.h> 26 #include "osif_vdev_sync.h" 27 #include <wlan_hdd_sysfs.h> 28 #include <wlan_hdd_sysfs_motion_detection.h> 29 #include "sme_api.h" 30 31 #define HDD_SYSFS_MT_CONFIG_UINT32_ARGS (10) 32 #define HDD_SYSFS_MT_CONFIG_UINT8_ARGS (5) 33 #define HDD_SYSFS_MT_CONFIG_NUM_ARGS (15) 34 #define HDD_SYSFS_MT_CONFIG_UINT8_INDEX (11) 35 #define MAX_SYSFS_MT_USER_COMMAND_SIZE_LENGTH (64) 36 37 static ssize_t __hdd_sysfs_mt_bl_config_store(struct net_device * net_dev,char const * buf,size_t count)38 __hdd_sysfs_mt_bl_config_store(struct net_device *net_dev, 39 char const *buf, size_t count) 40 { 41 struct sme_motion_det_base_line_cfg motion_det_base_line_cfg; 42 struct hdd_adapter *adapter = netdev_priv(net_dev); 43 char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1]; 44 struct hdd_context *hdd_ctx; 45 char *sptr, *token; 46 uint32_t bl_time_t, bl_packet_gap, bl_n, bl_num_meas; 47 int ret; 48 49 if (hdd_validate_adapter(adapter)) 50 return -EINVAL; 51 52 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 53 ret = wlan_hdd_validate_context(hdd_ctx); 54 if (ret != 0) 55 return ret; 56 57 if (!wlan_hdd_validate_modules_state(hdd_ctx)) 58 return -EINVAL; 59 60 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local), 61 buf, count); 62 63 if (ret) { 64 hdd_err_rl("invalid input"); 65 return ret; 66 } 67 68 sptr = buf_local; 69 hdd_debug("mt_bl_config: count %zu buf_local:(%s) net_devname %s", 70 count, buf_local, net_dev->name); 71 72 /* Get val1 */ 73 token = strsep(&sptr, " "); 74 if (!token) 75 return -EINVAL; 76 if (kstrtou32(token, 0, &bl_time_t)) 77 return -EINVAL; 78 79 /* Get val2 */ 80 token = strsep(&sptr, " "); 81 if (!token) 82 return -EINVAL; 83 if (kstrtou32(token, 0, &bl_packet_gap)) 84 return -EINVAL; 85 86 /* Get val3 */ 87 token = strsep(&sptr, " "); 88 if (!token) 89 return -EINVAL; 90 if (kstrtou32(token, 0, &bl_n)) 91 return -EINVAL; 92 93 /* Get val4 */ 94 token = strsep(&sptr, " "); 95 if (!token) 96 return -EINVAL; 97 if (kstrtou32(token, 0, &bl_num_meas)) 98 return -EINVAL; 99 100 motion_det_base_line_cfg.vdev_id = adapter->deflink->vdev_id; 101 motion_det_base_line_cfg.bl_time_t = bl_time_t; 102 motion_det_base_line_cfg.bl_packet_gap = bl_packet_gap; 103 motion_det_base_line_cfg.bl_n = bl_n; 104 motion_det_base_line_cfg.bl_num_meas = bl_num_meas; 105 sme_motion_det_base_line_config(hdd_ctx->mac_handle, 106 &motion_det_base_line_cfg); 107 108 return count; 109 } 110 111 static ssize_t hdd_sysfs_mt_bl_config_store(struct device * dev,struct device_attribute * attr,char const * buf,size_t count)112 hdd_sysfs_mt_bl_config_store(struct device *dev, 113 struct device_attribute *attr, 114 char const *buf, size_t count) 115 { 116 struct net_device *net_dev = container_of(dev, struct net_device, dev); 117 struct osif_vdev_sync *vdev_sync; 118 ssize_t errno_size; 119 120 errno_size = osif_vdev_sync_op_start(net_dev, &vdev_sync); 121 if (errno_size) 122 return errno_size; 123 124 errno_size = __hdd_sysfs_mt_bl_config_store(net_dev, buf, count); 125 126 osif_vdev_sync_op_stop(vdev_sync); 127 128 return errno_size; 129 } 130 131 static ssize_t __hdd_sysfs_mt_bl_start_store(struct net_device * net_dev,char const * buf,size_t count)132 __hdd_sysfs_mt_bl_start_store(struct net_device *net_dev, 133 char const *buf, size_t count) 134 { 135 struct sme_motion_det_base_line_en motion_det_base_line; 136 struct hdd_adapter *adapter = netdev_priv(net_dev); 137 char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1]; 138 struct hdd_context *hdd_ctx; 139 char *sptr, *token; 140 uint32_t value; 141 QDF_STATUS status; 142 int ret; 143 144 if (hdd_validate_adapter(adapter)) 145 return -EINVAL; 146 147 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 148 ret = wlan_hdd_validate_context(hdd_ctx); 149 if (ret != 0) 150 return ret; 151 152 if (!wlan_hdd_validate_modules_state(hdd_ctx)) 153 return -EINVAL; 154 155 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local), 156 buf, count); 157 158 if (ret) { 159 hdd_err_rl("invalid input"); 160 return ret; 161 } 162 163 /* Do not send baselining start/stop during motion detection phase */ 164 if (adapter->motion_det_in_progress) { 165 hdd_err("Motion detection still in progress, try later"); 166 return -EAGAIN; 167 } 168 169 sptr = buf_local; 170 hdd_debug("mt_bl_start: count %zu buf_local:(%s) net_devname %s", 171 count, buf_local, net_dev->name); 172 173 /* Get value */ 174 token = strsep(&sptr, " "); 175 if (!token) 176 return -EINVAL; 177 if (kstrtou32(token, 0, &value)) 178 return -EINVAL; 179 180 if (value < 0 || value > 1) { 181 hdd_err("Invalid value %d in mt_bl_start", value); 182 return -EINVAL; 183 } 184 185 motion_det_base_line.vdev_id = adapter->deflink->vdev_id; 186 motion_det_base_line.enable = value; 187 status = sme_motion_det_base_line_enable(hdd_ctx->mac_handle, 188 &motion_det_base_line); 189 190 if (status != QDF_STATUS_SUCCESS) 191 hdd_err("can't enable md baselining msg to scheduler"); 192 193 return count; 194 } 195 196 static ssize_t hdd_sysfs_mt_bl_start_store(struct device * dev,struct device_attribute * attr,char const * buf,size_t count)197 hdd_sysfs_mt_bl_start_store(struct device *dev, 198 struct device_attribute *attr, 199 char const *buf, size_t count) 200 { 201 struct net_device *net_dev = container_of(dev, struct net_device, dev); 202 struct osif_vdev_sync *vdev_sync; 203 ssize_t errno_size; 204 205 errno_size = osif_vdev_sync_op_start(net_dev, &vdev_sync); 206 if (errno_size) 207 return errno_size; 208 209 errno_size = __hdd_sysfs_mt_bl_start_store(net_dev, buf, count); 210 211 osif_vdev_sync_op_stop(vdev_sync); 212 213 return errno_size; 214 } 215 216 static ssize_t __hdd_sysfs_mt_config_store(struct net_device * net_dev,char const * buf,size_t count)217 __hdd_sysfs_mt_config_store(struct net_device *net_dev, 218 char const *buf, size_t count) 219 { 220 struct sme_motion_det_cfg motion_det_cfg; 221 struct hdd_adapter *adapter = netdev_priv(net_dev); 222 char buf_local[MAX_SYSFS_MT_USER_COMMAND_SIZE_LENGTH + 1]; 223 struct hdd_context *hdd_ctx; 224 char *sptr, *token; 225 uint8_t val_8[HDD_SYSFS_MT_CONFIG_UINT8_ARGS]; 226 uint32_t val_32[HDD_SYSFS_MT_CONFIG_UINT32_ARGS]; 227 int i, ret; 228 229 if (hdd_validate_adapter(adapter)) 230 return -EINVAL; 231 232 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 233 ret = wlan_hdd_validate_context(hdd_ctx); 234 if (ret != 0) 235 return ret; 236 237 if (!wlan_hdd_validate_modules_state(hdd_ctx)) 238 return -EINVAL; 239 240 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local), 241 buf, count); 242 243 if (ret) { 244 hdd_err_rl("invalid input"); 245 return ret; 246 } 247 248 sptr = buf_local; 249 hdd_debug("mt_config: count %zu buf_local:(%s) net_devname %s", 250 count, buf_local, net_dev->name); 251 252 for (i = 0; i < HDD_SYSFS_MT_CONFIG_NUM_ARGS; i++) { 253 token = strsep(&sptr, " "); 254 if (!token) { 255 hdd_err_rl("mt_config: not enough args(%d), expected args_num: 15", 256 i); 257 return -EINVAL; 258 } 259 if ( i >= HDD_SYSFS_MT_CONFIG_UINT8_INDEX) { 260 if (kstrtou8(token, 0, 261 &val_8[i - HDD_SYSFS_MT_CONFIG_UINT8_INDEX])) 262 return -EINVAL; 263 } else { 264 if (kstrtou32(token, 0, &val_32[i])) 265 return -EINVAL; 266 } 267 } 268 269 motion_det_cfg.vdev_id = adapter->deflink->vdev_id; 270 motion_det_cfg.time_t1 = val_32[0]; 271 motion_det_cfg.time_t2 = val_32[1]; 272 motion_det_cfg.n1 = val_32[2]; 273 motion_det_cfg.n2 = val_32[3]; 274 motion_det_cfg.time_t1_gap = val_32[4]; 275 motion_det_cfg.time_t2_gap = val_32[5]; 276 motion_det_cfg.coarse_K = val_32[6]; 277 motion_det_cfg.fine_K = val_32[7]; 278 motion_det_cfg.coarse_Q = val_32[8]; 279 motion_det_cfg.fine_Q = val_32[9]; 280 motion_det_cfg.md_coarse_thr_high = val_8[0]; 281 motion_det_cfg.md_fine_thr_high = val_8[1]; 282 motion_det_cfg.md_coarse_thr_low = val_8[2]; 283 motion_det_cfg.md_fine_thr_low = val_8[3]; 284 adapter->motion_detection_mode = val_8[4]; 285 sme_motion_det_config(hdd_ctx->mac_handle, &motion_det_cfg); 286 adapter->motion_det_cfg = true; 287 288 return count; 289 } 290 291 static ssize_t hdd_sysfs_mt_config_store(struct device * dev,struct device_attribute * attr,char const * buf,size_t count)292 hdd_sysfs_mt_config_store(struct device *dev, 293 struct device_attribute *attr, 294 char const *buf, size_t count) 295 { 296 struct net_device *net_dev = container_of(dev, struct net_device, dev); 297 struct osif_vdev_sync *vdev_sync; 298 ssize_t errno_size; 299 300 errno_size = osif_vdev_sync_op_start(net_dev, &vdev_sync); 301 if (errno_size) 302 return errno_size; 303 304 errno_size = __hdd_sysfs_mt_config_store(net_dev, buf, count); 305 306 osif_vdev_sync_op_stop(vdev_sync); 307 308 return errno_size; 309 } 310 311 static ssize_t __hdd_sysfs_mt_start_store(struct net_device * net_dev,char const * buf,size_t count)312 __hdd_sysfs_mt_start_store(struct net_device *net_dev, 313 char const *buf, size_t count) 314 { 315 struct sme_motion_det_en motion_det; 316 struct hdd_adapter *adapter = netdev_priv(net_dev); 317 char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1]; 318 struct hdd_context *hdd_ctx; 319 char *sptr, *token; 320 uint32_t value; 321 int ret; 322 323 if (hdd_validate_adapter(adapter)) 324 return -EINVAL; 325 326 hdd_ctx = WLAN_HDD_GET_CTX(adapter); 327 ret = wlan_hdd_validate_context(hdd_ctx); 328 if (ret != 0) 329 return ret; 330 331 if (!wlan_hdd_validate_modules_state(hdd_ctx)) 332 return -EINVAL; 333 334 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local), 335 buf, count); 336 337 if (ret) { 338 hdd_err_rl("invalid input"); 339 return ret; 340 } 341 342 sptr = buf_local; 343 hdd_debug("mt_start: count %zu buf_local:(%s) net_devname %s", 344 count, buf_local, net_dev->name); 345 346 /* Get value */ 347 token = strsep(&sptr, " "); 348 if (!token) 349 return -EINVAL; 350 if (kstrtou32(token, 0, &value)) 351 return -EINVAL; 352 353 if (value < 0 || value > 1) { 354 hdd_err("Invalid value %d in mt_start", value); 355 return -EINVAL; 356 } 357 358 if (!adapter->motion_det_cfg) { 359 hdd_err("Motion Detection config values not available"); 360 return -EINVAL; 361 } 362 363 if (!adapter->motion_det_baseline_value) { 364 hdd_err("Motion Detection Baselining not started/completed"); 365 return -EAGAIN; 366 } 367 368 motion_det.vdev_id = adapter->deflink->vdev_id; 369 motion_det.enable = value; 370 371 if (value) { 372 /* For motion detection start, set motion_det_in_progress */ 373 adapter->motion_det_in_progress = true; 374 } else { 375 /* For motion detection stop, reset motion_det_in_progress */ 376 adapter->motion_det_in_progress = false; 377 adapter->motion_detection_mode = 0; 378 } 379 380 sme_motion_det_enable(hdd_ctx->mac_handle, &motion_det); 381 382 return count; 383 } 384 385 static ssize_t hdd_sysfs_mt_start_store(struct device * dev,struct device_attribute * attr,char const * buf,size_t count)386 hdd_sysfs_mt_start_store(struct device *dev, 387 struct device_attribute *attr, 388 char const *buf, size_t count) 389 { 390 struct net_device *net_dev = container_of(dev, struct net_device, dev); 391 struct osif_vdev_sync *vdev_sync; 392 ssize_t errno_size; 393 394 errno_size = osif_vdev_sync_op_start(net_dev, &vdev_sync); 395 if (errno_size) 396 return errno_size; 397 398 errno_size = __hdd_sysfs_mt_start_store(net_dev, buf, count); 399 400 osif_vdev_sync_op_stop(vdev_sync); 401 402 return errno_size; 403 } 404 405 static DEVICE_ATTR(mt_bl_config, 0220, 406 NULL, hdd_sysfs_mt_bl_config_store); 407 408 static DEVICE_ATTR(mt_bl_start, 0220, 409 NULL, hdd_sysfs_mt_bl_start_store); 410 411 static DEVICE_ATTR(mt_config, 0220, 412 NULL, hdd_sysfs_mt_config_store); 413 414 static DEVICE_ATTR(mt_start, 0220, 415 NULL, hdd_sysfs_mt_start_store); 416 hdd_sysfs_mt_bl_config_create(struct hdd_adapter * adapter)417 static int hdd_sysfs_mt_bl_config_create(struct hdd_adapter *adapter) 418 { 419 int error; 420 421 error = device_create_file(&adapter->dev->dev, &dev_attr_mt_bl_config); 422 if (error) 423 hdd_err("could not create mt_bl_config sysfs file"); 424 425 return error; 426 } 427 hdd_sysfs_mt_bl_config_destroy(struct hdd_adapter * adapter)428 static void hdd_sysfs_mt_bl_config_destroy(struct hdd_adapter *adapter) 429 { 430 device_remove_file(&adapter->dev->dev, &dev_attr_mt_bl_config); 431 } 432 hdd_sysfs_mt_bl_start_create(struct hdd_adapter * adapter)433 static int hdd_sysfs_mt_bl_start_create(struct hdd_adapter *adapter) 434 { 435 int error; 436 437 error = device_create_file(&adapter->dev->dev, &dev_attr_mt_bl_start); 438 if (error) 439 hdd_err("could not create mt_bl_start sysfs file"); 440 441 return error; 442 } 443 hdd_sysfs_mt_bl_start_destroy(struct hdd_adapter * adapter)444 static void hdd_sysfs_mt_bl_start_destroy(struct hdd_adapter *adapter) 445 { 446 device_remove_file(&adapter->dev->dev, &dev_attr_mt_bl_start); 447 } 448 hdd_sysfs_mt_config_create(struct hdd_adapter * adapter)449 static int hdd_sysfs_mt_config_create(struct hdd_adapter *adapter) 450 { 451 int error; 452 453 error = device_create_file(&adapter->dev->dev, &dev_attr_mt_config); 454 if (error) 455 hdd_err("could not create mt_config sysfs file"); 456 457 return error; 458 } 459 hdd_sysfs_mt_config_destroy(struct hdd_adapter * adapter)460 static void hdd_sysfs_mt_config_destroy(struct hdd_adapter *adapter) 461 { 462 device_remove_file(&adapter->dev->dev, &dev_attr_mt_config); 463 } 464 hdd_sysfs_mt_start_create(struct hdd_adapter * adapter)465 static int hdd_sysfs_mt_start_create(struct hdd_adapter *adapter) 466 { 467 int error; 468 469 error = device_create_file(&adapter->dev->dev, &dev_attr_mt_start); 470 if (error) 471 hdd_err("could not create mt_start sysfs file"); 472 473 return error; 474 } 475 hdd_sysfs_mt_start_destroy(struct hdd_adapter * adapter)476 static void hdd_sysfs_mt_start_destroy(struct hdd_adapter *adapter) 477 { 478 device_remove_file(&adapter->dev->dev, &dev_attr_mt_start); 479 } 480 hdd_sysfs_motion_detection_create(struct hdd_adapter * adapter)481 void hdd_sysfs_motion_detection_create(struct hdd_adapter *adapter) 482 { 483 hdd_sysfs_mt_bl_config_create(adapter); 484 hdd_sysfs_mt_bl_start_create(adapter); 485 hdd_sysfs_mt_config_create(adapter); 486 hdd_sysfs_mt_start_create(adapter); 487 } 488 hdd_sysfs_motion_detection_destroy(struct hdd_adapter * adapter)489 void hdd_sysfs_motion_detection_destroy(struct hdd_adapter *adapter) 490 { 491 hdd_sysfs_mt_start_destroy(adapter); 492 hdd_sysfs_mt_config_destroy(adapter); 493 hdd_sysfs_mt_bl_start_destroy(adapter); 494 hdd_sysfs_mt_bl_config_destroy(adapter); 495 } 496