Adjust the total amount of memory for the newer Suunto's.
The D9tx, D6i and D4i have twice the amount of memory compared to the previous versions (64K versus 32K). To support both variants, a new layout descriptor is introduced.
This commit is contained in:
parent
76ab46304b
commit
2a0defe30d
@ -19,6 +19,7 @@
|
||||
* MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include <stdlib.h> // malloc
|
||||
#include <string.h> // memcmp, memcpy
|
||||
#include <assert.h> // assert
|
||||
|
||||
@ -28,22 +29,15 @@
|
||||
#include "checksum.h"
|
||||
#include "array.h"
|
||||
|
||||
#define D4i 0x19
|
||||
#define D6i 0x1A
|
||||
#define D9tx 0x1B
|
||||
|
||||
#define MAXRETRIES 2
|
||||
|
||||
#define SZ_VERSION 0x04
|
||||
#define SZ_MEMORY 0x8000
|
||||
#define SZ_PACKET 0x78
|
||||
#define SZ_MINIMUM 8
|
||||
|
||||
#define FP_OFFSET 0x15
|
||||
|
||||
#define RB_PROFILE_BEGIN 0x019A
|
||||
#define RB_PROFILE_END SZ_MEMORY - 2
|
||||
#define RB_PROFILE_DISTANCE(a,b,m) ringbuffer_distance (a, b, m, RB_PROFILE_BEGIN, RB_PROFILE_END)
|
||||
#define RB_PROFILE_DISTANCE(l,a,b,m) ringbuffer_distance (a, b, m, l->rb_profile_begin, l->rb_profile_end)
|
||||
|
||||
#define BACKEND(abstract) ((suunto_common2_device_backend_t *) abstract->backend)
|
||||
|
||||
@ -56,6 +50,7 @@ suunto_common2_device_init (suunto_common2_device_t *device, const suunto_common
|
||||
device_init (&device->base, &backend->base);
|
||||
|
||||
// Set the default values.
|
||||
device->layout = NULL;
|
||||
memset (device->fingerprint, 0, sizeof (device->fingerprint));
|
||||
}
|
||||
|
||||
@ -214,9 +209,14 @@ suunto_common2_device_write (device_t *abstract, unsigned int address, const uns
|
||||
device_status_t
|
||||
suunto_common2_device_dump (device_t *abstract, dc_buffer_t *buffer)
|
||||
{
|
||||
suunto_common2_device_t *device = (suunto_common2_device_t *) abstract;
|
||||
|
||||
assert (device != NULL);
|
||||
assert (device->layout != NULL);
|
||||
|
||||
// Erase the current contents of the buffer and
|
||||
// allocate the required amount of memory.
|
||||
if (!dc_buffer_clear (buffer) || !dc_buffer_resize (buffer, SZ_MEMORY)) {
|
||||
if (!dc_buffer_clear (buffer) || !dc_buffer_resize (buffer, device->layout->memsize)) {
|
||||
WARNING ("Insufficient buffer space available.");
|
||||
return DEVICE_STATUS_MEMORY;
|
||||
}
|
||||
@ -231,9 +231,15 @@ suunto_common2_device_foreach (device_t *abstract, dive_callback_t callback, voi
|
||||
{
|
||||
suunto_common2_device_t *device = (suunto_common2_device_t*) abstract;
|
||||
|
||||
assert (device != NULL);
|
||||
assert (device->layout != NULL);
|
||||
|
||||
const suunto_common2_layout_t *layout = device->layout;
|
||||
|
||||
// Enable progress notifications.
|
||||
device_progress_t progress = DEVICE_PROGRESS_INITIALIZER;
|
||||
progress.maximum = RB_PROFILE_END - RB_PROFILE_BEGIN + 8 + SZ_VERSION + (SZ_MINIMUM > 4 ? SZ_MINIMUM : 4);
|
||||
progress.maximum = layout->rb_profile_end - layout->rb_profile_begin +
|
||||
8 + SZ_VERSION + (SZ_MINIMUM > 4 ? SZ_MINIMUM : 4);
|
||||
device_event_emit (abstract, DEVICE_EVENT_PROGRESS, &progress);
|
||||
|
||||
// Read the version info.
|
||||
@ -249,11 +255,8 @@ suunto_common2_device_foreach (device_t *abstract, dive_callback_t callback, voi
|
||||
device_event_emit (abstract, DEVICE_EVENT_PROGRESS, &progress);
|
||||
|
||||
// Read the serial number.
|
||||
unsigned int addr = 0x0023;
|
||||
if (version[0] == D4i || version[0] == D6i || version[0] == D9tx)
|
||||
addr++;
|
||||
unsigned char serial[SZ_MINIMUM > 4 ? SZ_MINIMUM : 4] = {0};
|
||||
rc = suunto_common2_device_read (abstract, addr, serial, sizeof (serial));
|
||||
rc = suunto_common2_device_read (abstract, layout->serial, serial, sizeof (serial));
|
||||
if (rc != DEVICE_STATUS_SUCCESS) {
|
||||
WARNING ("Cannot read memory header.");
|
||||
return rc;
|
||||
@ -286,15 +289,19 @@ suunto_common2_device_foreach (device_t *abstract, dive_callback_t callback, voi
|
||||
|
||||
// Memory buffer to store all the dives.
|
||||
|
||||
unsigned char data[SZ_MINIMUM + RB_PROFILE_END - RB_PROFILE_BEGIN] = {0};
|
||||
unsigned char *data = (unsigned char *) malloc (layout->rb_profile_end - layout->rb_profile_begin + SZ_MINIMUM);
|
||||
if (data == NULL) {
|
||||
WARNING ("Failed to allocate memory.");
|
||||
return DEVICE_STATUS_MEMORY;
|
||||
}
|
||||
|
||||
// Calculate the total amount of bytes.
|
||||
|
||||
unsigned int remaining = RB_PROFILE_DISTANCE (begin, end, count != 0);
|
||||
unsigned int remaining = RB_PROFILE_DISTANCE (layout, begin, end, count != 0);
|
||||
|
||||
// Update and emit a progress event.
|
||||
|
||||
progress.maximum -= (RB_PROFILE_END - RB_PROFILE_BEGIN) - remaining;
|
||||
progress.maximum -= (layout->rb_profile_end - layout->rb_profile_begin) - remaining;
|
||||
progress.current += sizeof (header);
|
||||
device_event_emit (abstract, DEVICE_EVENT_PROGRESS, &progress);
|
||||
|
||||
@ -315,24 +322,26 @@ suunto_common2_device_foreach (device_t *abstract, dive_callback_t callback, voi
|
||||
unsigned int offset = remaining + SZ_MINIMUM;
|
||||
while (remaining) {
|
||||
// Calculate the size of the current dive.
|
||||
unsigned int size = RB_PROFILE_DISTANCE (current, previous, 1);
|
||||
unsigned int size = RB_PROFILE_DISTANCE (layout, current, previous, 1);
|
||||
|
||||
if (size < 4 || size > remaining) {
|
||||
WARNING ("Unexpected profile size.");
|
||||
free (data);
|
||||
return DEVICE_STATUS_ERROR;
|
||||
}
|
||||
|
||||
unsigned int nbytes = available;
|
||||
while (nbytes < size) {
|
||||
// Handle the ringbuffer wrap point.
|
||||
if (address == RB_PROFILE_BEGIN)
|
||||
address = RB_PROFILE_END;
|
||||
if (address == layout->rb_profile_begin)
|
||||
address = layout->rb_profile_end;
|
||||
|
||||
// Calculate the package size. Try with the largest possible
|
||||
// size first, and adjust when the end of the ringbuffer or
|
||||
// the end of the profile data is reached.
|
||||
unsigned int len = SZ_PACKET;
|
||||
if (RB_PROFILE_BEGIN + len > address)
|
||||
len = address - RB_PROFILE_BEGIN; // End of ringbuffer.
|
||||
if (layout->rb_profile_begin + len > address)
|
||||
len = address - layout->rb_profile_begin; // End of ringbuffer.
|
||||
if (nbytes + len > remaining)
|
||||
len = remaining - nbytes; // End of profile.
|
||||
/*if (nbytes + len > size)
|
||||
@ -354,6 +363,7 @@ suunto_common2_device_foreach (device_t *abstract, dive_callback_t callback, voi
|
||||
rc = suunto_common2_device_read (abstract, address - extra, data + offset - extra, len + extra);
|
||||
if (rc != DEVICE_STATUS_SUCCESS) {
|
||||
WARNING ("Cannot read memory.");
|
||||
free (data);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -377,6 +387,7 @@ suunto_common2_device_foreach (device_t *abstract, dive_callback_t callback, voi
|
||||
unsigned int next = array_uint16_le (p + 2);
|
||||
if (next != previous) {
|
||||
WARNING ("Profiles are not continuous.");
|
||||
free (data);
|
||||
return DEVICE_STATUS_ERROR;
|
||||
}
|
||||
|
||||
@ -388,12 +399,18 @@ suunto_common2_device_foreach (device_t *abstract, dive_callback_t callback, voi
|
||||
if (devinfo.model == 0x15)
|
||||
fp_offset += 6; // HelO2
|
||||
|
||||
if (memcmp (p + fp_offset, device->fingerprint, sizeof (device->fingerprint)) == 0)
|
||||
if (memcmp (p + fp_offset, device->fingerprint, sizeof (device->fingerprint)) == 0) {
|
||||
free (data);
|
||||
return DEVICE_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (callback && !callback (p + 4, size - 4, p + fp_offset, sizeof (device->fingerprint), userdata))
|
||||
if (callback && !callback (p + 4, size - 4, p + fp_offset, sizeof (device->fingerprint), userdata)) {
|
||||
free (data);
|
||||
return DEVICE_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
free (data);
|
||||
|
||||
return DEVICE_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
@ -28,8 +28,19 @@
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct suunto_common2_layout_t {
|
||||
// Memory size.
|
||||
unsigned int memsize;
|
||||
// Serial number.
|
||||
unsigned int serial;
|
||||
// Profile ringbuffer
|
||||
unsigned int rb_profile_begin;
|
||||
unsigned int rb_profile_end;
|
||||
} suunto_common2_layout_t;
|
||||
|
||||
typedef struct suunto_common2_device_t {
|
||||
device_t base;
|
||||
const suunto_common2_layout_t *layout;
|
||||
unsigned char fingerprint[7];
|
||||
} suunto_common2_device_t;
|
||||
|
||||
|
||||
@ -64,6 +64,20 @@ static const suunto_common2_device_backend_t suunto_d9_device_backend = {
|
||||
suunto_d9_device_packet
|
||||
};
|
||||
|
||||
static const suunto_common2_layout_t suunto_d9_layout = {
|
||||
0x8000, /* memsize */
|
||||
0x0023, /* serial */
|
||||
0x019A, /* rb_profile_begin */
|
||||
0x7FFE /* rb_profile_end */
|
||||
};
|
||||
|
||||
static const suunto_common2_layout_t suunto_d9tx_layout = {
|
||||
0x10000, /* memsize */
|
||||
0x0024, /* serial */
|
||||
0x019A, /* rb_profile_begin */
|
||||
0xFFFE /* rb_profile_end */
|
||||
};
|
||||
|
||||
static int
|
||||
device_is_suunto_d9 (device_t *abstract)
|
||||
{
|
||||
@ -176,6 +190,13 @@ suunto_d9_device_open (device_t **out, const char* name)
|
||||
return status;
|
||||
}
|
||||
|
||||
// Override the base class values.
|
||||
unsigned int model = device->version[0];
|
||||
if (model == D4i || model == D6i || model == D9tx)
|
||||
device->base.layout = &suunto_d9tx_layout;
|
||||
else
|
||||
device->base.layout = &suunto_d9_layout;
|
||||
|
||||
*out = (device_t*) device;
|
||||
|
||||
return DEVICE_STATUS_SUCCESS;
|
||||
|
||||
@ -56,6 +56,13 @@ static const suunto_common2_device_backend_t suunto_vyper2_device_backend = {
|
||||
suunto_vyper2_device_packet
|
||||
};
|
||||
|
||||
static const suunto_common2_layout_t suunto_vyper2_layout = {
|
||||
0x8000, /* memsize */
|
||||
0x0023, /* serial */
|
||||
0x019A, /* rb_profile_begin */
|
||||
0x7FFE /* rb_profile_end */
|
||||
};
|
||||
|
||||
static int
|
||||
device_is_suunto_vyper2 (device_t *abstract)
|
||||
{
|
||||
@ -124,6 +131,9 @@ suunto_vyper2_device_open (device_t **out, const char* name)
|
||||
// Make sure everything is in a sane state.
|
||||
serial_flush (device->port, SERIAL_QUEUE_BOTH);
|
||||
|
||||
// Override the base class values.
|
||||
device->base.layout = &suunto_vyper2_layout;
|
||||
|
||||
*out = (device_t*) device;
|
||||
|
||||
return DEVICE_STATUS_SUCCESS;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user