xref: /wlan-driver/qcacld-3.0/core/hdd/src/wlan_hdd_oemdata.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2012-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
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /**
21  *  DOC: wlan_hdd_oemdata.c
22  *
23  *  Support for generic OEM Data Request handling
24  *
25  */
26 
27 #if defined(FEATURE_OEM_DATA_SUPPORT) || defined(FEATURE_OEM_DATA)
28 #include <linux/version.h>
29 #include <linux/module.h>
30 #include <linux/kernel.h>
31 #include <linux/init.h>
32 #include <linux/wireless.h>
33 #include "osif_sync.h"
34 #include <wlan_hdd_includes.h>
35 #include <net/arp.h>
36 #include "qwlan_version.h"
37 #include "cds_utils.h"
38 #include "wma.h"
39 #include "sme_api.h"
40 #include "wlan_nlink_srv.h"
41 #include "wlan_hdd_oemdata.h"
42 #include "wlan_osif_request_manager.h"
43 #include "wlan_hdd_main.h"
44 #include "wlan_hdd_sysfs.h"
45 
46 #ifdef FEATURE_OEM_DATA_SUPPORT
47 #ifdef CNSS_GENL
48 #include <net/cnss_nl.h>
49 #endif
50 
51 static struct hdd_context *p_hdd_ctx;
52 
53 /**
54  * populate_oem_data_cap() - populate oem capabilities
55  * @adapter: device adapter
56  * @data_cap: pointer to populate the capabilities
57  *
58  * Return: error code
59  */
populate_oem_data_cap(struct hdd_adapter * adapter,struct oem_data_cap * data_cap)60 static int populate_oem_data_cap(struct hdd_adapter *adapter,
61 				 struct oem_data_cap *data_cap)
62 {
63 	QDF_STATUS status;
64 	struct hdd_config *config;
65 	uint32_t num_chan, i;
66 	uint32_t *chan_freq_list;
67 	uint8_t band_capability;
68 	uint32_t band_bitmap;
69 	uint16_t neighbor_scan_min_chan_time;
70 	uint16_t neighbor_scan_max_chan_time;
71 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
72 
73 	config = hdd_ctx->config;
74 	if (!config) {
75 		hdd_err("HDD configuration is null");
76 		return -EINVAL;
77 	}
78 
79 	status = ucfg_mlme_get_band_capability(hdd_ctx->psoc, &band_bitmap);
80 	if (QDF_IS_STATUS_ERROR(status)) {
81 		hdd_err("Failed to get MLME band capability");
82 		return -EIO;
83 	}
84 
85 	band_capability = wlan_reg_band_bitmap_to_band_info(band_bitmap);
86 
87 	chan_freq_list =
88 		qdf_mem_malloc(sizeof(uint32_t) * OEM_CAP_MAX_NUM_CHANNELS);
89 	if (!chan_freq_list)
90 		return -ENOMEM;
91 
92 	strlcpy(data_cap->oem_target_signature, OEM_TARGET_SIGNATURE,
93 		OEM_TARGET_SIGNATURE_LEN);
94 	data_cap->oem_target_type = hdd_ctx->target_type;
95 	data_cap->oem_fw_version = hdd_ctx->target_fw_version;
96 	data_cap->driver_version.major = QWLAN_VERSION_MAJOR;
97 	data_cap->driver_version.minor = QWLAN_VERSION_MINOR;
98 	data_cap->driver_version.patch = QWLAN_VERSION_PATCH;
99 	data_cap->driver_version.build = QWLAN_VERSION_BUILD;
100 	ucfg_mlme_get_neighbor_scan_max_chan_time(psoc,
101 						  &neighbor_scan_max_chan_time);
102 	ucfg_mlme_get_neighbor_scan_min_chan_time(psoc,
103 						  &neighbor_scan_min_chan_time);
104 	data_cap->allowed_dwell_time_min = neighbor_scan_min_chan_time;
105 	data_cap->allowed_dwell_time_max = neighbor_scan_max_chan_time;
106 	data_cap->curr_dwell_time_min =
107 		ucfg_cm_get_neighbor_scan_min_chan_time(
108 				hdd_ctx->psoc, adapter->deflink->vdev_id);
109 	data_cap->curr_dwell_time_max =
110 		ucfg_cm_get_neighbor_scan_max_chan_time(
111 				hdd_ctx->psoc, adapter->deflink->vdev_id);
112 	data_cap->supported_bands = band_capability;
113 
114 	/* request for max num of channels */
115 	num_chan = OEM_CAP_MAX_NUM_CHANNELS;
116 	status = sme_get_cfg_valid_channels(&chan_freq_list[0], &num_chan);
117 	if (QDF_STATUS_SUCCESS != status) {
118 		hdd_err("failed to get valid channel list, status: %d", status);
119 		qdf_mem_free(chan_freq_list);
120 		return -EINVAL;
121 	}
122 
123 	/* make sure num channels is not more than chan list array */
124 	if (num_chan > OEM_CAP_MAX_NUM_CHANNELS) {
125 		hdd_err("Num of channels-%d > length-%d of chan_freq_list",
126 			num_chan, OEM_CAP_MAX_NUM_CHANNELS);
127 		qdf_mem_free(chan_freq_list);
128 		return -ENOMEM;
129 	}
130 
131 	data_cap->num_channels = num_chan;
132 	for (i = 0; i < num_chan; i++) {
133 		data_cap->channel_list[i] =
134 			wlan_reg_freq_to_chan(hdd_ctx->pdev, chan_freq_list[i]);
135 	}
136 
137 	qdf_mem_free(chan_freq_list);
138 	return 0;
139 }
140 
141 /**
142  * iw_get_oem_data_cap() - Get OEM Data Capabilities
143  * @dev: net device upon which the request was received
144  * @info: ioctl request information
145  * @wrqu: ioctl request data
146  * @extra: ioctl data payload
147  *
148  * This function gets the capability information for OEM Data Request
149  * and Response.
150  *
151  * Return: 0 for success, negative errno value on failure
152  */
iw_get_oem_data_cap(struct net_device * dev,struct iw_request_info * info,union iwreq_data * wrqu,char * extra)153 int iw_get_oem_data_cap(struct net_device *dev,
154 			struct iw_request_info *info,
155 			union iwreq_data *wrqu, char *extra)
156 {
157 	struct oem_data_cap *oem_data_cap = (void *)extra;
158 	struct hdd_adapter *adapter = netdev_priv(dev);
159 	struct hdd_context *hdd_ctx;
160 	int errno;
161 
162 	hdd_enter();
163 
164 	hdd_ctx = WLAN_HDD_GET_CTX(adapter);
165 	errno = wlan_hdd_validate_context(hdd_ctx);
166 	if (errno)
167 		return errno;
168 
169 	qdf_mem_zero(oem_data_cap, sizeof(*oem_data_cap));
170 	errno = populate_oem_data_cap(adapter, oem_data_cap);
171 	if (errno) {
172 		hdd_err("Failed to populate oem data capabilities");
173 		return errno;
174 	}
175 
176 	hdd_exit();
177 	return 0;
178 }
179 
180 /**
181  * send_oem_reg_rsp_nlink_msg() - send oem registration response
182  *
183  * This function sends oem message to registered application process
184  *
185  * Return:  none
186  */
send_oem_reg_rsp_nlink_msg(void)187 static void send_oem_reg_rsp_nlink_msg(void)
188 {
189 	struct sk_buff *skb;
190 	struct nlmsghdr *nlh;
191 	tAniMsgHdr *ani_hdr;
192 	uint8_t *buf;
193 	uint8_t *num_interfaces;
194 	uint8_t *device_mode;
195 	uint8_t *vdev_id;
196 	struct hdd_adapter *adapter, *next_adapter = NULL;
197 	wlan_net_dev_ref_dbgid dbgid = NET_DEV_HOLD_SEND_OEM_REG_RSP_NLINK_MSG;
198 	struct wlan_hdd_link_info *link_info;
199 
200 	/* OEM msg is always to a specific process & cannot be a broadcast */
201 	if (p_hdd_ctx->oem_pid == 0) {
202 		hdd_err("invalid dest pid");
203 		return;
204 	}
205 
206 	skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
207 	if (!skb)
208 		return;
209 
210 	nlh = (struct nlmsghdr *)skb->data;
211 	nlh->nlmsg_pid = 0;     /* from kernel */
212 	nlh->nlmsg_flags = 0;
213 	nlh->nlmsg_seq = 0;
214 	nlh->nlmsg_type = WLAN_NL_MSG_OEM;
215 	ani_hdr = NLMSG_DATA(nlh);
216 	ani_hdr->type = ANI_MSG_APP_REG_RSP;
217 
218 	/* Fill message body:
219 	 *   First byte will be number of interfaces, followed by
220 	 *   two bytes for each interfaces
221 	 *     - one byte for device mode
222 	 *     - one byte for vdev id
223 	 */
224 	buf = (char *)((char *)ani_hdr + sizeof(tAniMsgHdr));
225 	num_interfaces = buf++;
226 	*num_interfaces = 0;
227 
228 	/* Iterate through each adapter and fill device mode and vdev id */
229 	hdd_for_each_adapter_dev_held_safe(p_hdd_ctx, adapter, next_adapter,
230 					   dbgid) {
231 		hdd_adapter_for_each_active_link_info(adapter, link_info) {
232 			device_mode = buf++;
233 			vdev_id = buf++;
234 			*device_mode = adapter->device_mode;
235 			*vdev_id = link_info->vdev_id;
236 			(*num_interfaces)++;
237 			hdd_debug("num_interfaces: %d, device_mode: %d, vdev_id: %d",
238 				  *num_interfaces, *device_mode, *vdev_id);
239 		}
240 		hdd_adapter_dev_put_debug(adapter, dbgid);
241 	}
242 
243 	ani_hdr->length =
244 		sizeof(uint8_t) + (*num_interfaces) * 2 * sizeof(uint8_t);
245 	nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + ani_hdr->length));
246 
247 	skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + ani_hdr->length)));
248 
249 	hdd_debug("sending App Reg Response length: %d to pid: %d",
250 		   ani_hdr->length, p_hdd_ctx->oem_pid);
251 
252 	(void)nl_srv_ucast_oem(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
253 }
254 
255 /**
256  * send_oem_err_rsp_nlink_msg() - send oem error response
257  * @app_pid: PID of oem application process
258  * @error_code: response error code
259  *
260  * This function sends error response to oem app
261  *
262  * Return: none
263  */
send_oem_err_rsp_nlink_msg(int32_t app_pid,uint8_t error_code)264 static void send_oem_err_rsp_nlink_msg(int32_t app_pid, uint8_t error_code)
265 {
266 	struct sk_buff *skb;
267 	struct nlmsghdr *nlh;
268 	tAniMsgHdr *ani_hdr;
269 	uint8_t *buf;
270 
271 	skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
272 	if (!skb)
273 		return;
274 
275 	nlh = (struct nlmsghdr *)skb->data;
276 	nlh->nlmsg_pid = 0;     /* from kernel */
277 	nlh->nlmsg_flags = 0;
278 	nlh->nlmsg_seq = 0;
279 	nlh->nlmsg_type = WLAN_NL_MSG_OEM;
280 	ani_hdr = NLMSG_DATA(nlh);
281 	ani_hdr->type = ANI_MSG_OEM_ERROR;
282 	ani_hdr->length = sizeof(uint8_t);
283 	nlh->nlmsg_len = NLMSG_LENGTH(sizeof(tAniMsgHdr) + ani_hdr->length);
284 
285 	/* message body will contain one byte of error code */
286 	buf = (char *)((char *)ani_hdr + sizeof(tAniMsgHdr));
287 	*buf = error_code;
288 
289 	skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + ani_hdr->length));
290 
291 	hdd_debug("sending oem error response to pid: %d", app_pid);
292 
293 	(void)nl_srv_ucast_oem(skb, app_pid, MSG_DONTWAIT);
294 }
295 
296 /**
297  * hdd_send_oem_data_rsp_msg() - send oem data response
298  * @oem_data_rsp: the actual OEM Data Response message
299  *
300  * This function sends an OEM Data Response message to a registered
301  * application process over the netlink socket.
302  *
303  * Return: 0 for success, non zero for failure
304  */
hdd_send_oem_data_rsp_msg(struct oem_data_rsp * oem_data_rsp)305 void hdd_send_oem_data_rsp_msg(struct oem_data_rsp *oem_data_rsp)
306 {
307 	struct sk_buff *skb;
308 	struct nlmsghdr *nlh;
309 	tAniMsgHdr *ani_hdr;
310 	uint8_t *oem_data;
311 
312 	/*
313 	 * OEM message is always to a specific process and cannot be a broadcast
314 	 */
315 	if (p_hdd_ctx->oem_pid == 0) {
316 		hdd_err("invalid dest pid");
317 		return;
318 	}
319 
320 	if (oem_data_rsp->rsp_len > OEM_DATA_RSP_SIZE) {
321 		hdd_err("invalid length of Oem Data response");
322 		return;
323 	}
324 
325 	skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + OEM_DATA_RSP_SIZE),
326 			GFP_KERNEL);
327 	if (!skb)
328 		return;
329 
330 	nlh = (struct nlmsghdr *)skb->data;
331 	nlh->nlmsg_pid = 0;     /* from kernel */
332 	nlh->nlmsg_flags = 0;
333 	nlh->nlmsg_seq = 0;
334 	nlh->nlmsg_type = WLAN_NL_MSG_OEM;
335 	ani_hdr = NLMSG_DATA(nlh);
336 	ani_hdr->type = ANI_MSG_OEM_DATA_RSP;
337 
338 	ani_hdr->length = oem_data_rsp->rsp_len;
339 	nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + ani_hdr->length));
340 	oem_data = (uint8_t *) ((char *)ani_hdr + sizeof(tAniMsgHdr));
341 	qdf_mem_copy(oem_data, oem_data_rsp->data, oem_data_rsp->rsp_len);
342 
343 	skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + ani_hdr->length)));
344 
345 	hdd_debug("sending Oem Data Response of len : %d to pid: %d",
346 		   oem_data_rsp->rsp_len, p_hdd_ctx->oem_pid);
347 
348 	(void)nl_srv_ucast_oem(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
349 }
350 
351 /**
352  * oem_process_data_req_msg() - process oem data request
353  * @oem_data_len: Length to OEM Data buffer
354  * @oem_data: Pointer to OEM Data buffer
355  *
356  * This function sends oem message to SME
357  *
358  * Return: QDF_STATUS enumeration
359  */
oem_process_data_req_msg(int oem_data_len,char * oem_data)360 static QDF_STATUS oem_process_data_req_msg(int oem_data_len, char *oem_data)
361 {
362 	struct oem_data_req oem_data_req;
363 	QDF_STATUS status = QDF_STATUS_SUCCESS;
364 
365 	/* for now, STA interface only */
366 	if (!hdd_get_adapter(p_hdd_ctx, QDF_STA_MODE) &&
367 	    !hdd_get_adapter(p_hdd_ctx, QDF_SAP_MODE)) {
368 		hdd_err("No adapter for STA or SAP mode");
369 		return QDF_STATUS_E_FAILURE;
370 	}
371 
372 	if (!oem_data) {
373 		hdd_err("oem_data is null");
374 		return QDF_STATUS_E_FAILURE;
375 	}
376 
377 	qdf_mem_zero(&oem_data_req, sizeof(oem_data_req));
378 
379 	oem_data_req.data = qdf_mem_malloc(oem_data_len);
380 	if (!oem_data_req.data)
381 		return QDF_STATUS_E_NOMEM;
382 
383 	oem_data_req.data_len = oem_data_len;
384 	qdf_mem_copy(oem_data_req.data, oem_data, oem_data_len);
385 
386 	status = sme_oem_req_cmd(p_hdd_ctx->mac_handle, &oem_data_req);
387 
388 	qdf_mem_free(oem_data_req.data);
389 	oem_data_req.data = NULL;
390 
391 	return status;
392 }
393 
hdd_update_channel_bw_info(struct hdd_context * hdd_ctx,uint32_t chan_freq,void * chan_info)394 void hdd_update_channel_bw_info(struct hdd_context *hdd_ctx,
395 				uint32_t chan_freq, void *chan_info)
396 {
397 	struct ch_params ch_params = {0};
398 	enum wlan_phymode phy_mode;
399 	uint16_t fw_phy_mode;
400 	uint32_t wni_dot11_mode;
401 	struct hdd_channel_info *hdd_chan_info = chan_info;
402 
403 	wni_dot11_mode = sme_get_wni_dot11_mode(hdd_ctx->mac_handle);
404 
405 	/* Passing CH_WIDTH_MAX will give the max bandwidth supported */
406 	ch_params.ch_width = CH_WIDTH_MAX;
407 
408 	wlan_reg_set_channel_params_for_pwrmode(
409 		hdd_ctx->pdev, chan_freq, 0, &ch_params, REG_CURRENT_PWR_MODE);
410 	if (ch_params.center_freq_seg0)
411 		hdd_chan_info->band_center_freq1 =
412 			cds_chan_to_freq(ch_params.center_freq_seg0);
413 
414 	if (ch_params.ch_width < CH_WIDTH_INVALID) {
415 		phy_mode = wma_chan_phy_mode(chan_freq, ch_params.ch_width,
416 					     wni_dot11_mode);
417 	}
418 	else
419 		/*
420 		 * If channel width is CH_WIDTH_INVALID, It mean channel is
421 		 * invalid and should not have been received in channel info
422 		 * req. Set invalid phymode in this case.
423 		 */
424 		phy_mode = WLAN_PHYMODE_AUTO;
425 
426 	fw_phy_mode = wmi_host_to_fw_phymode(phy_mode);
427 
428 	hdd_debug("chan %d dot11_mode %d ch_width %d sec offset %d freq_seg0 %d phy_mode %d fw_phy_mode %d",
429 		  chan_freq, wni_dot11_mode, ch_params.ch_width,
430 		  ch_params.sec_ch_offset,
431 		  hdd_chan_info->band_center_freq1, phy_mode, fw_phy_mode);
432 
433 	WMI_SET_CHANNEL_MODE(hdd_chan_info, fw_phy_mode);
434 }
435 
436 /**
437  * oem_process_channel_info_req_msg() - process oem channel_info request
438  * @numOfChannels: number of channels
439  * @chanList: list of channel information
440  *
441  * This function responds with channel info to oem process
442  *
443  * Return: 0 for success, non zero for failure
444  */
oem_process_channel_info_req_msg(int numOfChannels,char * chanList)445 static int oem_process_channel_info_req_msg(int numOfChannels, char *chanList)
446 {
447 	struct sk_buff *skb;
448 	struct nlmsghdr *nlh;
449 	tAniMsgHdr *ani_hdr;
450 	struct hdd_channel_info *pHddChanInfo;
451 	struct hdd_channel_info hddChanInfo;
452 	uint32_t reg_info_1;
453 	uint32_t reg_info_2;
454 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
455 	int i;
456 	uint8_t *buf;
457 	uint32_t chan_freq;
458 
459 	/* OEM msg is always to a specific process and cannot be a broadcast */
460 	if (p_hdd_ctx->oem_pid == 0) {
461 		hdd_err("invalid dest pid");
462 		return -EPERM;
463 	}
464 
465 	skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + sizeof(uint8_t) +
466 				    numOfChannels * sizeof(*pHddChanInfo)),
467 			GFP_KERNEL);
468 	if (!skb)
469 		return -ENOMEM;
470 
471 	nlh = (struct nlmsghdr *)skb->data;
472 	nlh->nlmsg_pid = 0;     /* from kernel */
473 	nlh->nlmsg_flags = 0;
474 	nlh->nlmsg_seq = 0;
475 	nlh->nlmsg_type = WLAN_NL_MSG_OEM;
476 	ani_hdr = NLMSG_DATA(nlh);
477 	ani_hdr->type = ANI_MSG_CHANNEL_INFO_RSP;
478 
479 	ani_hdr->length =
480 		sizeof(uint8_t) + numOfChannels * sizeof(*pHddChanInfo);
481 	nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + ani_hdr->length));
482 
483 	/* First byte of message body will have num of channels */
484 	buf = (char *)((char *)ani_hdr + sizeof(tAniMsgHdr));
485 	*buf++ = numOfChannels;
486 
487 	/* Next follows channel info struct for each channel id.
488 	 * If chan id is wrong or SME returns failure for a channel
489 	 * then fill in 0 in channel info for that particular channel
490 	 */
491 	for (i = 0; i < numOfChannels; i++) {
492 		pHddChanInfo = (struct hdd_channel_info *) ((char *)buf +
493 						    i *
494 						    sizeof(*pHddChanInfo));
495 
496 		chan_freq = wlan_reg_legacy_chan_to_freq(
497 				p_hdd_ctx->pdev, chanList[i]);
498 		status = sme_get_reg_info(p_hdd_ctx->mac_handle, chan_freq,
499 					  &reg_info_1, &reg_info_2);
500 		if (QDF_STATUS_SUCCESS == status) {
501 			/* copy into hdd chan info struct */
502 			hddChanInfo.reserved0 = 0;
503 			hddChanInfo.mhz = chan_freq;
504 			hddChanInfo.band_center_freq1 = hddChanInfo.mhz;
505 			hddChanInfo.band_center_freq2 = 0;
506 
507 			hddChanInfo.info = 0;
508 			if (CHANNEL_STATE_DFS ==
509 			    wlan_reg_get_channel_state_for_pwrmode(
510 						p_hdd_ctx->pdev, chan_freq,
511 						REG_CURRENT_PWR_MODE))
512 				WMI_SET_CHANNEL_FLAG(&hddChanInfo,
513 						     WMI_CHAN_FLAG_DFS);
514 
515 			hdd_update_channel_bw_info(p_hdd_ctx,
516 						chan_freq, &hddChanInfo);
517 			hddChanInfo.reg_info_1 = reg_info_1;
518 			hddChanInfo.reg_info_2 = reg_info_2;
519 		} else {
520 			/* channel info is not returned, fill in zeros in
521 			 * channel info struct
522 			 */
523 			hdd_debug("sme_get_reg_info failed for chan: %d, fill 0s",
524 				   chan_freq);
525 			hddChanInfo.reserved0 = 0;
526 			hddChanInfo.mhz = chan_freq;
527 			hddChanInfo.band_center_freq1 = 0;
528 			hddChanInfo.band_center_freq2 = 0;
529 			hddChanInfo.info = 0;
530 			hddChanInfo.reg_info_1 = 0;
531 			hddChanInfo.reg_info_2 = 0;
532 		}
533 		qdf_mem_copy(pHddChanInfo, &hddChanInfo,
534 			     sizeof(*pHddChanInfo));
535 	}
536 
537 	skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + ani_hdr->length)));
538 
539 	hdd_debug("sending channel info resp for num channels (%d) to pid (%d)",
540 		   numOfChannels, p_hdd_ctx->oem_pid);
541 
542 	(void)nl_srv_ucast_oem(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
543 
544 	return 0;
545 }
546 
547 /**
548  * oem_process_set_cap_req_msg() - process oem set capability request
549  * @oem_cap_len: Length of OEM capability
550  * @oem_cap: Pointer to OEM capability buffer
551  * @app_pid: process ID, to which rsp message is to be sent
552  *
553  * This function sends oem message to SME
554  *
555  * Return: error code
556  */
oem_process_set_cap_req_msg(int oem_cap_len,char * oem_cap,int32_t app_pid)557 static int oem_process_set_cap_req_msg(int oem_cap_len,
558 				       char *oem_cap, int32_t app_pid)
559 {
560 	QDF_STATUS status;
561 	int error_code;
562 	struct sk_buff *skb;
563 	struct nlmsghdr *nlh;
564 	tAniMsgHdr *ani_hdr;
565 	uint8_t *buf;
566 
567 	if (!oem_cap) {
568 		hdd_err("oem_cap is null");
569 		return -EINVAL;
570 	}
571 
572 	status = sme_oem_update_capability(p_hdd_ctx->mac_handle,
573 					(struct sme_oem_capability *)oem_cap);
574 	if (!QDF_IS_STATUS_SUCCESS(status))
575 		hdd_err("error updating rm capability, status: %d", status);
576 	error_code = qdf_status_to_os_return(status);
577 
578 	skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
579 	if (!skb)
580 		return -ENOMEM;
581 
582 	nlh = (struct nlmsghdr *)skb->data;
583 	nlh->nlmsg_pid = 0;     /* from kernel */
584 	nlh->nlmsg_flags = 0;
585 	nlh->nlmsg_seq = 0;
586 	nlh->nlmsg_type = WLAN_NL_MSG_OEM;
587 	ani_hdr = NLMSG_DATA(nlh);
588 	ani_hdr->type = ANI_MSG_SET_OEM_CAP_RSP;
589 	/* 64 bit alignment */
590 	ani_hdr->length = sizeof(error_code);
591 	nlh->nlmsg_len = NLMSG_LENGTH(sizeof(tAniMsgHdr) + ani_hdr->length);
592 
593 	/* message body will contain only status code */
594 	buf = (char *)((char *)ani_hdr + sizeof(tAniMsgHdr));
595 	qdf_mem_copy(buf, &error_code, ani_hdr->length);
596 
597 	skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + ani_hdr->length));
598 
599 	hdd_debug("sending oem response to pid %d", app_pid);
600 
601 	(void)nl_srv_ucast_oem(skb, app_pid, MSG_DONTWAIT);
602 
603 	return error_code;
604 }
605 
606 /**
607  * oem_process_get_cap_req_msg() - process oem get capability request
608  *
609  * This function process the get capability request from OEM and responds
610  * with the capability.
611  *
612  * Return: error code
613  */
oem_process_get_cap_req_msg(void)614 static int oem_process_get_cap_req_msg(void)
615 {
616 	int error_code;
617 	struct oem_get_capability_rsp *cap_rsp;
618 	struct oem_data_cap data_cap = { {0} };
619 	struct sme_oem_capability oem_cap;
620 	struct hdd_adapter *adapter;
621 	struct sk_buff *skb;
622 	struct nlmsghdr *nlh;
623 	tAniMsgHdr *ani_hdr;
624 	uint8_t *buf;
625 
626 	/* for now, STA interface only */
627 	adapter = hdd_get_adapter(p_hdd_ctx, QDF_STA_MODE);
628 	if (!adapter) {
629 		hdd_err("No adapter for STA mode");
630 		return -EINVAL;
631 	}
632 
633 	error_code = populate_oem_data_cap(adapter, &data_cap);
634 	if (0 != error_code)
635 		return error_code;
636 
637 	skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + sizeof(*cap_rsp)),
638 			GFP_KERNEL);
639 	if (!skb)
640 		return -ENOMEM;
641 
642 	nlh = (struct nlmsghdr *)skb->data;
643 	nlh->nlmsg_pid = 0;     /* from kernel */
644 	nlh->nlmsg_flags = 0;
645 	nlh->nlmsg_seq = 0;
646 	nlh->nlmsg_type = WLAN_NL_MSG_OEM;
647 	ani_hdr = NLMSG_DATA(nlh);
648 	ani_hdr->type = ANI_MSG_GET_OEM_CAP_RSP;
649 
650 	ani_hdr->length = sizeof(*cap_rsp);
651 	nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + ani_hdr->length));
652 
653 	buf = (char *)((char *)ani_hdr + sizeof(tAniMsgHdr));
654 	qdf_mem_copy(buf, &data_cap, sizeof(data_cap));
655 
656 	buf = (char *) buf +  sizeof(data_cap);
657 	qdf_mem_zero(&oem_cap, sizeof(oem_cap));
658 	sme_oem_get_capability(p_hdd_ctx->mac_handle, &oem_cap);
659 	qdf_mem_copy(buf, &oem_cap, sizeof(oem_cap));
660 
661 	skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + ani_hdr->length)));
662 	hdd_info("send rsp to oem-pid:%d for get_capability",
663 		 p_hdd_ctx->oem_pid);
664 
665 	(void)nl_srv_ucast_oem(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
666 	return 0;
667 }
668 
hdd_send_peer_status_ind_to_oem_app(struct qdf_mac_addr * peer_mac,uint8_t peer_status,uint8_t peer_capability,uint8_t vdev_id,struct oem_channel_info * chan_info,enum QDF_OPMODE dev_mode)669 void hdd_send_peer_status_ind_to_oem_app(struct qdf_mac_addr *peer_mac,
670 					 uint8_t peer_status,
671 					 uint8_t peer_capability,
672 					 uint8_t vdev_id,
673 					 struct oem_channel_info *chan_info,
674 					 enum QDF_OPMODE dev_mode)
675 {
676 	struct sk_buff *skb;
677 	struct nlmsghdr *nlh;
678 	tAniMsgHdr *ani_hdr;
679 	struct peer_status_info *peer_info;
680 
681 	if (!p_hdd_ctx) {
682 		hdd_err("HDD Ctx is null");
683 		return;
684 	}
685 
686 	/* check if oem app has registered and pid is valid */
687 	if ((!p_hdd_ctx->oem_app_registered) || (p_hdd_ctx->oem_pid == 0)) {
688 		hdd_info("OEM app is not registered(%d) or pid is invalid(%d)",
689 			 p_hdd_ctx->oem_app_registered,
690 			 p_hdd_ctx->oem_pid);
691 		return;
692 	}
693 
694 	skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) +
695 				    sizeof(*peer_info)),
696 			GFP_KERNEL);
697 	if (!skb)
698 		return;
699 
700 	nlh = (struct nlmsghdr *)skb->data;
701 	nlh->nlmsg_pid = 0;     /* from kernel */
702 	nlh->nlmsg_flags = 0;
703 	nlh->nlmsg_seq = 0;
704 	nlh->nlmsg_type = WLAN_NL_MSG_OEM;
705 	ani_hdr = NLMSG_DATA(nlh);
706 	ani_hdr->type = ANI_MSG_PEER_STATUS_IND;
707 
708 	ani_hdr->length = sizeof(*peer_info);
709 	nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + ani_hdr->length));
710 
711 	peer_info = (struct peer_status_info *) ((char *)ani_hdr + sizeof(tAniMsgHdr));
712 	qdf_mem_zero(peer_info, sizeof(*peer_info));
713 	qdf_mem_copy(peer_info->peer_mac_addr, peer_mac->bytes,
714 		     sizeof(peer_mac->bytes));
715 	peer_info->peer_status = peer_status;
716 	peer_info->vdev_id = vdev_id;
717 	peer_info->peer_capability = peer_capability;
718 	/* Set 0th bit of reserved0 for STA mode */
719 	if (QDF_STA_MODE == dev_mode)
720 		peer_info->reserved0 |= 0x01;
721 
722 	if (chan_info) {
723 		peer_info->peer_chan_info.reserved0 = 0;
724 		peer_info->peer_chan_info.mhz = chan_info->mhz;
725 		peer_info->peer_chan_info.band_center_freq1 =
726 			chan_info->band_center_freq1;
727 		peer_info->peer_chan_info.band_center_freq2 =
728 			chan_info->band_center_freq2;
729 		peer_info->peer_chan_info.info = chan_info->info;
730 		peer_info->peer_chan_info.reg_info_1 = chan_info->reg_info_1;
731 		peer_info->peer_chan_info.reg_info_2 = chan_info->reg_info_2;
732 	}
733 	skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + ani_hdr->length)));
734 
735 	hdd_info("sending peer " QDF_MAC_ADDR_FMT
736 		  " status(%d), peer_capability(%d), vdev_id(%d),"
737 		  " to oem app pid(%d), center freq 1 (%d), center freq 2 (%d),"
738 		  " info (0x%x), frequency (%d),reg info 1 (0x%x),"
739 		  " reg info 2 (0x%x)",
740 		  QDF_MAC_ADDR_REF(peer_mac->bytes),
741 		  peer_status, peer_capability,
742 		  vdev_id, p_hdd_ctx->oem_pid,
743 		  peer_info->peer_chan_info.band_center_freq1,
744 		  peer_info->peer_chan_info.band_center_freq2,
745 		  peer_info->peer_chan_info.info,
746 		  peer_info->peer_chan_info.mhz,
747 		  peer_info->peer_chan_info.reg_info_1,
748 		  peer_info->peer_chan_info.reg_info_2);
749 
750 	(void)nl_srv_ucast_oem(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
751 }
752 
753 /**
754  * oem_app_reg_req_handler() - function to handle APP registration request
755  *                             from userspace
756  * @hdd_ctx: handle to HDD context
757  * @msg_hdr: pointer to ANI message header
758  * @pid: Process ID
759  *
760  * Return: 0 if success, error code otherwise
761  */
oem_app_reg_req_handler(struct hdd_context * hdd_ctx,tAniMsgHdr * msg_hdr,int pid)762 static int oem_app_reg_req_handler(struct hdd_context *hdd_ctx,
763 				   tAniMsgHdr *msg_hdr, int pid)
764 {
765 	char *sign_str = NULL;
766 
767 	/* Registration request is only allowed for Qualcomm Application */
768 	hdd_debug("Received App Req Req from App pid: %d len: %d",
769 			   pid, msg_hdr->length);
770 
771 	sign_str = (char *)((char *)msg_hdr + sizeof(tAniMsgHdr));
772 	if ((OEM_APP_SIGNATURE_LEN == msg_hdr->length) &&
773 			(0 == strncmp(sign_str, OEM_APP_SIGNATURE_STR,
774 				      OEM_APP_SIGNATURE_LEN))) {
775 		hdd_debug("Valid App Req Req from oem app pid: %d", pid);
776 
777 		hdd_ctx->oem_app_registered = true;
778 		hdd_ctx->oem_pid = pid;
779 		send_oem_reg_rsp_nlink_msg();
780 	} else {
781 		hdd_err("Invalid signature in App Reg Req from pid: %d", pid);
782 		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_SIGNATURE);
783 		return -EPERM;
784 	}
785 
786 	return 0;
787 }
788 
789 /**
790  * oem_data_req_handler() - function to handle data_req from userspace
791  * @hdd_ctx: handle to HDD context
792  * @msg_hdr: pointer to ANI message header
793  * @pid: Process ID
794  *
795  * Return: 0 if success, error code otherwise
796  */
oem_data_req_handler(struct hdd_context * hdd_ctx,tAniMsgHdr * msg_hdr,int pid)797 static int oem_data_req_handler(struct hdd_context *hdd_ctx,
798 				tAniMsgHdr *msg_hdr, int pid)
799 {
800 	hdd_debug("Received Oem Data Request length: %d from pid: %d",
801 			msg_hdr->length, pid);
802 
803 	if ((!hdd_ctx->oem_app_registered) ||
804 			(pid != hdd_ctx->oem_pid)) {
805 		/* either oem app is not registered yet or pid is different */
806 		hdd_err("OEM DataReq: app not registered(%d) or incorrect pid(%d)",
807 				hdd_ctx->oem_app_registered, pid);
808 		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_APP_NOT_REGISTERED);
809 		return -EPERM;
810 	}
811 
812 	if ((!msg_hdr->length) || (OEM_DATA_REQ_SIZE < msg_hdr->length)) {
813 		hdd_err("Invalid length (%d) in Oem Data Request",
814 				msg_hdr->length);
815 		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_MESSAGE_LENGTH);
816 		return -EPERM;
817 	}
818 
819 	oem_process_data_req_msg(msg_hdr->length,
820 			(char *) ((char *)msg_hdr +
821 				sizeof(tAniMsgHdr)));
822 
823 	return 0;
824 }
825 
826 /**
827  * oem_chan_info_req_handler() - function to handle chan_info_req from userspace
828  * @hdd_ctx: handle to HDD context
829  * @msg_hdr: pointer to ANI message header
830  * @pid: Process ID
831  *
832  * Return: 0 if success, error code otherwise
833  */
oem_chan_info_req_handler(struct hdd_context * hdd_ctx,tAniMsgHdr * msg_hdr,int pid)834 static int oem_chan_info_req_handler(struct hdd_context *hdd_ctx,
835 					tAniMsgHdr *msg_hdr, int pid)
836 {
837 	hdd_debug("Received channel info request, num channel(%d) from pid: %d",
838 			msg_hdr->length, pid);
839 
840 	if ((!hdd_ctx->oem_app_registered) ||
841 			(pid != hdd_ctx->oem_pid)) {
842 		/* either oem app is not registered yet or pid is different */
843 		hdd_err("Chan InfoReq: app not registered(%d) or incorrect pid(%d)",
844 				hdd_ctx->oem_app_registered, pid);
845 		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_APP_NOT_REGISTERED);
846 		return -EPERM;
847 	}
848 
849 	/* message length contains list of channel ids */
850 	if ((!msg_hdr->length) ||
851 			(CFG_VALID_CHANNEL_LIST_LEN < msg_hdr->length)) {
852 		hdd_err("Invalid length (%d) in channel info request",
853 				msg_hdr->length);
854 		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_MESSAGE_LENGTH);
855 		return -EPERM;
856 	}
857 	oem_process_channel_info_req_msg(msg_hdr->length,
858 			(char *)((char *)msg_hdr + sizeof(tAniMsgHdr)));
859 
860 	return 0;
861 }
862 
863 /**
864  * oem_set_cap_req_handler() - function to handle set_cap_req from userspace
865  * @hdd_ctx: handle to HDD context
866  * @msg_hdr: pointer to ANI message header
867  * @pid: Process ID
868  *
869  * Return: 0 if success, error code otherwise
870  */
oem_set_cap_req_handler(struct hdd_context * hdd_ctx,tAniMsgHdr * msg_hdr,int pid)871 static int oem_set_cap_req_handler(struct hdd_context *hdd_ctx,
872 					tAniMsgHdr *msg_hdr, int pid)
873 {
874 	hdd_info("Received set oem cap req of length:%d from pid: %d",
875 			msg_hdr->length, pid);
876 
877 	if ((!hdd_ctx->oem_app_registered) ||
878 			(pid != hdd_ctx->oem_pid)) {
879 		/* oem app is not registered yet or pid is different */
880 		hdd_err("set_oem_capability : app not registered(%d) or incorrect pid(%d)",
881 				hdd_ctx->oem_app_registered, pid);
882 		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_APP_NOT_REGISTERED);
883 		return -EPERM;
884 	}
885 
886 	if ((!msg_hdr->length) ||
887 			(sizeof(struct sme_oem_capability) < msg_hdr->length)) {
888 		hdd_err("Invalid length (%d) in set_oem_capability",
889 				msg_hdr->length);
890 		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_MESSAGE_LENGTH);
891 		return -EPERM;
892 	}
893 
894 	oem_process_set_cap_req_msg(msg_hdr->length, (char *)
895 			((char *)msg_hdr + sizeof(tAniMsgHdr)),
896 			pid);
897 	return 0;
898 }
899 
900 /**
901  * oem_get_cap_req_handler() - function to handle get_cap_req from userspace
902  * @hdd_ctx: handle to HDD context
903  * @msg_hdr: pointer to ANI message header
904  * @pid: Process ID
905  *
906  * Return: 0 if success, error code otherwise
907  */
oem_get_cap_req_handler(struct hdd_context * hdd_ctx,tAniMsgHdr * msg_hdr,int pid)908 static int oem_get_cap_req_handler(struct hdd_context *hdd_ctx,
909 					tAniMsgHdr *msg_hdr, int pid)
910 {
911 	hdd_info("Rcvd get oem capability req - length:%d from pid: %d",
912 			msg_hdr->length, pid);
913 
914 	if ((!hdd_ctx->oem_app_registered) ||
915 			(pid != hdd_ctx->oem_pid)) {
916 		/* oem app is not registered yet or pid is different */
917 		hdd_err("get_oem_capability : app not registered(%d) or incorrect pid(%d)",
918 				hdd_ctx->oem_app_registered, pid);
919 		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_APP_NOT_REGISTERED);
920 		return -EPERM;
921 	}
922 
923 	oem_process_get_cap_req_msg();
924 	return 0;
925 }
926 
927 /**
928  * oem_request_dispatcher() - OEM command dispatcher API
929  * @msg_hdr: ANI Message Header
930  * @pid: process id
931  *
932  * This API is used to dispatch the command from OEM depending
933  * on the type of the message received.
934  *
935  * Return: None
936  */
oem_request_dispatcher(tAniMsgHdr * msg_hdr,int pid)937 static void oem_request_dispatcher(tAniMsgHdr *msg_hdr, int pid)
938 {
939 	switch (msg_hdr->type) {
940 	case ANI_MSG_APP_REG_REQ:
941 		oem_app_reg_req_handler(p_hdd_ctx, msg_hdr, pid);
942 		break;
943 
944 	case ANI_MSG_OEM_DATA_REQ:
945 		oem_data_req_handler(p_hdd_ctx, msg_hdr, pid);
946 		break;
947 
948 	case ANI_MSG_CHANNEL_INFO_REQ:
949 		oem_chan_info_req_handler(p_hdd_ctx, msg_hdr, pid);
950 		break;
951 
952 	case ANI_MSG_SET_OEM_CAP_REQ:
953 		oem_set_cap_req_handler(p_hdd_ctx, msg_hdr, pid);
954 		break;
955 
956 	case ANI_MSG_GET_OEM_CAP_REQ:
957 		oem_get_cap_req_handler(p_hdd_ctx, msg_hdr, pid);
958 		break;
959 
960 	default:
961 		hdd_err("Received Invalid message type (%d), length (%d)",
962 				msg_hdr->type, msg_hdr->length);
963 		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_MESSAGE_TYPE);
964 	}
965 }
966 
967 #ifdef CNSS_GENL
968 /**
969  * oem_cmd_handler() - API to handle OEM commands
970  * @data: Pointer to data
971  * @data_len: length of the received data
972  * @ctx: Pointer to the context
973  * @pid: Process id
974  *
975  * This API handles the command from OEM application from user space and
976  * send back event to user space if necessary.
977  *
978  * Return: None
979  */
oem_cmd_handler(const void * data,int data_len,void * ctx,int pid)980 static void oem_cmd_handler(const void *data, int data_len, void *ctx, int pid)
981 {
982 	tAniMsgHdr *msg_hdr;
983 	int msg_len;
984 	int ret;
985 	struct nlattr *tb[CLD80211_ATTR_MAX + 1];
986 
987 	ret = wlan_hdd_validate_context(p_hdd_ctx);
988 	if (ret)
989 		return;
990 
991 	/*
992 	 * audit note: it is ok to pass a NULL policy here since only
993 	 * one attribute is parsed and it is explicitly validated
994 	 */
995 	if (wlan_cfg80211_nla_parse(tb, CLD80211_ATTR_MAX,
996 				    data, data_len, NULL)) {
997 		hdd_err("Invalid ATTR");
998 		return;
999 	}
1000 
1001 	if (!tb[CLD80211_ATTR_DATA]) {
1002 		hdd_err("attr ATTR_DATA failed");
1003 		return;
1004 	}
1005 
1006 	msg_len = nla_len(tb[CLD80211_ATTR_DATA]);
1007 	if (msg_len < sizeof(*msg_hdr)) {
1008 		hdd_err("runt ATTR_DATA size %d", msg_len);
1009 		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_NULL_MESSAGE_HEADER);
1010 		return;
1011 	}
1012 
1013 	msg_hdr = nla_data(tb[CLD80211_ATTR_DATA]);
1014 	if (msg_len < (sizeof(*msg_hdr) + msg_hdr->length)) {
1015 		hdd_err("Invalid nl msg len %d, msg hdr len %d",
1016 			msg_len, msg_hdr->length);
1017 		send_oem_err_rsp_nlink_msg(pid, OEM_ERR_INVALID_MESSAGE_LENGTH);
1018 		return;
1019 	}
1020 
1021 	oem_request_dispatcher(msg_hdr, pid);
1022 }
1023 
oem_activate_service(struct hdd_context * hdd_ctx)1024 int oem_activate_service(struct hdd_context *hdd_ctx)
1025 {
1026 	p_hdd_ctx = hdd_ctx;
1027 	register_cld_cmd_cb(WLAN_NL_MSG_OEM, oem_cmd_handler, NULL);
1028 	return 0;
1029 }
1030 
oem_deactivate_service(void)1031 int oem_deactivate_service(void)
1032 {
1033 	deregister_cld_cmd_cb(WLAN_NL_MSG_OEM);
1034 	return 0;
1035 }
1036 #else
1037 
1038 /*
1039  * Callback function invoked by Netlink service for all netlink
1040  * messages (from user space) addressed to WLAN_NL_MSG_OEM
1041  */
1042 
1043 /**
1044  * oem_msg_callback() - callback invoked by netlink service
1045  * @skb:    skb with netlink message
1046  *
1047  * This function gets invoked by netlink service when a message
1048  * is received from user space addressed to WLAN_NL_MSG_OEM
1049  *
1050  * Return: zero on success
1051  *         On error, error number will be returned.
1052  */
oem_msg_callback(struct sk_buff * skb)1053 static int oem_msg_callback(struct sk_buff *skb)
1054 {
1055 	struct nlmsghdr *nlh;
1056 	tAniMsgHdr *msg_hdr;
1057 	int ret;
1058 
1059 	nlh = (struct nlmsghdr *)skb->data;
1060 	if (!nlh) {
1061 		hdd_err("Netlink header null");
1062 		return -EPERM;
1063 	}
1064 
1065 	ret = wlan_hdd_validate_context(p_hdd_ctx);
1066 	if (ret)
1067 		return ret;
1068 
1069 	msg_hdr = NLMSG_DATA(nlh);
1070 
1071 	if (!msg_hdr) {
1072 		hdd_err("Message header null");
1073 		send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
1074 					   OEM_ERR_NULL_MESSAGE_HEADER);
1075 		return -EPERM;
1076 	}
1077 
1078 	if (nlh->nlmsg_len <
1079 	    NLMSG_LENGTH(sizeof(tAniMsgHdr) + msg_hdr->length)) {
1080 		hdd_err("Invalid nl msg len, nlh->nlmsg_len (%d), msg_hdr->len (%d)",
1081 			nlh->nlmsg_len, msg_hdr->length);
1082 		send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
1083 					   OEM_ERR_INVALID_MESSAGE_LENGTH);
1084 		return -EPERM;
1085 	}
1086 
1087 	oem_request_dispatcher(msg_hdr, nlh->nlmsg_pid);
1088 	return 0;
1089 }
1090 
__oem_msg_callback(struct sk_buff * skb)1091 static int __oem_msg_callback(struct sk_buff *skb)
1092 {
1093 	struct hdd_context *hdd_ctx = p_hdd_ctx;
1094 	struct osif_psoc_sync *psoc_sync;
1095 	int errno;
1096 
1097 	errno = wlan_hdd_validate_context(hdd_ctx);
1098 	if (errno)
1099 		return errno;
1100 
1101 	errno = osif_psoc_sync_op_start(hdd_ctx->parent_dev, &psoc_sync);
1102 	if (errno)
1103 		return errno;
1104 
1105 	errno = oem_msg_callback(skb);
1106 
1107 	osif_psoc_sync_op_stop(psoc_sync);
1108 
1109 	return errno;
1110 }
1111 
oem_activate_service(struct hdd_context * hdd_ctx)1112 int oem_activate_service(struct hdd_context *hdd_ctx)
1113 {
1114 	p_hdd_ctx = hdd_ctx;
1115 
1116 	/* Register the msg handler for msgs addressed to WLAN_NL_MSG_OEM */
1117 	return nl_srv_register(WLAN_NL_MSG_OEM, __oem_msg_callback);
1118 }
1119 
oem_deactivate_service(void)1120 int oem_deactivate_service(void)
1121 {
1122 	/* Deregister the msg handler for msgs addressed to WLAN_NL_MSG_OEM */
1123 	return nl_srv_unregister(WLAN_NL_MSG_OEM, __oem_msg_callback);
1124 }
1125 
1126 #endif
1127 #endif
1128 
1129 #ifdef FEATURE_OEM_DATA
1130 const struct nla_policy
1131 oem_data_attr_policy[QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_MAX + 1] = {
1132 	[QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA] = {
1133 						    .type = NLA_BINARY,
1134 						    .len = OEM_DATA_MAX_SIZE
1135 	},
1136 
1137 	[QCA_WLAN_VENDOR_ATTR_OEM_DEVICE_INFO] = {.type = NLA_U8},
1138 	[QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED] = {.type = NLA_FLAG},
1139 };
1140 
1141 /**
1142  * hdd_copy_file_name_and_oem_data() - Copy file name and oem data
1143  * @hdd_ctx: pointer to hdd context
1144  * @oem_event_data: oem event data param buffe
1145  *
1146  * Return: none
1147  */
hdd_copy_file_name_and_oem_data(struct hdd_context * hdd_ctx,const struct oem_data * oem_event_data)1148 static void hdd_copy_file_name_and_oem_data(
1149 				struct hdd_context *hdd_ctx,
1150 				const struct oem_data *oem_event_data)
1151 {
1152 	if (!oem_event_data->data_len || !oem_event_data->file_name_len) {
1153 		hdd_err("Invalid file name or data length");
1154 		return;
1155 	}
1156 
1157 	if (oem_event_data->data_len > HDD_MAX_OEM_DATA_LEN ||
1158 	    oem_event_data->file_name_len > HDD_MAX_FILE_NAME_LEN) {
1159 		hdd_err("Invalid oem data len %zu or file name len %d",
1160 			oem_event_data->data_len,
1161 			oem_event_data->file_name_len);
1162 		return;
1163 	}
1164 	qdf_mem_zero(hdd_ctx->oem_data, HDD_MAX_OEM_DATA_LEN);
1165 	qdf_mem_zero(hdd_ctx->file_name, HDD_MAX_FILE_NAME_LEN);
1166 
1167 	qdf_mem_copy(hdd_ctx->oem_data, oem_event_data->data,
1168 		     oem_event_data->data_len);
1169 	hdd_ctx->oem_data_len = oem_event_data->data_len;
1170 
1171 	qdf_mem_copy(hdd_ctx->file_name, oem_event_data->file_name,
1172 		     oem_event_data->file_name_len);
1173 }
1174 
hdd_oem_event_async_cb(const struct oem_data * oem_event_data)1175 void hdd_oem_event_async_cb(const struct oem_data *oem_event_data)
1176 {
1177 	struct sk_buff *vendor_event;
1178 	uint32_t len;
1179 	int ret;
1180 	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1181 	struct wlan_hdd_link_info *link_info;
1182 	struct wireless_dev *wdev = NULL;
1183 
1184 	hdd_enter();
1185 
1186 	if (!hdd_ctx)
1187 		return;
1188 
1189 	if (oem_event_data->file_name) {
1190 		hdd_copy_file_name_and_oem_data(hdd_ctx, oem_event_data);
1191 		return;
1192 	}
1193 
1194 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, oem_event_data->vdev_id);
1195 	if (link_info)
1196 		wdev = &link_info->adapter->wdev;
1197 
1198 	len = nla_total_size(oem_event_data->data_len) + NLMSG_HDRLEN;
1199 	vendor_event = wlan_cfg80211_vendor_event_alloc(
1200 				hdd_ctx->wiphy, wdev, len,
1201 				QCA_NL80211_VENDOR_SUBCMD_OEM_DATA_INDEX,
1202 				GFP_KERNEL);
1203 
1204 	if (!vendor_event) {
1205 		hdd_err("wlan_cfg80211_vendor_event_alloc failed");
1206 		return;
1207 	}
1208 
1209 	ret = nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA,
1210 		      oem_event_data->data_len, oem_event_data->data);
1211 	if (ret) {
1212 		hdd_err("OEM event put fails status %d", ret);
1213 		wlan_cfg80211_vendor_free_skb(vendor_event);
1214 		return;
1215 	}
1216 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1217 	hdd_exit();
1218 }
1219 
hdd_oem_event_handler_cb(const struct oem_data * oem_event_data,uint8_t vdev_id)1220 void hdd_oem_event_handler_cb(const struct oem_data *oem_event_data,
1221 			      uint8_t vdev_id)
1222 {
1223 	struct sk_buff *vendor_event;
1224 	struct osif_request *request;
1225 	uint32_t len;
1226 	int ret;
1227 	struct oem_data *oem_data;
1228 	struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
1229 	struct wlan_hdd_link_info *link_info;
1230 	struct hdd_adapter *hdd_adapter;
1231 	struct wireless_dev *wdev = NULL;
1232 
1233 	hdd_enter();
1234 
1235 	ret = wlan_hdd_validate_context(hdd_ctx);
1236 	if (ret)
1237 		return;
1238 
1239 	if (!oem_event_data || !(oem_event_data->data)) {
1240 		hdd_err("Invalid oem event data");
1241 		return;
1242 	}
1243 
1244 	link_info = hdd_get_link_info_by_vdev(hdd_ctx, vdev_id);
1245 	if (!link_info || hdd_validate_adapter(link_info->adapter))
1246 		return;
1247 
1248 	hdd_adapter = link_info->adapter;
1249 	if (hdd_adapter->response_expected) {
1250 		request = osif_request_get(hdd_adapter->cookie);
1251 		if (!request) {
1252 			hdd_err("Invalid request");
1253 			return;
1254 		}
1255 
1256 		oem_data = osif_request_priv(request);
1257 		oem_data->data_len = oem_event_data->data_len;
1258 		oem_data->data = qdf_mem_malloc(oem_data->data_len);
1259 		if (!oem_data->data) {
1260 			osif_request_put(request);
1261 			return;
1262 		}
1263 
1264 		qdf_mem_copy(oem_data->data, oem_event_data->data,
1265 			     oem_data->data_len);
1266 		oem_data->vdev_id = link_info->vdev_id;
1267 		osif_request_complete(request);
1268 		osif_request_put(request);
1269 	} else {
1270 		wdev = &(hdd_adapter->wdev);
1271 
1272 		len = nla_total_size(oem_event_data->data_len) + NLMSG_HDRLEN;
1273 		vendor_event =
1274 			wlan_cfg80211_vendor_event_alloc(
1275 				hdd_ctx->wiphy, wdev, len,
1276 				QCA_NL80211_VENDOR_SUBCMD_OEM_DATA_INDEX,
1277 				GFP_KERNEL);
1278 
1279 		if (!vendor_event) {
1280 			hdd_err("wlan_cfg80211_vendor_event_alloc failed");
1281 			return;
1282 		}
1283 
1284 		ret = nla_put(vendor_event,
1285 			      QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA,
1286 			      oem_event_data->data_len, oem_event_data->data);
1287 		if (ret) {
1288 			hdd_err("OEM event put fails status %d", ret);
1289 			wlan_cfg80211_vendor_free_skb(vendor_event);
1290 			return;
1291 		}
1292 		wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
1293 	}
1294 	sme_oem_event_deinit(hdd_ctx->mac_handle);
1295 
1296 	hdd_exit();
1297 }
1298 
1299 /**
1300  *wlan_hdd_free_oem_data: delete data of priv data
1301  *@priv: osif request private data
1302  *
1303  *Return: void
1304  */
wlan_hdd_free_oem_data(void * priv)1305 static void wlan_hdd_free_oem_data(void *priv)
1306 {
1307 	struct oem_data *local_priv = priv;
1308 
1309 	if (!local_priv)
1310 		return;
1311 
1312 	if (local_priv->data) {
1313 		qdf_mem_free(local_priv->data);
1314 		local_priv->data = NULL;
1315 	}
1316 }
1317 
1318 /**
1319  * __wlan_hdd_cfg80211_oem_data_handler() - the handler for oem data
1320  * @wiphy: wiphy structure pointer
1321  * @wdev: Wireless device structure pointer
1322  * @data: Pointer to the data received
1323  * @data_len: Length of @data
1324  *
1325  * Return: 0 on success; errno on failure
1326  */
1327 static int
__wlan_hdd_cfg80211_oem_data_handler(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1328 __wlan_hdd_cfg80211_oem_data_handler(struct wiphy *wiphy,
1329 				     struct wireless_dev *wdev,
1330 				     const void *data, int data_len)
1331 {
1332 	struct net_device *dev = wdev->netdev;
1333 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1334 	uint8_t mac_id;
1335 	int ret;
1336 	struct sk_buff *skb = NULL;
1337 	struct oem_data oem_data = {0};
1338 	struct oem_data *get_oem_data = NULL;
1339 	struct hdd_adapter *adapter = WLAN_HDD_GET_PRIV_PTR(dev);
1340 	struct hdd_context *hdd_ctx = WLAN_HDD_GET_CTX(adapter);
1341 	struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_MAX + 1];
1342 	struct osif_request *request = NULL;
1343 	struct oem_data *priv;
1344 	static const struct osif_request_params params = {
1345 		.priv_size = sizeof(*priv),
1346 		.timeout_ms = WLAN_WAIT_TIME_GET_OEM_DATA,
1347 		.dealloc = wlan_hdd_free_oem_data,
1348 	};
1349 
1350 	if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
1351 		hdd_err("Command not allowed in FTM mode");
1352 		return -EPERM;
1353 	}
1354 
1355 	ret = wlan_hdd_validate_context(hdd_ctx);
1356 	if (ret)
1357 		return ret;
1358 
1359 	if (hdd_validate_adapter(adapter))
1360 		return -EINVAL;
1361 
1362 	if (adapter->oem_data_in_progress) {
1363 		hdd_err("oem request already in progress");
1364 		return -EBUSY;
1365 	}
1366 
1367 	if (wlan_cfg80211_nla_parse(tb,
1368 				    QCA_WLAN_VENDOR_ATTR_OEM_DATA_PARAMS_MAX,
1369 				    data, data_len, oem_data_attr_policy)) {
1370 		hdd_err("Invalid attributes");
1371 		return -EINVAL;
1372 	}
1373 
1374 	if (!tb[QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA]) {
1375 		hdd_err("oem data is missing!");
1376 		return -EINVAL;
1377 	}
1378 
1379 	if (tb[QCA_WLAN_VENDOR_ATTR_OEM_DEVICE_INFO])
1380 		oem_data.pdev_vdev_flag =
1381 			nla_get_u8(tb[QCA_WLAN_VENDOR_ATTR_OEM_DEVICE_INFO]);
1382 
1383 	if (oem_data.pdev_vdev_flag) {
1384 		status = policy_mgr_get_mac_id_by_session_id(
1385 						    hdd_ctx->psoc,
1386 						    adapter->deflink->vdev_id,
1387 						    &mac_id);
1388 		if (QDF_IS_STATUS_ERROR(status)) {
1389 			hdd_err("get mac id failed");
1390 			return -EINVAL;
1391 		}
1392 		oem_data.pdev_id = mac_id;
1393 		oem_data.is_host_pdev_id = true;
1394 	}
1395 	oem_data.data_len =
1396 		nla_len(tb[QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA]);
1397 	if (!oem_data.data_len) {
1398 		hdd_err("oem data len is 0!");
1399 		return -EINVAL;
1400 	}
1401 	oem_data.vdev_id = adapter->deflink->vdev_id;
1402 	oem_data.data = nla_data(tb[QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA]);
1403 
1404 	if (tb[QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED])
1405 		adapter->response_expected = nla_get_flag(
1406 			   tb[QCA_WLAN_VENDOR_ATTR_OEM_DATA_RESPONSE_EXPECTED]);
1407 
1408 	if (adapter->response_expected) {
1409 		int skb_len = 0;
1410 
1411 		adapter->oem_data_in_progress = true;
1412 		qdf_runtime_pm_prevent_suspend(
1413 					&hdd_ctx->runtime_context.oem_data_cmd);
1414 		request = osif_request_alloc(&params);
1415 		if (!request) {
1416 			hdd_err("request allocation failure");
1417 			ret = -ENOMEM;
1418 			goto err;
1419 		}
1420 
1421 		adapter->cookie = osif_request_cookie(request);
1422 
1423 		status = sme_oem_data_cmd(hdd_ctx->mac_handle,
1424 					  hdd_oem_event_handler_cb,
1425 					  &oem_data, adapter->deflink->vdev_id);
1426 		if (QDF_IS_STATUS_ERROR(status)) {
1427 			hdd_err("Failure while sending command to fw");
1428 			ret = -EAGAIN;
1429 			goto err;
1430 		}
1431 		ret = osif_request_wait_for_response(request);
1432 		if (ret) {
1433 			hdd_err("Timedout while retrieving oem get data");
1434 			goto err;
1435 		}
1436 
1437 		get_oem_data = osif_request_priv(request);
1438 		if (!get_oem_data || !(get_oem_data->data)) {
1439 			hdd_err("invalid get_oem_data");
1440 			ret = -EINVAL;
1441 			goto err;
1442 		}
1443 
1444 		skb_len = NLMSG_HDRLEN + nla_total_size(get_oem_data->data_len);
1445 		skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1446 							       skb_len);
1447 		if (!skb) {
1448 			hdd_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
1449 			ret = -ENOMEM;
1450 			goto err;
1451 		}
1452 
1453 		if (nla_put(skb, QCA_WLAN_VENDOR_ATTR_OEM_DATA_CMD_DATA,
1454 			    get_oem_data->data_len, get_oem_data->data)) {
1455 			hdd_err("nla put failure");
1456 			wlan_cfg80211_vendor_free_skb(skb);
1457 			ret =  -EINVAL;
1458 			goto err;
1459 		}
1460 		wlan_cfg80211_vendor_cmd_reply(skb);
1461 
1462 	} else {
1463 		status = sme_oem_data_cmd(hdd_ctx->mac_handle,
1464 					  hdd_oem_event_handler_cb,
1465 					  &oem_data, adapter->deflink->vdev_id);
1466 		return qdf_status_to_os_return(status);
1467 	}
1468 
1469 err:
1470 	if (request)
1471 		osif_request_put(request);
1472 	adapter->oem_data_in_progress = false;
1473 	adapter->response_expected = false;
1474 	qdf_runtime_pm_allow_suspend(&hdd_ctx->runtime_context.oem_data_cmd);
1475 
1476 	return ret;
1477 
1478 }
1479 
wlan_hdd_cfg80211_oem_data_handler(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)1480 int wlan_hdd_cfg80211_oem_data_handler(struct wiphy *wiphy,
1481 				       struct wireless_dev *wdev,
1482 				       const void *data, int data_len)
1483 {
1484 	struct osif_vdev_sync *vdev_sync;
1485 	int ret;
1486 
1487 	ret = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
1488 	if (ret)
1489 		return ret;
1490 
1491 	ret = __wlan_hdd_cfg80211_oem_data_handler(wiphy, wdev,
1492 						   data, data_len);
1493 	osif_vdev_sync_op_stop(vdev_sync);
1494 
1495 	return ret;
1496 }
1497 #endif
1498 #endif
1499