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