Home | History | Annotate | Download | only in wifi
      1 //
      2 //  Copyright (C) 2016 Google, Inc.
      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 #include <rapidjson/document.h>
     17 #include <rapidjson/writer.h>
     18 #include <rapidjson/stringbuffer.h>
     19 #include <net/if.h>
     20 #include <sys/ioctl.h>
     21 #include <sys/socket.h>
     22 
     23 #include <base.h>
     24 #include <base/at_exit.h>
     25 #include <base/command_line.h>
     26 #include <base/logging.h>
     27 #include <base/macros.h>
     28 #include <base/strings/string_split.h>
     29 #include <base/strings/string_util.h>
     30 #include <utils/command_receiver.h>
     31 #include <utils/common_utils.h>
     32 #include <wifi_hal.h>
     33 #include <wifi_hal_stub.h>
     34 
     35 #include "wifi_facade.h"
     36 
     37 const char kWlanInterface[] = "wlan0";
     38 const char kP2pInterface[] = "p2p0";
     39 
     40 std::tuple<bool, int> WifiFacade::WifiInit() {
     41   if (!WifiStartHal()) {
     42     return std::make_tuple(false, sl4n_error_codes::kFailInt);
     43   }
     44 
     45   if (!WifiGetInterfaces() || wlan0_index == -1) {
     46     return std::make_tuple(false, sl4n_error_codes::kFailInt);
     47   }
     48 
     49   return std::make_tuple(true, sl4n_error_codes::kPassInt);
     50 }
     51 
     52 bool WifiFacade::WifiStartHal() {
     53   if (wifi_hal_handle == NULL) {
     54     if (init_wifi_stub_hal_func_table(&hal_fn) != 0) {
     55       LOG(ERROR) << sl4n::kTagStr
     56           << ": Can not initialize the basic function pointer table";
     57       return false;
     58     }
     59 
     60     wifi_error res = init_wifi_vendor_hal_func_table(&hal_fn);
     61     if (res != WIFI_SUCCESS) {
     62       LOG(ERROR) << sl4n::kTagStr
     63           << ": Can not initialize the vendor function pointer table";
     64       return false;
     65     }
     66 
     67     int ret = BringInterfaceUpDown(kWlanInterface, 1);
     68     if (ret != 0) {
     69       return false;
     70     }
     71 
     72     res = hal_fn.wifi_initialize(&wifi_hal_handle);
     73     return res == WIFI_SUCCESS;
     74   } else {
     75     return BringInterfaceUpDown(kWlanInterface, 1) == 0;
     76   }
     77 }
     78 
     79 bool WifiFacade::WifiGetInterfaces() {
     80   int num_ifaces;
     81   int result = hal_fn.wifi_get_ifaces(wifi_hal_handle, &num_ifaces,
     82                                       &wifi_iface_handles);
     83   if (result < 0) {
     84     LOG(ERROR) << sl4n::kTagStr << ": Can not get Wi-Fi interfaces";
     85     return false;
     86   }
     87 
     88   if (num_ifaces < 0) {
     89     LOG(ERROR) << sl4n::kTagStr << ": Negative number of interfaces";
     90     return false;
     91   }
     92 
     93   if (wifi_iface_handles == NULL) {
     94     LOG(ERROR) << sl4n::kTagStr
     95         << "wifi_get_ifaces returned null interface array";
     96     return false;
     97   }
     98 
     99   if (num_ifaces > 8) {
    100     LOG(ERROR) << sl4n::kTagStr
    101         << "wifi_get_ifaces returned too many interfaces";
    102     return false;
    103   }
    104 
    105   char buf[128];
    106   for (int i = 0; i < num_ifaces; ++i) {
    107     int result = hal_fn.wifi_get_iface_name(wifi_iface_handles[i], buf,
    108                                             sizeof(buf));
    109     if (result < 0) {
    110       LOG(ERROR) << sl4n::kTagStr
    111           << "Can't obtain interface name for interface #" << i;
    112       continue;
    113     }
    114     if (!strcmp(buf, kWlanInterface)) {
    115       wlan0_index = i;
    116     } else if (!strcmp(buf, kP2pInterface)) {
    117       p2p0_index = i;
    118     }
    119   }
    120 
    121   return true;
    122 }
    123 
    124 bool WifiFacade::SharedValidator() {
    125   if (wifi_hal_handle == NULL) {
    126     LOG(ERROR) << sl4n::kTagStr << "HAL handle not initialized";
    127     return false;
    128   }
    129 
    130   if (wifi_iface_handles == NULL) {
    131     LOG(ERROR) << sl4n::kTagStr << "HAL interfaces not initialized";
    132     return false;
    133   }
    134 
    135   if (wlan0_index == -1) {
    136     LOG(ERROR) << sl4n::kTagStr << kWlanInterface << " interface not found";
    137     return false;
    138   }
    139 
    140   return true;
    141 }
    142 
    143 std::tuple<int, int> WifiFacade::WifiGetSupportedFeatureSet() {
    144   if (!SharedValidator()) {
    145     return std::make_tuple(0, sl4n_error_codes::kFailInt);
    146   }
    147 
    148   feature_set set = 0;
    149   int result = hal_fn.wifi_get_supported_feature_set(
    150       wifi_iface_handles[wlan0_index], &set);
    151   if (result == WIFI_SUCCESS) {
    152     return std::make_tuple(set, sl4n_error_codes::kPassInt);
    153   } else {
    154     return std::make_tuple(0, sl4n_error_codes::kFailInt);
    155   }
    156 }
    157 
    158 // TODO: copy of set_iface_flags from Wi-Fi JNI. Consolidate into a support
    159 // library.
    160 int WifiFacade::BringInterfaceUpDown(const char *ifname, int dev_up) {
    161   struct ifreq ifr;
    162   int ret;
    163   int sock = socket(PF_INET, SOCK_DGRAM, 0);
    164   if (sock < 0) {
    165     LOG(ERROR) << "Bad socket: " << sock;
    166     return -errno;
    167   }
    168 
    169   memset(&ifr, 0, sizeof(ifr));
    170   strlcpy(ifr.ifr_name, ifname, IFNAMSIZ);
    171 
    172   if (ioctl(sock, SIOCGIFFLAGS, &ifr) != 0) {
    173     ret = errno ? -errno : -999;
    174     LOG(ERROR) << "Could not read interface " << ifname << " flags: " << errno;
    175     close(sock);
    176     return ret;
    177   }
    178 
    179   if (dev_up) {
    180     if (ifr.ifr_flags & IFF_UP) {
    181       close(sock);
    182       return 0;
    183     }
    184     ifr.ifr_flags |= IFF_UP;
    185   } else {
    186     if (!(ifr.ifr_flags & IFF_UP)) {
    187       close(sock);
    188       return 0;
    189     }
    190     ifr.ifr_flags &= ~IFF_UP;
    191   }
    192 
    193   if (ioctl(sock, SIOCSIFFLAGS, &ifr) != 0) {
    194     LOG(ERROR) << "Could not set interface " << ifname << " flags: " << errno;
    195     ret = errno ? -errno : -999;
    196     close(sock);
    197     return ret;
    198   }
    199   close(sock);
    200   return 0;
    201 }
    202 
    203 //////////////////
    204 // wrappers
    205 /////////////////
    206 
    207 static WifiFacade facade;  // triggers registration with CommandReceiver
    208 
    209 void wifi_init_wrapper(rapidjson::Document &doc) {
    210   int expected_param_size = 0;
    211   if (!CommonUtils::IsParamLengthMatching(doc, expected_param_size)) {
    212     return;
    213   }
    214   bool result;
    215   int error_code;
    216   std::tie(result, error_code) = facade.WifiInit();
    217   if (error_code == sl4n_error_codes::kFailInt) {
    218     doc.AddMember(sl4n::kResultStr, false, doc.GetAllocator());
    219     doc.AddMember(sl4n::kErrorStr, sl4n::kFailStr, doc.GetAllocator());
    220   } else {
    221     doc.AddMember(sl4n::kResultStr, result, doc.GetAllocator());
    222     doc.AddMember(sl4n::kErrorStr, NULL, doc.GetAllocator());
    223   }
    224 }
    225 
    226 void wifi_get_supported_feature_set_wrapper(rapidjson::Document &doc) {
    227   int expected_param_size = 0;
    228   if (!CommonUtils::IsParamLengthMatching(doc, expected_param_size)) {
    229     return;
    230   }
    231   int result;
    232   int error_code;
    233   std::tie(result, error_code) = facade.WifiGetSupportedFeatureSet();
    234   if (error_code == sl4n_error_codes::kFailInt) {
    235     doc.AddMember(sl4n::kResultStr, false, doc.GetAllocator());
    236     doc.AddMember(sl4n::kErrorStr, sl4n::kFailStr, doc.GetAllocator());
    237   } else {
    238     doc.AddMember(sl4n::kResultStr, result, doc.GetAllocator());
    239     doc.AddMember(sl4n::kErrorStr, NULL, doc.GetAllocator());
    240   }
    241 }
    242 
    243 ////////////////
    244 // constructor
    245 ////////////////
    246 
    247 WifiFacade::WifiFacade() {
    248   wifi_hal_handle = NULL;
    249   wifi_iface_handles = NULL;
    250   num_wifi_iface_handles = 0;
    251   wlan0_index = -1;
    252   p2p0_index = -1;
    253 
    254   CommandReceiver::RegisterCommand("WifiInit", &wifi_init_wrapper);
    255   CommandReceiver::RegisterCommand("WifiGetSupportedFeatureSet",
    256                                    &wifi_get_supported_feature_set_wrapper);
    257 }
    258