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