blob: df015ac40a5fc84d473626af50fdc7c90d0b0bee [file] [log] [blame]
Jeff Johnsone7245742012-09-05 17:12:55 -07001/*
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +05302 * Copyright (c) 2015-2017 The Linux Foundation. All rights reserved.
Kiet Lam842dad02014-02-18 18:44:02 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
Gopichand Nakkala92f07d82013-01-08 21:16:34 -080020 */
Kiet Lam842dad02014-02-18 18:44:02 -080021
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
Jeff Johnsone7245742012-09-05 17:12:55 -070028#ifdef FEATURE_OEM_DATA_SUPPORT
29
30/*================================================================================
31 \file wlan_hdd_oemdata.c
32
33 \brief Linux Wireless Extensions for oem data req/rsp
34
35 $Id: wlan_hdd_oemdata.c,v 1.34 2010/04/15 01:49:23 -- VINAY
36
37 Copyright (C) Qualcomm Inc.
38
39================================================================================*/
40
41#include <linux/version.h>
42#include <linux/module.h>
43#include <linux/kernel.h>
44#include <linux/init.h>
45#include <linux/wireless.h>
46#include <wlan_hdd_includes.h>
47#include <net/arp.h>
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +053048#include <vos_sched.h>
Padma, Santhosh Kumar8dcdb702015-10-20 14:06:21 +053049#include "qwlan_version.h"
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +053050
51static struct hdd_context_s *pHddCtx;
52
Jeff Johnsone7245742012-09-05 17:12:55 -070053/*---------------------------------------------------------------------------------------------
54
55 \brief hdd_OemDataReqCallback() -
56
57 This function also reports the results to the user space
58
c_hpothuddce3aa2014-05-08 20:30:49 +053059 \return - eHalStatus enumeration
Jeff Johnsone7245742012-09-05 17:12:55 -070060
61-----------------------------------------------------------------------------------------------*/
62static eHalStatus hdd_OemDataReqCallback(tHalHandle hHal,
63 void *pContext,
64 tANI_U32 oemDataReqID,
65 eOemDataReqStatus oemDataReqStatus)
66{
67 eHalStatus status = eHAL_STATUS_SUCCESS;
68 struct net_device *dev = (struct net_device *) pContext;
69 union iwreq_data wrqu;
70 char buffer[IW_CUSTOM_MAX+1];
71
72 memset(&wrqu, '\0', sizeof(wrqu));
73 memset(buffer, '\0', sizeof(buffer));
74
75 //now if the status is success, then send an event up
76 //so that the application can request for the data
77 //else no need to send the event up
78 if(oemDataReqStatus == eOEM_DATA_REQ_FAILURE)
79 {
80 snprintf(buffer, IW_CUSTOM_MAX, "QCOM: OEM-DATA-REQ-FAILED");
Arif Hussain6d2a3322013-11-17 19:50:10 -080081 hddLog(LOGW, "%s: oem data req %d failed", __func__, oemDataReqID);
Jeff Johnsone7245742012-09-05 17:12:55 -070082 }
83 else if(oemDataReqStatus == eOEM_DATA_REQ_INVALID_MODE)
84 {
85 snprintf(buffer, IW_CUSTOM_MAX, "QCOM: OEM-DATA-REQ-INVALID-MODE");
Arif Hussain6d2a3322013-11-17 19:50:10 -080086 hddLog(LOGW, "%s: oem data req %d failed because the driver is in invalid mode (IBSS|BTAMP|AP)", __func__, oemDataReqID);
Jeff Johnsone7245742012-09-05 17:12:55 -070087 }
88 else
89 {
90 snprintf(buffer, IW_CUSTOM_MAX, "QCOM: OEM-DATA-REQ-SUCCESS");
91 //everything went alright
92 }
93
94 wrqu.data.pointer = buffer;
95 wrqu.data.length = strlen(buffer);
96
97 wireless_send_event(dev, IWEVCUSTOM, &wrqu, buffer);
98
99 return status;
100}
101
102/**--------------------------------------------------------------------------------------------
103
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530104 \brief __iw_get_oem_data_rsp() -
Jeff Johnsone7245742012-09-05 17:12:55 -0700105
106 This function gets the oem data response. This invokes
107 the respective sme functionality. Function for handling the oem data rsp
108 IOCTL
109
110 \param - dev - Pointer to the net device
111 - info - Pointer to the iw_oem_data_req
112 - wrqu - Pointer to the iwreq data
113 - extra - Pointer to the data
114
115 \return - 0 for success, non zero for failure
116
117-----------------------------------------------------------------------------------------------*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530118int __iw_get_oem_data_rsp(
119 struct net_device *dev,
Jeff Johnsone7245742012-09-05 17:12:55 -0700120 struct iw_request_info *info,
121 union iwreq_data *wrqu,
122 char *extra)
123{
c_hpothuddce3aa2014-05-08 20:30:49 +0530124 int rc = 0;
125 eHalStatus status;
Jeff Johnsone7245742012-09-05 17:12:55 -0700126 struct iw_oem_data_rsp* pHddOemDataRsp;
127 tOemDataRsp* pSmeOemDataRsp;
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530128 hdd_adapter_t *pAdapter;
129 hdd_context_t *pHddCtx;
Jeff Johnsone7245742012-09-05 17:12:55 -0700130
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530131 ENTER();
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530132 pAdapter = (netdev_priv(dev));
133 if (NULL == pAdapter)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800134 {
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530135 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
136 "%s: Adapter is NULL",__func__);
137 return -EINVAL;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800138 }
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530139 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
140 rc = wlan_hdd_validate_context(pHddCtx);
141 if (0 != rc)
142 {
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530143 return rc;
144 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700145 do
146 {
147 //get the oem data response from sme
148 status = sme_getOemDataRsp(WLAN_HDD_GET_HAL_CTX(pAdapter), &pSmeOemDataRsp);
c_hpothuddce3aa2014-05-08 20:30:49 +0530149 if (status != eHAL_STATUS_SUCCESS)
Jeff Johnsone7245742012-09-05 17:12:55 -0700150 {
Arif Hussain6d2a3322013-11-17 19:50:10 -0800151 hddLog(LOGE, "%s: failed in sme_getOemDataRsp", __func__);
c_hpothuddce3aa2014-05-08 20:30:49 +0530152 rc = -EIO;
Jeff Johnsone7245742012-09-05 17:12:55 -0700153 break;
154 }
155 else
156 {
c_hpothuddce3aa2014-05-08 20:30:49 +0530157 if (pSmeOemDataRsp != NULL)
Jeff Johnsone7245742012-09-05 17:12:55 -0700158 {
159 pHddOemDataRsp = (struct iw_oem_data_rsp*)(extra);
160 vos_mem_copy(pHddOemDataRsp->oemDataRsp, pSmeOemDataRsp->oemDataRsp, OEM_DATA_RSP_SIZE);
161 }
162 else
163 {
Arif Hussain6d2a3322013-11-17 19:50:10 -0800164 hddLog(LOGE, "%s: pSmeOemDataRsp = NULL", __func__);
c_hpothuddce3aa2014-05-08 20:30:49 +0530165 rc = -EIO;
Jeff Johnsone7245742012-09-05 17:12:55 -0700166 break;
167 }
168 }
169 } while(0);
170
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530171 EXIT();
c_hpothuddce3aa2014-05-08 20:30:49 +0530172 return rc;
Jeff Johnsone7245742012-09-05 17:12:55 -0700173}
174
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530175int iw_get_oem_data_rsp(
176 struct net_device *dev,
177 struct iw_request_info *info,
178 union iwreq_data *wrqu,
179 char *extra)
180{
181 int ret;
182
183 vos_ssr_protect(__func__);
184 ret = __iw_get_oem_data_rsp(dev, info, wrqu, extra);
185 vos_ssr_unprotect(__func__);
186
187 return ret;
188}
189
Jeff Johnsone7245742012-09-05 17:12:55 -0700190/**--------------------------------------------------------------------------------------------
191
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530192 \brief __iw_set_oem_data_req() -
Jeff Johnsone7245742012-09-05 17:12:55 -0700193
194 This function sets the oem data req configuration. This invokes
195 the respective sme oem data req functionality. Function for
196 handling the set IOCTL for the oem data req configuration
197
198 \param - dev - Pointer to the net device
199 - info - Pointer to the iw_oem_data_req
200 - wrqu - Pointer to the iwreq data
201 - extra - Pointer to the data
202
203 \return - 0 for success, non zero for failure
204
205-----------------------------------------------------------------------------------------------*/
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530206int __iw_set_oem_data_req(
207 struct net_device *dev,
Jeff Johnsone7245742012-09-05 17:12:55 -0700208 struct iw_request_info *info,
209 union iwreq_data *wrqu,
210 char *extra)
211{
c_hpothuddce3aa2014-05-08 20:30:49 +0530212 int rc = 0;
Jeff Johnsone7245742012-09-05 17:12:55 -0700213 eHalStatus status = eHAL_STATUS_SUCCESS;
214 struct iw_oem_data_req *pOemDataReq = NULL;
215 tOemDataReqConfig oemDataReqConfig;
Jeff Johnsone7245742012-09-05 17:12:55 -0700216 tANI_U32 oemDataReqID = 0;
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530217 hdd_adapter_t *pAdapter;
218 hdd_context_t *pHddCtx;
219 hdd_wext_state_t *pwextBuf;
Jeff Johnsone7245742012-09-05 17:12:55 -0700220
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530221 ENTER();
Hanumantha Reddy Pothula0c51f9f2015-10-27 20:48:17 +0530222
223 if (!capable(CAP_NET_ADMIN))
224 {
225 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
226 FL("permission check failed"));
227 return -EPERM;
228 }
229
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530230 pAdapter = (netdev_priv(dev));
231 if (NULL == pAdapter)
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800232 {
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530233 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
234 "%s: Adapter is NULL",__func__);
235 return -EINVAL;
236 }
237 pHddCtx = WLAN_HDD_GET_CTX(pAdapter);
238 rc = wlan_hdd_validate_context(pHddCtx);
239 if (0 != rc)
240 {
Mahesh A Saptasagar153c4662015-02-06 12:13:08 +0530241 return rc;
242 }
243
244 pwextBuf = WLAN_HDD_GET_WEXT_STATE_PTR(pAdapter);
245 if (NULL == pwextBuf)
246 {
247 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
248 "%s: pwextBuf is NULL",__func__);
249 return -EINVAL;
Sameer Thalappil75ea31a2013-02-21 19:38:16 -0800250 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700251
Hanumantha Reddy Pothula4b6be062015-08-18 14:06:24 +0530252 if (pHddCtx->isPnoEnable)
253 {
254 VOS_TRACE( VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
255 FL("pno scan in progress"));
256 return -EBUSY;
257 }
258
Jeff Johnsone7245742012-09-05 17:12:55 -0700259 do
260 {
c_hpothuddce3aa2014-05-08 20:30:49 +0530261 if (NULL != wrqu->data.pointer)
Jeff Johnsone7245742012-09-05 17:12:55 -0700262 {
263 pOemDataReq = (struct iw_oem_data_req *)wrqu->data.pointer;
264 }
265
c_hpothuddce3aa2014-05-08 20:30:49 +0530266 if (pOemDataReq == NULL)
Jeff Johnsone7245742012-09-05 17:12:55 -0700267 {
Arif Hussain6d2a3322013-11-17 19:50:10 -0800268 hddLog(LOGE, "in %s oemDataReq == NULL", __func__);
c_hpothuddce3aa2014-05-08 20:30:49 +0530269 rc = -EIO;
Jeff Johnsone7245742012-09-05 17:12:55 -0700270 break;
271 }
272
273 vos_mem_zero(&oemDataReqConfig, sizeof(tOemDataReqConfig));
274
Yue Ma63993e32013-10-21 23:10:53 -0700275 if (copy_from_user((&oemDataReqConfig)->oemDataReq,
276 pOemDataReq->oemDataReq, OEM_DATA_REQ_SIZE))
277 {
278 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_FATAL,
279 "%s: copy_from_user() failed!", __func__);
c_hpothuddce3aa2014-05-08 20:30:49 +0530280 rc = -EFAULT;
281 break;
Yue Ma63993e32013-10-21 23:10:53 -0700282 }
283
Jeff Johnsone7245742012-09-05 17:12:55 -0700284 status = sme_OemDataReq(WLAN_HDD_GET_HAL_CTX(pAdapter),
285 pAdapter->sessionId,
286 &oemDataReqConfig,
287 &oemDataReqID,
288 &hdd_OemDataReqCallback,
289 dev);
c_hpothuddce3aa2014-05-08 20:30:49 +0530290 if (status != eHAL_STATUS_SUCCESS)
291 {
292 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
293 "%s: sme_OemDataReq status %d", __func__, status);
294 rc = -EFAULT;
295 break;
296 }
Jeff Johnsone7245742012-09-05 17:12:55 -0700297
298 pwextBuf->oemDataReqID = oemDataReqID;
299 pwextBuf->oemDataReqInProgress = TRUE;
300
301 } while(0);
c_hpothuddce3aa2014-05-08 20:30:49 +0530302
Hanumantha Reddy Pothula7dc0e6c2015-03-06 15:11:16 +0530303 EXIT();
c_hpothuddce3aa2014-05-08 20:30:49 +0530304 return rc;
Jeff Johnsone7245742012-09-05 17:12:55 -0700305}
306
Mahesh A Saptasagard68eb282014-12-17 14:20:19 +0530307int iw_set_oem_data_req(
308 struct net_device *dev,
309 struct iw_request_info *info,
310 union iwreq_data *wrqu,
311 char *extra)
312{
313 int ret;
314
315 vos_ssr_protect(__func__);
316 ret = __iw_set_oem_data_req(dev, info, wrqu, extra);
317 vos_ssr_unprotect(__func__);
318
319 return ret;
320}
Jeff Johnsone7245742012-09-05 17:12:55 -0700321
Padma, Santhosh Kumar8dcdb702015-10-20 14:06:21 +0530322/**---------------------------------------------------------------------------
323
324 \brief iw_get_oem_data_cap()
325
326 This function gets the capability information for OEM Data Request
327 and Response.
328
329 \param - dev - Pointer to the net device
330 - info - Pointer to the t_iw_oem_data_cap
331 - wrqu - Pointer to the iwreq data
332 - extra - Pointer to the data
333
334 \return - 0 for success, non zero for failure
335
336----------------------------------------------------------------------------*/
337int iw_get_oem_data_cap(
338 struct net_device *dev,
339 struct iw_request_info *info,
340 union iwreq_data *wrqu,
341 char *extra)
342{
343 eHalStatus status;
344 t_iw_oem_data_cap oemDataCap;
345 t_iw_oem_data_cap *pHddOemDataCap;
346 hdd_adapter_t *pAdapter = netdev_priv(dev);
347 hdd_context_t *pHddContext;
348 hdd_config_t *pConfig;
349 tANI_U32 numChannels;
350 tANI_U8 chanList[OEM_CAP_MAX_NUM_CHANNELS];
351 tANI_U32 i;
352 int ret;
353
354 ENTER();
355
356 if (!pAdapter)
357 {
358 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
359 "%s:Invalid context, pAdapter is null", __func__);
360 return -EINVAL;
361 }
362
363 pHddContext = WLAN_HDD_GET_CTX(pAdapter);
364 ret = wlan_hdd_validate_context(pHddContext);
365 if (0 != ret)
366 return ret;
367
368 pConfig = pHddContext->cfg_ini;
369
370 do
371 {
372 vos_mem_zero(&oemDataCap, sizeof(oemDataCap));
373 strlcpy(oemDataCap.oem_target_signature, OEM_TARGET_SIGNATURE,
374 OEM_TARGET_SIGNATURE_LEN);
375 oemDataCap.oem_target_type = TARGET_TYPE_PRONTO;
376 oemDataCap.oem_fw_version = 0;
377 oemDataCap.driver_version.major = QWLAN_VERSION_MAJOR;
378 oemDataCap.driver_version.minor = QWLAN_VERSION_MINOR;
379 oemDataCap.driver_version.patch = QWLAN_VERSION_PATCH;
380 oemDataCap.driver_version.build = QWLAN_VERSION_BUILD;
381 oemDataCap.allowed_dwell_time_min = pConfig->nNeighborScanMinChanTime;
382 oemDataCap.allowed_dwell_time_max = pConfig->nNeighborScanMaxChanTime;
383 oemDataCap.curr_dwell_time_min =
384 sme_getNeighborScanMinChanTime(pHddContext->hHal);
385 oemDataCap.curr_dwell_time_max =
386 sme_getNeighborScanMaxChanTime(pHddContext->hHal);
387 oemDataCap.supported_bands = pConfig->nBandCapability;
388
389 /* request for max num of channels */
390 numChannels = WNI_CFG_VALID_CHANNEL_LIST_LEN;
391 status = sme_GetCfgValidChannels(pHddContext->hHal,
392 &chanList[0],
393 &numChannels);
394 if (eHAL_STATUS_SUCCESS != status)
395 {
396 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
397 "%s:failed to get valid channel list", __func__);
398 return -ENOENT;
399 }
400 else
401 {
402 /* make sure num channels is not more than chan list array */
403 if (numChannels > OEM_CAP_MAX_NUM_CHANNELS)
404 {
405 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
406 "%s:Num of channels(%d) more than length(%d) of chanlist",
407 __func__, numChannels, OEM_CAP_MAX_NUM_CHANNELS);
408 return -ENOMEM;
409 }
410
411 oemDataCap.num_channels = numChannels;
412 for (i = 0; i < numChannels; i++)
413 {
414 oemDataCap.channel_list[i] = chanList[i];
415 }
416 }
417
418 pHddOemDataCap = (t_iw_oem_data_cap *)(extra);
419 vos_mem_copy(pHddOemDataCap, &oemDataCap, sizeof(*pHddOemDataCap));
420 } while (0);
421
422 EXIT();
423 return 0;
424}
425
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +0530426/**---------------------------------------------------------------------------
427
428 \brief send_oem_reg_rsp_nlink_msg() - send oem registration response
429
430 This function sends oem message to registered application process
431
432 \param -
433 - none
434
435 \return - none
436
437 --------------------------------------------------------------------------*/
438static void send_oem_reg_rsp_nlink_msg(void)
439{
440 struct sk_buff *skb;
441 struct nlmsghdr *nlh;
442 tAniMsgHdr *aniHdr;
443 tANI_U8 *buf;
444 tANI_U8 *numInterfaces;
445 tANI_U8 *deviceMode;
446 tANI_U8 *vdevId;
447 hdd_adapter_list_node_t *pAdapterNode = NULL;
448 hdd_adapter_list_node_t *pNext = NULL;
449 hdd_adapter_t *pAdapter = NULL;
450 VOS_STATUS status = 0;
451
452 /* OEM message is always to a specific process and cannot be a broadcast */
453 if (pHddCtx->oem_pid == 0)
454 {
455 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
456 "%s: invalid dest pid", __func__);
457 return;
458 }
459
460 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
461 if (skb == NULL)
462 {
463 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
464 "%s: alloc_skb failed", __func__);
465 return;
466 }
467
468 nlh = (struct nlmsghdr *)skb->data;
469 nlh->nlmsg_pid = 0; /* from kernel */
470 nlh->nlmsg_flags = 0;
471 nlh->nlmsg_seq = 0;
472 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
473 aniHdr = NLMSG_DATA(nlh);
474 aniHdr->type = ANI_MSG_APP_REG_RSP;
475
476 /* Fill message body:
477 * First byte will be number of interfaces, followed by
478 * two bytes for each interfaces
479 * - one byte for device mode
480 * - one byte for vdev id
481 */
482 buf = (char *) ((char *)aniHdr + sizeof(tAniMsgHdr));
483 numInterfaces = buf++;
484 *numInterfaces = 0;
485
486 /* Iterate through each of the adapters and fill device mode and vdev id */
487 status = hdd_get_front_adapter(pHddCtx, &pAdapterNode);
488 while ((VOS_STATUS_SUCCESS == status) && pAdapterNode)
489 {
490 pAdapter = pAdapterNode->pAdapter;
491 if (pAdapter)
492 {
493 deviceMode = buf++;
494 vdevId = buf++;
495 *deviceMode = pAdapter->device_mode;
496 *vdevId = pAdapter->sessionId;
497 (*numInterfaces)++;
498 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
499 "%s: numInterfaces: %d, deviceMode: %d, vdevId: %d",
500 __func__, *numInterfaces, *deviceMode, *vdevId);
501 }
502 status = hdd_get_next_adapter(pHddCtx, pAdapterNode, &pNext);
503 pAdapterNode = pNext;
504 }
505
506 aniHdr->length = sizeof(tANI_U8) + (*numInterfaces) * 2 * sizeof(tANI_U8);
507 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + aniHdr->length));
508
509 skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length)));
510
511 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
512 "%s: sending App Reg Response length (%d) to process pid (%d)",
513 __func__, aniHdr->length, pHddCtx->oem_pid);
514
515 (void)nl_srv_ucast(skb, pHddCtx->oem_pid, MSG_DONTWAIT);
516
517 return;
518}
519
520/**---------------------------------------------------------------------------
521
522 \brief send_oem_err_rsp_nlink_msg() - send oem error response
523
524 This function sends error response to oem app
525
526 \param -
527 - app_pid - PID of oem application process
528
529 \return - none
530
531 --------------------------------------------------------------------------*/
532static void send_oem_err_rsp_nlink_msg(v_SINT_t app_pid, tANI_U8 error_code)
533{
534 struct sk_buff *skb;
535 struct nlmsghdr *nlh;
536 tAniMsgHdr *aniHdr;
537 tANI_U8 *buf;
538
539 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
540 if (skb == NULL)
541 {
542 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
543 "%s: alloc_skb failed", __func__);
544 return;
545 }
546
547 nlh = (struct nlmsghdr *)skb->data;
548 nlh->nlmsg_pid = 0; /* from kernel */
549 nlh->nlmsg_flags = 0;
550 nlh->nlmsg_seq = 0;
551 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
552 aniHdr = NLMSG_DATA(nlh);
553 aniHdr->type = ANI_MSG_OEM_ERROR;
554 aniHdr->length = sizeof(tANI_U8);
555 nlh->nlmsg_len = NLMSG_LENGTH(sizeof(tAniMsgHdr) + aniHdr->length);
556
557 /* message body will contain one byte of error code */
558 buf = (char *) ((char *) aniHdr + sizeof(tAniMsgHdr));
559 *buf = error_code;
560
561 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + aniHdr->length));
562
563 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
564 "%s: sending oem error response to process pid (%d)",
565 __func__, app_pid);
566
567 (void)nl_srv_ucast(skb, app_pid, MSG_DONTWAIT);
568
569 return;
570}
571
572/**---------------------------------------------------------------------------
573
574 \brief send_oem_data_rsp_msg() - send oem data response
575
576 This function sends oem data rsp message to registered application process
577 over the netlink socket.
578
579 \param -
580 - oemDataRsp - Pointer to OEM Data Response struct
581
582 \return - 0 for success, non zero for failure
583
584 --------------------------------------------------------------------------*/
Padma, Santhosh Kumaree7c3d22016-01-25 10:36:08 +0530585void send_oem_data_rsp_msg(tANI_U32 length, tANI_U8 *oemDataRsp)
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +0530586{
587 struct sk_buff *skb;
588 struct nlmsghdr *nlh;
589 tAniMsgHdr *aniHdr;
590 tANI_U8 *oemData;
591
592 /* OEM message is always to a specific process and cannot be a broadcast */
593 if (pHddCtx->oem_pid == 0)
594 {
595 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
596 "%s: invalid dest pid", __func__);
597 return;
598 }
599
600 if (length > NEW_OEM_DATA_RSP_SIZE)
601 {
602 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
603 "%s: invalid length of Oem Data response", __func__);
604 return;
605 }
606
Padma, Santhosh Kumaree7c3d22016-01-25 10:36:08 +0530607 skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + length),
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +0530608 GFP_KERNEL);
609 if (skb == NULL)
610 {
611 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
612 "%s: alloc_skb failed", __func__);
613 return;
614 }
615
616 nlh = (struct nlmsghdr *)skb->data;
617 nlh->nlmsg_pid = 0; /* from kernel */
618 nlh->nlmsg_flags = 0;
619 nlh->nlmsg_seq = 0;
620 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
621 aniHdr = NLMSG_DATA(nlh);
622 aniHdr->type = ANI_MSG_OEM_DATA_RSP;
623
624 aniHdr->length = length;
625 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + aniHdr->length));
626 oemData = (tANI_U8 *) ((char *)aniHdr + sizeof(tAniMsgHdr));
627 vos_mem_copy(oemData, oemDataRsp, length);
628
629 skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length)));
630
631 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
632 "%s: sending Oem Data Response of len (%d) to process pid (%d)",
633 __func__, length, pHddCtx->oem_pid);
634
635 (void)nl_srv_ucast(skb, pHddCtx->oem_pid, MSG_DONTWAIT);
636
637 return;
638}
639
640/**---------------------------------------------------------------------------
641
642 \brief oem_process_channel_info_req_msg() - process oem channel_info request
643
644 This function responds with channel info to oem process
645
646 \param -
647 - numOfChannels - number of channels
648 - chanList - channel list
649
650 \return - 0 for success, non zero for failure
651
652 --------------------------------------------------------------------------*/
653static int oem_process_channel_info_req_msg(int numOfChannels, char *chanList)
654{
655 struct sk_buff *skb;
656 struct nlmsghdr *nlh;
657 tAniMsgHdr *aniHdr;
658 tHddChannelInfo *pHddChanInfo;
659 tHddChannelInfo hddChanInfo;
660 tANI_U8 chanId;
661 tANI_U32 reg_info_1;
662 tANI_U32 reg_info_2;
663 eHalStatus status = eHAL_STATUS_FAILURE;
664 int i;
665 tANI_U8 *buf;
666
667 /* OEM message is always to a specific process and cannot be a broadcast */
668 if (pHddCtx->oem_pid == 0)
669 {
670 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
671 "%s: invalid dest pid", __func__);
672 return -1;
673 }
674
675 skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + sizeof(tANI_U8) +
676 numOfChannels * sizeof(tHddChannelInfo)), GFP_KERNEL);
677 if (skb == NULL)
678 {
679 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
680 "%s: alloc_skb failed", __func__);
681 return -1;
682 }
683
684 nlh = (struct nlmsghdr *)skb->data;
685 nlh->nlmsg_pid = 0; /* from kernel */
686 nlh->nlmsg_flags = 0;
687 nlh->nlmsg_seq = 0;
688 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
689 aniHdr = NLMSG_DATA(nlh);
690 aniHdr->type = ANI_MSG_CHANNEL_INFO_RSP;
691
692 aniHdr->length = sizeof(tANI_U8) + numOfChannels * sizeof(tHddChannelInfo);
693 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + aniHdr->length));
694
695 /* First byte of message body will have num of channels */
696 buf = (char *) ((char *)aniHdr + sizeof(tAniMsgHdr));
697 *buf++ = numOfChannels;
698
699 /* Next follows channel info struct for each channel id.
700 * If chan id is wrong or SME returns failure for a channel
701 * then fill in 0 in channel info for that particular channel
702 */
703 for (i = 0 ; i < numOfChannels; i++)
704 {
705 pHddChanInfo = (tHddChannelInfo *) ((char *) buf +
706 i * sizeof(tHddChannelInfo));
707
708 chanId = chanList[i];
709 status = sme_getRegInfo(pHddCtx->hHal, chanId,
710 &reg_info_1, &reg_info_2);
711 if (eHAL_STATUS_SUCCESS == status)
712 {
713 /* band center freq1, and freq2 depends on peer's capability
714 * and at this time we might not be associated on the given
715 * channel, so fill freq1=mhz, and freq2=0
716 */
717 hddChanInfo.chan_id = chanId;
718 hddChanInfo.reserved0 = 0;
719 hddChanInfo.mhz = vos_chan_to_freq(chanId);
720 hddChanInfo.band_center_freq1 = hddChanInfo.mhz;
721 hddChanInfo.band_center_freq2 = 0;
722
723 /* set only DFS flag in info, rest of the fields will be filled in
724 * by the OEM App
725 */
726 hddChanInfo.info = 0;
727 if (NV_CHANNEL_DFS == vos_nv_getChannelEnabledState(chanId))
728 hddChanInfo.info |= (1 << WLAN_HAL_CHAN_FLAG_DFS);
729
730 hddChanInfo.reg_info_1 = reg_info_1;
731 hddChanInfo.reg_info_2 = reg_info_2;
732 }
733 else
734 {
735 /* chanId passed to sme_getRegInfo is not valid, fill in zeros
736 * in channel info struct
737 */
738 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
739 "%s: sme_getRegInfo failed for chan (%d), return info 0",
740 __func__, chanId);
741 hddChanInfo.chan_id = chanId;
742 hddChanInfo.reserved0 = 0;
743 hddChanInfo.mhz = 0;
744 hddChanInfo.band_center_freq1 = 0;
745 hddChanInfo.band_center_freq2 = 0;
746 hddChanInfo.info = 0;
747 hddChanInfo.reg_info_1 = 0;
748 hddChanInfo.reg_info_2 = 0;
749 }
750 vos_mem_copy(pHddChanInfo, &hddChanInfo, sizeof(tHddChannelInfo));
751 }
752
753 skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length)));
754
755 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
756 "%s: sending channel info resp for num channels (%d) to pid (%d)",
757 __func__, numOfChannels, pHddCtx->oem_pid);
758
759 (void)nl_srv_ucast(skb, pHddCtx->oem_pid, MSG_DONTWAIT);
760
761 return 0;
762}
763
764/**---------------------------------------------------------------------------
765
766 \brief oem_process_data_req_msg() - process oem data request
767
768 This function sends oem message to SME
769
770 \param -
771 - oemDataLen - Length to OEM Data buffer
772 - oemData - Pointer to OEM Data buffer
773
774 \return - eHalStatus enumeration
775
776 --------------------------------------------------------------------------*/
777void oem_process_data_req_msg(int oemDataLen, char *oemData)
778{
779 tOemDataReqNewConfig oemDataReqNewConfig;
Padma, Santhosh Kumar70380cf2016-01-11 18:42:20 +0530780 hdd_adapter_t *pAdapter = NULL;
781
782 /* for now, STA interface only */
783 pAdapter = hdd_get_adapter(pHddCtx, WLAN_HDD_INFRA_STATION);
784 if (!pAdapter)
785 {
786 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
787 "%s: No adapter for STA mode", __func__);
788 return;
789 }
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +0530790
791 if (!oemData)
792 {
793 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_ERROR,
794 "%s: oemData is null", __func__);
795 return;
796 }
797
798 vos_mem_zero(&oemDataReqNewConfig, sizeof(tOemDataReqNewConfig));
Padma, Santhosh Kumar70380cf2016-01-11 18:42:20 +0530799 vos_mem_copy(&oemDataReqNewConfig.selfMacAddr,
800 pAdapter->macAddressCurrent.bytes, sizeof(tSirMacAddr));
801 vos_mem_copy(&oemDataReqNewConfig.oemDataReqNew, oemData, oemDataLen);
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +0530802
803 VOS_TRACE(VOS_MODULE_ID_HDD, VOS_TRACE_LEVEL_INFO,
Padma, Santhosh Kumar70380cf2016-01-11 18:42:20 +0530804 "selfMacAddr: " MAC_ADDRESS_STR" ",
805 MAC_ADDR_ARRAY(oemDataReqNewConfig.selfMacAddr));
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +0530806
807 sme_OemDataReqNew(pHddCtx->hHal,
808 &oemDataReqNewConfig);
809}
810
811/*
812 * Callback function invoked by Netlink service for all netlink
813 * messages (from user space) addressed to WLAN_NL_MSG_OEM
814 */
815
816/**
817 * oem_msg_callback() - callback invoked by netlink service
818 * @skb: skb with netlink message
819 *
820 * This function gets invoked by netlink service when a message
821 * is received from user space addressed to WLAN_NL_MSG_OEM
822 *
823 * Return: zero on success
824 * On error, error number will be returned.
825 */
826static int oem_msg_callback(struct sk_buff *skb)
827{
828 struct nlmsghdr *nlh;
829 tAniMsgHdr *msg_hdr;
830 int ret;
831 char *sign_str = NULL;
Padma, Santhosh Kumar2ccac212015-10-20 17:27:27 +0530832 char* aniMsgBody;
833 tANI_U32 *oemMsgSubType;
834
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +0530835 nlh = (struct nlmsghdr *)skb->data;
836
837 if (!nlh) {
838 hddLog(LOGE, FL("Netlink header null"));
839 return -EPERM;
840 }
841
842 ret = wlan_hdd_validate_context(pHddCtx);
843 if (0 != ret) {
844 hddLog(LOGE, FL("HDD context is not valid"));
845 return ret;
846 }
847
848 msg_hdr = NLMSG_DATA(nlh);
849
850 if (!msg_hdr) {
851 hddLog(LOGE, FL("Message header null"));
852 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid, OEM_ERR_NULL_MESSAGE_HEADER);
853 return -EPERM;
854 }
855
856 if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(tAniMsgHdr) + msg_hdr->length)) {
857 hddLog(LOGE, FL("Invalid nl msg len, nlh->nlmsg_len (%d), msg_hdr->len (%d)"),
858 nlh->nlmsg_len, msg_hdr->length);
859 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
860 OEM_ERR_INVALID_MESSAGE_LENGTH);
861 return -EPERM;
862 }
863
Padma, Santhosh Kumar2ccac212015-10-20 17:27:27 +0530864 hddLog(LOG1, FL("Received App msg type: %d"), msg_hdr->type);
865
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +0530866 switch (msg_hdr->type) {
867 case ANI_MSG_APP_REG_REQ:
868 /* Registration request is only allowed for Qualcomm Application */
869 hddLog(LOG1, FL("Received App Req Req from App process pid(%d), len(%d)"),
870 nlh->nlmsg_pid, msg_hdr->length);
871
872 sign_str = (char *)((char *)msg_hdr + sizeof(tAniMsgHdr));
873 if ((OEM_APP_SIGNATURE_LEN == msg_hdr->length) &&
874 (0 == strncmp(sign_str, OEM_APP_SIGNATURE_STR,
875 OEM_APP_SIGNATURE_LEN))) {
876 hddLog(LOG1, FL("Valid App Req Req from oem app process pid(%d)"),
877 nlh->nlmsg_pid);
878
879 pHddCtx->oem_app_registered = TRUE;
880 pHddCtx->oem_pid = nlh->nlmsg_pid;
881 send_oem_reg_rsp_nlink_msg();
882 } else {
883 hddLog(LOGE, FL("Invalid signature in App Reg Request from pid(%d)"),
884 nlh->nlmsg_pid);
885 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
886 OEM_ERR_INVALID_SIGNATURE);
887 return -EPERM;
888 }
889 break;
890
891 case ANI_MSG_OEM_DATA_REQ:
892 hddLog(LOG1, FL("Received Oem Data Request length(%d) from pid: %d"),
893 msg_hdr->length, nlh->nlmsg_pid);
894
895 if ((!pHddCtx->oem_app_registered) ||
896 (nlh->nlmsg_pid != pHddCtx->oem_pid)) {
897 /* either oem app is not registered yet or pid is different */
898 hddLog(LOGE, FL("OEM DataReq: app not registered(%d) or incorrect pid(%d)"),
899 pHddCtx->oem_app_registered, nlh->nlmsg_pid);
900 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
901 OEM_ERR_APP_NOT_REGISTERED);
902 return -EPERM;
903 }
904
905 if ((!msg_hdr->length) || (OEM_DATA_REQ_SIZE < msg_hdr->length)) {
906 hddLog(LOGE, FL("Invalid length (%d) in Oem Data Request"),
907 msg_hdr->length);
908 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
909 OEM_ERR_INVALID_MESSAGE_LENGTH);
910 return -EPERM;
911 }
Padma, Santhosh Kumar2ccac212015-10-20 17:27:27 +0530912 aniMsgBody = (char *)((char *)msg_hdr + sizeof(tAniMsgHdr));
913 oemMsgSubType = (tANI_U32*) aniMsgBody;
Abhishek Singha8b92102016-09-09 12:34:42 +0530914 hddLog(LOG1, FL("oemMsgSubType: 0x%x"), *oemMsgSubType);
Padma, Santhosh Kumar2ccac212015-10-20 17:27:27 +0530915
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +0530916 oem_process_data_req_msg(msg_hdr->length,
917 (char *) ((char *)msg_hdr +
918 sizeof(tAniMsgHdr)));
919 break;
920
921 case ANI_MSG_CHANNEL_INFO_REQ:
922 hddLog(LOG1,
923 FL("Received channel info request, num channel(%d) from pid: %d"),
924 msg_hdr->length, nlh->nlmsg_pid);
925
926 if ((!pHddCtx->oem_app_registered) ||
927 (nlh->nlmsg_pid != pHddCtx->oem_pid)) {
928 /* either oem app is not registered yet or pid is different */
929 hddLog(LOGE,
930 FL("Chan InfoReq: app not registered(%d) or incorrect pid(%d)"),
931 pHddCtx->oem_app_registered, nlh->nlmsg_pid);
932 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
933 OEM_ERR_APP_NOT_REGISTERED);
934 return -EPERM;
935 }
936
937 /* message length contains list of channel ids */
938 if ((!msg_hdr->length) ||
939 (WNI_CFG_VALID_CHANNEL_LIST_LEN < msg_hdr->length)) {
940 hddLog(LOGE,
941 FL("Invalid length (%d) in channel info request"),
942 msg_hdr->length);
943 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
944 OEM_ERR_INVALID_MESSAGE_LENGTH);
945 return -EPERM;
946 }
947 oem_process_channel_info_req_msg(msg_hdr->length,
948 (char *)((char*)msg_hdr + sizeof(tAniMsgHdr)));
949 break;
950
951 default:
952 hddLog(LOGE,
953 FL("Received Invalid message type (%d), length (%d)"),
954 msg_hdr->type, msg_hdr->length);
955 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
956 OEM_ERR_INVALID_MESSAGE_TYPE);
957 return -EPERM;
958 }
959 return 0;
960}
961
962static int __oem_msg_callback(struct sk_buff *skb)
963{
964 int ret;
965
966 vos_ssr_protect(__func__);
967 ret = oem_msg_callback(skb);
968 vos_ssr_unprotect(__func__);
969
970 return ret;
971}
972
973/**---------------------------------------------------------------------------
974
975 \brief oem_activate_service() - Activate oem message handler
976
977 This function registers a handler to receive netlink message from
978 an OEM application process.
979
980 \param -
981 - pAdapter - pointer to HDD adapter
982
983 \return - 0 for success, non zero for failure
984
985 --------------------------------------------------------------------------*/
986int oem_activate_service(void *pAdapter)
987{
988 pHddCtx = (struct hdd_context_s*) pAdapter;
989
990 /* Register the msg handler for msgs addressed to WLAN_NL_MSG_OEM */
991 nl_srv_register(WLAN_NL_MSG_OEM, __oem_msg_callback);
992 return 0;
993}
994
Hanumanth Reddy Pothula13789c42017-09-12 15:18:13 +0530995/**---------------------------------------------------------------------------
996
997 \brief oem_deactivate_service() - Deactivate oem message handler
998
999 This function unregisters a handler to receive netlink message from
1000 an OEM application process.
1001
1002 \return - none
1003 --------------------------------------------------------------------------*/
1004void oem_deactivate_service()
1005{
1006 /* unregister the msg handler for msgs addressed to WLAN_NL_MSG_OEM */
1007 nl_srv_unregister(WLAN_NL_MSG_OEM, __oem_msg_callback);
1008}
1009
Padma, Santhosh Kumar2762e9d2015-10-20 15:02:57 +05301010
Jeff Johnsone7245742012-09-05 17:12:55 -07001011#endif