blob: 4fff12bd158df739fa5551d162cca93c0803ac0f [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
2 * Copyright (c) 2012-2015 The Linux Foundation. All rights reserved.
3 *
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 * DOC: wlan_hdd_nan.c
24 *
25 * WLAN Host Device Driver NAN API implementation
26 */
27
28#include <linux/version.h>
29#include <linux/module.h>
30#include <linux/kernel.h>
31#include <net/cfg80211.h>
32#include <ani_global.h>
33#include "sme_api.h"
34#include "nan_api.h"
35#include "wlan_hdd_main.h"
36#include "wlan_hdd_nan.h"
37
38/**
39 * __wlan_hdd_cfg80211_nan_request() - cfg80211 NAN request handler
40 * @wiphy: driver's wiphy struct
41 * @wdev: wireless device to which the request is targeted
42 * @data: actual request data (netlink-encapsulated)
43 * @data_len: length of @data
44 *
45 * This is called when userspace needs to send a nan request to
46 * firmware. The wlan host driver simply de-encapsulates the
47 * request from the netlink payload and then forwards it to
48 * firmware via SME.
49 *
50 * Return: 0 on success, negative errno on failure
51 */
52static int __wlan_hdd_cfg80211_nan_request(struct wiphy *wiphy,
53 struct wireless_dev *wdev,
54 const void *data,
55 int data_len)
56{
57 tNanRequestReq nan_req;
58 CDF_STATUS status;
59 int ret_val;
60 hdd_context_t *hdd_ctx = wiphy_priv(wiphy);
61
62 ENTER();
63
64 ret_val = wlan_hdd_validate_context(hdd_ctx);
65 if (ret_val)
66 return ret_val;
67
68 if (CDF_FTM_MODE == hdd_get_conparam()) {
69 hdd_err("Command not allowed in FTM mode");
70 return -EPERM;
71 }
72
73 if (!hdd_ctx->config->enable_nan_support) {
74 hdd_err("NaN support is not enabled in INI");
75 return -EPERM;
76 }
77
78 nan_req.request_data_len = data_len;
79 nan_req.request_data = data;
80
81 status = sme_nan_request(&nan_req);
82 if (CDF_STATUS_SUCCESS != status) {
83 ret_val = -EINVAL;
84 }
85 return ret_val;
86}
87
88/**
89 * wlan_hdd_cfg80211_nan_request() - handle NAN request
90 * @wiphy: pointer to wireless wiphy structure.
91 * @wdev: pointer to wireless_dev structure.
92 * @data: Pointer to the data to be passed via vendor interface
93 * @data_len:Length of the data to be passed
94 *
95 * This function is called by userspace to send a NAN request to
96 * firmware. This is an SSR-protected wrapper function.
97 *
98 * Return: 0 on success, negative errno on failure
99 */
100int wlan_hdd_cfg80211_nan_request(struct wiphy *wiphy,
101 struct wireless_dev *wdev,
102 const void *data,
103 int data_len)
104
105{
106 int ret;
107
108 cds_ssr_protect(__func__);
109 ret = __wlan_hdd_cfg80211_nan_request(wiphy, wdev, data, data_len);
110 cds_ssr_unprotect(__func__);
111
112 return ret;
113}
114
115/**
116 * wlan_hdd_cfg80211_nan_callback() - cfg80211 NAN event handler
117 * @ctx: global HDD context
118 * @msg: NAN event message
119 *
120 * This is a callback function and it gets called when we need to report
121 * a nan event to userspace. The wlan host driver simply encapsulates the
122 * event into a netlink payload and then forwards it to userspace via a
123 * cfg80211 vendor event.
124 *
125 * Return: nothing
126 */
127static void wlan_hdd_cfg80211_nan_callback(void *ctx, tSirNanEvent *msg)
128{
129 hdd_context_t *hdd_ctx = ctx;
130 struct sk_buff *vendor_event;
131 int status;
132
133 if (NULL == msg) {
134 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
135 FL("msg received here is null"));
136 return;
137 }
138
139 status = wlan_hdd_validate_context(hdd_ctx);
140 if (0 != status) {
141 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
142 FL("HDD context is not valid"));
143 return;
144 }
145
146 vendor_event =
147 cfg80211_vendor_event_alloc(hdd_ctx->wiphy,
148 NULL,
149 msg->event_data_len + NLMSG_HDRLEN,
150 QCA_NL80211_VENDOR_SUBCMD_NAN_INDEX,
151 GFP_KERNEL);
152
153 if (!vendor_event) {
154 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
155 FL("cfg80211_vendor_event_alloc failed"));
156 return;
157 }
158 if (nla_put(vendor_event, QCA_WLAN_VENDOR_ATTR_NAN,
159 msg->event_data_len, msg->event_data)) {
160 CDF_TRACE(CDF_MODULE_ID_HDD, CDF_TRACE_LEVEL_ERROR,
161 FL("QCA_WLAN_VENDOR_ATTR_NAN put fail"));
162 kfree_skb(vendor_event);
163 return;
164 }
165 cfg80211_vendor_event(vendor_event, GFP_KERNEL);
166}
167
168/**
169 * wlan_hdd_nan_is_supported() - HDD NAN support query function
170 *
171 * This function is called to determine if NAN is supported by the
172 * driver and by the firmware.
173 *
174 * Return: true if NAN is supported by the driver and firmware
175 */
176bool wlan_hdd_nan_is_supported(void)
177{
178 return sme_is_feature_supported_by_fw(NAN);
179}
180
181/**
182 * wlan_hdd_nan_init() - HDD NAN initialization function
183 * @hdd_ctx: Global HDD context
184 *
185 * This function is called to initialize the HDD NAN feature. Currently
186 * the only operation required is to register a callback with SME.
187 *
188 * Return: void
189 */
190void wlan_hdd_nan_init(hdd_context_t *hdd_ctx)
191{
192 sme_nan_register_callback(hdd_ctx->hHal,
193 wlan_hdd_cfg80211_nan_callback);
194}