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