From bc89e0a3de4e6a7f34ef9d556082ec59853f51ff Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Fri, 26 Jul 2013 22:39:56 +0200 Subject: [PATCH] Autodetect the bootloader protocol variant. When updating the firmware while the OSTC is running in normal mode, the V2 protocol should be used. However, the OSTC can also be rebooted from the menu or reset using the magnetic switch, and then the V1 protocol should be used. The only difference with the V2 protocol is the slower baudrate (19200 vs 115200). True autodetection of the protocol variant is difficult, because the bootloader will abort the firmware update when not receiving a 0xC1 byte. But we can still take advantage of the fact that the normal firmware does ignore any 0xC1 bytes sent at the wrong baudrate, and probe with the V1 protocol first. If the bootloader is already running, it will respond immediately and we're done. If the normal firmware is still running, it won't respond and the probing with the V1 protocol will fail. If we then switch to the V2 protocol, the firmware update will continue as before. The result is a firmware updater which supports both bootloader protocols without requiring any manual configuration. --- src/hw_ostc.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/hw_ostc.c b/src/hw_ostc.c index c005e2d..4a389ad 100644 --- a/src/hw_ostc.c +++ b/src/hw_ostc.c @@ -793,7 +793,7 @@ hw_ostc_firmware_setup_internal (hw_ostc_device_t *device) static dc_status_t -hw_ostc_firmware_setup (hw_ostc_device_t *device) +hw_ostc_firmware_setup (hw_ostc_device_t *device, unsigned int maxretries) { dc_status_t rc = DC_STATUS_SUCCESS; @@ -803,7 +803,7 @@ hw_ostc_firmware_setup (hw_ostc_device_t *device) break; // Abort if the maximum number of retries is reached. - if (nretries++ >= MAXRETRIES) + if (nretries++ >= maxretries) break; } @@ -893,7 +893,21 @@ hw_ostc_device_fwupdate (dc_device_t *abstract, const char *filename) serial_set_timeout (device->port, 300); // Setup the bootloader. - rc = hw_ostc_firmware_setup (device); + const unsigned int baudrates[] = {19200, 115200}; + for (unsigned int i = 0; i < C_ARRAY_SIZE(baudrates); ++i) { + // Adjust the baudrate. + if (serial_configure (device->port, baudrates[i], 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE) == -1) { + ERROR (abstract->context, "Failed to set the terminal attributes."); + free (firmware); + return DC_STATUS_IO; + } + + // Try to setup the bootloader. + unsigned int maxretries = (i == 0 ? 1 : MAXRETRIES); + rc = hw_ostc_firmware_setup (device, maxretries); + if (rc == DC_STATUS_SUCCESS) + break; + } if (rc != DC_STATUS_SUCCESS) { ERROR (abstract->context, "Failed to setup the bootloader."); free (firmware);