From bdbe95f221b788c754933f6e49c4292bf4c40e18 Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Tue, 3 Mar 2015 21:33:32 +0100 Subject: [PATCH] Detect and report unsupported commands. When trying to send an unsupported command, the ostc will simply ignore the command. Instead of echoing the command byte back, the ostc will immediately send the ready byte, to indicate it's ready to receive the next command. We can use this to detect unsupported commands, because the ready byte is a reserved value and guaranteed to never be a valid command byte. Normally we don't send invalid commands. But newer firmware version can always introduce new commands to support new features. To maintain backwards compatibility with older firmware versions, it's important to be able to detect unsupported commands and provide a fallback. --- src/hw_ostc3.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/hw_ostc3.c b/src/hw_ostc3.c index a59fceb..f280eaf 100644 --- a/src/hw_ostc3.c +++ b/src/hw_ostc3.c @@ -151,6 +151,9 @@ hw_ostc3_transfer (hw_ostc3_device_t *device, if (device_is_cancelled (abstract)) return DC_STATUS_CANCELLED; + // Get the correct ready byte for the current state. + const unsigned char ready = (device->state == SERVICE ? S_READY : READY); + // Send the command. unsigned char command[1] = {cmd}; int n = serial_write (device->port, command, sizeof (command)); @@ -169,8 +172,13 @@ hw_ostc3_transfer (hw_ostc3_device_t *device, // Verify the echo. if (memcmp (echo, command, sizeof (command)) != 0) { - ERROR (abstract->context, "Unexpected echo."); - return DC_STATUS_PROTOCOL; + if (echo[0] == ready) { + ERROR (abstract->context, "Unsupported command."); + return DC_STATUS_UNSUPPORTED; + } else { + ERROR (abstract->context, "Unexpected echo."); + return DC_STATUS_PROTOCOL; + } } if (input) { @@ -216,16 +224,15 @@ hw_ostc3_transfer (hw_ostc3_device_t *device, if (cmd != EXIT) { // Read the ready byte. - unsigned char ready[1] = {0}; - unsigned char expected = (device->state == SERVICE ? S_READY : READY); - n = serial_read (device->port, ready, sizeof (ready)); - if (n != sizeof (ready)) { + unsigned char answer[1] = {0}; + n = serial_read (device->port, answer, sizeof (answer)); + if (n != sizeof (answer)) { ERROR (abstract->context, "Failed to receive the ready byte."); return EXITCODE (n); } // Verify the ready byte. - if (ready[0] != expected) { + if (answer[0] != ready) { ERROR (abstract->context, "Unexpected ready byte."); return DC_STATUS_PROTOCOL; }