Revamp the main function of huddly firmware updater
Performs reboot if the device is in abnormal Bootloader mode.
Converting the APP mode to Bootloader mode.
Invoke Flasher.
BUG=chromium:710302
TEST=Build package for Guado board
Change-Id: I39f460ac2f63889f83964700d7155a2d0f8e0bc9
Reviewed-on: https://chromium-review.googlesource.com/487404
Commit-Ready: Jiwoong Lee <porce@chromium.org>
Tested-by: Jiwoong Lee <porce@chromium.org>
Reviewed-by: Ben Chan <benchan@chromium.org>
diff --git a/src/main.cc b/src/main.cc
index 83c2f55..015ee33 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -6,39 +6,174 @@
#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;
- huddly::Firmware firmware;
+ 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;
}
- */
- // TODO(porce): Write UsbDevice class, initialized by VID and PID.
- // psdudo code plan
- // UsbDevice usbdev(VID, PID);
- // if (!usbdev.IsUpgradeEligible(firmware)) { byebye; }
- // usbdev.FlashFirmware();
- // usbdev.VerifyFirmware();
+ // Flash App
+ huddly::Flasher flasher(firmware, &minidev);
- // Huddly camera in UVC mode.
- const int16_t kVendorId = 0x2bd9;
- const int16_t kProductId = 0x0011;
-
- huddly::UsbDevice usbdev(kVendorId, kProductId);
- if (!usbdev.Setup(&err_msg)) {
- std::cout << ".. failed to setup: " << err_msg << std::endl;
+ if (!flasher.FlashApp(&err_msg)) {
+ err_msg += ".. failed to flash";
+ std::cout << err_msg << std::endl;
return EXIT_FAILURE;
}
- std::cout << ".. peripheral firmware version: "
- << usbdev.QueryFirmwareVersion() << std::endl;
+ 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;
+}
diff --git a/src/module.mk b/src/module.mk
index 799fe39..7b7e274 100644
--- a/src/module.mk
+++ b/src/module.mk
@@ -11,6 +11,6 @@
CPPFLAGS += $(PC_CFLAGS)
-CXX_BINARY(huddly-updater): src/main.o src/firmware.o src/tools.o src/usb_device.o
+CXX_BINARY(huddly-updater): src/main.o src/firmware.o src/tools.o src/usb_device.o src/flasher.o src/minicam_device.o
all: CXX_BINARY(huddly-updater)
clean: CLEAN(CXX_BINARY(huddly-updater))