| // Copyright (c) 2012 The Chromium OS Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "debugd/src/debug_mode_tool.h" |
| |
| #include <memory> |
| |
| #include <base/files/file_util.h> |
| #include <chromeos/dbus/service_constants.h> |
| #include <dbus/bus.h> |
| #include <dbus/message.h> |
| #include <dbus/object_proxy.h> |
| #include <dbus/property.h> |
| #include <shill/dbus-proxies.h> |
| |
| namespace debugd { |
| |
| namespace { |
| |
| const int kFlimflamLogLevelVerbose3 = -3; |
| const int kFlimflamLogLevelInfo = 0; |
| |
| const char kSupplicantServiceName[] = "fi.w1.wpa_supplicant1"; |
| const char kSupplicantObjectPath[] = "/f1/w1/wpa_supplicant1"; |
| const char kSupplicantDebugLevel[] = "DebugLevel"; |
| |
| class SupplicantProxy { |
| public: |
| struct Properties : public dbus::PropertySet { |
| dbus::Property<std::string> debug_level; |
| |
| explicit Properties(dbus::ObjectProxy* proxy) |
| : dbus::PropertySet(proxy, kSupplicantServiceName, |
| dbus::PropertySet::PropertyChangedCallback()) { |
| RegisterProperty(kSupplicantDebugLevel, &debug_level); |
| } |
| |
| ~Properties() override = default; |
| }; |
| |
| explicit SupplicantProxy(scoped_refptr<dbus::Bus> bus) |
| : bus_(bus), |
| properties_(bus->GetObjectProxy( |
| kSupplicantServiceName, dbus::ObjectPath(kSupplicantObjectPath))) {} |
| |
| ~SupplicantProxy() {} |
| |
| void SetDebugLevel(const std::string& level) { |
| properties_.debug_level.SetAndBlock(level); |
| } |
| |
| private: |
| scoped_refptr<dbus::Bus> bus_; |
| Properties properties_; |
| |
| DISALLOW_COPY_AND_ASSIGN(SupplicantProxy); |
| }; |
| |
| // Marvell wifi. |
| constexpr char kMwifiexDebugMask[] = |
| "/sys/kernel/debug/mwifiex/mlan0/debug_mask"; |
| // Enable extra debugging: MSG | FATAL | ERROR | CMD | EVENT. |
| constexpr char kMwifiexEnable[] = "0x37"; |
| // Default debugging level: MSG | FATAL | ERROR. |
| constexpr char kMwifiexDisable[] = "0x7"; |
| |
| // Intel wifi. |
| constexpr char kIwlwifiDebugFlag[] = "/sys/module/iwlwifi/parameters/debug"; |
| // Full debugging: see below file for details on each bit: |
| // drivers/net/wireless-$(WIFIVERSION)/iwl7000/iwlwifi/iwl-debug.h |
| constexpr char kIwlwifiEnable[] = "0xFFFFFFFF"; |
| // Default debugging: none |
| constexpr char kIwlwifiDisable[] = "0x0"; |
| |
| void MaybeWriteSysfs(const char* sysfs_path, const char* data) { |
| base::FilePath path(sysfs_path); |
| |
| if (base::PathExists(path)) { |
| int len = strlen(data); |
| if (base::WriteFile(path, data, len) != len) |
| PLOG(WARNING) << "Writing to " << path.value() << " failed"; |
| } |
| } |
| void WifiSetDebugLevels(bool enable) { |
| MaybeWriteSysfs(kIwlwifiDebugFlag, |
| enable ? kIwlwifiEnable : kIwlwifiDisable); |
| |
| MaybeWriteSysfs(kMwifiexDebugMask, |
| enable ? kMwifiexEnable : kMwifiexDisable); |
| } |
| |
| } // namespace |
| |
| #if USE_CELLULAR |
| |
| namespace { |
| |
| const char kDBusListNames[] = "ListNames"; |
| const char kModemManager[] = "ModemManager"; |
| const char kSetLogging[] = "SetLogging"; |
| |
| } // namespace |
| |
| #endif // USE_CELLULAR |
| |
| DebugModeTool::DebugModeTool(scoped_refptr<dbus::Bus> bus) : bus_(bus) {} |
| |
| void DebugModeTool::SetDebugMode(const std::string& subsystem) { |
| std::string flimflam_tags; |
| std::string supplicant_level = "info"; |
| std::string modemmanager_level = "info"; |
| bool wifi_debug = false; |
| |
| if (subsystem == "wifi") { |
| flimflam_tags = "service+wifi+inet+device+manager"; |
| supplicant_level = "msgdump"; |
| wifi_debug = true; |
| } else if (subsystem == "wimax") { |
| flimflam_tags = "service+wimax+device+manager"; |
| } else if (subsystem == "cellular") { |
| flimflam_tags = "service+cellular+modem+device+manager"; |
| modemmanager_level = "debug"; |
| } else if (subsystem == "ethernet") { |
| flimflam_tags = "service+ethernet+device+manager"; |
| } else if (subsystem == "none") { |
| flimflam_tags = ""; |
| } |
| |
| auto shill = std::make_unique<org::chromium::flimflam::ManagerProxy>(bus_); |
| if (shill) { |
| shill->SetDebugTags(flimflam_tags, nullptr); |
| if (flimflam_tags.length()) { |
| shill->SetDebugLevel(kFlimflamLogLevelVerbose3, nullptr); |
| } else { |
| shill->SetDebugLevel(kFlimflamLogLevelInfo, nullptr); |
| } |
| } |
| |
| WifiSetDebugLevels(wifi_debug); |
| |
| SupplicantProxy supplicant(bus_); |
| supplicant.SetDebugLevel(supplicant_level); |
| |
| SetAllModemManagersLogging(modemmanager_level); |
| } |
| |
| void DebugModeTool::GetAllModemManagers(std::vector<std::string>* managers) { |
| #if USE_CELLULAR |
| managers->clear(); |
| |
| dbus::ObjectProxy* proxy = |
| bus_->GetObjectProxy(dbus::kDBusServiceName, |
| dbus::ObjectPath(dbus::kDBusServicePath)); |
| dbus::MethodCall method_call(dbus::kDBusInterface, kDBusListNames); |
| std::unique_ptr<dbus::Response> response = |
| proxy->CallMethodAndBlock(&method_call, |
| dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); |
| |
| std::vector<std::string> names; |
| dbus::MessageReader reader(response.get()); |
| if (!reader.PopArrayOfStrings(&names)) |
| return; |
| |
| for (const auto& name : names) { |
| if (name.find(kModemManager) != std::string::npos) |
| managers->push_back(name); |
| } |
| #endif // USE_CELLULAR |
| } |
| |
| void DebugModeTool::SetModemManagerLogging(const std::string& service_name, |
| const std::string& service_path, |
| const std::string& level) { |
| dbus::ObjectProxy* proxy = |
| bus_->GetObjectProxy(service_name, dbus::ObjectPath(service_path)); |
| dbus::MethodCall method_call(service_name, kSetLogging); |
| dbus::MessageWriter writer(&method_call); |
| writer.AppendString(level); |
| proxy->CallMethodAndBlock(&method_call, |
| dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); |
| } |
| |
| void DebugModeTool::SetAllModemManagersLogging(const std::string& level) { |
| #if USE_CELLULAR |
| std::vector<std::string> managers; |
| GetAllModemManagers(&managers); |
| for (const auto& manager : managers) { |
| if (manager == cromo::kCromoServiceName) { |
| SetModemManagerLogging(cromo::kCromoServiceName, |
| cromo::kCromoServicePath, |
| (level == "err" ? "error" : level)); |
| } else if (manager == modemmanager::kModemManager1ServiceName) { |
| SetModemManagerLogging(modemmanager::kModemManager1ServiceName, |
| modemmanager::kModemManager1ServicePath, |
| level); |
| } |
| } |
| #endif // USE_CELLULAR |
| } |
| |
| } // namespace debugd |