1 /* Copyright (c) 2015, 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 
31 #define LOG_TAG  "WifiHAL"
32 
33 #include <utils/Log.h>
34 
35 #include "wifi_hal.h"
36 #include "common.h"
37 #include "cpp_bindings.h"
38 #include "rssi_monitor.h"
39 #include "vendor_definitions.h"
40 
41 /* Used to handle rssi command events from driver/firmware.*/
42 typedef struct rssi_monitor_event_handler_s {
43     RSSIMonitorCommand* mRSSIMonitorCommandInstance;
44 } rssi_monitor_event_handlers;
45 
initializeRSSIMonitorHandler(hal_info * info)46 wifi_error initializeRSSIMonitorHandler(hal_info *info)
47 {
48     info->rssi_handlers = (rssi_monitor_event_handlers *)malloc(sizeof(
49                               rssi_monitor_event_handlers));
50     if (info->rssi_handlers) {
51         memset(info->rssi_handlers, 0, sizeof(rssi_monitor_event_handlers));
52     }
53     else {
54         ALOGE("%s: Allocation of RSSI event handlers failed",
55               __FUNCTION__);
56         return WIFI_ERROR_OUT_OF_MEMORY;
57     }
58     return WIFI_SUCCESS;
59 }
60 
cleanupRSSIMonitorHandler(hal_info * info)61 wifi_error cleanupRSSIMonitorHandler(hal_info *info)
62 {
63     rssi_monitor_event_handlers* event_handlers;
64     if (info && info->rssi_handlers) {
65         event_handlers = (rssi_monitor_event_handlers*) info->rssi_handlers;
66         if (event_handlers->mRSSIMonitorCommandInstance) {
67             delete event_handlers->mRSSIMonitorCommandInstance;
68         }
69         memset(event_handlers, 0, sizeof(rssi_monitor_event_handlers));
70         return WIFI_SUCCESS;
71     }
72     ALOGE ("%s: info or info->rssi_handlers NULL", __FUNCTION__);
73     return WIFI_ERROR_UNKNOWN;
74 }
75 
enableEventHandling()76 void RSSIMonitorCommand::enableEventHandling()
77 {
78     pthread_mutex_lock(&rm_lock);
79     mEventHandlingEnabled = true;
80     pthread_mutex_unlock(&rm_lock);
81 }
82 
disableEventHandling()83 void RSSIMonitorCommand::disableEventHandling()
84 {
85     pthread_mutex_lock(&rm_lock);
86     mEventHandlingEnabled = false;
87     pthread_mutex_unlock(&rm_lock);
88 }
89 
isEventHandlingEnabled()90 bool RSSIMonitorCommand::isEventHandlingEnabled()
91 {
92     bool eventHandlingEnabled;
93     pthread_mutex_lock(&rm_lock);
94     eventHandlingEnabled = mEventHandlingEnabled;
95     pthread_mutex_unlock(&rm_lock);
96 
97     return eventHandlingEnabled;
98 }
99 
setCallbackHandler(wifi_rssi_event_handler handler)100 void RSSIMonitorCommand::setCallbackHandler(wifi_rssi_event_handler handler)
101 {
102     mHandler = handler;
103 }
104 
RSSIMonitorCommand(wifi_handle handle,int id,u32 vendor_id,u32 subcmd)105 RSSIMonitorCommand::RSSIMonitorCommand(wifi_handle handle, int id,
106                                        u32 vendor_id, u32 subcmd)
107         : WifiVendorCommand(handle, id, vendor_id, subcmd)
108 {
109     memset(&mHandler, 0, sizeof(mHandler));
110     if (registerVendorHandler(vendor_id, subcmd)) {
111         /* Error case should not happen print log */
112         ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u",
113               __FUNCTION__, vendor_id, subcmd);
114     }
115     pthread_mutex_init(&rm_lock, NULL);
116     disableEventHandling();
117 }
118 
~RSSIMonitorCommand()119 RSSIMonitorCommand::~RSSIMonitorCommand()
120 {
121     unregisterVendorHandler(mVendor_id, mSubcmd);
122     pthread_mutex_destroy(&rm_lock);
123 }
124 
setReqId(wifi_request_id reqid)125 void RSSIMonitorCommand::setReqId(wifi_request_id reqid)
126 {
127     mId = reqid;
128 }
129 
instance(wifi_handle handle,wifi_request_id id)130 RSSIMonitorCommand* RSSIMonitorCommand::instance(wifi_handle handle,
131                                                  wifi_request_id id)
132 {
133     if (handle == NULL) {
134         ALOGE("Interface Handle is invalid");
135         return NULL;
136     }
137     hal_info *info = getHalInfo(handle);
138     if (!info || !info->rssi_handlers) {
139         ALOGE("rssi_handlers is invalid");
140         return NULL;
141     }
142 
143     RSSIMonitorCommand* mRSSIMonitorCommandInstance =
144         info->rssi_handlers->mRSSIMonitorCommandInstance;
145 
146     if (mRSSIMonitorCommandInstance == NULL) {
147         mRSSIMonitorCommandInstance = new RSSIMonitorCommand(handle, id,
148                 OUI_QCA,
149                 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI);
150         info->rssi_handlers->mRSSIMonitorCommandInstance = mRSSIMonitorCommandInstance;
151         return mRSSIMonitorCommandInstance;
152     }
153     else
154     {
155         if (handle != getWifiHandle(mRSSIMonitorCommandInstance->mInfo))
156         {
157             /* upper layer must have cleaned up the handle and reinitialized,
158                so we need to update the same */
159             ALOGV("Handle different, update the handle");
160             mRSSIMonitorCommandInstance->mInfo = (hal_info *)handle;
161         }
162         mRSSIMonitorCommandInstance->setReqId(id);
163     }
164     return mRSSIMonitorCommandInstance;
165 }
166 
167 /* This function will be the main handler for incoming event.
168  * Call the appropriate callback handler after parsing the vendor data.
169  */
handleEvent(WifiEvent & event)170 int RSSIMonitorCommand::handleEvent(WifiEvent &event)
171 {
172     int ret = WIFI_SUCCESS;
173 
174     if (isEventHandlingEnabled() == false) {
175         ALOGE("%s: RSSI monitor isn't running or already stopped. "
176               "Nothing to do. Exit", __FUNCTION__);
177         return ret;
178     }
179 
180     WifiVendorCommand::handleEvent(event);
181 
182     /* Parse the vendordata and get the attribute */
183     switch(mSubcmd)
184     {
185         case QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI:
186         {
187             mac_addr addr;
188             s8 rssi;
189             wifi_request_id reqId;
190             struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
191                                      + 1];
192             nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX,
193                     (struct nlattr *)mVendorData,
194                     mDataLen, NULL);
195 
196             memset(addr, 0, sizeof(mac_addr));
197 
198             if (!tb_vendor[
199                 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID])
200             {
201                 ALOGE("%s: ATTR_RSSI_MONITORING_REQUEST_ID not found. Exit.",
202                     __FUNCTION__);
203                 ret = WIFI_ERROR_INVALID_ARGS;
204                 break;
205             }
206             reqId = nla_get_u32(
207                     tb_vendor[QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID]
208                     );
209             /* If event has a different request_id, ignore that and use the
210              *  request_id value which we're maintaining.
211              */
212             if (reqId != id()) {
213                 ALOGV("%s: Event has Req. ID:%d <> Ours:%d, continue...",
214                     __FUNCTION__, reqId, id());
215                 reqId = id();
216             }
217             ret = get_mac_addr(tb_vendor,
218                     QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
219                     addr);
220             if (ret != WIFI_SUCCESS) {
221                 return ret;
222             }
223             ALOGV(MAC_ADDR_STR, MAC_ADDR_ARRAY(addr));
224 
225             if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI])
226             {
227                 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI"
228                       " not found", __FUNCTION__);
229                 return WIFI_ERROR_INVALID_ARGS;
230             }
231             rssi = get_s8(tb_vendor[
232                         QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI]);
233             ALOGV("Current RSSI : %d ", rssi);
234 
235             if (mHandler.on_rssi_threshold_breached)
236                 (*mHandler.on_rssi_threshold_breached)(reqId, addr, rssi);
237             else
238                 ALOGE("RSSI Monitoring: No Callback registered: ");
239         }
240         break;
241 
242         default:
243             /* Error case should not happen print log */
244             ALOGE("%s: Wrong subcmd received %d", __FUNCTION__, mSubcmd);
245     }
246 
247     return ret;
248 }
249 
wifi_start_rssi_monitoring(wifi_request_id id,wifi_interface_handle iface,s8 max_rssi,s8 min_rssi,wifi_rssi_event_handler eh)250 wifi_error wifi_start_rssi_monitoring(wifi_request_id id,
251                                       wifi_interface_handle iface,
252                                       s8 max_rssi,
253                                       s8 min_rssi,
254                                       wifi_rssi_event_handler eh)
255 {
256     int ret = WIFI_SUCCESS;
257     struct nlattr *nlData;
258     WifiVendorCommand *vCommand = NULL;
259     wifi_handle wifiHandle = getWifiHandle(iface);
260     RSSIMonitorCommand *rssiCommand;
261 
262     ret = initialize_vendor_cmd(iface, id,
263                                 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
264                                 &vCommand);
265     if (ret != WIFI_SUCCESS) {
266         ALOGE("%s: Initialization failed", __FUNCTION__);
267         return (wifi_error)ret;
268     }
269 
270     ALOGV("%s: Max RSSI:%d Min RSSI:%d", __FUNCTION__,
271           max_rssi, min_rssi);
272     /* Add the vendor specific attributes for the NL command. */
273     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
274     if (!nlData)
275         goto cleanup;
276 
277     if (vCommand->put_u32(
278             QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL,
279             QCA_WLAN_RSSI_MONITORING_START) ||
280         vCommand->put_u32(
281             QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
282             id) ||
283         vCommand->put_s8(
284             QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI,
285             max_rssi) ||
286         vCommand->put_s8(
287             QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI,
288             min_rssi))
289     {
290         goto cleanup;
291     }
292 
293     vCommand->attr_end(nlData);
294 
295     rssiCommand = RSSIMonitorCommand::instance(wifiHandle, id);
296     if (rssiCommand == NULL) {
297         ALOGE("%s: Error rssiCommand NULL", __FUNCTION__);
298         return WIFI_ERROR_OUT_OF_MEMORY;
299     }
300 
301     rssiCommand->setCallbackHandler(eh);
302 
303     ret = vCommand->requestResponse();
304     if (ret < 0)
305         goto cleanup;
306 
307     rssiCommand->enableEventHandling();
308 
309 cleanup:
310     delete vCommand;
311     return (wifi_error)ret;
312 }
313 
wifi_stop_rssi_monitoring(wifi_request_id id,wifi_interface_handle iface)314 wifi_error wifi_stop_rssi_monitoring(wifi_request_id id,
315                                      wifi_interface_handle iface)
316 {
317     int ret = WIFI_SUCCESS;
318     struct nlattr *nlData;
319     WifiVendorCommand *vCommand = NULL;
320     wifi_handle wifiHandle = getWifiHandle(iface);
321     RSSIMonitorCommand *rssiCommand;
322     rssi_monitor_event_handlers* event_handlers;
323     hal_info *info = getHalInfo(wifiHandle);
324 
325     event_handlers = (rssi_monitor_event_handlers*)info->rssi_handlers;
326     rssiCommand = event_handlers->mRSSIMonitorCommandInstance;
327 
328     if (rssiCommand == NULL ||
329         rssiCommand->isEventHandlingEnabled() == false) {
330         ALOGE("%s: RSSI monitor isn't running or already stopped. "
331             "Nothing to do. Exit", __FUNCTION__);
332         return WIFI_ERROR_NOT_AVAILABLE;
333     }
334 
335     ret = initialize_vendor_cmd(iface, id,
336                                 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
337                                 &vCommand);
338     if (ret != WIFI_SUCCESS) {
339         ALOGE("%s: Initialization failed", __FUNCTION__);
340         return (wifi_error)ret;
341     }
342 
343     /* Add the vendor specific attributes for the NL command. */
344     nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
345     if (!nlData)
346         goto cleanup;
347 
348     if (vCommand->put_u32(
349             QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL,
350             QCA_WLAN_RSSI_MONITORING_STOP) ||
351         vCommand->put_u32(
352             QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
353             id))
354     {
355         goto cleanup;
356     }
357 
358     vCommand->attr_end(nlData);
359 
360     ret = vCommand->requestResponse();
361     if (ret < 0)
362         goto cleanup;
363 
364     rssiCommand->disableEventHandling();
365 
366 
367 cleanup:
368     delete vCommand;
369     return (wifi_error)ret;
370 }
371