blob: ffa0934207f0bfc031c1af615ed4529b1a3d68be [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -08002 * Copyright (c) 2012-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -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.
20 */
21
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
28#ifdef FEATURE_OEM_DATA_SUPPORT
29
30/**
31 * DOC: wlan_hdd_oemdata.c
32 *
33 * Support for generic OEM Data Request handling
34 *
35 */
36
Jeff Johnsonbfa02062016-05-26 10:09:04 -070037/* denote that this file does not allow legacy hddLog */
38#define HDD_DISALLOW_LEGACY_HDDLOG 1
39
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080040#include <linux/version.h>
41#include <linux/module.h>
42#include <linux/kernel.h>
43#include <linux/init.h>
44#include <linux/wireless.h>
45#include <wlan_hdd_includes.h>
46#include <net/arp.h>
47#include "qwlan_version.h"
48#include "cds_utils.h"
49#include "wma.h"
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -080050#include "sme_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080051
52static struct hdd_context_s *p_hdd_ctx;
53
54/**
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -080055 * populate_oem_data_cap() - populate oem capabilities
56 * @adapter: device adapter
57 * @data_cap: pointer to populate the capabilities
58 *
59 * Return: error code
60 */
61static int populate_oem_data_cap(hdd_adapter_t *adapter,
62 t_iw_oem_data_cap *data_cap)
63{
Krishna Kumaar Natarajanc4f8a932016-04-16 13:51:42 +053064 QDF_STATUS status;
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -080065 struct hdd_config *config;
66 uint32_t num_chan;
67 uint8_t *chan_list;
68 hdd_context_t *hdd_ctx = adapter->pHddCtx;
69
70 config = hdd_ctx->config;
71 if (!config) {
72 hdd_err("HDD configuration is null");
73 return -EINVAL;
74 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053075 chan_list = qdf_mem_malloc(sizeof(uint8_t) * OEM_CAP_MAX_NUM_CHANNELS);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -080076 if (NULL == chan_list) {
77 hdd_err("Memory allocation failed");
78 return -ENOMEM;
79 }
80
81 strlcpy(data_cap->oem_target_signature, OEM_TARGET_SIGNATURE,
82 OEM_TARGET_SIGNATURE_LEN);
83 data_cap->oem_target_type = hdd_ctx->target_type;
84 data_cap->oem_fw_version = hdd_ctx->target_fw_version;
85 data_cap->driver_version.major = QWLAN_VERSION_MAJOR;
86 data_cap->driver_version.minor = QWLAN_VERSION_MINOR;
87 data_cap->driver_version.patch = QWLAN_VERSION_PATCH;
88 data_cap->driver_version.build = QWLAN_VERSION_BUILD;
89 data_cap->allowed_dwell_time_min = config->nNeighborScanMinChanTime;
90 data_cap->allowed_dwell_time_max = config->nNeighborScanMaxChanTime;
91 data_cap->curr_dwell_time_min =
92 sme_get_neighbor_scan_min_chan_time(hdd_ctx->hHal,
93 adapter->sessionId);
94 data_cap->curr_dwell_time_max =
95 sme_get_neighbor_scan_max_chan_time(hdd_ctx->hHal,
96 adapter->sessionId);
97 data_cap->supported_bands = config->nBandCapability;
98
99 /* request for max num of channels */
Krishna Kumaar Natarajanc4f8a932016-04-16 13:51:42 +0530100 num_chan = OEM_CAP_MAX_NUM_CHANNELS;
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800101 status = sme_get_cfg_valid_channels(hdd_ctx->hHal,
102 &chan_list[0], &num_chan);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530103 if (QDF_STATUS_SUCCESS != status) {
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800104 hdd_err("failed to get valid channel list, status: %d", status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530105 qdf_mem_free(chan_list);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800106 return -EINVAL;
107 }
108
109 /* make sure num channels is not more than chan list array */
110 if (num_chan > OEM_CAP_MAX_NUM_CHANNELS) {
111 hdd_err("Num of channels-%d > length-%d of chan_list",
112 num_chan, OEM_CAP_MAX_NUM_CHANNELS);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530113 qdf_mem_free(chan_list);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800114 return -ENOMEM;
115 }
116
117 data_cap->num_channels = num_chan;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530118 qdf_mem_copy(data_cap->channel_list, chan_list,
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800119 sizeof(uint8_t) * num_chan);
120
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530121 qdf_mem_free(chan_list);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800122 return 0;
123}
124
125/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800126 * iw_get_oem_data_cap() - Get OEM Data Capabilities
127 * @dev: net device upon which the request was received
128 * @info: ioctl request information
129 * @wrqu: ioctl request data
130 * @extra: ioctl data payload
131 *
132 * This function gets the capability information for OEM Data Request
133 * and Response.
134 *
135 * Return: 0 for success, negative errno value on failure
136 */
137int iw_get_oem_data_cap(struct net_device *dev,
138 struct iw_request_info *info,
139 union iwreq_data *wrqu, char *extra)
140{
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800141 int status;
142 t_iw_oem_data_cap oemDataCap = { {0} };
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800143 t_iw_oem_data_cap *pHddOemDataCap;
144 hdd_adapter_t *pAdapter = (netdev_priv(dev));
145 hdd_context_t *pHddContext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800146 int ret;
147
148 ENTER();
149
150 pHddContext = WLAN_HDD_GET_CTX(pAdapter);
151 ret = wlan_hdd_validate_context(pHddContext);
152 if (0 != ret)
153 return ret;
154
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800155 status = populate_oem_data_cap(pAdapter, &oemDataCap);
Krishna Kumaar Natarajanbc7e4942016-02-11 15:09:40 -0800156 if (0 != status) {
157 hdd_err("Failed to populate oem data capabilities");
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800158 return status;
Krishna Kumaar Natarajanbc7e4942016-02-11 15:09:40 -0800159 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800160
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800161 pHddOemDataCap = (t_iw_oem_data_cap *) (extra);
162 *pHddOemDataCap = oemDataCap;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800163
164 EXIT();
165 return 0;
166}
167
168/**
169 * send_oem_reg_rsp_nlink_msg() - send oem registration response
170 *
171 * This function sends oem message to registered application process
172 *
173 * Return: none
174 */
175static void send_oem_reg_rsp_nlink_msg(void)
176{
177 struct sk_buff *skb;
178 struct nlmsghdr *nlh;
179 tAniMsgHdr *aniHdr;
180 uint8_t *buf;
181 uint8_t *numInterfaces;
182 uint8_t *deviceMode;
183 uint8_t *vdevId;
184 hdd_adapter_list_node_t *pAdapterNode = NULL;
185 hdd_adapter_list_node_t *pNext = NULL;
186 hdd_adapter_t *pAdapter = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530187 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800188
189 /* OEM message is always to a specific process and cannot be a broadcast */
190 if (p_hdd_ctx->oem_pid == 0) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700191 hdd_err("invalid dest pid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800192 return;
193 }
194
195 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
196 if (skb == NULL) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700197 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800198 return;
199 }
200
201 nlh = (struct nlmsghdr *)skb->data;
202 nlh->nlmsg_pid = 0; /* from kernel */
203 nlh->nlmsg_flags = 0;
204 nlh->nlmsg_seq = 0;
205 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
206 aniHdr = NLMSG_DATA(nlh);
207 aniHdr->type = ANI_MSG_APP_REG_RSP;
208
209 /* Fill message body:
210 * First byte will be number of interfaces, followed by
211 * two bytes for each interfaces
212 * - one byte for device mode
213 * - one byte for vdev id
214 */
215 buf = (char *)((char *)aniHdr + sizeof(tAniMsgHdr));
216 numInterfaces = buf++;
217 *numInterfaces = 0;
218
219 /* Iterate through each of the adapters and fill device mode and vdev id */
220 status = hdd_get_front_adapter(p_hdd_ctx, &pAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530221 while ((QDF_STATUS_SUCCESS == status) && pAdapterNode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800222 pAdapter = pAdapterNode->pAdapter;
223 if (pAdapter) {
224 deviceMode = buf++;
225 vdevId = buf++;
226 *deviceMode = pAdapter->device_mode;
227 *vdevId = pAdapter->sessionId;
228 (*numInterfaces)++;
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700229 hdd_notice("numInterfaces: %d, deviceMode: %d, vdevId: %d",
230 *numInterfaces, *deviceMode,
231 *vdevId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800232 }
233 status = hdd_get_next_adapter(p_hdd_ctx, pAdapterNode, &pNext);
234 pAdapterNode = pNext;
235 }
236
237 aniHdr->length =
238 sizeof(uint8_t) + (*numInterfaces) * 2 * sizeof(uint8_t);
239 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + aniHdr->length));
240
241 skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length)));
242
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700243 hdd_notice("sending App Reg Response length (%d) to process pid (%d)",
244 aniHdr->length, p_hdd_ctx->oem_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800245
246 (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
247
248 return;
249}
250
251/**
252 * send_oem_err_rsp_nlink_msg() - send oem error response
253 * @app_pid: PID of oem application process
254 * @error_code: response error code
255 *
256 * This function sends error response to oem app
257 *
258 * Return: none
259 */
260static void send_oem_err_rsp_nlink_msg(int32_t app_pid, uint8_t error_code)
261{
262 struct sk_buff *skb;
263 struct nlmsghdr *nlh;
264 tAniMsgHdr *aniHdr;
265 uint8_t *buf;
266
267 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
268 if (skb == NULL) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700269 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800270 return;
271 }
272
273 nlh = (struct nlmsghdr *)skb->data;
274 nlh->nlmsg_pid = 0; /* from kernel */
275 nlh->nlmsg_flags = 0;
276 nlh->nlmsg_seq = 0;
277 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
278 aniHdr = NLMSG_DATA(nlh);
279 aniHdr->type = ANI_MSG_OEM_ERROR;
280 aniHdr->length = sizeof(uint8_t);
281 nlh->nlmsg_len = NLMSG_LENGTH(sizeof(tAniMsgHdr) + aniHdr->length);
282
283 /* message body will contain one byte of error code */
284 buf = (char *)((char *)aniHdr + sizeof(tAniMsgHdr));
285 *buf = error_code;
286
287 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + aniHdr->length));
288
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700289 hdd_notice("sending oem error response to process pid (%d)", app_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800290
291 (void)nl_srv_ucast(skb, app_pid, MSG_DONTWAIT);
292
293 return;
294}
295
296/**
297 * hdd_send_oem_data_rsp_msg() - send oem data response
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700298 * @oem_data_rsp: the actual OEM Data Response message
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800299 *
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 */
Krishna Kumaar Natarajanc1fa17d2016-08-03 14:19:20 -0700305void hdd_send_oem_data_rsp_msg(struct oem_data_rsp *oem_data_rsp)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800306{
307 struct sk_buff *skb;
308 struct nlmsghdr *nlh;
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700309 tAniMsgHdr *ani_hdr;
310 uint8_t *oem_data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800311
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700312 /*
313 * OEM message is always to a specific process and cannot be a broadcast
314 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800315 if (p_hdd_ctx->oem_pid == 0) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700316 hdd_err("invalid dest pid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800317 return;
318 }
319
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700320 if (oem_data_rsp->rsp_len > OEM_DATA_RSP_SIZE) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700321 hdd_err("invalid length of Oem Data response");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800322 return;
323 }
324
325 skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + OEM_DATA_RSP_SIZE),
326 GFP_KERNEL);
327 if (skb == NULL) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700328 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800329 return;
330 }
331
332 nlh = (struct nlmsghdr *)skb->data;
333 nlh->nlmsg_pid = 0; /* from kernel */
334 nlh->nlmsg_flags = 0;
335 nlh->nlmsg_seq = 0;
336 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700337 ani_hdr = NLMSG_DATA(nlh);
338 ani_hdr->type = ANI_MSG_OEM_DATA_RSP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800339
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700340 ani_hdr->length = oem_data_rsp->rsp_len;
341 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + ani_hdr->length));
342 oem_data = (uint8_t *) ((char *)ani_hdr + sizeof(tAniMsgHdr));
343 qdf_mem_copy(oem_data, oem_data_rsp->data, oem_data_rsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800344
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700345 skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + ani_hdr->length)));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800346
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700347 hdd_notice("sending Oem Data Response of len (%d) to process pid (%d)",
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700348 oem_data_rsp->rsp_len, p_hdd_ctx->oem_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800349
350 (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
351
352 return;
353}
354
355/**
356 * oem_process_data_req_msg() - process oem data request
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700357 * @oem_data_len: Length to OEM Data buffer
358 * @oem_data: Pointer to OEM Data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800359 *
360 * This function sends oem message to SME
361 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530362 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800363 */
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700364static QDF_STATUS oem_process_data_req_msg(int oem_data_len, char *oem_data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800365{
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700366 hdd_adapter_t *adapter = NULL;
Krishna Kumaar Natarajanc1fa17d2016-08-03 14:19:20 -0700367 struct oem_data_req oem_data_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530368 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800369
370 /* for now, STA interface only */
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700371 adapter = hdd_get_adapter(p_hdd_ctx, QDF_STA_MODE);
372 if (!adapter) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700373 hdd_err("No adapter for STA mode");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530374 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800375 }
376
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700377 if (!oem_data) {
378 hdd_err("oem_data is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530379 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800380 }
381
Krishna Kumaar Natarajanc1fa17d2016-08-03 14:19:20 -0700382 qdf_mem_zero(&oem_data_req, sizeof(oem_data_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800383
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700384 oem_data_req.data = qdf_mem_malloc(oem_data_len);
385 if (!oem_data_req.data) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700386 hdd_err("malloc failed for data req buffer");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530387 return QDF_STATUS_E_NOMEM;
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -0800388 }
389
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700390 oem_data_req.data_len = oem_data_len;
391 qdf_mem_copy(oem_data_req.data, oem_data, oem_data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800392
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700393 hdd_notice("calling sme_oem_data_req");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800394
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700395 status = sme_oem_data_req(p_hdd_ctx->hHal, &oem_data_req);
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -0800396
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700397 qdf_mem_free(oem_data_req.data);
398 oem_data_req.data = NULL;
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -0800399
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800400 return status;
401}
402
403/**
Abhishek Singh1c676222016-05-09 14:20:28 +0530404 * update_channel_bw_info() - set bandwidth info for the chan
405 * @hdd_ctx: hdd context
406 * @chan: channel for which info are required
407 * @hdd_chan_info: struct where the bandwidth info is filled
408 *
409 * This function find the maximum bandwidth allowed, secondary
410 * channel offset and center freq for the channel as per regulatory
411 * domain and using these info calculate the phy mode for the
412 * channel.
413 *
414 * Return: void
415 */
416static void hdd_update_channel_bw_info(hdd_context_t *hdd_ctx,
417 uint16_t chan, tHddChannelInfo *hdd_chan_info)
418{
419 struct ch_params_s ch_params = {0};
420 uint16_t sec_ch_2g = 0;
421 WLAN_PHY_MODE phy_mode;
422 uint32_t wni_dot11_mode;
423
424 wni_dot11_mode = sme_get_wni_dot11_mode(hdd_ctx->hHal);
425
426 /* Passing CH_WIDTH_MAX will give the max bandwidth supported */
427 ch_params.ch_width = CH_WIDTH_MAX;
428
429 cds_set_channel_params(chan, sec_ch_2g, &ch_params);
430 if (ch_params.center_freq_seg0)
431 hdd_chan_info->band_center_freq1 =
432 cds_chan_to_freq(ch_params.center_freq_seg0);
433
434 hdd_info("chan %d dot11_mode %d ch_width %d sec offset %d freq_seg0 %d",
435 chan, wni_dot11_mode, ch_params.ch_width,
436 ch_params.sec_ch_offset, hdd_chan_info->band_center_freq1);
437
438 phy_mode = wma_chan_phy_mode(chan, ch_params.ch_width, wni_dot11_mode);
439 WMI_SET_CHANNEL_MODE(hdd_chan_info, phy_mode);
440}
441
442/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800443 * oem_process_channel_info_req_msg() - process oem channel_info request
444 * @numOfChannels: number of channels
445 * @chanList: list of channel information
446 *
447 * This function responds with channel info to oem process
448 *
449 * Return: 0 for success, non zero for failure
450 */
451static int oem_process_channel_info_req_msg(int numOfChannels, char *chanList)
452{
453 struct sk_buff *skb;
454 struct nlmsghdr *nlh;
455 tAniMsgHdr *aniHdr;
456 tHddChannelInfo *pHddChanInfo;
457 tHddChannelInfo hddChanInfo;
458 uint8_t chanId;
459 uint32_t reg_info_1;
460 uint32_t reg_info_2;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530461 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800462 int i;
463 uint8_t *buf;
464
465 /* OEM message is always to a specific process and cannot be a broadcast */
466 if (p_hdd_ctx->oem_pid == 0) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700467 hdd_err("invalid dest pid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800468 return -EPERM;
469 }
470
471 skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + sizeof(uint8_t) +
472 numOfChannels * sizeof(tHddChannelInfo)),
473 GFP_KERNEL);
474 if (skb == NULL) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700475 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800476 return -ENOMEM;
477 }
478
479 nlh = (struct nlmsghdr *)skb->data;
480 nlh->nlmsg_pid = 0; /* from kernel */
481 nlh->nlmsg_flags = 0;
482 nlh->nlmsg_seq = 0;
483 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
484 aniHdr = NLMSG_DATA(nlh);
485 aniHdr->type = ANI_MSG_CHANNEL_INFO_RSP;
486
487 aniHdr->length =
488 sizeof(uint8_t) + numOfChannels * sizeof(tHddChannelInfo);
489 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + aniHdr->length));
490
491 /* First byte of message body will have num of channels */
492 buf = (char *)((char *)aniHdr + sizeof(tAniMsgHdr));
493 *buf++ = numOfChannels;
494
495 /* Next follows channel info struct for each channel id.
496 * If chan id is wrong or SME returns failure for a channel
497 * then fill in 0 in channel info for that particular channel
498 */
499 for (i = 0; i < numOfChannels; i++) {
500 pHddChanInfo = (tHddChannelInfo *) ((char *)buf +
501 i *
502 sizeof(tHddChannelInfo));
503
504 chanId = chanList[i];
505 status = sme_get_reg_info(p_hdd_ctx->hHal, chanId,
506 &reg_info_1, &reg_info_2);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530507 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800508 /* copy into hdd chan info struct */
509 hddChanInfo.chan_id = chanId;
510 hddChanInfo.reserved0 = 0;
511 hddChanInfo.mhz = cds_chan_to_freq(chanId);
512 hddChanInfo.band_center_freq1 = hddChanInfo.mhz;
513 hddChanInfo.band_center_freq2 = 0;
514
515 hddChanInfo.info = 0;
516 if (CHANNEL_STATE_DFS ==
517 cds_get_channel_state(chanId))
518 WMI_SET_CHANNEL_FLAG(&hddChanInfo,
519 WMI_CHAN_FLAG_DFS);
Abhishek Singh1c676222016-05-09 14:20:28 +0530520
521 hdd_update_channel_bw_info(p_hdd_ctx,
522 chanId, &hddChanInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800523 hddChanInfo.reg_info_1 = reg_info_1;
524 hddChanInfo.reg_info_2 = reg_info_2;
525 } else {
526 /* channel info is not returned, fill in zeros in channel
527 * info struct
528 */
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700529 hdd_notice("sme_get_reg_info failed for chan (%d), return info 0",
530 chanId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800531 hddChanInfo.chan_id = chanId;
532 hddChanInfo.reserved0 = 0;
533 hddChanInfo.mhz = 0;
534 hddChanInfo.band_center_freq1 = 0;
535 hddChanInfo.band_center_freq2 = 0;
536 hddChanInfo.info = 0;
537 hddChanInfo.reg_info_1 = 0;
538 hddChanInfo.reg_info_2 = 0;
539 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530540 qdf_mem_copy(pHddChanInfo, &hddChanInfo,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800541 sizeof(tHddChannelInfo));
542 }
543
544 skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length)));
545
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700546 hdd_notice("sending channel info resp for num channels (%d) to pid (%d)",
547 numOfChannels, p_hdd_ctx->oem_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800548
549 (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
550
551 return 0;
552}
553
554/**
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800555 * oem_process_set_cap_req_msg() - process oem set capability request
556 * @oem_cap_len: Length of OEM capability
557 * @oem_cap: Pointer to OEM capability buffer
558 * @app_pid: process ID, to which rsp message is to be sent
559 *
560 * This function sends oem message to SME
561 *
562 * Return: error code
563 */
564static int oem_process_set_cap_req_msg(int oem_cap_len,
565 char *oem_cap, int32_t app_pid)
566{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530567 QDF_STATUS status;
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800568 int error_code;
569 struct sk_buff *skb;
570 struct nlmsghdr *nlh;
571 tAniMsgHdr *ani_hdr;
572 uint8_t *buf;
573
574 if (!oem_cap) {
575 hdd_err("oem_cap is null");
576 return -EINVAL;
577 }
578
579 status = sme_oem_update_capability(p_hdd_ctx->hHal,
580 (struct sme_oem_capability *)oem_cap);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530581 if (!QDF_IS_STATUS_SUCCESS(status))
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800582 hdd_err("error updating rm capability, status: %d", status);
Anurag Chouhanc5548422016-02-24 18:33:27 +0530583 error_code = qdf_status_to_os_return(status);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800584
585 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
586 if (skb == NULL) {
587 hdd_err("alloc_skb failed");
588 return -ENOMEM;
589 }
590
591 nlh = (struct nlmsghdr *)skb->data;
592 nlh->nlmsg_pid = 0; /* from kernel */
593 nlh->nlmsg_flags = 0;
594 nlh->nlmsg_seq = 0;
595 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
596 ani_hdr = NLMSG_DATA(nlh);
597 ani_hdr->type = ANI_MSG_SET_OEM_CAP_RSP;
598 /* 64 bit alignment */
599 ani_hdr->length = sizeof(error_code);
600 nlh->nlmsg_len = NLMSG_LENGTH(sizeof(tAniMsgHdr) + ani_hdr->length);
601
602 /* message body will contain only status code */
603 buf = (char *)((char *)ani_hdr + sizeof(tAniMsgHdr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530604 qdf_mem_copy(buf, &error_code, ani_hdr->length);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800605
606 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + ani_hdr->length));
607
608 hdd_info("sending oem response to process pid %d", app_pid);
609
610 (void)nl_srv_ucast(skb, app_pid, MSG_DONTWAIT);
611
612 return error_code;
613}
614
615/**
616 * oem_process_get_cap_req_msg() - process oem get capability request
617 *
618 * This function process the get capability request from OEM and responds
619 * with the capability.
620 *
621 * Return: error code
622 */
623static int oem_process_get_cap_req_msg(void)
624{
625 int error_code;
626 struct oem_get_capability_rsp *cap_rsp;
627 t_iw_oem_data_cap data_cap = { {0} };
628 struct sme_oem_capability oem_cap;
629 hdd_adapter_t *adapter;
630 struct sk_buff *skb;
631 struct nlmsghdr *nlh;
632 tAniMsgHdr *ani_hdr;
633 uint8_t *buf;
634
635 /* for now, STA interface only */
Krunal Sonibe766b02016-03-10 13:00:44 -0800636 adapter = hdd_get_adapter(p_hdd_ctx, QDF_STA_MODE);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800637 if (!adapter) {
638 hdd_err("No adapter for STA mode");
639 return -EINVAL;
640 }
641
642 error_code = populate_oem_data_cap(adapter, &data_cap);
643 if (0 != error_code)
644 return error_code;
645
646 skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + sizeof(*cap_rsp)),
647 GFP_KERNEL);
648 if (skb == NULL) {
649 hdd_err("alloc_skb failed");
650 return -ENOMEM;
651 }
652
653 nlh = (struct nlmsghdr *)skb->data;
654 nlh->nlmsg_pid = 0; /* from kernel */
655 nlh->nlmsg_flags = 0;
656 nlh->nlmsg_seq = 0;
657 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
658 ani_hdr = NLMSG_DATA(nlh);
659 ani_hdr->type = ANI_MSG_GET_OEM_CAP_RSP;
660
661 ani_hdr->length = sizeof(*cap_rsp);
662 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + ani_hdr->length));
663
664 buf = (char *)((char *)ani_hdr + sizeof(tAniMsgHdr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530665 qdf_mem_copy(buf, &data_cap, sizeof(data_cap));
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800666
667 buf = (char *) buf + sizeof(data_cap);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530668 qdf_mem_zero(&oem_cap, sizeof(oem_cap));
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800669 sme_oem_get_capability(p_hdd_ctx->hHal, &oem_cap);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530670 qdf_mem_copy(buf, &oem_cap, sizeof(oem_cap));
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800671
672 skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + ani_hdr->length)));
673 hdd_info("send rsp to oem-pid:%d for get_capability",
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700674 p_hdd_ctx->oem_pid);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800675
676 (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
677 return 0;
678}
679
680/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800681 * hdd_send_peer_status_ind_to_oem_app() -
Abhishek Singh1c676222016-05-09 14:20:28 +0530682 * Function to send peer status to a registered application
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800683 * @peerMac: MAC address of peer
684 * @peerStatus: ePeerConnected or ePeerDisconnected
685 * @peerTimingMeasCap: 0: RTT/RTT2, 1: RTT3. Default is 0
686 * @sessionId: SME session id, i.e. vdev_id
687 * @chan_info: operating channel information
Abhishek Singh1c676222016-05-09 14:20:28 +0530688 * @dev_mode: dev mode for which indication is sent
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800689 *
690 * Return: none
691 */
Anurag Chouhan6d760662016-02-20 16:05:43 +0530692void hdd_send_peer_status_ind_to_oem_app(struct qdf_mac_addr *peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800693 uint8_t peerStatus,
694 uint8_t peerTimingMeasCap,
695 uint8_t sessionId,
Abhishek Singh1c676222016-05-09 14:20:28 +0530696 tSirSmeChanInfo *chan_info,
697 enum tQDF_ADAPTER_MODE dev_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800698{
699 struct sk_buff *skb;
700 struct nlmsghdr *nlh;
701 tAniMsgHdr *aniHdr;
702 tPeerStatusInfo *pPeerInfo;
703
704 if (!p_hdd_ctx || !p_hdd_ctx->hHal) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700705 hdd_err("Either HDD Ctx is null or Hal Ctx is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800706 return;
707 }
708
709 /* check if oem app has registered and pid is valid */
710 if ((!p_hdd_ctx->oem_app_registered) || (p_hdd_ctx->oem_pid == 0)) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700711 hdd_info("OEM app is not registered(%d) or pid is invalid(%d)",
712 p_hdd_ctx->oem_app_registered,
713 p_hdd_ctx->oem_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800714 return;
715 }
716
717 skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) +
718 sizeof(tPeerStatusInfo)),
719 GFP_KERNEL);
720 if (skb == NULL) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700721 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800722 return;
723 }
724
725 nlh = (struct nlmsghdr *)skb->data;
726 nlh->nlmsg_pid = 0; /* from kernel */
727 nlh->nlmsg_flags = 0;
728 nlh->nlmsg_seq = 0;
729 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
730 aniHdr = NLMSG_DATA(nlh);
731 aniHdr->type = ANI_MSG_PEER_STATUS_IND;
732
733 aniHdr->length = sizeof(tPeerStatusInfo);
734 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + aniHdr->length));
735
736 pPeerInfo = (tPeerStatusInfo *) ((char *)aniHdr + sizeof(tAniMsgHdr));
737
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530738 qdf_mem_copy(pPeerInfo->peer_mac_addr, peerMac->bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800739 sizeof(peerMac->bytes));
740 pPeerInfo->peer_status = peerStatus;
741 pPeerInfo->vdev_id = sessionId;
742 pPeerInfo->peer_capability = peerTimingMeasCap;
743 pPeerInfo->reserved0 = 0;
Abhishek Singh1c676222016-05-09 14:20:28 +0530744 /* Set 0th bit of reserved0 for STA mode */
745 if (QDF_STA_MODE == dev_mode)
746 pPeerInfo->reserved0 |= 0x01;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800747
748 if (chan_info) {
749 pPeerInfo->peer_chan_info.chan_id = chan_info->chan_id;
750 pPeerInfo->peer_chan_info.reserved0 = 0;
751 pPeerInfo->peer_chan_info.mhz = chan_info->mhz;
752 pPeerInfo->peer_chan_info.band_center_freq1 =
753 chan_info->band_center_freq1;
754 pPeerInfo->peer_chan_info.band_center_freq2 =
755 chan_info->band_center_freq2;
756 pPeerInfo->peer_chan_info.info = chan_info->info;
757 pPeerInfo->peer_chan_info.reg_info_1 = chan_info->reg_info_1;
758 pPeerInfo->peer_chan_info.reg_info_2 = chan_info->reg_info_2;
759 } else {
760 pPeerInfo->peer_chan_info.chan_id = 0;
761 pPeerInfo->peer_chan_info.reserved0 = 0;
762 pPeerInfo->peer_chan_info.mhz = 0;
763 pPeerInfo->peer_chan_info.band_center_freq1 = 0;
764 pPeerInfo->peer_chan_info.band_center_freq2 = 0;
765 pPeerInfo->peer_chan_info.info = 0;
766 pPeerInfo->peer_chan_info.reg_info_1 = 0;
767 pPeerInfo->peer_chan_info.reg_info_2 = 0;
768 }
769 skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length)));
770
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700771 hdd_info("sending peer " MAC_ADDRESS_STR
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800772 " status(%d), peerTimingMeasCap(%d), vdevId(%d), chanId(%d)"
773 " to oem app pid(%d), center freq 1 (%d), center freq 2 (%d),"
774 " info (0x%x), frequency (%d),reg info 1 (0x%x),"
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700775 " reg info 2 (0x%x)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800776 MAC_ADDR_ARRAY(peerMac->bytes),
777 peerStatus, peerTimingMeasCap,
778 sessionId, pPeerInfo->peer_chan_info.chan_id,
779 p_hdd_ctx->oem_pid,
780 pPeerInfo->peer_chan_info.band_center_freq1,
781 pPeerInfo->peer_chan_info.band_center_freq2,
782 pPeerInfo->peer_chan_info.info,
783 pPeerInfo->peer_chan_info.mhz,
784 pPeerInfo->peer_chan_info.reg_info_1,
785 pPeerInfo->peer_chan_info.reg_info_2);
786
787 (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
788
789 return;
790}
791
792/*
793 * Callback function invoked by Netlink service for all netlink
794 * messages (from user space) addressed to WLAN_NL_MSG_OEM
795 */
796
797/**
798 * oem_msg_callback() - callback invoked by netlink service
799 * @skb: skb with netlink message
800 *
801 * This function gets invoked by netlink service when a message
802 * is received from user space addressed to WLAN_NL_MSG_OEM
803 *
804 * Return: zero on success
805 * On error, error number will be returned.
806 */
807static int oem_msg_callback(struct sk_buff *skb)
808{
809 struct nlmsghdr *nlh;
810 tAniMsgHdr *msg_hdr;
811 int ret;
812 char *sign_str = NULL;
813 nlh = (struct nlmsghdr *)skb->data;
814
815 if (!nlh) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700816 hdd_err("Netlink header null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800817 return -EPERM;
818 }
819
820 ret = wlan_hdd_validate_context(p_hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530821 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800822 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800823
824 msg_hdr = NLMSG_DATA(nlh);
825
826 if (!msg_hdr) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700827 hdd_err("Message header null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800828 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
829 OEM_ERR_NULL_MESSAGE_HEADER);
830 return -EPERM;
831 }
832
833 if (nlh->nlmsg_len <
834 NLMSG_LENGTH(sizeof(tAniMsgHdr) + msg_hdr->length)) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700835 hdd_err("Invalid nl msg len, nlh->nlmsg_len (%d), msg_hdr->len (%d)",
836 nlh->nlmsg_len, msg_hdr->length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800837 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
838 OEM_ERR_INVALID_MESSAGE_LENGTH);
839 return -EPERM;
840 }
841
842 switch (msg_hdr->type) {
843 case ANI_MSG_APP_REG_REQ:
844 /* Registration request is only allowed for Qualcomm Application */
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700845 hdd_notice("Received App Req Req from App process pid(%d), len(%d)",
846 nlh->nlmsg_pid, msg_hdr->length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800847
848 sign_str = (char *)((char *)msg_hdr + sizeof(tAniMsgHdr));
849 if ((OEM_APP_SIGNATURE_LEN == msg_hdr->length) &&
850 (0 == strncmp(sign_str, OEM_APP_SIGNATURE_STR,
851 OEM_APP_SIGNATURE_LEN))) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700852 hdd_notice("Valid App Req Req from oem app process pid(%d)",
853 nlh->nlmsg_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800854
855 p_hdd_ctx->oem_app_registered = true;
856 p_hdd_ctx->oem_pid = nlh->nlmsg_pid;
857 send_oem_reg_rsp_nlink_msg();
858 } else {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700859 hdd_err("Invalid signature in App Reg Request from pid(%d)",
860 nlh->nlmsg_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800861 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
862 OEM_ERR_INVALID_SIGNATURE);
863 return -EPERM;
864 }
865 break;
866
867 case ANI_MSG_OEM_DATA_REQ:
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700868 hdd_notice("Received Oem Data Request length(%d) from pid: %d",
869 msg_hdr->length, nlh->nlmsg_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800870
871 if ((!p_hdd_ctx->oem_app_registered) ||
872 (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) {
873 /* either oem app is not registered yet or pid is different */
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700874 hdd_err("OEM DataReq: app not registered(%d) or incorrect pid(%d)",
875 p_hdd_ctx->oem_app_registered,
876 nlh->nlmsg_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800877 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
878 OEM_ERR_APP_NOT_REGISTERED);
879 return -EPERM;
880 }
881
882 if ((!msg_hdr->length) || (OEM_DATA_REQ_SIZE < msg_hdr->length)) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700883 hdd_err("Invalid length (%d) in Oem Data Request",
884 msg_hdr->length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800885 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
886 OEM_ERR_INVALID_MESSAGE_LENGTH);
887 return -EPERM;
888 }
889 oem_process_data_req_msg(msg_hdr->length,
890 (char *)((char *)msg_hdr +
891 sizeof(tAniMsgHdr)));
892 break;
893
894 case ANI_MSG_CHANNEL_INFO_REQ:
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700895 hdd_notice("Received channel info request, num channel(%d) from pid: %d",
896 msg_hdr->length, nlh->nlmsg_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800897
898 if ((!p_hdd_ctx->oem_app_registered) ||
899 (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) {
900 /* either oem app is not registered yet or pid is different */
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700901 hdd_err("Chan InfoReq: app not registered(%d) or incorrect pid(%d)",
902 p_hdd_ctx->oem_app_registered,
903 nlh->nlmsg_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800904 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
905 OEM_ERR_APP_NOT_REGISTERED);
906 return -EPERM;
907 }
908
909 /* message length contains list of channel ids */
910 if ((!msg_hdr->length) ||
911 (WNI_CFG_VALID_CHANNEL_LIST_LEN < msg_hdr->length)) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700912 hdd_err("Invalid length (%d) in channel info request",
913 msg_hdr->length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800914 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
915 OEM_ERR_INVALID_MESSAGE_LENGTH);
916 return -EPERM;
917 }
918 oem_process_channel_info_req_msg(msg_hdr->length,
919 (char *)((char *)msg_hdr +
920 sizeof(tAniMsgHdr)));
921 break;
922
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800923 case ANI_MSG_SET_OEM_CAP_REQ:
924 hdd_info("Received set oem capability req of length:%d from pid: %d",
925 msg_hdr->length, nlh->nlmsg_pid);
926
927 if ((!p_hdd_ctx->oem_app_registered) ||
928 (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) {
929 /* oem app is not registered yet or pid is different */
930 hdd_err("set_oem_capability : app not registered(%d) or incorrect pid(%d)",
931 p_hdd_ctx->oem_app_registered,
932 nlh->nlmsg_pid);
933 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
934 OEM_ERR_APP_NOT_REGISTERED);
935 return -EPERM;
936 }
937
938 if ((!msg_hdr->length) ||
939 (sizeof(struct sme_oem_capability) < msg_hdr->length)) {
940 hdd_err("Invalid length (%d) in set_oem_capability",
941 msg_hdr->length);
942 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
943 OEM_ERR_INVALID_MESSAGE_LENGTH);
944 return -EPERM;
945 }
946
947 oem_process_set_cap_req_msg(msg_hdr->length,
948 (char *)((char *)msg_hdr +
949 sizeof(tAniMsgHdr)),
950 nlh->nlmsg_pid);
951 break;
952
953 case ANI_MSG_GET_OEM_CAP_REQ:
954 hdd_info("Rcvd get oem capability req of length:%d from pid: %d",
955 msg_hdr->length, nlh->nlmsg_pid);
956
957 if ((!p_hdd_ctx->oem_app_registered) ||
958 (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) {
959 /* oem app is not registered yet or pid is different */
960 hdd_err("get_oem_capability : app not registered(%d) or incorrect pid(%d)",
961 p_hdd_ctx->oem_app_registered,
962 nlh->nlmsg_pid);
963 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
964 OEM_ERR_APP_NOT_REGISTERED);
965 return -EPERM;
966 }
967
968 oem_process_get_cap_req_msg();
969 break;
970
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800971 default:
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700972 hdd_err("Received Invalid message type (%d), length (%d)",
973 msg_hdr->type, msg_hdr->length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800974 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
975 OEM_ERR_INVALID_MESSAGE_TYPE);
976 return -EPERM;
977 }
978 return 0;
979}
980
981static int __oem_msg_callback(struct sk_buff *skb)
982{
983 int ret;
984
985 cds_ssr_protect(__func__);
986 ret = oem_msg_callback(skb);
987 cds_ssr_unprotect(__func__);
988
989 return ret;
990}
991
992/**
993 * oem_activate_service() - Activate oem message handler
994 * @hdd_ctx: pointer to global HDD context
995 *
996 * This function registers a handler to receive netlink message from
997 * an OEM application process.
998 *
999 * Return: zero on success
1000 * On error, error number will be returned.
1001 */
1002int oem_activate_service(struct hdd_context_s *hdd_ctx)
1003{
1004 p_hdd_ctx = hdd_ctx;
1005
1006 /* Register the msg handler for msgs addressed to WLAN_NL_MSG_OEM */
1007 return nl_srv_register(WLAN_NL_MSG_OEM, __oem_msg_callback);
1008}
1009
1010#endif