1 /* Copyright (c) 2014, The Linux Foundation. All rights reserved.
2 *
3 * Redistribution and use in source and binary forms, with or without
4 * modification, are permitted provided that the following conditions
5 * are met:
6 * * Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 * * Redistributions in binary form must reproduce the above copyright
9 * notice, this list of conditions and the following disclaimer in
10 * the documentation and/or other materials provided with the
11 * distribution.
12 * * Neither the name of The Linux Foundation nor the names of its
13 * contributors may be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
26 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "sync.h"
30 #define LOG_TAG "WifiHAL"
31 #include <utils/Log.h>
32 #include <time.h>
33
34 #include "ifaceeventhandler.h"
35
36 /* Used to handle NL command events from driver/firmware. */
37 IfaceEventHandlerCommand *mwifiEventHandler = NULL;
38
39 /* Set the interface event monitor handler*/
wifi_set_iface_event_handler(wifi_request_id id,wifi_interface_handle iface,wifi_event_handler eh)40 wifi_error wifi_set_iface_event_handler(wifi_request_id id,
41 wifi_interface_handle iface,
42 wifi_event_handler eh)
43 {
44 int i, numAp, ret = 0;
45 interface_info *ifaceInfo = getIfaceInfo(iface);
46 wifi_handle wifiHandle = getWifiHandle(iface);
47
48 /* Check if a similar request to set iface event handler was made earlier.
49 * Right now we don't differentiate between the case where (i) the new
50 * Request Id is different from the current one vs (ii) both new and
51 * Request Ids are the same.
52 */
53 if (mwifiEventHandler)
54 {
55 if (id == mwifiEventHandler->get_request_id()) {
56 ALOGE("%s: Iface Event Handler Set for request Id %d is still"
57 "running. Exit", __func__, id);
58 return WIFI_ERROR_TOO_MANY_REQUESTS;
59 } else {
60 ALOGE("%s: Iface Event Handler Set for a different Request "
61 "Id:%d is requested. Not supported. Exit", __func__, id);
62 return WIFI_ERROR_NOT_SUPPORTED;
63 }
64 }
65
66 mwifiEventHandler = new IfaceEventHandlerCommand(
67 wifiHandle,
68 id,
69 NL80211_CMD_REG_CHANGE);
70 if (mwifiEventHandler == NULL) {
71 ALOGE("%s: Error mwifiEventHandler NULL", __func__);
72 return WIFI_ERROR_UNKNOWN;
73 }
74 mwifiEventHandler->setCallbackHandler(eh);
75
76 cleanup:
77 return (wifi_error)ret;
78 }
79
80 /* Reset monitoring for the NL event*/
wifi_reset_iface_event_handler(wifi_request_id id,wifi_interface_handle iface)81 wifi_error wifi_reset_iface_event_handler(wifi_request_id id,
82 wifi_interface_handle iface)
83 {
84 int ret = 0;
85
86 if (mwifiEventHandler)
87 {
88 if (id == mwifiEventHandler->get_request_id()) {
89 ALOGV("Delete Object mwifiEventHandler for id = %d", id);
90 delete mwifiEventHandler;
91 mwifiEventHandler = NULL;
92 } else {
93 ALOGE("%s: Iface Event Handler Set for a different Request "
94 "Id:%d is requested. Not supported. Exit", __func__, id);
95 return WIFI_ERROR_NOT_SUPPORTED;
96 }
97 } else {
98 ALOGV("Object mwifiEventHandler for id = %d already Deleted", id);
99 }
100
101 cleanup:
102 return (wifi_error)ret;
103 }
104
105 /* This function will be the main handler for the registered incoming
106 * (from driver) Commads. Calls the appropriate callback handler after
107 * parsing the vendor data.
108 */
handleEvent(WifiEvent & event)109 int IfaceEventHandlerCommand::handleEvent(WifiEvent &event)
110 {
111 int ret = WIFI_SUCCESS;
112
113 wifiEventHandler::handleEvent(event);
114
115 switch(mSubcmd)
116 {
117 case NL80211_CMD_REG_CHANGE:
118 {
119 char code[2];
120 memset(&code[0], 0, 2);
121 if(tb[NL80211_ATTR_REG_ALPHA2])
122 {
123 memcpy(&code[0], (char *) nla_data(tb[NL80211_ATTR_REG_ALPHA2]), 2);
124 } else {
125 ALOGE("%s: NL80211_ATTR_REG_ALPHA2 not found", __func__);
126 }
127 ALOGV("Country : %c%c", code[0], code[1]);
128 if(mHandler.on_country_code_changed)
129 {
130 mHandler.on_country_code_changed(code);
131 }
132 }
133 break;
134 default:
135 ALOGV("NL Event : %d Not supported", mSubcmd);
136 }
137
138 return NL_SKIP;
139 }
140
IfaceEventHandlerCommand(wifi_handle handle,int id,u32 subcmd)141 IfaceEventHandlerCommand::IfaceEventHandlerCommand(wifi_handle handle, int id, u32 subcmd)
142 : wifiEventHandler(handle, id, subcmd)
143 {
144 ALOGV("wifiEventHandler %p constructed", this);
145 registerHandler(mSubcmd);
146 memset(&mHandler, 0, sizeof(wifi_event_handler));
147 mEventData = NULL;
148 mDataLen = 0;
149 }
150
~IfaceEventHandlerCommand()151 IfaceEventHandlerCommand::~IfaceEventHandlerCommand()
152 {
153 ALOGV("IfaceEventHandlerCommand %p destructor", this);
154 unregisterHandler(mSubcmd);
155 }
156
setCallbackHandler(wifi_event_handler nHandler)157 void IfaceEventHandlerCommand::setCallbackHandler(wifi_event_handler nHandler)
158 {
159 mHandler = nHandler;
160 }
161
get_request_id()162 int wifiEventHandler::get_request_id()
163 {
164 return mRequestId;
165 }
166
get_request_id()167 int IfaceEventHandlerCommand::get_request_id()
168 {
169 return wifiEventHandler::get_request_id();
170 }
171
wifiEventHandler(wifi_handle handle,int id,u32 subcmd)172 wifiEventHandler::wifiEventHandler(wifi_handle handle, int id, u32 subcmd)
173 : WifiCommand(handle, id)
174 {
175 mRequestId = id;
176 mSubcmd = subcmd;
177 registerHandler(mSubcmd);
178 ALOGV("wifiEventHandler %p constructed", this);
179 }
180
~wifiEventHandler()181 wifiEventHandler::~wifiEventHandler()
182 {
183 ALOGV("wifiEventHandler %p destructor", this);
184 unregisterHandler(mSubcmd);
185 }
186
handleEvent(WifiEvent & event)187 int wifiEventHandler::handleEvent(WifiEvent &event)
188 {
189 struct genlmsghdr *gnlh = event.header();
190 mSubcmd = gnlh->cmd;
191 nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
192 genlmsg_attrlen(gnlh, 0), NULL);
193 ALOGV("Got NL Event : %d from the Driver.", gnlh->cmd);
194
195 return NL_SKIP;
196 }
197
WifihalGeneric(wifi_handle handle,int id,u32 vendor_id,u32 subcmd)198 WifihalGeneric::WifihalGeneric(wifi_handle handle, int id, u32 vendor_id,
199 u32 subcmd)
200 : WifiVendorCommand(handle, id, vendor_id, subcmd)
201 {
202 /* Initialize the member data variables here */
203 mSet = 0;
204 mSetSizeMax = 0;
205 mSetSizePtr = NULL;
206 mConcurrencySet = 0;
207 filterVersion = 0;
208 filterLength = 0;
209 firmware_bus_max_size = 0;
210 }
211
~WifihalGeneric()212 WifihalGeneric::~WifihalGeneric()
213 {
214 }
215
requestResponse()216 int WifihalGeneric::requestResponse()
217 {
218 return WifiCommand::requestResponse(mMsg);
219 }
220
handleResponse(WifiEvent & reply)221 int WifihalGeneric::handleResponse(WifiEvent &reply)
222 {
223 ALOGV("Got a Wi-Fi HAL module message from Driver");
224 int i = 0;
225 u32 status;
226 WifiVendorCommand::handleResponse(reply);
227
228 // Parse the vendordata and get the attribute
229 switch(mSubcmd)
230 {
231 case QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES:
232 {
233 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX + 1];
234 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX,
235 (struct nlattr *)mVendorData,
236 mDataLen, NULL);
237
238 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET])
239 {
240 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_FEATURE_SET not found", __func__);
241 return WIFI_ERROR_INVALID_ARGS;
242 }
243 mSet = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]);
244 ALOGV("Supported feature set : %x", mSet);
245
246 break;
247 }
248 case QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX:
249 {
250 struct nlattr *tb_vendor[
251 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
252 nla_parse(tb_vendor,
253 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
254 (struct nlattr *)mVendorData,mDataLen, NULL);
255
256 if (tb_vendor[
257 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]) {
258 u32 val;
259 val = nla_get_u32(
260 tb_vendor[
261 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]);
262
263 ALOGV("%s: Num of concurrency combinations: %d",
264 __func__, val);
265 val = val > (unsigned int)mSetSizeMax ?
266 (unsigned int)mSetSizeMax : val;
267 *mSetSizePtr = val;
268
269 /* Extract the list of channels. */
270 if (*mSetSizePtr > 0 &&
271 tb_vendor[
272 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET]) {
273 nla_memcpy(mConcurrencySet,
274 tb_vendor[
275 QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET],
276 sizeof(feature_set) * (*mSetSizePtr));
277 }
278
279 ALOGV("%s: Get concurrency matrix response received.",
280 __func__);
281 ALOGV("%s: Num of concurrency combinations : %d",
282 __func__, *mSetSizePtr);
283 ALOGV("%s: List of valid concurrency combinations is: ",
284 __func__);
285 for(i = 0; i < *mSetSizePtr; i++)
286 {
287 ALOGV("%x", *(mConcurrencySet + i));
288 }
289 }
290 }
291 break;
292 case QCA_NL80211_VENDOR_SUBCMD_PACKET_FILTER:
293 {
294 struct nlattr *tb_vendor[
295 QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX + 1];
296 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_MAX,
297 (struct nlattr *)mVendorData,
298 mDataLen, NULL);
299
300 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION])
301 {
302 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION"
303 " not found", __FUNCTION__);
304 return WIFI_ERROR_INVALID_ARGS;
305 }
306 filterVersion = nla_get_u32(
307 tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_VERSION]);
308 ALOGV("Current version : %u", filterVersion);
309
310 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH])
311 {
312 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH"
313 " not found", __FUNCTION__);
314 return WIFI_ERROR_INVALID_ARGS;
315 }
316 filterLength = nla_get_u32(
317 tb_vendor[QCA_WLAN_VENDOR_ATTR_PACKET_FILTER_TOTAL_LENGTH]);
318 ALOGV("Max filter length Supported : %u", filterLength);
319
320 }
321 break;
322 case QCA_NL80211_VENDOR_SUBCMD_GET_BUS_SIZE:
323 {
324 struct nlattr *tb_vendor[
325 QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX + 1];
326 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_DRV_INFO_MAX,
327 (struct nlattr *)mVendorData, mDataLen, NULL);
328
329 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE])
330 {
331 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE"
332 " not found", __FUNCTION__);
333 return WIFI_ERROR_INVALID_ARGS;
334 }
335 firmware_bus_max_size = nla_get_u32(
336 tb_vendor[QCA_WLAN_VENDOR_ATTR_DRV_INFO_BUS_SIZE]);
337 ALOGV("Max BUS size Supported: %d", firmware_bus_max_size);
338 }
339 break;
340 default :
341 ALOGE("%s: Wrong Wi-Fi HAL event received %d", __func__, mSubcmd);
342 }
343 return NL_SKIP;
344 }
345
getResponseparams(feature_set * pset)346 void WifihalGeneric::getResponseparams(feature_set *pset)
347 {
348 *pset = mSet;
349 }
350
setMaxSetSize(int set_size_max)351 void WifihalGeneric::setMaxSetSize(int set_size_max) {
352 mSetSizeMax = set_size_max;
353 }
354
setConcurrencySet(feature_set set[])355 void WifihalGeneric::setConcurrencySet(feature_set set[]) {
356 mConcurrencySet = set;
357 }
358
setSizePtr(int * set_size)359 void WifihalGeneric::setSizePtr(int *set_size) {
360 mSetSizePtr = set_size;
361 }
362
getFilterVersion()363 int WifihalGeneric::getFilterVersion() {
364 return filterVersion;
365 }
366
getFilterLength()367 int WifihalGeneric::getFilterLength() {
368 return filterLength;
369 }
370
getBusSize()371 int WifihalGeneric::getBusSize() {
372 return firmware_bus_max_size;
373 }
374