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 "qca-vendor.h"
40 #include "vendor_definitions.h"
41
42 //Singleton Static Instance
43 RSSIMonitorCommand* RSSIMonitorCommand::mRSSIMonitorCommandInstance = NULL;
44
RSSIMonitorCommand(wifi_handle handle,int id,u32 vendor_id,u32 subcmd)45 RSSIMonitorCommand::RSSIMonitorCommand(wifi_handle handle, int id,
46 u32 vendor_id, u32 subcmd)
47 : WifiVendorCommand(handle, id, vendor_id, subcmd)
48 {
49 mRSSIMonitorCommandInstance = NULL;
50 memset(&mHandler, 0, sizeof(mHandler));
51 }
52
~RSSIMonitorCommand()53 RSSIMonitorCommand::~RSSIMonitorCommand()
54 {
55 mRSSIMonitorCommandInstance = NULL;
56 }
57
setReqId(wifi_request_id reqid)58 void RSSIMonitorCommand::setReqId(wifi_request_id reqid)
59 {
60 mId = reqid;
61 }
62
instance(wifi_handle handle,wifi_request_id id)63 RSSIMonitorCommand* RSSIMonitorCommand::instance(wifi_handle handle,
64 wifi_request_id id)
65 {
66 if (handle == NULL) {
67 ALOGE("Interface Handle is invalid");
68 return NULL;
69 }
70 if (mRSSIMonitorCommandInstance == NULL) {
71 mRSSIMonitorCommandInstance = new RSSIMonitorCommand(handle, id,
72 OUI_QCA,
73 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI);
74 return mRSSIMonitorCommandInstance;
75 }
76 else
77 {
78 if (handle != getWifiHandle(mRSSIMonitorCommandInstance->mInfo))
79 {
80 /* upper layer must have cleaned up the handle and reinitialized,
81 so we need to update the same */
82 ALOGV("Handle different, update the handle");
83 mRSSIMonitorCommandInstance->mInfo = (hal_info *)handle;
84 }
85 mRSSIMonitorCommandInstance->setReqId(id);
86 }
87 return mRSSIMonitorCommandInstance;
88 }
89
90 /* This function will be the main handler for incoming event.
91 * Call the appropriate callback handler after parsing the vendor data.
92 */
handleEvent(WifiEvent & event)93 int RSSIMonitorCommand::handleEvent(WifiEvent &event)
94 {
95 int ret = WIFI_SUCCESS;
96 WifiVendorCommand::handleEvent(event);
97
98 /* Parse the vendordata and get the attribute */
99 switch(mSubcmd)
100 {
101 case QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI:
102 {
103 mac_addr addr;
104 s8 rssi;
105 wifi_request_id reqId;
106 struct nlattr *tb_vendor[QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX
107 + 1];
108 nla_parse(tb_vendor, QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX,
109 (struct nlattr *)mVendorData,
110 mDataLen, NULL);
111
112 memset(addr, 0, sizeof(mac_addr));
113
114 if (!tb_vendor[
115 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID])
116 {
117 ALOGE("%s: ATTR_RSSI_MONITORING_REQUEST_ID not found. Exit.",
118 __FUNCTION__);
119 ret = WIFI_ERROR_INVALID_ARGS;
120 break;
121 }
122 reqId = nla_get_u32(
123 tb_vendor[QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID]
124 );
125 /* If event has a different request_id, ignore that and use the
126 * request_id value which we're maintaining.
127 */
128 if (reqId != id()) {
129 ALOGV("%s: Event has Req. ID:%d <> Ours:%d, continue...",
130 __FUNCTION__, reqId, id());
131 reqId = id();
132 }
133 ret = get_mac_addr(tb_vendor,
134 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_BSSID,
135 addr);
136 if (ret != WIFI_SUCCESS) {
137 return ret;
138 }
139 ALOGV(MAC_ADDR_STR, MAC_ADDR_ARRAY(addr));
140
141 if (!tb_vendor[QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI])
142 {
143 ALOGE("%s: QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI"
144 " not found", __FUNCTION__);
145 return WIFI_ERROR_INVALID_ARGS;
146 }
147 rssi = get_s8(tb_vendor[
148 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CUR_RSSI]);
149 ALOGV("Current RSSI : %d ", rssi);
150
151 if (mHandler.on_rssi_threshold_breached)
152 (*mHandler.on_rssi_threshold_breached)(reqId, addr, rssi);
153 else
154 ALOGE("RSSI Monitoring: No Callback registered: ");
155 }
156 break;
157
158 default:
159 /* Error case should not happen print log */
160 ALOGE("%s: Wrong subcmd received %d", __FUNCTION__, mSubcmd);
161 }
162
163 return NL_SKIP;
164 }
165
setCallbackHandler(wifi_rssi_event_handler nHandler,u32 event)166 int RSSIMonitorCommand::setCallbackHandler(wifi_rssi_event_handler nHandler,
167 u32 event)
168 {
169 int ret;
170 mHandler = nHandler;
171 ret = registerVendorHandler(mVendor_id, event);
172 if (ret != 0) {
173 /* Error case should not happen print log */
174 ALOGE("%s: Unable to register Vendor Handler Vendor Id=0x%x subcmd=%u",
175 __FUNCTION__, mVendor_id, mSubcmd);
176 }
177 return ret;
178 }
179
unregisterHandler(u32 subCmd)180 wifi_error RSSIMonitorCommand::unregisterHandler(u32 subCmd)
181 {
182 unregisterVendorHandler(mVendor_id, subCmd);
183 return WIFI_SUCCESS;
184 }
185
wifi_start_rssi_monitoring(wifi_request_id id,wifi_interface_handle iface,s8 max_rssi,s8 min_rssi,wifi_rssi_event_handler eh)186 wifi_error wifi_start_rssi_monitoring(wifi_request_id id,
187 wifi_interface_handle iface,
188 s8 max_rssi,
189 s8 min_rssi,
190 wifi_rssi_event_handler eh)
191 {
192 int ret = WIFI_SUCCESS;
193 struct nlattr *nlData;
194 WifiVendorCommand *vCommand = NULL;
195 wifi_handle wifiHandle = getWifiHandle(iface);
196 RSSIMonitorCommand *rssiCommand;
197
198 ret = initialize_vendor_cmd(iface, id,
199 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
200 &vCommand);
201 if (ret != WIFI_SUCCESS) {
202 ALOGE("%s: Initialization failed", __FUNCTION__);
203 return (wifi_error)ret;
204 }
205
206 ALOGV("%s: Max RSSI:%d Min RSSI:%d", __FUNCTION__,
207 max_rssi, min_rssi);
208 /* Add the vendor specific attributes for the NL command. */
209 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
210 if (!nlData)
211 goto cleanup;
212
213 if (vCommand->put_u32(
214 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL,
215 QCA_WLAN_RSSI_MONITORING_START) ||
216 vCommand->put_u32(
217 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
218 id) ||
219 vCommand->put_s8(
220 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MAX_RSSI,
221 max_rssi) ||
222 vCommand->put_s8(
223 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_MIN_RSSI,
224 min_rssi))
225 {
226 goto cleanup;
227 }
228
229 vCommand->attr_end(nlData);
230
231 rssiCommand = RSSIMonitorCommand::instance(wifiHandle, id);
232 if (rssiCommand == NULL) {
233 ALOGE("%s: Error rssiCommand NULL", __FUNCTION__);
234 return WIFI_ERROR_OUT_OF_MEMORY;
235 }
236
237 ret = rssiCommand->setCallbackHandler(eh,
238 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI);
239 if (ret < 0)
240 goto cleanup;
241
242 ret = vCommand->requestResponse();
243 if (ret < 0)
244 goto cleanup;
245
246 cleanup:
247 delete vCommand;
248 return (wifi_error)ret;
249 }
250
wifi_stop_rssi_monitoring(wifi_request_id id,wifi_interface_handle iface)251 wifi_error wifi_stop_rssi_monitoring(wifi_request_id id,
252 wifi_interface_handle iface)
253 {
254 int ret = WIFI_SUCCESS;
255 struct nlattr *nlData;
256 WifiVendorCommand *vCommand = NULL;
257 wifi_handle wifiHandle = getWifiHandle(iface);
258 RSSIMonitorCommand *rssiCommand;
259
260 ret = initialize_vendor_cmd(iface, id,
261 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI,
262 &vCommand);
263 if (ret != WIFI_SUCCESS) {
264 ALOGE("%s: Initialization failed", __FUNCTION__);
265 return (wifi_error)ret;
266 }
267
268 /* Add the vendor specific attributes for the NL command. */
269 nlData = vCommand->attr_start(NL80211_ATTR_VENDOR_DATA);
270 if (!nlData)
271 goto cleanup;
272
273 if (vCommand->put_u32(
274 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_CONTROL,
275 QCA_WLAN_RSSI_MONITORING_STOP) ||
276 vCommand->put_u32(
277 QCA_WLAN_VENDOR_ATTR_RSSI_MONITORING_REQUEST_ID,
278 id))
279 {
280 goto cleanup;
281 }
282
283 vCommand->attr_end(nlData);
284
285 ret = vCommand->requestResponse();
286 if (ret < 0)
287 goto cleanup;
288
289 rssiCommand = RSSIMonitorCommand::instance(wifiHandle, id);
290 if (rssiCommand == NULL) {
291 ALOGE("%s: Error rssiCommand NULL", __FUNCTION__);
292 ret = WIFI_ERROR_OUT_OF_MEMORY;
293 goto cleanup;
294 }
295
296 ret = rssiCommand->unregisterHandler(
297 QCA_NL80211_VENDOR_SUBCMD_MONITOR_RSSI);
298 if (ret != WIFI_SUCCESS)
299 goto cleanup;
300
301 delete rssiCommand;
302
303 cleanup:
304 delete vCommand;
305 return (wifi_error)ret;
306 }
307