• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "interface.h"
18 
19 #include "log.h"
20 #include "netlink.h"
21 #include "netlinkmessage.h"
22 
23 #include <linux/rtnetlink.h>
24 
25 // Provide some arbitrary firmware and driver versions for now
26 static const char kFirmwareVersion[] = "1.0";
27 static const char kDriverVersion[] = "1.0";
28 
29 // A list of supported channels in the 2.4 GHz band, values in MHz
30 static const wifi_channel k2p4Channels[] = {
31     2412,
32     2417,
33     2422,
34     2427,
35     2432,
36     2437,
37     2442,
38     2447,
39     2452,
40     2457,
41     2462,
42     2467,
43     2472,
44     2484
45 };
46 
47 template<typename T, size_t N>
arraySize(const T (&)[N])48 constexpr size_t arraySize(const T (&)[N]) {
49     return N;
50 }
51 
Interface(Netlink & netlink,const char * name)52 Interface::Interface(Netlink& netlink, const char* name)
53     : mNetlink(netlink)
54     , mName(name)
55     , mInterfaceIndex(0) {
56 }
57 
Interface(Interface && other)58 Interface::Interface(Interface&& other) noexcept
59     : mNetlink(other.mNetlink)
60     , mName(std::move(other.mName))
61     , mInterfaceIndex(other.mInterfaceIndex) {
62 }
63 
init()64 bool Interface::init() {
65     mInterfaceIndex = if_nametoindex(mName.c_str());
66     if (mInterfaceIndex == 0) {
67         ALOGE("Unable to get interface index for %s", mName.c_str());
68         return false;
69     }
70     return true;
71 }
72 
getSupportedFeatureSet(feature_set * set)73 wifi_error Interface::getSupportedFeatureSet(feature_set* set) {
74     if (set == nullptr) {
75         return WIFI_ERROR_INVALID_ARGS;
76     }
77     *set = 0;
78     return WIFI_SUCCESS;
79 }
80 
getName(char * name,size_t size)81 wifi_error Interface::getName(char* name, size_t size) {
82     if (size < mName.size() + 1) {
83         return WIFI_ERROR_INVALID_ARGS;
84     }
85     strlcpy(name, mName.c_str(), size);
86     return WIFI_SUCCESS;
87 }
88 
89 // Wifi legacy HAL implicitly assumes getLinkStats is blocking and
90 // handler will be set to nullptr immediately after invocation.
91 // Therefore, this function will wait until onLinkStatsReply is called.
getLinkStats(wifi_request_id requestId,wifi_stats_result_handler handler)92 wifi_error Interface::getLinkStats(wifi_request_id requestId,
93                                    wifi_stats_result_handler handler) {
94     NetlinkMessage message(RTM_GETLINK, mNetlink.getSequenceNumber());
95 
96     ifinfomsg* info = message.payload<ifinfomsg>();
97     info->ifi_family = AF_UNSPEC;
98     info->ifi_type = 1;
99     info->ifi_index = mInterfaceIndex;
100     info->ifi_flags = 0;
101     info->ifi_change = 0xFFFFFFFF;
102 
103     std::condition_variable condition;
104     std::mutex mutex;
105     std::unique_lock<std::mutex> lock(mutex);
106     bool stopped = false;
107     auto callback = [this, requestId, &handler,
108         &mutex, &condition, &stopped] (const NetlinkMessage& message) {
109         stopped = true;
110         std::unique_lock<std::mutex> lock(mutex);
111         onLinkStatsReply(requestId, handler, message);
112         condition.notify_all();
113     };
114     bool success = mNetlink.sendMessage(message, callback);
115     while (!stopped) {
116         condition.wait(lock);
117     }
118     return success ? WIFI_SUCCESS : WIFI_ERROR_UNKNOWN;
119 }
120 
setLinkStats(wifi_link_layer_params)121 wifi_error Interface::setLinkStats(wifi_link_layer_params /*params*/) {
122     return WIFI_SUCCESS;
123 }
124 
setAlertHandler(wifi_request_id,wifi_alert_handler)125 wifi_error Interface::setAlertHandler(wifi_request_id /*id*/,
126                                          wifi_alert_handler /*handler*/) {
127     return WIFI_SUCCESS;
128 }
129 
resetAlertHandler(wifi_request_id)130 wifi_error Interface::resetAlertHandler(wifi_request_id /*id*/) {
131     return WIFI_SUCCESS;
132 }
133 
getFirmwareVersion(char * buffer,size_t size)134 wifi_error Interface::getFirmwareVersion(char* buffer, size_t size) {
135     if (size < sizeof(kFirmwareVersion)) {
136         return WIFI_ERROR_INVALID_ARGS;
137     }
138     strcpy(buffer, kFirmwareVersion);
139     return WIFI_SUCCESS;
140 }
141 
getDriverVersion(char * buffer,size_t size)142 wifi_error Interface::getDriverVersion(char* buffer, size_t size) {
143     if (size < sizeof(kDriverVersion)) {
144         return WIFI_ERROR_INVALID_ARGS;
145     }
146     strcpy(buffer, kDriverVersion);
147     return WIFI_SUCCESS;
148 }
149 
setScanningMacOui(oui)150 wifi_error Interface::setScanningMacOui(oui /*scan_oui*/) {
151     return WIFI_SUCCESS;
152 }
153 
clearLinkStats(u32,u32 * responseMask,u8,u8 * response)154 wifi_error Interface::clearLinkStats(u32 /*requestMask*/,
155                                      u32* responseMask,
156                                      u8 /*request*/,
157                                      u8* response) {
158     if (responseMask == nullptr || response == nullptr) {
159         return WIFI_ERROR_INVALID_ARGS;
160     }
161     return WIFI_SUCCESS;
162 }
163 
getValidChannels(int band,int maxChannels,wifi_channel * channels,int * numChannels)164 wifi_error Interface::getValidChannels(int band,
165                                        int maxChannels,
166                                        wifi_channel* channels,
167                                        int* numChannels) {
168     if (channels == nullptr || numChannels == nullptr || maxChannels < 0) {
169         return WIFI_ERROR_INVALID_ARGS;
170     }
171     switch (band) {
172         case WIFI_BAND_BG: // 2.4 GHz
173             *numChannels = std::min<int>(maxChannels,
174                                          arraySize(k2p4Channels));
175             memcpy(channels, k2p4Channels, *numChannels);
176 
177             return WIFI_SUCCESS;
178         default:
179             return WIFI_ERROR_NOT_SUPPORTED;
180     }
181 }
182 
startLogging(u32,u32,u32,u32,char *)183 wifi_error Interface::startLogging(u32 /*verboseLevel*/,
184                                    u32 /*flags*/,
185                                    u32 /*maxIntervalSec*/,
186                                    u32 /*minDataSize*/,
187                                    char* /*ringName*/) {
188     return WIFI_SUCCESS;
189 }
190 
setCountryCode(const char *)191 wifi_error Interface::setCountryCode(const char* /*countryCode*/) {
192     return WIFI_SUCCESS;
193 }
194 
setLogHandler(wifi_request_id,wifi_ring_buffer_data_handler)195 wifi_error Interface::setLogHandler(wifi_request_id /*id*/,
196                                     wifi_ring_buffer_data_handler /*handler*/) {
197     return WIFI_SUCCESS;
198 }
199 
getRingBuffersStatus(u32 * numRings,wifi_ring_buffer_status * status)200 wifi_error Interface::getRingBuffersStatus(u32* numRings,
201                                            wifi_ring_buffer_status* status) {
202     if (numRings == nullptr || status == nullptr || *numRings == 0) {
203         return WIFI_ERROR_INVALID_ARGS;
204     }
205 
206     memset(status, 0, sizeof(*status));
207     strlcpy(reinterpret_cast<char*>(status->name),
208             "ring0",
209             sizeof(status->name));
210     *numRings = 1;
211     return WIFI_SUCCESS;
212 }
213 
getLoggerSupportedFeatureSet(unsigned int * support)214 wifi_error Interface::getLoggerSupportedFeatureSet(unsigned int* support) {
215     if (support == nullptr) {
216         return WIFI_ERROR_INVALID_ARGS;
217     }
218     *support = 0;
219     return WIFI_SUCCESS;
220 }
221 
getRingData(char *)222 wifi_error Interface::getRingData(char* /*ringName*/) {
223     return WIFI_SUCCESS;
224 }
225 
configureNdOffload(u8)226 wifi_error Interface::configureNdOffload(u8 /*enable*/) {
227     return WIFI_SUCCESS;
228 }
229 
startPacketFateMonitoring()230 wifi_error Interface::startPacketFateMonitoring() {
231     return WIFI_SUCCESS;
232 }
233 
getTxPacketFates(wifi_tx_report *,size_t,size_t * numProvidedFates)234 wifi_error Interface::getTxPacketFates(wifi_tx_report* /*txReportBuffers*/,
235                                        size_t /*numRequestedFates*/,
236                                        size_t* numProvidedFates) {
237     if (numProvidedFates == nullptr) {
238         return WIFI_ERROR_INVALID_ARGS;
239     }
240     *numProvidedFates = 0;
241     return WIFI_SUCCESS;
242 }
243 
getRxPacketFates(wifi_rx_report *,size_t,size_t * numProvidedFates)244 wifi_error Interface::getRxPacketFates(wifi_rx_report* /*rxReportBuffers*/,
245                                        size_t /*numRequestedFates*/,
246                                        size_t* numProvidedFates) {
247     if (numProvidedFates == nullptr) {
248         return WIFI_ERROR_INVALID_ARGS;
249     }
250     *numProvidedFates = 0;
251     return WIFI_SUCCESS;
252 }
253 
getPacketFilterCapabilities(u32 * version,u32 * maxLength)254 wifi_error Interface::getPacketFilterCapabilities(u32* version,
255                                                   u32* maxLength) {
256     if (version == nullptr || maxLength == nullptr) {
257         return WIFI_ERROR_INVALID_ARGS;
258     }
259     *version = 0;
260     *maxLength = 0;
261     return WIFI_SUCCESS;
262 }
263 
264 wifi_error
getWakeReasonStats(WLAN_DRIVER_WAKE_REASON_CNT * wakeReasonCount)265 Interface::getWakeReasonStats(WLAN_DRIVER_WAKE_REASON_CNT* wakeReasonCount) {
266     if (wakeReasonCount == nullptr) {
267         return WIFI_ERROR_INVALID_ARGS;
268     }
269     return WIFI_SUCCESS;
270 }
271 
startSendingOffloadedPacket(wifi_request_id,u16,u8 *,u16,u8 *,u8 *,u32)272 wifi_error Interface::startSendingOffloadedPacket(wifi_request_id /*id*/,
273                                                   u16 /*ether_type*/,
274                                                   u8 * /*ip_packet*/,
275                                                   u16 /*ip_packet_len*/,
276                                                   u8 * /*src_mac_addr*/,
277                                                   u8 * /*dst_mac_addr*/,
278                                                   u32 /*period_msec*/) {
279     // Drop the packet and pretend everything is fine. Currentlty this is only
280     // used for keepalive packets to allow the CPU to go to sleep and let the
281     // hardware send keepalive packets on its own. By dropping this we lose the
282     // keepalive packets but networking will still be fine.
283     return WIFI_SUCCESS;
284 }
285 
stopSendingOffloadedPacket(wifi_request_id)286 wifi_error Interface::stopSendingOffloadedPacket(wifi_request_id /*id*/) {
287     return WIFI_SUCCESS;
288 }
289 
onLinkStatsReply(wifi_request_id requestId,wifi_stats_result_handler handler,const NetlinkMessage & message)290 void Interface::onLinkStatsReply(wifi_request_id requestId,
291                                  wifi_stats_result_handler handler,
292                                  const NetlinkMessage& message) {
293     if (message.size() < sizeof(nlmsghdr) + sizeof(ifinfomsg)) {
294         ALOGE("Invalid link stats response, too small");
295         return;
296     }
297     if (message.type() != RTM_NEWLINK) {
298         ALOGE("Recieved invalid link stats reply type: %u",
299               static_cast<unsigned int>(message.type()));
300         return;
301     }
302 
303     int numRadios = 1;
304     wifi_radio_stat radioStats;
305     memset(&radioStats, 0, sizeof(radioStats));
306 
307     wifi_iface_stat ifStats;
308     memset(&ifStats, 0, sizeof(ifStats));
309     ifStats.iface = reinterpret_cast<wifi_interface_handle>(this);
310 
311     rtnl_link_stats64 netlinkStats64;
312     rtnl_link_stats netlinkStats;
313     if (message.getAttribute(IFLA_STATS64, &netlinkStats64)) {
314         ifStats.ac[WIFI_AC_BE].tx_mpdu = netlinkStats64.tx_packets;
315         ifStats.ac[WIFI_AC_BE].rx_mpdu = netlinkStats64.rx_packets;
316     } else if (message.getAttribute(IFLA_STATS, &netlinkStats)) {
317         ifStats.ac[WIFI_AC_BE].tx_mpdu = netlinkStats.tx_packets;
318         ifStats.ac[WIFI_AC_BE].rx_mpdu = netlinkStats.rx_packets;
319     } else {
320         return;
321     }
322 
323     handler.on_link_stats_results(requestId, &ifStats, numRadios, &radioStats);
324 }
325