• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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