blob: 1f9e6392ec017b905cbf2e402d24c71ff872d191 [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
37#include <linux/version.h>
38#include <linux/module.h>
39#include <linux/kernel.h>
40#include <linux/init.h>
41#include <linux/wireless.h>
42#include <wlan_hdd_includes.h>
43#include <net/arp.h>
44#include "qwlan_version.h"
45#include "cds_utils.h"
46#include "wma.h"
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -080047#include "sme_api.h"
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080048
49static struct hdd_context_s *p_hdd_ctx;
50
51/**
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -080052 * populate_oem_data_cap() - populate oem capabilities
53 * @adapter: device adapter
54 * @data_cap: pointer to populate the capabilities
55 *
56 * Return: error code
57 */
58static int populate_oem_data_cap(hdd_adapter_t *adapter,
59 t_iw_oem_data_cap *data_cap)
60{
Krishna Kumaar Natarajanc4f8a932016-04-16 13:51:42 +053061 QDF_STATUS status;
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -080062 struct hdd_config *config;
63 uint32_t num_chan;
64 uint8_t *chan_list;
65 hdd_context_t *hdd_ctx = adapter->pHddCtx;
66
67 config = hdd_ctx->config;
68 if (!config) {
69 hdd_err("HDD configuration is null");
70 return -EINVAL;
71 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +053072 chan_list = qdf_mem_malloc(sizeof(uint8_t) * OEM_CAP_MAX_NUM_CHANNELS);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -080073 if (NULL == chan_list) {
74 hdd_err("Memory allocation failed");
75 return -ENOMEM;
76 }
77
78 strlcpy(data_cap->oem_target_signature, OEM_TARGET_SIGNATURE,
79 OEM_TARGET_SIGNATURE_LEN);
80 data_cap->oem_target_type = hdd_ctx->target_type;
81 data_cap->oem_fw_version = hdd_ctx->target_fw_version;
82 data_cap->driver_version.major = QWLAN_VERSION_MAJOR;
83 data_cap->driver_version.minor = QWLAN_VERSION_MINOR;
84 data_cap->driver_version.patch = QWLAN_VERSION_PATCH;
85 data_cap->driver_version.build = QWLAN_VERSION_BUILD;
86 data_cap->allowed_dwell_time_min = config->nNeighborScanMinChanTime;
87 data_cap->allowed_dwell_time_max = config->nNeighborScanMaxChanTime;
88 data_cap->curr_dwell_time_min =
89 sme_get_neighbor_scan_min_chan_time(hdd_ctx->hHal,
90 adapter->sessionId);
91 data_cap->curr_dwell_time_max =
92 sme_get_neighbor_scan_max_chan_time(hdd_ctx->hHal,
93 adapter->sessionId);
94 data_cap->supported_bands = config->nBandCapability;
95
96 /* request for max num of channels */
Krishna Kumaar Natarajanc4f8a932016-04-16 13:51:42 +053097 num_chan = OEM_CAP_MAX_NUM_CHANNELS;
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -080098 status = sme_get_cfg_valid_channels(hdd_ctx->hHal,
99 &chan_list[0], &num_chan);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530100 if (QDF_STATUS_SUCCESS != status) {
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800101 hdd_err("failed to get valid channel list, status: %d", status);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530102 qdf_mem_free(chan_list);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800103 return -EINVAL;
104 }
105
106 /* make sure num channels is not more than chan list array */
107 if (num_chan > OEM_CAP_MAX_NUM_CHANNELS) {
108 hdd_err("Num of channels-%d > length-%d of chan_list",
109 num_chan, OEM_CAP_MAX_NUM_CHANNELS);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530110 qdf_mem_free(chan_list);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800111 return -ENOMEM;
112 }
113
114 data_cap->num_channels = num_chan;
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530115 qdf_mem_copy(data_cap->channel_list, chan_list,
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800116 sizeof(uint8_t) * num_chan);
117
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530118 qdf_mem_free(chan_list);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800119 return 0;
120}
121
122/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800123 * iw_get_oem_data_cap() - Get OEM Data Capabilities
124 * @dev: net device upon which the request was received
125 * @info: ioctl request information
126 * @wrqu: ioctl request data
127 * @extra: ioctl data payload
128 *
129 * This function gets the capability information for OEM Data Request
130 * and Response.
131 *
132 * Return: 0 for success, negative errno value on failure
133 */
134int iw_get_oem_data_cap(struct net_device *dev,
135 struct iw_request_info *info,
136 union iwreq_data *wrqu, char *extra)
137{
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800138 int status;
139 t_iw_oem_data_cap oemDataCap = { {0} };
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800140 t_iw_oem_data_cap *pHddOemDataCap;
141 hdd_adapter_t *pAdapter = (netdev_priv(dev));
142 hdd_context_t *pHddContext;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800143 int ret;
144
145 ENTER();
146
147 pHddContext = WLAN_HDD_GET_CTX(pAdapter);
148 ret = wlan_hdd_validate_context(pHddContext);
149 if (0 != ret)
150 return ret;
151
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800152 status = populate_oem_data_cap(pAdapter, &oemDataCap);
Krishna Kumaar Natarajanbc7e4942016-02-11 15:09:40 -0800153 if (0 != status) {
154 hdd_err("Failed to populate oem data capabilities");
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800155 return status;
Krishna Kumaar Natarajanbc7e4942016-02-11 15:09:40 -0800156 }
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800157
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800158 pHddOemDataCap = (t_iw_oem_data_cap *) (extra);
159 *pHddOemDataCap = oemDataCap;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800160
161 EXIT();
162 return 0;
163}
164
165/**
166 * send_oem_reg_rsp_nlink_msg() - send oem registration response
167 *
168 * This function sends oem message to registered application process
169 *
170 * Return: none
171 */
172static void send_oem_reg_rsp_nlink_msg(void)
173{
174 struct sk_buff *skb;
175 struct nlmsghdr *nlh;
176 tAniMsgHdr *aniHdr;
177 uint8_t *buf;
178 uint8_t *numInterfaces;
179 uint8_t *deviceMode;
180 uint8_t *vdevId;
181 hdd_adapter_list_node_t *pAdapterNode = NULL;
182 hdd_adapter_list_node_t *pNext = NULL;
183 hdd_adapter_t *pAdapter = NULL;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530184 QDF_STATUS status = 0;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800185
186 /* OEM message is always to a specific process and cannot be a broadcast */
187 if (p_hdd_ctx->oem_pid == 0) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700188 hdd_err("invalid dest pid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800189 return;
190 }
191
192 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
193 if (skb == NULL) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700194 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800195 return;
196 }
197
198 nlh = (struct nlmsghdr *)skb->data;
199 nlh->nlmsg_pid = 0; /* from kernel */
200 nlh->nlmsg_flags = 0;
201 nlh->nlmsg_seq = 0;
202 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
203 aniHdr = NLMSG_DATA(nlh);
204 aniHdr->type = ANI_MSG_APP_REG_RSP;
205
206 /* Fill message body:
207 * First byte will be number of interfaces, followed by
208 * two bytes for each interfaces
209 * - one byte for device mode
210 * - one byte for vdev id
211 */
212 buf = (char *)((char *)aniHdr + sizeof(tAniMsgHdr));
213 numInterfaces = buf++;
214 *numInterfaces = 0;
215
216 /* Iterate through each of the adapters and fill device mode and vdev id */
217 status = hdd_get_front_adapter(p_hdd_ctx, &pAdapterNode);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530218 while ((QDF_STATUS_SUCCESS == status) && pAdapterNode) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800219 pAdapter = pAdapterNode->pAdapter;
220 if (pAdapter) {
221 deviceMode = buf++;
222 vdevId = buf++;
223 *deviceMode = pAdapter->device_mode;
224 *vdevId = pAdapter->sessionId;
225 (*numInterfaces)++;
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700226 hdd_notice("numInterfaces: %d, deviceMode: %d, vdevId: %d",
227 *numInterfaces, *deviceMode,
228 *vdevId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800229 }
230 status = hdd_get_next_adapter(p_hdd_ctx, pAdapterNode, &pNext);
231 pAdapterNode = pNext;
232 }
233
234 aniHdr->length =
235 sizeof(uint8_t) + (*numInterfaces) * 2 * sizeof(uint8_t);
236 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + aniHdr->length));
237
238 skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length)));
239
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700240 hdd_notice("sending App Reg Response length (%d) to process pid (%d)",
241 aniHdr->length, p_hdd_ctx->oem_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800242
243 (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
244
245 return;
246}
247
248/**
249 * send_oem_err_rsp_nlink_msg() - send oem error response
250 * @app_pid: PID of oem application process
251 * @error_code: response error code
252 *
253 * This function sends error response to oem app
254 *
255 * Return: none
256 */
257static void send_oem_err_rsp_nlink_msg(int32_t app_pid, uint8_t error_code)
258{
259 struct sk_buff *skb;
260 struct nlmsghdr *nlh;
261 tAniMsgHdr *aniHdr;
262 uint8_t *buf;
263
264 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
265 if (skb == NULL) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700266 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800267 return;
268 }
269
270 nlh = (struct nlmsghdr *)skb->data;
271 nlh->nlmsg_pid = 0; /* from kernel */
272 nlh->nlmsg_flags = 0;
273 nlh->nlmsg_seq = 0;
274 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
275 aniHdr = NLMSG_DATA(nlh);
276 aniHdr->type = ANI_MSG_OEM_ERROR;
277 aniHdr->length = sizeof(uint8_t);
278 nlh->nlmsg_len = NLMSG_LENGTH(sizeof(tAniMsgHdr) + aniHdr->length);
279
280 /* message body will contain one byte of error code */
281 buf = (char *)((char *)aniHdr + sizeof(tAniMsgHdr));
282 *buf = error_code;
283
284 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + aniHdr->length));
285
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700286 hdd_notice("sending oem error response to process pid (%d)", app_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800287
288 (void)nl_srv_ucast(skb, app_pid, MSG_DONTWAIT);
289
290 return;
291}
292
293/**
294 * hdd_send_oem_data_rsp_msg() - send oem data response
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700295 * @oem_data_rsp: the actual OEM Data Response message
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800296 *
297 * This function sends an OEM Data Response message to a registered
298 * application process over the netlink socket.
299 *
300 * Return: 0 for success, non zero for failure
301 */
Krishna Kumaar Natarajanc1fa17d2016-08-03 14:19:20 -0700302void hdd_send_oem_data_rsp_msg(struct oem_data_rsp *oem_data_rsp)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800303{
304 struct sk_buff *skb;
305 struct nlmsghdr *nlh;
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700306 tAniMsgHdr *ani_hdr;
307 uint8_t *oem_data;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800308
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700309 /*
310 * OEM message is always to a specific process and cannot be a broadcast
311 */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800312 if (p_hdd_ctx->oem_pid == 0) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700313 hdd_err("invalid dest pid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800314 return;
315 }
316
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700317 if (oem_data_rsp->rsp_len > OEM_DATA_RSP_SIZE) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700318 hdd_err("invalid length of Oem Data response");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800319 return;
320 }
321
322 skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + OEM_DATA_RSP_SIZE),
323 GFP_KERNEL);
324 if (skb == NULL) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700325 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800326 return;
327 }
328
329 nlh = (struct nlmsghdr *)skb->data;
330 nlh->nlmsg_pid = 0; /* from kernel */
331 nlh->nlmsg_flags = 0;
332 nlh->nlmsg_seq = 0;
333 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700334 ani_hdr = NLMSG_DATA(nlh);
335 ani_hdr->type = ANI_MSG_OEM_DATA_RSP;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800336
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700337 ani_hdr->length = oem_data_rsp->rsp_len;
338 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + ani_hdr->length));
339 oem_data = (uint8_t *) ((char *)ani_hdr + sizeof(tAniMsgHdr));
340 qdf_mem_copy(oem_data, oem_data_rsp->data, oem_data_rsp->rsp_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800341
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700342 skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + ani_hdr->length)));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800343
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700344 hdd_notice("sending Oem Data Response of len (%d) to process pid (%d)",
Krishna Kumaar Natarajan73ea9f22016-06-30 18:38:47 -0700345 oem_data_rsp->rsp_len, p_hdd_ctx->oem_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800346
347 (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
348
349 return;
350}
351
352/**
353 * oem_process_data_req_msg() - process oem data request
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700354 * @oem_data_len: Length to OEM Data buffer
355 * @oem_data: Pointer to OEM Data buffer
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800356 *
357 * This function sends oem message to SME
358 *
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530359 * Return: QDF_STATUS enumeration
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800360 */
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700361static QDF_STATUS oem_process_data_req_msg(int oem_data_len, char *oem_data)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800362{
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700363 hdd_adapter_t *adapter = NULL;
Krishna Kumaar Natarajanc1fa17d2016-08-03 14:19:20 -0700364 struct oem_data_req oem_data_req;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530365 QDF_STATUS status = QDF_STATUS_SUCCESS;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800366
367 /* for now, STA interface only */
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700368 adapter = hdd_get_adapter(p_hdd_ctx, QDF_STA_MODE);
369 if (!adapter) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700370 hdd_err("No adapter for STA mode");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530371 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800372 }
373
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700374 if (!oem_data) {
375 hdd_err("oem_data is null");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530376 return QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800377 }
378
Krishna Kumaar Natarajanc1fa17d2016-08-03 14:19:20 -0700379 qdf_mem_zero(&oem_data_req, sizeof(oem_data_req));
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800380
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700381 oem_data_req.data = qdf_mem_malloc(oem_data_len);
382 if (!oem_data_req.data) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700383 hdd_err("malloc failed for data req buffer");
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530384 return QDF_STATUS_E_NOMEM;
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -0800385 }
386
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700387 oem_data_req.data_len = oem_data_len;
388 qdf_mem_copy(oem_data_req.data, oem_data, oem_data_len);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800389
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700390 hdd_notice("calling sme_oem_data_req");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800391
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700392 status = sme_oem_data_req(p_hdd_ctx->hHal, &oem_data_req);
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -0800393
Krishna Kumaar Natarajanc5e06ac2016-06-30 16:49:19 -0700394 qdf_mem_free(oem_data_req.data);
395 oem_data_req.data = NULL;
Krishna Kumaar Natarajan9ac8efd2015-11-20 13:40:24 -0800396
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800397 return status;
398}
399
400/**
Abhishek Singh1c676222016-05-09 14:20:28 +0530401 * update_channel_bw_info() - set bandwidth info for the chan
402 * @hdd_ctx: hdd context
403 * @chan: channel for which info are required
404 * @hdd_chan_info: struct where the bandwidth info is filled
405 *
406 * This function find the maximum bandwidth allowed, secondary
407 * channel offset and center freq for the channel as per regulatory
408 * domain and using these info calculate the phy mode for the
409 * channel.
410 *
411 * Return: void
412 */
413static void hdd_update_channel_bw_info(hdd_context_t *hdd_ctx,
414 uint16_t chan, tHddChannelInfo *hdd_chan_info)
415{
416 struct ch_params_s ch_params = {0};
417 uint16_t sec_ch_2g = 0;
418 WLAN_PHY_MODE phy_mode;
419 uint32_t wni_dot11_mode;
420
421 wni_dot11_mode = sme_get_wni_dot11_mode(hdd_ctx->hHal);
422
423 /* Passing CH_WIDTH_MAX will give the max bandwidth supported */
424 ch_params.ch_width = CH_WIDTH_MAX;
425
426 cds_set_channel_params(chan, sec_ch_2g, &ch_params);
427 if (ch_params.center_freq_seg0)
428 hdd_chan_info->band_center_freq1 =
429 cds_chan_to_freq(ch_params.center_freq_seg0);
430
431 hdd_info("chan %d dot11_mode %d ch_width %d sec offset %d freq_seg0 %d",
432 chan, wni_dot11_mode, ch_params.ch_width,
433 ch_params.sec_ch_offset, hdd_chan_info->band_center_freq1);
434
435 phy_mode = wma_chan_phy_mode(chan, ch_params.ch_width, wni_dot11_mode);
436 WMI_SET_CHANNEL_MODE(hdd_chan_info, phy_mode);
437}
438
439/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800440 * oem_process_channel_info_req_msg() - process oem channel_info request
441 * @numOfChannels: number of channels
442 * @chanList: list of channel information
443 *
444 * This function responds with channel info to oem process
445 *
446 * Return: 0 for success, non zero for failure
447 */
448static int oem_process_channel_info_req_msg(int numOfChannels, char *chanList)
449{
450 struct sk_buff *skb;
451 struct nlmsghdr *nlh;
452 tAniMsgHdr *aniHdr;
453 tHddChannelInfo *pHddChanInfo;
454 tHddChannelInfo hddChanInfo;
455 uint8_t chanId;
456 uint32_t reg_info_1;
457 uint32_t reg_info_2;
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530458 QDF_STATUS status = QDF_STATUS_E_FAILURE;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800459 int i;
460 uint8_t *buf;
461
462 /* OEM message is always to a specific process and cannot be a broadcast */
463 if (p_hdd_ctx->oem_pid == 0) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700464 hdd_err("invalid dest pid");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800465 return -EPERM;
466 }
467
468 skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + sizeof(uint8_t) +
469 numOfChannels * sizeof(tHddChannelInfo)),
470 GFP_KERNEL);
471 if (skb == NULL) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700472 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800473 return -ENOMEM;
474 }
475
476 nlh = (struct nlmsghdr *)skb->data;
477 nlh->nlmsg_pid = 0; /* from kernel */
478 nlh->nlmsg_flags = 0;
479 nlh->nlmsg_seq = 0;
480 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
481 aniHdr = NLMSG_DATA(nlh);
482 aniHdr->type = ANI_MSG_CHANNEL_INFO_RSP;
483
484 aniHdr->length =
485 sizeof(uint8_t) + numOfChannels * sizeof(tHddChannelInfo);
486 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + aniHdr->length));
487
488 /* First byte of message body will have num of channels */
489 buf = (char *)((char *)aniHdr + sizeof(tAniMsgHdr));
490 *buf++ = numOfChannels;
491
492 /* Next follows channel info struct for each channel id.
493 * If chan id is wrong or SME returns failure for a channel
494 * then fill in 0 in channel info for that particular channel
495 */
496 for (i = 0; i < numOfChannels; i++) {
497 pHddChanInfo = (tHddChannelInfo *) ((char *)buf +
498 i *
499 sizeof(tHddChannelInfo));
500
501 chanId = chanList[i];
502 status = sme_get_reg_info(p_hdd_ctx->hHal, chanId,
503 &reg_info_1, &reg_info_2);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530504 if (QDF_STATUS_SUCCESS == status) {
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800505 /* copy into hdd chan info struct */
506 hddChanInfo.chan_id = chanId;
507 hddChanInfo.reserved0 = 0;
508 hddChanInfo.mhz = cds_chan_to_freq(chanId);
509 hddChanInfo.band_center_freq1 = hddChanInfo.mhz;
510 hddChanInfo.band_center_freq2 = 0;
511
512 hddChanInfo.info = 0;
513 if (CHANNEL_STATE_DFS ==
514 cds_get_channel_state(chanId))
515 WMI_SET_CHANNEL_FLAG(&hddChanInfo,
516 WMI_CHAN_FLAG_DFS);
Abhishek Singh1c676222016-05-09 14:20:28 +0530517
518 hdd_update_channel_bw_info(p_hdd_ctx,
519 chanId, &hddChanInfo);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800520 hddChanInfo.reg_info_1 = reg_info_1;
521 hddChanInfo.reg_info_2 = reg_info_2;
522 } else {
523 /* channel info is not returned, fill in zeros in channel
524 * info struct
525 */
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700526 hdd_notice("sme_get_reg_info failed for chan (%d), return info 0",
527 chanId);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800528 hddChanInfo.chan_id = chanId;
529 hddChanInfo.reserved0 = 0;
530 hddChanInfo.mhz = 0;
531 hddChanInfo.band_center_freq1 = 0;
532 hddChanInfo.band_center_freq2 = 0;
533 hddChanInfo.info = 0;
534 hddChanInfo.reg_info_1 = 0;
535 hddChanInfo.reg_info_2 = 0;
536 }
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530537 qdf_mem_copy(pHddChanInfo, &hddChanInfo,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800538 sizeof(tHddChannelInfo));
539 }
540
541 skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length)));
542
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700543 hdd_notice("sending channel info resp for num channels (%d) to pid (%d)",
544 numOfChannels, p_hdd_ctx->oem_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800545
546 (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
547
548 return 0;
549}
550
551/**
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800552 * oem_process_set_cap_req_msg() - process oem set capability request
553 * @oem_cap_len: Length of OEM capability
554 * @oem_cap: Pointer to OEM capability buffer
555 * @app_pid: process ID, to which rsp message is to be sent
556 *
557 * This function sends oem message to SME
558 *
559 * Return: error code
560 */
561static int oem_process_set_cap_req_msg(int oem_cap_len,
562 char *oem_cap, int32_t app_pid)
563{
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530564 QDF_STATUS status;
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800565 int error_code;
566 struct sk_buff *skb;
567 struct nlmsghdr *nlh;
568 tAniMsgHdr *ani_hdr;
569 uint8_t *buf;
570
571 if (!oem_cap) {
572 hdd_err("oem_cap is null");
573 return -EINVAL;
574 }
575
576 status = sme_oem_update_capability(p_hdd_ctx->hHal,
577 (struct sme_oem_capability *)oem_cap);
Anurag Chouhanfb54ab02016-02-18 18:00:46 +0530578 if (!QDF_IS_STATUS_SUCCESS(status))
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800579 hdd_err("error updating rm capability, status: %d", status);
Anurag Chouhanc5548422016-02-24 18:33:27 +0530580 error_code = qdf_status_to_os_return(status);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800581
582 skb = alloc_skb(NLMSG_SPACE(WLAN_NL_MAX_PAYLOAD), GFP_KERNEL);
583 if (skb == NULL) {
584 hdd_err("alloc_skb failed");
585 return -ENOMEM;
586 }
587
588 nlh = (struct nlmsghdr *)skb->data;
589 nlh->nlmsg_pid = 0; /* from kernel */
590 nlh->nlmsg_flags = 0;
591 nlh->nlmsg_seq = 0;
592 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
593 ani_hdr = NLMSG_DATA(nlh);
594 ani_hdr->type = ANI_MSG_SET_OEM_CAP_RSP;
595 /* 64 bit alignment */
596 ani_hdr->length = sizeof(error_code);
597 nlh->nlmsg_len = NLMSG_LENGTH(sizeof(tAniMsgHdr) + ani_hdr->length);
598
599 /* message body will contain only status code */
600 buf = (char *)((char *)ani_hdr + sizeof(tAniMsgHdr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530601 qdf_mem_copy(buf, &error_code, ani_hdr->length);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800602
603 skb_put(skb, NLMSG_SPACE(sizeof(tAniMsgHdr) + ani_hdr->length));
604
605 hdd_info("sending oem response to process pid %d", app_pid);
606
607 (void)nl_srv_ucast(skb, app_pid, MSG_DONTWAIT);
608
609 return error_code;
610}
611
612/**
613 * oem_process_get_cap_req_msg() - process oem get capability request
614 *
615 * This function process the get capability request from OEM and responds
616 * with the capability.
617 *
618 * Return: error code
619 */
620static int oem_process_get_cap_req_msg(void)
621{
622 int error_code;
623 struct oem_get_capability_rsp *cap_rsp;
624 t_iw_oem_data_cap data_cap = { {0} };
625 struct sme_oem_capability oem_cap;
626 hdd_adapter_t *adapter;
627 struct sk_buff *skb;
628 struct nlmsghdr *nlh;
629 tAniMsgHdr *ani_hdr;
630 uint8_t *buf;
631
632 /* for now, STA interface only */
Krunal Sonibe766b02016-03-10 13:00:44 -0800633 adapter = hdd_get_adapter(p_hdd_ctx, QDF_STA_MODE);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800634 if (!adapter) {
635 hdd_err("No adapter for STA mode");
636 return -EINVAL;
637 }
638
639 error_code = populate_oem_data_cap(adapter, &data_cap);
640 if (0 != error_code)
641 return error_code;
642
643 skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) + sizeof(*cap_rsp)),
644 GFP_KERNEL);
645 if (skb == NULL) {
646 hdd_err("alloc_skb failed");
647 return -ENOMEM;
648 }
649
650 nlh = (struct nlmsghdr *)skb->data;
651 nlh->nlmsg_pid = 0; /* from kernel */
652 nlh->nlmsg_flags = 0;
653 nlh->nlmsg_seq = 0;
654 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
655 ani_hdr = NLMSG_DATA(nlh);
656 ani_hdr->type = ANI_MSG_GET_OEM_CAP_RSP;
657
658 ani_hdr->length = sizeof(*cap_rsp);
659 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + ani_hdr->length));
660
661 buf = (char *)((char *)ani_hdr + sizeof(tAniMsgHdr));
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530662 qdf_mem_copy(buf, &data_cap, sizeof(data_cap));
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800663
664 buf = (char *) buf + sizeof(data_cap);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530665 qdf_mem_zero(&oem_cap, sizeof(oem_cap));
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800666 sme_oem_get_capability(p_hdd_ctx->hHal, &oem_cap);
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530667 qdf_mem_copy(buf, &oem_cap, sizeof(oem_cap));
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800668
669 skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + ani_hdr->length)));
670 hdd_info("send rsp to oem-pid:%d for get_capability",
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700671 p_hdd_ctx->oem_pid);
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800672
673 (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
674 return 0;
675}
676
677/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800678 * hdd_send_peer_status_ind_to_oem_app() -
Abhishek Singh1c676222016-05-09 14:20:28 +0530679 * Function to send peer status to a registered application
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800680 * @peerMac: MAC address of peer
681 * @peerStatus: ePeerConnected or ePeerDisconnected
682 * @peerTimingMeasCap: 0: RTT/RTT2, 1: RTT3. Default is 0
683 * @sessionId: SME session id, i.e. vdev_id
684 * @chan_info: operating channel information
Abhishek Singh1c676222016-05-09 14:20:28 +0530685 * @dev_mode: dev mode for which indication is sent
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800686 *
687 * Return: none
688 */
Anurag Chouhan6d760662016-02-20 16:05:43 +0530689void hdd_send_peer_status_ind_to_oem_app(struct qdf_mac_addr *peerMac,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800690 uint8_t peerStatus,
691 uint8_t peerTimingMeasCap,
692 uint8_t sessionId,
Abhishek Singh1c676222016-05-09 14:20:28 +0530693 tSirSmeChanInfo *chan_info,
694 enum tQDF_ADAPTER_MODE dev_mode)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800695{
696 struct sk_buff *skb;
697 struct nlmsghdr *nlh;
698 tAniMsgHdr *aniHdr;
699 tPeerStatusInfo *pPeerInfo;
700
701 if (!p_hdd_ctx || !p_hdd_ctx->hHal) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700702 hdd_err("Either HDD Ctx is null or Hal Ctx is null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800703 return;
704 }
705
706 /* check if oem app has registered and pid is valid */
707 if ((!p_hdd_ctx->oem_app_registered) || (p_hdd_ctx->oem_pid == 0)) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700708 hdd_info("OEM app is not registered(%d) or pid is invalid(%d)",
709 p_hdd_ctx->oem_app_registered,
710 p_hdd_ctx->oem_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800711 return;
712 }
713
714 skb = alloc_skb(NLMSG_SPACE(sizeof(tAniMsgHdr) +
715 sizeof(tPeerStatusInfo)),
716 GFP_KERNEL);
717 if (skb == NULL) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700718 hdd_err("alloc_skb failed");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800719 return;
720 }
721
722 nlh = (struct nlmsghdr *)skb->data;
723 nlh->nlmsg_pid = 0; /* from kernel */
724 nlh->nlmsg_flags = 0;
725 nlh->nlmsg_seq = 0;
726 nlh->nlmsg_type = WLAN_NL_MSG_OEM;
727 aniHdr = NLMSG_DATA(nlh);
728 aniHdr->type = ANI_MSG_PEER_STATUS_IND;
729
730 aniHdr->length = sizeof(tPeerStatusInfo);
731 nlh->nlmsg_len = NLMSG_LENGTH((sizeof(tAniMsgHdr) + aniHdr->length));
732
733 pPeerInfo = (tPeerStatusInfo *) ((char *)aniHdr + sizeof(tAniMsgHdr));
734
Anurag Chouhan600c3a02016-03-01 10:33:54 +0530735 qdf_mem_copy(pPeerInfo->peer_mac_addr, peerMac->bytes,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800736 sizeof(peerMac->bytes));
737 pPeerInfo->peer_status = peerStatus;
738 pPeerInfo->vdev_id = sessionId;
739 pPeerInfo->peer_capability = peerTimingMeasCap;
740 pPeerInfo->reserved0 = 0;
Abhishek Singh1c676222016-05-09 14:20:28 +0530741 /* Set 0th bit of reserved0 for STA mode */
742 if (QDF_STA_MODE == dev_mode)
743 pPeerInfo->reserved0 |= 0x01;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800744
745 if (chan_info) {
746 pPeerInfo->peer_chan_info.chan_id = chan_info->chan_id;
747 pPeerInfo->peer_chan_info.reserved0 = 0;
748 pPeerInfo->peer_chan_info.mhz = chan_info->mhz;
749 pPeerInfo->peer_chan_info.band_center_freq1 =
750 chan_info->band_center_freq1;
751 pPeerInfo->peer_chan_info.band_center_freq2 =
752 chan_info->band_center_freq2;
753 pPeerInfo->peer_chan_info.info = chan_info->info;
754 pPeerInfo->peer_chan_info.reg_info_1 = chan_info->reg_info_1;
755 pPeerInfo->peer_chan_info.reg_info_2 = chan_info->reg_info_2;
756 } else {
757 pPeerInfo->peer_chan_info.chan_id = 0;
758 pPeerInfo->peer_chan_info.reserved0 = 0;
759 pPeerInfo->peer_chan_info.mhz = 0;
760 pPeerInfo->peer_chan_info.band_center_freq1 = 0;
761 pPeerInfo->peer_chan_info.band_center_freq2 = 0;
762 pPeerInfo->peer_chan_info.info = 0;
763 pPeerInfo->peer_chan_info.reg_info_1 = 0;
764 pPeerInfo->peer_chan_info.reg_info_2 = 0;
765 }
766 skb_put(skb, NLMSG_SPACE((sizeof(tAniMsgHdr) + aniHdr->length)));
767
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700768 hdd_info("sending peer " MAC_ADDRESS_STR
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800769 " status(%d), peerTimingMeasCap(%d), vdevId(%d), chanId(%d)"
770 " to oem app pid(%d), center freq 1 (%d), center freq 2 (%d),"
771 " info (0x%x), frequency (%d),reg info 1 (0x%x),"
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700772 " reg info 2 (0x%x)",
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800773 MAC_ADDR_ARRAY(peerMac->bytes),
774 peerStatus, peerTimingMeasCap,
775 sessionId, pPeerInfo->peer_chan_info.chan_id,
776 p_hdd_ctx->oem_pid,
777 pPeerInfo->peer_chan_info.band_center_freq1,
778 pPeerInfo->peer_chan_info.band_center_freq2,
779 pPeerInfo->peer_chan_info.info,
780 pPeerInfo->peer_chan_info.mhz,
781 pPeerInfo->peer_chan_info.reg_info_1,
782 pPeerInfo->peer_chan_info.reg_info_2);
783
784 (void)nl_srv_ucast(skb, p_hdd_ctx->oem_pid, MSG_DONTWAIT);
785
786 return;
787}
788
789/*
790 * Callback function invoked by Netlink service for all netlink
791 * messages (from user space) addressed to WLAN_NL_MSG_OEM
792 */
793
794/**
795 * oem_msg_callback() - callback invoked by netlink service
796 * @skb: skb with netlink message
797 *
798 * This function gets invoked by netlink service when a message
799 * is received from user space addressed to WLAN_NL_MSG_OEM
800 *
801 * Return: zero on success
802 * On error, error number will be returned.
803 */
804static int oem_msg_callback(struct sk_buff *skb)
805{
806 struct nlmsghdr *nlh;
807 tAniMsgHdr *msg_hdr;
808 int ret;
809 char *sign_str = NULL;
810 nlh = (struct nlmsghdr *)skb->data;
811
812 if (!nlh) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700813 hdd_err("Netlink header null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800814 return -EPERM;
815 }
816
817 ret = wlan_hdd_validate_context(p_hdd_ctx);
Abhishek Singh23edd1c2016-05-05 11:56:06 +0530818 if (ret)
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800819 return ret;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800820
821 msg_hdr = NLMSG_DATA(nlh);
822
823 if (!msg_hdr) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700824 hdd_err("Message header null");
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800825 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
826 OEM_ERR_NULL_MESSAGE_HEADER);
827 return -EPERM;
828 }
829
830 if (nlh->nlmsg_len <
831 NLMSG_LENGTH(sizeof(tAniMsgHdr) + msg_hdr->length)) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700832 hdd_err("Invalid nl msg len, nlh->nlmsg_len (%d), msg_hdr->len (%d)",
833 nlh->nlmsg_len, msg_hdr->length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800834 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
835 OEM_ERR_INVALID_MESSAGE_LENGTH);
836 return -EPERM;
837 }
838
839 switch (msg_hdr->type) {
840 case ANI_MSG_APP_REG_REQ:
841 /* Registration request is only allowed for Qualcomm Application */
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700842 hdd_notice("Received App Req Req from App process pid(%d), len(%d)",
843 nlh->nlmsg_pid, msg_hdr->length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800844
845 sign_str = (char *)((char *)msg_hdr + sizeof(tAniMsgHdr));
846 if ((OEM_APP_SIGNATURE_LEN == msg_hdr->length) &&
847 (0 == strncmp(sign_str, OEM_APP_SIGNATURE_STR,
848 OEM_APP_SIGNATURE_LEN))) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700849 hdd_notice("Valid App Req Req from oem app process pid(%d)",
850 nlh->nlmsg_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800851
852 p_hdd_ctx->oem_app_registered = true;
853 p_hdd_ctx->oem_pid = nlh->nlmsg_pid;
854 send_oem_reg_rsp_nlink_msg();
855 } else {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700856 hdd_err("Invalid signature in App Reg Request from pid(%d)",
857 nlh->nlmsg_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800858 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
859 OEM_ERR_INVALID_SIGNATURE);
860 return -EPERM;
861 }
862 break;
863
864 case ANI_MSG_OEM_DATA_REQ:
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700865 hdd_notice("Received Oem Data Request length(%d) from pid: %d",
866 msg_hdr->length, nlh->nlmsg_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800867
868 if ((!p_hdd_ctx->oem_app_registered) ||
869 (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) {
870 /* either oem app is not registered yet or pid is different */
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700871 hdd_err("OEM DataReq: app not registered(%d) or incorrect pid(%d)",
872 p_hdd_ctx->oem_app_registered,
873 nlh->nlmsg_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800874 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
875 OEM_ERR_APP_NOT_REGISTERED);
876 return -EPERM;
877 }
878
879 if ((!msg_hdr->length) || (OEM_DATA_REQ_SIZE < msg_hdr->length)) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700880 hdd_err("Invalid length (%d) in Oem Data Request",
881 msg_hdr->length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800882 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
883 OEM_ERR_INVALID_MESSAGE_LENGTH);
884 return -EPERM;
885 }
886 oem_process_data_req_msg(msg_hdr->length,
887 (char *)((char *)msg_hdr +
888 sizeof(tAniMsgHdr)));
889 break;
890
891 case ANI_MSG_CHANNEL_INFO_REQ:
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700892 hdd_notice("Received channel info request, num channel(%d) from pid: %d",
893 msg_hdr->length, nlh->nlmsg_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800894
895 if ((!p_hdd_ctx->oem_app_registered) ||
896 (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) {
897 /* either oem app is not registered yet or pid is different */
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700898 hdd_err("Chan InfoReq: app not registered(%d) or incorrect pid(%d)",
899 p_hdd_ctx->oem_app_registered,
900 nlh->nlmsg_pid);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800901 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
902 OEM_ERR_APP_NOT_REGISTERED);
903 return -EPERM;
904 }
905
906 /* message length contains list of channel ids */
907 if ((!msg_hdr->length) ||
908 (WNI_CFG_VALID_CHANNEL_LIST_LEN < msg_hdr->length)) {
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700909 hdd_err("Invalid length (%d) in channel info request",
910 msg_hdr->length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800911 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
912 OEM_ERR_INVALID_MESSAGE_LENGTH);
913 return -EPERM;
914 }
915 oem_process_channel_info_req_msg(msg_hdr->length,
916 (char *)((char *)msg_hdr +
917 sizeof(tAniMsgHdr)));
918 break;
919
Krishna Kumaar Natarajan53ca2902015-12-04 14:01:46 -0800920 case ANI_MSG_SET_OEM_CAP_REQ:
921 hdd_info("Received set oem capability req of length:%d from pid: %d",
922 msg_hdr->length, nlh->nlmsg_pid);
923
924 if ((!p_hdd_ctx->oem_app_registered) ||
925 (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) {
926 /* oem app is not registered yet or pid is different */
927 hdd_err("set_oem_capability : app not registered(%d) or incorrect pid(%d)",
928 p_hdd_ctx->oem_app_registered,
929 nlh->nlmsg_pid);
930 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
931 OEM_ERR_APP_NOT_REGISTERED);
932 return -EPERM;
933 }
934
935 if ((!msg_hdr->length) ||
936 (sizeof(struct sme_oem_capability) < msg_hdr->length)) {
937 hdd_err("Invalid length (%d) in set_oem_capability",
938 msg_hdr->length);
939 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
940 OEM_ERR_INVALID_MESSAGE_LENGTH);
941 return -EPERM;
942 }
943
944 oem_process_set_cap_req_msg(msg_hdr->length,
945 (char *)((char *)msg_hdr +
946 sizeof(tAniMsgHdr)),
947 nlh->nlmsg_pid);
948 break;
949
950 case ANI_MSG_GET_OEM_CAP_REQ:
951 hdd_info("Rcvd get oem capability req of length:%d from pid: %d",
952 msg_hdr->length, nlh->nlmsg_pid);
953
954 if ((!p_hdd_ctx->oem_app_registered) ||
955 (nlh->nlmsg_pid != p_hdd_ctx->oem_pid)) {
956 /* oem app is not registered yet or pid is different */
957 hdd_err("get_oem_capability : app not registered(%d) or incorrect pid(%d)",
958 p_hdd_ctx->oem_app_registered,
959 nlh->nlmsg_pid);
960 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
961 OEM_ERR_APP_NOT_REGISTERED);
962 return -EPERM;
963 }
964
965 oem_process_get_cap_req_msg();
966 break;
967
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800968 default:
Jeff Johnsonbfa02062016-05-26 10:09:04 -0700969 hdd_err("Received Invalid message type (%d), length (%d)",
970 msg_hdr->type, msg_hdr->length);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800971 send_oem_err_rsp_nlink_msg(nlh->nlmsg_pid,
972 OEM_ERR_INVALID_MESSAGE_TYPE);
973 return -EPERM;
974 }
975 return 0;
976}
977
978static int __oem_msg_callback(struct sk_buff *skb)
979{
980 int ret;
981
982 cds_ssr_protect(__func__);
983 ret = oem_msg_callback(skb);
984 cds_ssr_unprotect(__func__);
985
986 return ret;
987}
988
989/**
990 * oem_activate_service() - Activate oem message handler
991 * @hdd_ctx: pointer to global HDD context
992 *
993 * This function registers a handler to receive netlink message from
994 * an OEM application process.
995 *
996 * Return: zero on success
997 * On error, error number will be returned.
998 */
999int oem_activate_service(struct hdd_context_s *hdd_ctx)
1000{
1001 p_hdd_ctx = hdd_ctx;
1002
1003 /* Register the msg handler for msgs addressed to WLAN_NL_MSG_OEM */
1004 return nl_srv_register(WLAN_NL_MSG_OEM, __oem_msg_callback);
1005}
1006
1007#endif