blob: 015ee336c49a14c427849df360774a1e13545a50 [file] [log] [blame]
// 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.
#include <stdlib.h>
#include <iostream>
#include "firmware.h"
#include "flasher.h"
#include "minicam_device.h"
#include "tools.h"
#include "usb_device.h"
bool WaitForUsbDevice(uint16_t vendor_id, uint16_t product_id);
bool IsCameraAttached(int16_t product_id, std::string* err_msg);
bool HasCamera();
bool EnterBootloaderMode();
bool HasCameraBootloader(huddly::MinicamDevice* minidev);
int main(void) {
std::cout << "Starting Huddly Package Updater .." << std::endl;
if (!HasCamera()) { // printing errors inside, upon failure.
return EXIT_FAILURE;
}
// Has camera in APP state.
if (!EnterBootloaderMode()) { // printing errors inside, upon failure.
return EXIT_FAILURE;
}
// Detected a camera in Bootloader mode
huddly::MinicamDevice minidev(huddly::kProductIdBootloader);
if (!HasCameraBootloader(&minidev)) {
// printing errors inside, upon failure.
return EXIT_FAILURE;
}
// Prepare the firmware package/images
huddly::Firmware firmware;
std::string err_msg;
if (!firmware.IsReady(&err_msg)) {
std::cout << ".. Firmware is not ready: " << err_msg << std::endl;
return EXIT_FAILURE;
}
// Flash App
huddly::Flasher flasher(firmware, &minidev);
if (!flasher.FlashApp(&err_msg)) {
err_msg += ".. failed to flash";
std::cout << err_msg << std::endl;
return EXIT_FAILURE;
}
std::cout << ".. rebooting back to APP mode" << std::endl;
if (!minidev.RebootInMode(huddly::BootMode::APP, &err_msg)) {
std::cout << ".. failed to reboot back to APP mode" << std::endl;
return EXIT_FAILURE;
}
std::cout << ".. upgrade complete." << std::endl;
return EXIT_SUCCESS;
}
bool IsCameraAttached(int16_t product_id, std::string* err_msg) {
huddly::UsbDevice usbdev(huddly::kVendorId, product_id);
if (!usbdev.Setup(err_msg)) {
*err_msg += ".. not found: " + std::to_string(product_id);
return false;
}
huddly::MinicamDevice minidev(product_id);
if (!minidev.Setup(err_msg)) {
*err_msg +=
".. failed to Setup as Minicamdevice " + std::to_string(product_id);
return false;
}
uint8_t hw_rev;
if (!minidev.GetHwRevision(&hw_rev, err_msg)) {
*err_msg += ". failed to get hardware revision";
return false;
}
if (hw_rev != 6) {
*err_msg += ".. unsupported hardware revision: " + std::to_string(hw_rev) +
" in product id: " + std::to_string(product_id);
return false;
}
return true;
}
bool WaitForUsbDevice(uint16_t vendor_id, uint16_t product_id) {
const int kRetries = 30;
std::string err_msg;
huddly::UsbDevice usbdev(vendor_id, product_id);
for (int retry = 0; retry < kRetries; retry++) {
if (usbdev.Setup(&err_msg)) {
// Device came up;
return true;
}
huddly::SleepMilliSec(1000); // 1 sec
continue;
}
return false;
}
bool HasCamera() {
std::string err_msg;
if (IsCameraAttached(huddly::kProductIdBootloader, &err_msg)) {
// Abnormal initial state. Upgrading from this initial state is not
// supported. Reboot in APP mode to bring it back to normal state. For users
// performing upgrade manually: rerun this program.
std::cout << ".. detected abnormal initial state: Bootloader" << std::endl;
std::cout << ".. rebooting in APP mode" << std::endl;
huddly::MinicamDevice minidev(huddly::kProductIdBootloader);
if (!minidev.Setup(&err_msg)) {
err_msg += ".. failed to setup for rebooting.";
std::cout << err_msg << std::endl;
return false;
}
std::cout << ".. successfully rebooting. Rerun this upgrader manually."
<< std::endl;
return false;
}
// Camera is not in Bootloader mode
if (!IsCameraAttached(huddly::kProductIdApp, &err_msg)) {
err_msg += ".. no camera is attached.";
std::cout << err_msg << std::endl;
return false;
}
return true;
}
bool EnterBootloaderMode() {
std::string err_msg;
huddly::MinicamDevice minidev_app(huddly::kProductIdApp);
if (minidev_app.Setup(&err_msg) &&
minidev_app.RebootInMode(huddly::BootMode::BOOTLOADER, &err_msg) &&
WaitForUsbDevice(huddly::kVendorId, huddly::kProductIdBootloader)) {
std::cout << ".. rebooted in BOOTLOADER mode" << err_msg << std::endl;
return true;
}
err_msg += ".. failed to upgrade";
std::cout << err_msg << std::endl;
return false;
}
bool HasCameraBootloader(huddly::MinicamDevice* minidev) {
std::string err_msg;
if (minidev->Setup(&err_msg)) {
return true;
}
err_msg += ".. failed to upgrade. attempt to recover to APP mode";
std::cout << err_msg << std::endl;
// Escape sequence: Already in strange state. Best effort recovery.
if (!minidev->RebootInMode(huddly::BootMode::APP, &err_msg)) {
err_msg +=
".. failed to recover from unexpected state. The device might be in "
"BOOTLOADER mode.";
std::cout << err_msg << std::endl;
return false;
}
std::cout << ".. rebooting in APP mode" << std::endl;
return false;
}