Add support for the new extended hardware descriptor.

The latest v2.09 (hwOS) and v1.1.0 (hwOS4) firmware introduced a new
variant of the hardware descriptor command. This extended command
returns:

 - a 16 bit hardware descriptor
 - a 16 bit feature descriptor
 - an 8 bit model descriptor

The hardware descriptor is backwards compatible with the existing one
(upper bits are all zero for now). For the OSTC4, the feature descriptor
is currently used to indicated the Bonex scooter version (0x01), and the
model descriptor is 0x43. For all other models, the feature and model
descriptors are always zero for now.

For older firmware versions, which do not support the new extended
descriptor yet, there is an automatic fallback to the previous
descriptor.
This commit is contained in:
Jef Driesen 2016-07-21 22:26:48 +02:00
parent 9ef840fc96
commit b4dc2532e8

View File

@ -42,6 +42,7 @@
#define SZ_CUSTOMTEXT 60
#define SZ_VERSION (SZ_CUSTOMTEXT + 4)
#define SZ_HARDWARE 1
#define SZ_HARDWARE2 5
#define SZ_MEMORY 0x400000
#define SZ_CONFIG 4
#define SZ_FWINFO 4
@ -59,6 +60,7 @@
#define S_READY 0x4C
#define READY 0x4D
#define S_UPGRADE 0x50
#define HARDWARE2 0x60
#define HEADER 0x61
#define CLOCK 0x62
#define CUSTOMTEXT 0x63
@ -95,6 +97,8 @@ typedef struct hw_ostc3_device_t {
dc_device_t base;
dc_serial_t *port;
unsigned int hardware;
unsigned int feature;
unsigned int model;
unsigned char fingerprint[5];
hw_ostc3_state_t state;
} hw_ostc3_device_t;
@ -330,6 +334,8 @@ hw_ostc3_device_open (dc_device_t **out, dc_context_t *context, const char *name
// Set the default values.
device->port = NULL;
device->hardware = INVALID;
device->feature = 0;
device->model = 0;
memset (device->fingerprint, 0, sizeof (device->fingerprint));
// Open the device.
@ -371,6 +377,33 @@ error_free:
}
static dc_status_t
hw_ostc3_device_id (hw_ostc3_device_t *device, unsigned char data[], unsigned int size)
{
dc_status_t status = DC_STATUS_SUCCESS;
if (size != SZ_HARDWARE && size != SZ_HARDWARE2)
return DC_STATUS_INVALIDARGS;
// Send the command.
unsigned char hardware[SZ_HARDWARE2] = {0};
status = hw_ostc3_transfer (device, NULL, HARDWARE2, NULL, 0, hardware, SZ_HARDWARE2, NODELAY);
if (status == DC_STATUS_UNSUPPORTED) {
status = hw_ostc3_transfer (device, NULL, HARDWARE, NULL, 0, hardware + 1, SZ_HARDWARE, NODELAY);
}
if (status != DC_STATUS_SUCCESS)
return status;
if (size == SZ_HARDWARE2) {
memcpy (data, hardware, SZ_HARDWARE2);
} else {
memcpy (data, hardware + 1, SZ_HARDWARE);
}
return DC_STATUS_SUCCESS;
}
static dc_status_t
hw_ostc3_device_init_download (hw_ostc3_device_t *device)
{
@ -466,15 +499,17 @@ hw_ostc3_device_init (hw_ostc3_device_t *device, hw_ostc3_state_t state)
return DC_STATUS_SUCCESS;
// Read the hardware descriptor.
unsigned char hardware[SZ_HARDWARE] = {UNKNOWN};
rc = hw_ostc3_transfer (device, NULL, HARDWARE, NULL, 0, hardware, sizeof(hardware), NODELAY);
unsigned char hardware[SZ_HARDWARE2] = {0, UNKNOWN};
rc = hw_ostc3_device_id (device, hardware, sizeof(hardware));
if (rc != DC_STATUS_SUCCESS && rc != DC_STATUS_UNSUPPORTED) {
ERROR (abstract->context, "Failed to read the hardware descriptor.");
return rc;
}
// Cache the descriptor.
device->hardware = hardware[0];
device->hardware = array_uint16_be(hardware + 0);
device->feature = array_uint16_be(hardware + 2);
device->model = hardware[4];
return DC_STATUS_SUCCESS;
}
@ -555,7 +590,7 @@ hw_ostc3_device_hardware (dc_device_t *abstract, unsigned char data[], unsigned
if (!ISINSTANCE (abstract))
return DC_STATUS_INVALIDARGS;
if (size != SZ_HARDWARE)
if (size != SZ_HARDWARE && size != SZ_HARDWARE2)
return DC_STATUS_INVALIDARGS;
dc_status_t rc = hw_ostc3_device_init (device, DOWNLOAD);
@ -563,7 +598,7 @@ hw_ostc3_device_hardware (dc_device_t *abstract, unsigned char data[], unsigned
return rc;
// Send the command.
rc = hw_ostc3_transfer (device, NULL, HARDWARE, NULL, 0, data, size, NODELAY);
rc = hw_ostc3_device_id (device, data, size);
if (rc != DC_STATUS_SUCCESS)
return rc;