| // Copyright 2017 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. |
| |
| #ifndef MODEMFWD_MODEM_FLASHER_H_ |
| #define MODEMFWD_MODEM_FLASHER_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <set> |
| #include <string> |
| |
| #include <base/callback.h> |
| #include <base/macros.h> |
| |
| #include "modemfwd/firmware_directory.h" |
| #include "modemfwd/journal.h" |
| #include "modemfwd/modem.h" |
| |
| namespace modemfwd { |
| |
| // ModemFlasher contains all of the logic to make decisions about whether |
| // or not it should flash new firmware onto the modem. |
| class ModemFlasher { |
| public: |
| ModemFlasher(std::unique_ptr<FirmwareDirectory> firmware_directory, |
| std::unique_ptr<Journal> journal); |
| |
| // Returns a callback that should be executed when the modem reappears. |
| base::Closure TryFlash(Modem* modem); |
| |
| private: |
| class FlashState { |
| public: |
| FlashState() = default; |
| ~FlashState() = default; |
| |
| void OnFlashFailed() { tries_--; } |
| bool ShouldFlash() const { return tries_ > 0; } |
| |
| void OnFlashedMainFirmware() { should_flash_main_fw_ = false; } |
| bool ShouldFlashMainFirmware() const { return should_flash_main_fw_; } |
| |
| void OnFlashedCarrierFirmware(const base::FilePath& path) { |
| last_carrier_fw_flashed_ = path; |
| } |
| bool ShouldFlashCarrierFirmware(const base::FilePath& path) const { |
| return last_carrier_fw_flashed_ != path; |
| } |
| |
| void OnCarrierSeen(const std::string& carrier_id) { |
| if (carrier_id == last_carrier_id_) |
| return; |
| |
| last_carrier_id_ = carrier_id; |
| should_flash_main_fw_ = true; |
| } |
| |
| private: |
| // Unlike carrier firmware, we should usually successfully flash the main |
| // firmware at most once per boot. In the past vendors have failed to |
| // update the version that the firmware reports itself as so we can mitigate |
| // some of the potential issues by recording which modems we have deemed |
| // don't need updates or were already updated and avoid checking them again. |
| // |
| // We should retry flashing the main firmware if the carrier changes since |
| // we might have different main firmware versions. As such, when we see a |
| // new carrier, reset the |should_flash_main_fw_| for this modem. |
| bool should_flash_main_fw_ = true; |
| std::string last_carrier_id_; |
| |
| // For carrier firmware, once we've tried to upgrade versions on a |
| // particular modem without changing carriers, we should not try to upgrade |
| // versions again (but should still flash if the carrier is different) to |
| // avoid the same problem as the above. Keep track of the last carrier |
| // firmware we flashed so we don't flash twice in a row. |
| base::FilePath last_carrier_fw_flashed_; |
| |
| // If we fail to flash firmware, we will retry once, but after that we |
| // should stop flashing the modem to prevent us from trying it over and |
| // over. |
| static const int kDefaultTries = 2; |
| int tries_ = kDefaultTries; |
| }; |
| |
| std::unique_ptr<FirmwareDirectory> firmware_directory_; |
| std::unique_ptr<Journal> journal_; |
| |
| std::map<std::string, FlashState> modem_info_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ModemFlasher); |
| }; |
| |
| } // namespace modemfwd |
| |
| #endif // MODEMFWD_MODEM_FLASHER_H_ |