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 ®_info_1, ®_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(¶ms);
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