1 /*
2  * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  * DOC: wlan_hdd_sysfs_wifi_features.c
19  *
20  * Wifi Feature sysfs implementation
21  */
22 
23 #include <linux/kobject.h>
24 
25 #include "wlan_hdd_includes.h"
26 #include "wlan_hdd_sysfs_wifi_features.h"
27 #include "wlan_hdd_sysfs.h"
28 #include "osif_sync.h"
29 
__hdd_sysfs_feature_set_show(struct hdd_context * hdd_ctx,struct kobj_attribute * attr,char * buf)30 static ssize_t  __hdd_sysfs_feature_set_show(struct hdd_context *hdd_ctx,
31 					     struct kobj_attribute *attr,
32 					     char *buf)
33 {
34 	ssize_t ret_val = 0;
35 	uint8_t i = 0;
36 	char const *solution_provider = "QCT";
37 
38 	if (!hdd_ctx->oem_data_len) {
39 		hdd_debug("Feature info is not available");
40 		return 0;
41 	}
42 
43 	for (i = 0; i < hdd_ctx->oem_data_len; i++) {
44 		/* The Solution Provider Info is from index 2 to 4 */
45 		if (i == 2) {
46 			ret_val += scnprintf(buf + ret_val, PAGE_SIZE - ret_val,
47 					     "%s", solution_provider);
48 			i = i + 2;
49 			continue;
50 		}
51 		ret_val += scnprintf(buf + ret_val, PAGE_SIZE - ret_val, "%.2X",
52 				     hdd_ctx->oem_data[i]);
53 	}
54 
55 	buf[ret_val] = '\n';
56 
57 	return ret_val;
58 }
59 
hdd_sysfs_feature_set_show(struct kobject * kobj,struct kobj_attribute * attr,char * buf)60 static ssize_t hdd_sysfs_feature_set_show(struct kobject *kobj,
61 					  struct kobj_attribute *attr,
62 					  char *buf)
63 {
64 	struct osif_psoc_sync *psoc_sync;
65 	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
66 	ssize_t errno_size;
67 	int ret;
68 
69 	ret = wlan_hdd_validate_context(hdd_ctx);
70 	if (ret != 0)
71 		return ret;
72 
73 	errno_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy),
74 					     &psoc_sync);
75 	if (errno_size)
76 		return errno_size;
77 
78 	errno_size = __hdd_sysfs_feature_set_show(hdd_ctx, attr, buf);
79 
80 	osif_psoc_sync_op_stop(psoc_sync);
81 
82 	return errno_size;
83 }
84 
85 static struct kobj_attribute feature_set_attribute =
86 	__ATTR(feature, 0660, hdd_sysfs_feature_set_show, NULL);
87 
hdd_sysfs_create_wifi_feature_interface(struct kobject * wifi_kobject)88 void hdd_sysfs_create_wifi_feature_interface(struct kobject *wifi_kobject)
89 {
90 	int error;
91 
92 	if (!wifi_kobject) {
93 		hdd_err("could not get wifi kobject!");
94 		return;
95 	}
96 
97 	error = sysfs_create_file(wifi_kobject,
98 				  &feature_set_attribute.attr);
99 	if (error)
100 		hdd_err("could not create dump in progress sysfs file");
101 }
102 
hdd_sysfs_destroy_wifi_feature_interface(struct kobject * wifi_kobject)103 void hdd_sysfs_destroy_wifi_feature_interface(struct kobject *wifi_kobject)
104 {
105 	if (!wifi_kobject) {
106 		hdd_err("could not get wifi kobject!");
107 		return;
108 	}
109 
110 	sysfs_remove_file(wifi_kobject,
111 			  &feature_set_attribute.attr);
112 }
113