1 // 2 // Copyright (C) 2014 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 "apmanager/device.h" 18 19 #include <base/strings/stringprintf.h> 20 #include <brillo/strings/string_utils.h> 21 #include <shill/net/attribute_list.h> 22 #include <shill/net/ieee80211.h> 23 24 #include "apmanager/config.h" 25 #include "apmanager/control_interface.h" 26 #include "apmanager/manager.h" 27 28 using shill::ByteString; 29 using std::string; 30 31 namespace apmanager { 32 33 Device::Device(Manager* manager, 34 const string& device_name, 35 int identifier) 36 : manager_(manager), 37 supports_ap_mode_(false), 38 identifier_(identifier), 39 adaptor_(manager->control_interface()->CreateDeviceAdaptor(this)) { 40 SetDeviceName(device_name); 41 SetInUse(false); 42 } 43 44 Device::~Device() {} 45 46 void Device::RegisterInterface(const WiFiInterface& new_interface) { 47 LOG(INFO) << "RegisteringInterface " << new_interface.iface_name 48 << " on device " << GetDeviceName(); 49 for (const auto& interface : interface_list_) { 50 // Done if interface already in the list. 51 if (interface.iface_index == new_interface.iface_index) { 52 LOG(INFO) << "Interface " << new_interface.iface_name 53 << " already registered."; 54 return; 55 } 56 } 57 interface_list_.push_back(new_interface); 58 UpdatePreferredAPInterface(); 59 } 60 61 void Device::DeregisterInterface(const WiFiInterface& interface) { 62 LOG(INFO) << "DeregisteringInterface " << interface.iface_name 63 << " on device " << GetDeviceName(); 64 for (auto it = interface_list_.begin(); it != interface_list_.end(); ++it) { 65 if (it->iface_index == interface.iface_index) { 66 interface_list_.erase(it); 67 UpdatePreferredAPInterface(); 68 return; 69 } 70 } 71 } 72 73 void Device::ParseWiphyCapability(const shill::Nl80211Message& msg) { 74 // Parse NL80211_ATTR_SUPPORTED_IFTYPES for AP mode interface support. 75 shill::AttributeListConstRefPtr supported_iftypes; 76 if (!msg.const_attributes()->ConstGetNestedAttributeList( 77 NL80211_ATTR_SUPPORTED_IFTYPES, &supported_iftypes)) { 78 LOG(ERROR) << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_SUPPORTED_IFTYPES"; 79 return; 80 } 81 supported_iftypes->GetFlagAttributeValue(NL80211_IFTYPE_AP, 82 &supports_ap_mode_); 83 84 // Parse WiFi band capabilities. 85 shill::AttributeListConstRefPtr wiphy_bands; 86 if (!msg.const_attributes()->ConstGetNestedAttributeList( 87 NL80211_ATTR_WIPHY_BANDS, &wiphy_bands)) { 88 LOG(ERROR) << "NL80211_CMD_NEW_WIPHY had no NL80211_ATTR_WIPHY_BANDS"; 89 return; 90 } 91 92 shill::AttributeIdIterator band_iter(*wiphy_bands); 93 for (; !band_iter.AtEnd(); band_iter.Advance()) { 94 BandCapability band_cap; 95 96 shill::AttributeListConstRefPtr wiphy_band; 97 if (!wiphy_bands->ConstGetNestedAttributeList(band_iter.GetId(), 98 &wiphy_band)) { 99 LOG(WARNING) << "WiFi band " << band_iter.GetId() << " not found"; 100 continue; 101 } 102 103 // ...Each band has a FREQS attribute... 104 shill::AttributeListConstRefPtr frequencies; 105 if (!wiphy_band->ConstGetNestedAttributeList(NL80211_BAND_ATTR_FREQS, 106 &frequencies)) { 107 LOG(ERROR) << "BAND " << band_iter.GetId() 108 << " had no 'frequencies' attribute"; 109 continue; 110 } 111 112 // ...And each FREQS attribute contains an array of information about the 113 // frequency... 114 shill::AttributeIdIterator freq_iter(*frequencies); 115 for (; !freq_iter.AtEnd(); freq_iter.Advance()) { 116 shill::AttributeListConstRefPtr frequency; 117 if (frequencies->ConstGetNestedAttributeList(freq_iter.GetId(), 118 &frequency)) { 119 // ...Including the frequency, itself (the part we want). 120 uint32_t frequency_value = 0; 121 if (frequency->GetU32AttributeValue(NL80211_FREQUENCY_ATTR_FREQ, 122 &frequency_value)) { 123 band_cap.frequencies.push_back(frequency_value); 124 } 125 } 126 } 127 128 wiphy_band->GetU16AttributeValue(NL80211_BAND_ATTR_HT_CAPA, 129 &band_cap.ht_capability_mask); 130 wiphy_band->GetU16AttributeValue(NL80211_BAND_ATTR_VHT_CAPA, 131 &band_cap.vht_capability_mask); 132 band_capability_.push_back(band_cap); 133 } 134 } 135 136 bool Device::ClaimDevice(bool full_control) { 137 if (GetInUse()) { 138 LOG(ERROR) << "Failed to claim device [" << GetDeviceName() 139 << "]: already in used."; 140 return false; 141 } 142 143 if (full_control) { 144 for (const auto& interface : interface_list_) { 145 manager_->ClaimInterface(interface.iface_name); 146 claimed_interfaces_.insert(interface.iface_name); 147 } 148 } else { 149 manager_->ClaimInterface(GetPreferredApInterface()); 150 claimed_interfaces_.insert(GetPreferredApInterface()); 151 } 152 SetInUse(true); 153 return true; 154 } 155 156 bool Device::ReleaseDevice() { 157 if (!GetInUse()) { 158 LOG(ERROR) << "Failed to release device [" << GetDeviceName() 159 << "]: not currently in-used."; 160 return false; 161 } 162 163 for (const auto& interface : claimed_interfaces_) { 164 manager_->ReleaseInterface(interface); 165 } 166 claimed_interfaces_.clear(); 167 SetInUse(false); 168 return true; 169 } 170 171 bool Device::InterfaceExists(const string& interface_name) { 172 for (const auto& interface : interface_list_) { 173 if (interface.iface_name == interface_name) { 174 return true; 175 } 176 } 177 return false; 178 } 179 180 bool Device::GetHTCapability(uint16_t channel, string* ht_cap) { 181 // Get the band capability based on the channel. 182 BandCapability band_cap; 183 if (!GetBandCapability(channel, &band_cap)) { 184 LOG(ERROR) << "No band capability found for channel " << channel; 185 return false; 186 } 187 188 std::vector<string> ht_capability; 189 // LDPC coding capability. 190 if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskLdpcCoding) { 191 ht_capability.push_back("LDPC"); 192 } 193 194 // Supported channel width set. 195 if (band_cap.ht_capability_mask & 196 shill::IEEE_80211::kHTCapMaskSupWidth2040) { 197 // Determine secondary channel is below or above the primary. 198 bool above = false; 199 if (!GetHTSecondaryChannelLocation(channel, &above)) { 200 LOG(ERROR) << "Unable to determine secondary channel location for " 201 << "channel " << channel; 202 return false; 203 } 204 if (above) { 205 ht_capability.push_back("HT40+"); 206 } else { 207 ht_capability.push_back("HT40-"); 208 } 209 } 210 211 // Spatial Multiplexing (SM) Power Save. 212 uint16_t power_save_mask = 213 (band_cap.ht_capability_mask >> 214 shill::IEEE_80211::kHTCapMaskSmPsShift) & 0x3; 215 if (power_save_mask == 0) { 216 ht_capability.push_back("SMPS-STATIC"); 217 } else if (power_save_mask == 1) { 218 ht_capability.push_back("SMPS-DYNAMIC"); 219 } 220 221 // HT-greenfield. 222 if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskGrnFld) { 223 ht_capability.push_back("GF"); 224 } 225 226 // Short GI for 20 MHz. 227 if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskSgi20) { 228 ht_capability.push_back("SHORT-GI-20"); 229 } 230 231 // Short GI for 40 MHz. 232 if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskSgi40) { 233 ht_capability.push_back("SHORT-GI-40"); 234 } 235 236 // Tx STBC. 237 if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskTxStbc) { 238 ht_capability.push_back("TX-STBC"); 239 } 240 241 // Rx STBC. 242 uint16_t rx_stbc = 243 (band_cap.ht_capability_mask >> 244 shill::IEEE_80211::kHTCapMaskRxStbcShift) & 0x3; 245 if (rx_stbc == 1) { 246 ht_capability.push_back("RX-STBC1"); 247 } else if (rx_stbc == 2) { 248 ht_capability.push_back("RX-STBC12"); 249 } else if (rx_stbc == 3) { 250 ht_capability.push_back("RX-STBC123"); 251 } 252 253 // HT-delayed Block Ack. 254 if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskDelayBA) { 255 ht_capability.push_back("DELAYED-BA"); 256 } 257 258 // Maximum A-MSDU length. 259 if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskMaxAmsdu) { 260 ht_capability.push_back("MAX-AMSDU-7935"); 261 } 262 263 // DSSS/CCK Mode in 40 MHz. 264 if (band_cap.ht_capability_mask & shill::IEEE_80211::kHTCapMaskDsssCck40) { 265 ht_capability.push_back("DSSS_CCK-40"); 266 } 267 268 // 40 MHz intolerant. 269 if (band_cap.ht_capability_mask & 270 shill::IEEE_80211::kHTCapMask40MHzIntolerant) { 271 ht_capability.push_back("40-INTOLERANT"); 272 } 273 274 *ht_cap = base::StringPrintf("[%s]", 275 brillo::string_utils::Join(" ", ht_capability).c_str()); 276 return true; 277 } 278 279 bool Device::GetVHTCapability(uint16_t channel, string* vht_cap) { 280 // TODO(zqiu): to be implemented. 281 return false; 282 } 283 284 void Device::SetDeviceName(const std::string& device_name) { 285 adaptor_->SetDeviceName(device_name); 286 } 287 288 string Device::GetDeviceName() const { 289 return adaptor_->GetDeviceName(); 290 } 291 292 void Device::SetPreferredApInterface(const std::string& interface_name) { 293 adaptor_->SetPreferredApInterface(interface_name); 294 } 295 296 string Device::GetPreferredApInterface() const { 297 return adaptor_->GetPreferredApInterface(); 298 } 299 300 void Device::SetInUse(bool in_use) { 301 return adaptor_->SetInUse(in_use); 302 } 303 304 bool Device::GetInUse() const { 305 return adaptor_->GetInUse(); 306 } 307 308 // static 309 bool Device::GetHTSecondaryChannelLocation(uint16_t channel, bool* above) { 310 bool ret_val = true; 311 312 // Determine secondary channel location base on the channel. Refer to 313 // ht_cap section in hostapd.conf documentation. 314 switch (channel) { 315 case 7: 316 case 8: 317 case 9: 318 case 10: 319 case 11: 320 case 12: 321 case 13: 322 case 40: 323 case 48: 324 case 56: 325 case 64: 326 *above = false; 327 break; 328 329 case 1: 330 case 2: 331 case 3: 332 case 4: 333 case 5: 334 case 6: 335 case 36: 336 case 44: 337 case 52: 338 case 60: 339 *above = true; 340 break; 341 342 default: 343 ret_val = false; 344 break; 345 } 346 347 return ret_val; 348 } 349 350 bool Device::GetBandCapability(uint16_t channel, BandCapability* capability) { 351 uint32_t frequency; 352 if (!Config::GetFrequencyFromChannel(channel, &frequency)) { 353 LOG(ERROR) << "Invalid channel " << channel; 354 return false; 355 } 356 357 for (const auto& band : band_capability_) { 358 if (std::find(band.frequencies.begin(), 359 band.frequencies.end(), 360 frequency) != band.frequencies.end()) { 361 *capability = band; 362 return true; 363 } 364 } 365 return false; 366 } 367 368 void Device::UpdatePreferredAPInterface() { 369 // Return if device doesn't support AP interface mode. 370 if (!supports_ap_mode_) { 371 return; 372 } 373 374 // Use the first registered AP mode interface if there is one, otherwise use 375 // the first registered managed mode interface. If none are available, then 376 // no interface can be used for AP operation on this device. 377 WiFiInterface preferred_interface; 378 for (const auto& interface : interface_list_) { 379 if (interface.iface_type == NL80211_IFTYPE_AP) { 380 preferred_interface = interface; 381 break; 382 } else if (interface.iface_type == NL80211_IFTYPE_STATION && 383 preferred_interface.iface_name.empty()) { 384 preferred_interface = interface; 385 } 386 // Ignore all other interface types. 387 } 388 // Update preferred AP interface property. 389 SetPreferredApInterface(preferred_interface.iface_name); 390 } 391 392 } // namespace apmanager 393