• 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     ALOGE("Setting iface event handler, halHandle = %p", wifiHandle);
49 
50     /* Check if a similar request to set iface event handler was made earlier.
51      * Right now we don't differentiate between the case where (i) the new
52      * Request Id is different from the current one vs (ii) both new and
53      * Request Ids are the same.
54      */
55     if (mwifiEventHandler)
56     {
57         if (id == mwifiEventHandler->get_request_id()) {
58             ALOGE("%s: Iface Event Handler Set for request Id %d is still"
59                 "running. Exit", __func__, id);
60             return WIFI_ERROR_TOO_MANY_REQUESTS;
61         } else {
62             ALOGE("%s: Iface Event Handler Set for a different Request "
63                 "Id:%d is requested. Not supported. Exit", __func__, id);
64             return WIFI_ERROR_NOT_SUPPORTED;
65         }
66     }
67 
68     mwifiEventHandler = new IfaceEventHandlerCommand(
69                     wifiHandle,
70                     id,
71                     NL80211_CMD_REG_CHANGE);
72     if (mwifiEventHandler == NULL) {
73         ALOGE("%s: Error mwifiEventHandler NULL", __func__);
74         return WIFI_ERROR_UNKNOWN;
75     }
76     mwifiEventHandler->setCallbackHandler(eh);
77 
78 cleanup:
79     return (wifi_error)ret;
80 }
81 
82 /* Reset monitoring for the NL event*/
wifi_reset_iface_event_handler(wifi_request_id id,wifi_interface_handle iface)83 wifi_error wifi_reset_iface_event_handler(wifi_request_id id,
84                                           wifi_interface_handle iface)
85 {
86     int ret = 0;
87 
88     if (mwifiEventHandler)
89     {
90         if (id == mwifiEventHandler->get_request_id()) {
91             ALOGI("Delete Object mwifiEventHandler for id = %d", id);
92             delete mwifiEventHandler;
93             mwifiEventHandler = NULL;
94         } else {
95             ALOGE("%s: Iface Event Handler Set for a different Request "
96                 "Id:%d is requested. Not supported. Exit", __func__, id);
97             return WIFI_ERROR_NOT_SUPPORTED;
98         }
99     } else {
100         ALOGI("Object mwifiEventHandler for id = %d already Deleted", id);
101     }
102 
103 cleanup:
104     return (wifi_error)ret;
105 }
106 
107 /* This function will be the main handler for the registered incoming
108  * (from driver) Commads. Calls the appropriate callback handler after
109  * parsing the vendor data.
110  */
handleEvent(WifiEvent & event)111 int IfaceEventHandlerCommand::handleEvent(WifiEvent &event)
112 {
113     int ret = WIFI_SUCCESS;
114 
115     wifiEventHandler::handleEvent(event);
116 
117     switch(mSubcmd)
118     {
119         case NL80211_CMD_REG_CHANGE:
120         {
121             char code[2];
122             memset(&code[0], 0, 2);
123             if(tb[NL80211_ATTR_REG_ALPHA2])
124             {
125                 memcpy(&code[0], (char *) nla_data(tb[NL80211_ATTR_REG_ALPHA2]), 2);
126             } else {
127                 ALOGE("%s: NL80211_ATTR_REG_ALPHA2 not found", __func__);
128             }
129             ALOGI("Country : %c%c", code[0], code[1]);
130             if(mHandler.on_country_code_changed)
131             {
132                 mHandler.on_country_code_changed(code);
133             }
134         }
135         break;
136         default:
137             ALOGI("NL Event : %d Not supported", mSubcmd);
138     }
139 
140     return NL_SKIP;
141 }
142 
IfaceEventHandlerCommand(wifi_handle handle,int id,u32 subcmd)143 IfaceEventHandlerCommand::IfaceEventHandlerCommand(wifi_handle handle, int id, u32 subcmd)
144         : wifiEventHandler(handle, id, subcmd)
145 {
146     ALOGD("wifiEventHandler %p constructed", this);
147     registerHandler(mSubcmd);
148     memset(&mHandler, 0, sizeof(wifi_event_handler));
149     mEventData = NULL;
150     mDataLen = 0;
151 }
152 
~IfaceEventHandlerCommand()153 IfaceEventHandlerCommand::~IfaceEventHandlerCommand()
154 {
155     ALOGD("IfaceEventHandlerCommand %p destructor", this);
156     unregisterHandler(mSubcmd);
157 }
158 
setCallbackHandler(wifi_event_handler nHandler)159 void IfaceEventHandlerCommand::setCallbackHandler(wifi_event_handler nHandler)
160 {
161     mHandler = nHandler;
162 }
163 
get_request_id()164 int wifiEventHandler::get_request_id()
165 {
166     return mRequestId;
167 }
168 
get_request_id()169 int IfaceEventHandlerCommand::get_request_id()
170 {
171     return wifiEventHandler::get_request_id();
172 }
173 
wifiEventHandler(wifi_handle handle,int id,u32 subcmd)174 wifiEventHandler::wifiEventHandler(wifi_handle handle, int id, u32 subcmd)
175         : WifiCommand(handle, id)
176 {
177     mRequestId = id;
178     mSubcmd = subcmd;
179     registerHandler(mSubcmd);
180     ALOGD("wifiEventHandler %p constructed", this);
181 }
182 
~wifiEventHandler()183 wifiEventHandler::~wifiEventHandler()
184 {
185     ALOGD("wifiEventHandler %p destructor", this);
186     unregisterHandler(mSubcmd);
187 }
188 
handleEvent(WifiEvent & event)189 int wifiEventHandler::handleEvent(WifiEvent &event)
190 {
191     ALOGI("wifiEventHandler::handleEvent");
192     struct genlmsghdr *gnlh = event.header();
193     mSubcmd = gnlh->cmd;
194     nla_parse(tb, NL80211_ATTR_MAX, genlmsg_attrdata(gnlh, 0),
195             genlmsg_attrlen(gnlh, 0), NULL);
196     ALOGI("Got NL Event : %d from the Driver.", gnlh->cmd);
197 
198     return NL_SKIP;
199 }
200 
WifihalGeneric(wifi_handle handle,int id,u32 vendor_id,u32 subcmd)201 WifihalGeneric::WifihalGeneric(wifi_handle handle, int id, u32 vendor_id,
202                                   u32 subcmd)
203         : WifiVendorCommand(handle, id, vendor_id, subcmd)
204 {
205     ALOGD("WifihalGeneric %p constructed", this);
206     /* Initialize the member data variables here */
207     mSet = 0;
208     mSetSizeMax = 0;
209     mSetSizePtr = NULL;
210     mConcurrencySet = 0;
211 }
212 
~WifihalGeneric()213 WifihalGeneric::~WifihalGeneric()
214 {
215     ALOGD("WifihalGeneric %p destructor", this);
216 }
217 
requestResponse()218 int WifihalGeneric::requestResponse()
219 {
220     return WifiCommand::requestResponse(mMsg);
221 }
222 
handleResponse(WifiEvent & reply)223 int WifihalGeneric::handleResponse(WifiEvent &reply)
224 {
225     ALOGI("Got a Wi-Fi HAL module message from Driver");
226     int i = 0;
227     u32 status;
228     WifiVendorCommand::handleResponse(reply);
229 
230     // Parse the vendordata and get the attribute
231     switch(mSubcmd)
232     {
233         case QCA_NL80211_VENDOR_SUBCMD_GET_SUPPORTED_FEATURES:
234             {
235                 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX + 1];
236                 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_FEATURE_SET_MAX,
237                         (struct nlattr *)mVendorData,
238                         mDataLen, NULL);
239 
240                 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET])
241                 {
242                     ALOGE("%s: QCA_WLAN_VENDOR_ATTR_FEATURE_SET not found", __func__);
243                     return WIFI_ERROR_INVALID_ARGS;
244                 }
245                 mSet = nla_get_u32(tb_vendor[QCA_WLAN_VENDOR_ATTR_FEATURE_SET]);
246                 ALOGI("Supported feature set : %x", mSet);
247 
248                 break;
249             }
250         case QCA_NL80211_VENDOR_SUBCMD_GET_CONCURRENCY_MATRIX:
251             {
252                 struct nlattr *tb_vendor[
253                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX + 1];
254                 nla_parse(tb_vendor,
255                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_MAX,
256                     (struct nlattr *)mVendorData,mDataLen, NULL);
257 
258                 if (tb_vendor[
259                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]) {
260                     u32 val;
261                     val = nla_get_u32(
262                         tb_vendor[
263                     QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET_SIZE]);
264 
265                     ALOGD("%s: Num of concurrency combinations: %d",
266                         __func__, val);
267                     val = val > (unsigned int)mSetSizeMax ?
268                           (unsigned int)mSetSizeMax : val;
269                     *mSetSizePtr = val;
270 
271                     /* Extract the list of channels. */
272                     if (*mSetSizePtr > 0 &&
273                         tb_vendor[
274                         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET]) {
275                         nla_memcpy(mConcurrencySet,
276                             tb_vendor[
277                         QCA_WLAN_VENDOR_ATTR_GET_CONCURRENCY_MATRIX_RESULTS_SET],
278                             sizeof(feature_set) * (*mSetSizePtr));
279                     }
280 
281                     ALOGD("%s: Get concurrency matrix response received.",
282                         __func__);
283                     ALOGD("%s: Num of concurrency combinations : %d",
284                         __func__, *mSetSizePtr);
285                     ALOGD("%s: List of valid concurrency combinations is: ",
286                         __func__);
287                     for(i = 0; i < *mSetSizePtr; i++)
288                     {
289                         ALOGD("%x", *(mConcurrencySet + i));
290                     }
291                 }
292             }
293             break;
294         default :
295             ALOGE("%s: Wrong Wi-Fi HAL event received %d", __func__, mSubcmd);
296     }
297     return NL_SKIP;
298 }
299 
getResponseparams(feature_set * pset)300 void WifihalGeneric::getResponseparams(feature_set *pset)
301 {
302     *pset = mSet;
303 }
304 
setMaxSetSize(int set_size_max)305 void WifihalGeneric::setMaxSetSize(int set_size_max) {
306     mSetSizeMax = set_size_max;
307 }
308 
setConcurrencySet(feature_set set[])309 void WifihalGeneric::setConcurrencySet(feature_set set[]) {
310     mConcurrencySet = set;
311 }
312 
setSizePtr(int * set_size)313 void WifihalGeneric::setSizePtr(int *set_size) {
314     mSetSizePtr = set_size;
315 }
316