From ada569faf3204b6bb02f45890b05b1f5137c2eeb Mon Sep 17 00:00:00 2001 From: Jef Driesen Date: Thu, 11 Aug 2011 21:12:14 +0200 Subject: [PATCH] Autodetect the baudrate for the Suunto D4i, D6i and D9tx. These new models use a faster baudrate. The correct baudrate is detected by probing with the version command. To speedup the detection, the model code can be supplied by the caller as a hint, which is then used to start the autodetection directly with the correct baudrate. To maintain backwards compatibility, the model hint is not enabled yet. --- src/suunto_d9.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/src/suunto_d9.c b/src/suunto_d9.c index 1dd249f..e1edd01 100644 --- a/src/suunto_d9.c +++ b/src/suunto_d9.c @@ -35,6 +35,12 @@ rc == -1 ? DEVICE_STATUS_IO : DEVICE_STATUS_TIMEOUT \ ) +#define C_ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a))) + +#define D4i 0x19 +#define D6i 0x1A +#define D9tx 0x1B + typedef struct suunto_d9_device_t { suunto_common2_device_t base; serial_t *port; @@ -67,6 +73,41 @@ device_is_suunto_d9 (device_t *abstract) } +static device_status_t +suunto_d9_device_autodetect (suunto_d9_device_t *device, unsigned int model) +{ + device_status_t status = DEVICE_STATUS_SUCCESS; + + // The list with possible baudrates. + const int baudrates[] = {9600, 115200}; + + // Use the model number as a hint to speedup the detection. + unsigned int hint = 0; + if (model == D4i || model == D6i || model == D9tx) + hint = 1; + + for (unsigned int i = 0; i < C_ARRAY_SIZE(baudrates); ++i) { + // Use the baudrate array as circular array, starting from the hint. + unsigned int idx = (hint + i) % C_ARRAY_SIZE(baudrates); + + // Adjust the baudrate. + int rc = serial_configure (device->port, baudrates[idx], 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE); + if (rc == -1) { + WARNING ("Failed to set the terminal attributes."); + return DEVICE_STATUS_IO; + } + + // Try reading the version info. + unsigned char version[4] = {0}; + status = suunto_common2_device_version ((device_t *) device, version, sizeof (version)); + if (status == DEVICE_STATUS_SUCCESS) + break; + } + + return status; +} + + device_status_t suunto_d9_device_open (device_t **out, const char* name) { @@ -125,6 +166,15 @@ suunto_d9_device_open (device_t **out, const char* name) // Make sure everything is in a sane state. serial_flush (device->port, SERIAL_QUEUE_BOTH); + // Try to autodetect the protocol variant. + device_status_t status = suunto_d9_device_autodetect (device, 0); + if (status != DEVICE_STATUS_SUCCESS) { + WARNING ("Failed to identify the protocol variant."); + serial_close (device->port); + free (device); + return status; + } + *out = (device_t*) device; return DEVICE_STATUS_SUCCESS;