Ejemplo n.º 1
0
device_status_t
suunto_common2_device_write (device_t *abstract, unsigned int address, const unsigned char data[], unsigned int size)
{
	// The data transmission is split in packages
	// of maximum $SZ_PACKET bytes.

	unsigned int nbytes = 0;
	while (nbytes < size) {
		// Calculate the package size.
		unsigned int len = size - nbytes;
		if (len > SZ_PACKET)
			len = SZ_PACKET;

		// Write the package.
		unsigned char answer[7] = {0};
		unsigned char command[SZ_PACKET + 7] = {0x06, 0x00, len + 3,
				(address >> 8) & 0xFF, // high
				(address     ) & 0xFF, // low
				len, // count
				0};  // data + CRC
		memcpy (command + 6, data, len);
		command[len + 6] = checksum_xor_uint8 (command, len + 6, 0x00);
		device_status_t rc = suunto_common2_transfer (abstract, command, len + 7, answer, sizeof (answer), 0);
		if (rc != DEVICE_STATUS_SUCCESS)
			return rc;

		nbytes += len;
		address += len;
		data += len;
	}

	return DEVICE_STATUS_SUCCESS;
}
Ejemplo n.º 2
0
static dc_status_t
uwatec_meridian_transfer (uwatec_meridian_device_t *device, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize)
{
	dc_device_t *abstract = (dc_device_t *) device;

	assert (csize > 0 && csize <= 255);

	// Build the packet.
	unsigned char packet[255 + 12] = {
		0xFF, 0xFF, 0xFF,
		0xA6, 0x59, 0xBD, 0xC2,
		0x00, /* length */
		0x00, 0x00, 0x00,
		0x00}; /* data and checksum */
	memcpy (packet + 11, command, csize);
	packet[7] = csize;
	packet[11 + csize] = checksum_xor_uint8 (packet + 7, csize + 4, 0x00);

	// Send the packet.
	int n = serial_write (device->port, packet, csize + 12);
	if (n != csize + 12) {
		ERROR (abstract->context, "Failed to send the command.");
		return EXITCODE (n);
	}

	// Read the echo.
	unsigned char echo[sizeof(packet)];
	n = serial_read (device->port, echo, csize + 12);
	if (n != csize + 12) {
		ERROR (abstract->context, "Failed to receive the echo.");
		return EXITCODE (n);
	}

	// Verify the echo.
	if (memcmp (echo, packet, csize + 12) != 0) {
		WARNING (abstract->context, "Unexpected echo.");
		return DC_STATUS_PROTOCOL;
	}

	// Read the header.
	unsigned char header[6];
	n = serial_read (device->port, header, sizeof (header));
	if (n != sizeof (header)) {
		ERROR (abstract->context, "Failed to receive the header.");
		return EXITCODE (n);
	}

	// Verify the header.
	if (header[0] != ACK || array_uint32_le (header + 1) != asize + 1 || header[5] != packet[11]) {
		WARNING (abstract->context, "Unexpected header.");
		return DC_STATUS_PROTOCOL;
	}

	// Read the packet.
	n = serial_read (device->port, answer, asize);
	if (n != asize) {
		ERROR (abstract->context, "Failed to receive the packet.");
		return EXITCODE (n);
	}

	// Read the checksum.
	unsigned char csum = 0x00;
	n = serial_read (device->port, &csum, sizeof (csum));
	if (n != sizeof (csum)) {
		ERROR (abstract->context, "Failed to receive the checksum.");
		return EXITCODE (n);
	}

	// Verify the checksum.
	unsigned char ccsum = 0x00;
	ccsum = checksum_xor_uint8 (header + 1, sizeof (header) - 1, ccsum);
	ccsum = checksum_xor_uint8 (answer, asize, ccsum);
	if (csum != ccsum) {
		ERROR (abstract->context, "Unexpected answer checksum.");
		return DC_STATUS_PROTOCOL;
	}

	return DC_STATUS_SUCCESS;
}
Ejemplo n.º 3
0
static dc_status_t
uwatec_meridian_device_dump (dc_device_t *abstract, dc_buffer_t *buffer)
{
	uwatec_meridian_device_t *device = (uwatec_meridian_device_t*) abstract;
	dc_status_t rc = DC_STATUS_SUCCESS;

	// Erase the current contents of the buffer.
	if (!dc_buffer_clear (buffer)) {
		ERROR (abstract->context, "Insufficient buffer space available.");
		return DC_STATUS_NOMEMORY;
	}

	// Enable progress notifications.
	dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
	device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress);

	// Command template.
	unsigned char command[9] = {0x00,
			(device->timestamp      ) & 0xFF,
			(device->timestamp >> 8 ) & 0xFF,
			(device->timestamp >> 16) & 0xFF,
			(device->timestamp >> 24) & 0xFF,
			0x10,
			0x27,
			0,
			0};

	// Read the model number.
	command[0] = 0x10;
	unsigned char model[1] = {0};
	rc = uwatec_meridian_transfer (device, command, 1, model, sizeof (model));
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	// Read the serial number.
	command[0] = 0x14;
	unsigned char serial[4] = {0};
	rc = uwatec_meridian_transfer (device, command, 1, serial, sizeof (serial));
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	// Read the device clock.
	command[0] = 0x1A;
	unsigned char devtime[4] = {0};
	rc = uwatec_meridian_transfer (device, command, 1, devtime, sizeof (devtime));
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	// Store the clock calibration values.
	device->systime = dc_datetime_now ();
	device->devtime = array_uint32_le (devtime);

	// Update and emit a progress event.
	progress.current += 9;
	device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress);

	// Emit a clock event.
	dc_event_clock_t clock;
	clock.systime = device->systime;
	clock.devtime = device->devtime;
	device_event_emit (&device->base, DC_EVENT_CLOCK, &clock);

	// Emit a device info event.
	dc_event_devinfo_t devinfo;
	devinfo.model = model[0];
	devinfo.firmware = 0;
	devinfo.serial = array_uint32_le (serial);
	device_event_emit (&device->base, DC_EVENT_DEVINFO, &devinfo);

	// Data Length.
	command[0] = 0xC6;
	unsigned char answer[4] = {0};
	rc = uwatec_meridian_transfer (device, command, sizeof (command), answer, sizeof (answer));
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	unsigned int length = array_uint32_le (answer);

	// Update and emit a progress event.
	progress.maximum = 4 + 9 + (length ? length + 4 : 0);
	progress.current += 4;
	device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress);

	if (length == 0)
		return DC_STATUS_SUCCESS;

	// Allocate the required amount of memory.
	if (!dc_buffer_resize (buffer, length)) {
		ERROR (abstract->context, "Insufficient buffer space available.");
		return DC_STATUS_NOMEMORY;
	}

	unsigned char *data = dc_buffer_get_data (buffer);

	// Data.
	command[0] = 0xC4;
	rc = uwatec_meridian_transfer (device, command, sizeof (command), answer, sizeof (answer));
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	unsigned int total = array_uint32_le (answer);

	// Update and emit a progress event.
	progress.current += 4;
	device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress);

	if (total != length + 4) {
		ERROR (abstract->context, "Received an unexpected size.");
		return DC_STATUS_PROTOCOL;
	}

	unsigned int nbytes = 0;
	while (nbytes < length) {

		// Read the header.
		unsigned char header[5];
		int n = serial_read (device->port, header, sizeof (header));
		if (n != sizeof (header)) {
			ERROR (abstract->context, "Failed to receive the header.");
			return EXITCODE (n);
		}

		// Get the packet size.
		unsigned int packetsize = array_uint32_le (header);
		if (packetsize < 1 || nbytes + packetsize - 1 > length) {
			WARNING (abstract->context, "Unexpected header.");
			return DC_STATUS_PROTOCOL;
		}

		// Read the packet data.
		n = serial_read (device->port, data + nbytes, packetsize - 1);
		if (n != packetsize - 1) {
			ERROR (abstract->context, "Failed to receive the packet.");
			return EXITCODE (n);
		}

		// Read the checksum.
		unsigned char csum = 0x00;
		n = serial_read (device->port, &csum, sizeof (csum));
		if (n != sizeof (csum)) {
			ERROR (abstract->context, "Failed to receive the checksum.");
			return EXITCODE (n);
		}

		// Verify the checksum.
		unsigned char ccsum = 0x00;
		ccsum = checksum_xor_uint8 (header, sizeof (header), ccsum);
		ccsum = checksum_xor_uint8 (data + nbytes, packetsize - 1, ccsum);
		if (csum != ccsum) {
			ERROR (abstract->context, "Unexpected answer checksum.");
			return DC_STATUS_PROTOCOL;
		}


		// Update and emit a progress event.
		progress.current += packetsize - 1;
		device_event_emit (&device->base, DC_EVENT_PROGRESS, &progress);

		nbytes += packetsize - 1;
	}

	return DC_STATUS_SUCCESS;
}
Ejemplo n.º 4
0
static device_status_t
suunto_d9_device_packet (device_t *abstract, const unsigned char command[], unsigned int csize, unsigned char answer[], unsigned int asize, unsigned int size)
{
	suunto_d9_device_t *device = (suunto_d9_device_t *) abstract;

	if (device_is_cancelled (abstract))
		return DEVICE_STATUS_CANCELLED;

	// Clear RTS to send the command.
	serial_set_rts (device->port, 0);

	// Send the command to the dive computer.
	int n = serial_write (device->port, command, csize);
	if (n != csize) {
		WARNING ("Failed to send the command.");
		return EXITCODE (n);
	}

	// Wait until all data has been transmitted.
	serial_drain (device->port);

	// Receive the echo.
	unsigned char echo[128] = {0};
	assert (sizeof (echo) >= csize);
	n = serial_read (device->port, echo, csize);
	if (n != csize) {
		WARNING ("Failed to receive the echo.");
		return EXITCODE (n);
	}

	// Verify the echo.
	if (memcmp (command, echo, csize) != 0) {
		WARNING ("Unexpected echo.");
		return DEVICE_STATUS_PROTOCOL;
	}

	// Set RTS to receive the reply.
	serial_set_rts (device->port, 1);

	// Receive the answer of the dive computer.
	n = serial_read (device->port, answer, asize);
	if (n != asize) {
		WARNING ("Failed to receive the answer.");
		return EXITCODE (n);
	}

	// Verify the header of the package.
	if (answer[0] != command[0]) {
		WARNING ("Unexpected answer header.");
		return DEVICE_STATUS_PROTOCOL;
	}

	// Verify the size of the package.
	if (array_uint16_be (answer + 1) + 4 != asize) {
		WARNING ("Unexpected answer size.");
		return DEVICE_STATUS_PROTOCOL;
	}

	// Verify the parameters of the package.
	if (memcmp (command + 3, answer + 3, asize - size - 4) != 0) {
		WARNING ("Unexpected answer parameters.");
		return DEVICE_STATUS_PROTOCOL;
	}

	// Verify the checksum of the package.
	unsigned char crc = answer[asize - 1];
	unsigned char ccrc = checksum_xor_uint8 (answer, asize - 1, 0x00);
	if (crc != ccrc) {
		WARNING ("Unexpected answer CRC.");
		return DEVICE_STATUS_PROTOCOL;
	}

	return DEVICE_STATUS_SUCCESS;
}