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 <hardware_legacy/wifi_hal.h>
33#include <wifi_system/hal_tool.h>
34#include <wifi_system/interface_tool.h>
35
36#include "wifi_facade.h"
37
38const char kWlanInterface[] = "wlan0";
39const char kP2pInterface[] = "p2p0";
40
41std::tuple<bool, int> WifiFacade::WifiInit() {
42  if (!WifiStartHal()) {
43    return std::make_tuple(false, sl4n_error_codes::kFailInt);
44  }
45
46  if (!WifiGetInterfaces() || wlan0_index == -1) {
47    return std::make_tuple(false, sl4n_error_codes::kFailInt);
48  }
49
50  return std::make_tuple(true, sl4n_error_codes::kPassInt);
51}
52
53bool WifiFacade::WifiStartHal() {
54  android::wifi_system::InterfaceTool if_tool;
55  if (wifi_hal_handle == NULL) {
56    android::wifi_system::HalTool hal_tool;
57    if (!hal_tool.InitFunctionTable(&hal_fn)) {
58      return false;
59    }
60
61    if (!if_tool.SetWifiUpState(true)) {
62      return false;
63    }
64
65    res = hal_fn.wifi_initialize(&wifi_hal_handle);
66    return res == WIFI_SUCCESS;
67  } else {
68    return if_tool.SetWifiUpState(true);
69  }
70}
71
72bool WifiFacade::WifiGetInterfaces() {
73  int num_ifaces;
74  int result = hal_fn.wifi_get_ifaces(wifi_hal_handle, &num_ifaces,
75                                      &wifi_iface_handles);
76  if (result < 0) {
77    LOG(ERROR) << sl4n::kTagStr << ": Can not get Wi-Fi interfaces";
78    return false;
79  }
80
81  if (num_ifaces < 0) {
82    LOG(ERROR) << sl4n::kTagStr << ": Negative number of interfaces";
83    return false;
84  }
85
86  if (wifi_iface_handles == NULL) {
87    LOG(ERROR) << sl4n::kTagStr
88        << "wifi_get_ifaces returned null interface array";
89    return false;
90  }
91
92  if (num_ifaces > 8) {
93    LOG(ERROR) << sl4n::kTagStr
94        << "wifi_get_ifaces returned too many interfaces";
95    return false;
96  }
97
98  char buf[128];
99  for (int i = 0; i < num_ifaces; ++i) {
100    int result = hal_fn.wifi_get_iface_name(wifi_iface_handles[i], buf,
101                                            sizeof(buf));
102    if (result < 0) {
103      LOG(ERROR) << sl4n::kTagStr
104          << "Can't obtain interface name for interface #" << i;
105      continue;
106    }
107    if (!strcmp(buf, kWlanInterface)) {
108      wlan0_index = i;
109    } else if (!strcmp(buf, kP2pInterface)) {
110      p2p0_index = i;
111    }
112  }
113
114  return true;
115}
116
117bool WifiFacade::SharedValidator() {
118  if (wifi_hal_handle == NULL) {
119    LOG(ERROR) << sl4n::kTagStr << "HAL handle not initialized";
120    return false;
121  }
122
123  if (wifi_iface_handles == NULL) {
124    LOG(ERROR) << sl4n::kTagStr << "HAL interfaces not initialized";
125    return false;
126  }
127
128  if (wlan0_index == -1) {
129    LOG(ERROR) << sl4n::kTagStr << kWlanInterface << " interface not found";
130    return false;
131  }
132
133  return true;
134}
135
136std::tuple<int, int> WifiFacade::WifiGetSupportedFeatureSet() {
137  if (!SharedValidator()) {
138    return std::make_tuple(0, sl4n_error_codes::kFailInt);
139  }
140
141  feature_set set = 0;
142  int result = hal_fn.wifi_get_supported_feature_set(
143      wifi_iface_handles[wlan0_index], &set);
144  if (result == WIFI_SUCCESS) {
145    return std::make_tuple(set, sl4n_error_codes::kPassInt);
146  } else {
147    return std::make_tuple(0, sl4n_error_codes::kFailInt);
148  }
149}
150
151//////////////////
152// wrappers
153/////////////////
154
155static WifiFacade facade;  // triggers registration with CommandReceiver
156
157void wifi_init_wrapper(rapidjson::Document &doc) {
158  int expected_param_size = 0;
159  if (!CommonUtils::IsParamLengthMatching(doc, expected_param_size)) {
160    return;
161  }
162  bool result;
163  int error_code;
164  std::tie(result, error_code) = facade.WifiInit();
165  if (error_code == sl4n_error_codes::kFailInt) {
166    doc.AddMember(sl4n::kResultStr, false, doc.GetAllocator());
167    doc.AddMember(sl4n::kErrorStr, sl4n::kFailStr, doc.GetAllocator());
168  } else {
169    doc.AddMember(sl4n::kResultStr, result, doc.GetAllocator());
170    doc.AddMember(sl4n::kErrorStr, NULL, doc.GetAllocator());
171  }
172}
173
174void wifi_get_supported_feature_set_wrapper(rapidjson::Document &doc) {
175  int expected_param_size = 0;
176  if (!CommonUtils::IsParamLengthMatching(doc, expected_param_size)) {
177    return;
178  }
179  int result;
180  int error_code;
181  std::tie(result, error_code) = facade.WifiGetSupportedFeatureSet();
182  if (error_code == sl4n_error_codes::kFailInt) {
183    doc.AddMember(sl4n::kResultStr, false, doc.GetAllocator());
184    doc.AddMember(sl4n::kErrorStr, sl4n::kFailStr, doc.GetAllocator());
185  } else {
186    doc.AddMember(sl4n::kResultStr, result, doc.GetAllocator());
187    doc.AddMember(sl4n::kErrorStr, NULL, doc.GetAllocator());
188  }
189}
190
191////////////////
192// constructor
193////////////////
194
195WifiFacade::WifiFacade() {
196  wifi_hal_handle = NULL;
197  wifi_iface_handles = NULL;
198  num_wifi_iface_handles = 0;
199  wlan0_index = -1;
200  p2p0_index = -1;
201
202  CommandReceiver::RegisterCommand("WifiInit", &wifi_init_wrapper);
203  CommandReceiver::RegisterCommand("WifiGetSupportedFeatureSet",
204                                   &wifi_get_supported_feature_set_wrapper);
205}
206