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