Beispiel #1
0
dc_status_t
hw_ostc_device_md2hash (dc_device_t *abstract, unsigned char data[], unsigned int size)
{
	hw_ostc_device_t *device = (hw_ostc_device_t *) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	if (size < SZ_MD2HASH) {
		ERROR (abstract->context, "Insufficient buffer space available.");
		return DC_STATUS_INVALIDARGS;
	}

	// Send the command.
	dc_status_t rc = hw_ostc_send (device, 'e', 0);
	if (rc != DC_STATUS_SUCCESS)
		return rc;

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

	return DC_STATUS_SUCCESS;
}
Beispiel #2
0
dc_status_t
hw_ostc_device_eeprom_write (dc_device_t *abstract, unsigned int bank, const unsigned char data[], unsigned int size)
{
	hw_ostc_device_t *device = (hw_ostc_device_t *) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	if (bank > 2) {
		ERROR (abstract->context, "Invalid eeprom bank specified.");
		return DC_STATUS_INVALIDARGS;
	}

	if (size != SZ_EEPROM) {
		ERROR (abstract->context, "Insufficient buffer space available.");
		return DC_STATUS_INVALIDARGS;
	}

	// Send the command.
	const unsigned char command[] = {'d', 'i', 'n'};
	dc_status_t rc = hw_ostc_send (device, command[bank], 1);
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	for (unsigned int i = 4; i < SZ_EEPROM; ++i) {
		// Send the data byte.
		rc = hw_ostc_send (device, data[i], 1);
		if (rc != DC_STATUS_SUCCESS)
			return rc;
	}

	return DC_STATUS_SUCCESS;
}
Beispiel #3
0
dc_status_t
hw_ostc_device_eeprom_read (dc_device_t *abstract, unsigned int bank, unsigned char data[], unsigned int size)
{
	hw_ostc_device_t *device = (hw_ostc_device_t *) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	if (bank > 2) {
		ERROR (abstract->context, "Invalid eeprom bank specified.");
		return DC_STATUS_INVALIDARGS;
	}

	if (size < SZ_EEPROM) {
		ERROR (abstract->context, "Insufficient buffer space available.");
		return DC_STATUS_INVALIDARGS;
	}

	// Send the command.
	const unsigned char command[] = {'g', 'j', 'm'};
	dc_status_t rc = hw_ostc_send (device, command[bank], 0);
	if (rc != DC_STATUS_SUCCESS)
		return rc;

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

	return DC_STATUS_SUCCESS;
}
Beispiel #4
0
dc_status_t
hw_ostc_device_clock (dc_device_t *abstract, const dc_datetime_t *datetime)
{
	hw_ostc_device_t *device = (hw_ostc_device_t *) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	if (datetime == NULL) {
		ERROR (abstract->context, "Invalid parameter specified.");
		return DC_STATUS_INVALIDARGS;
	}

	// Send the command.
	dc_status_t rc = hw_ostc_send (device, 'b', 1);
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	// Send the data packet.
	unsigned char packet[6] = {
		datetime->hour, datetime->minute, datetime->second,
		datetime->month, datetime->day, datetime->year - 2000};
	int n = serial_write (device->port, packet, sizeof (packet));
	if (n != sizeof (packet)) {
		ERROR (abstract->context, "Failed to send the data packet.");
		return EXITCODE (n);
	}

	return DC_STATUS_SUCCESS;
}
Beispiel #5
0
dc_status_t
uwatec_meridian_extract_dives (dc_device_t *abstract, const unsigned char data[], unsigned int size, dc_dive_callback_t callback, void *userdata)
{
	if (abstract && !ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	const unsigned char header[4] = {0xa5, 0xa5, 0x5a, 0x5a};

	// Search the data stream for start markers.
	unsigned int previous = size;
	unsigned int current = (size >= 4 ? size - 4 : 0);
	while (current > 0) {
		current--;
		if (memcmp (data + current, header, sizeof (header)) == 0) {
			// Get the length of the profile data.
			unsigned int len = array_uint32_le (data + current + 4);

			// Check for a buffer overflow.
			if (current + len > previous)
				return DC_STATUS_DATAFORMAT;

			if (callback && !callback (data + current, len, data + current + 8, 4, userdata))
				return DC_STATUS_SUCCESS;

			// Prepare for the next dive.
			previous = current;
			current = (current >= 4 ? current - 4 : 0);
		}
	}

	return DC_STATUS_SUCCESS;
}
Beispiel #6
0
dc_status_t
oceanic_vtpro_device_version (dc_device_t *abstract, unsigned char data[], unsigned int size)
{
	oceanic_vtpro_device_t *device = (oceanic_vtpro_device_t*) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	if (size < PAGESIZE)
		return DC_STATUS_INVALIDARGS;

	// Switch the device into download mode. The response is ignored here,
	// since it is identical (except for the missing trailing byte) to the
	// response of the first part of the other command in this function.

	unsigned char cmd[2] = {0x88, 0x00};
	unsigned char ans[PAGESIZE / 2 + 1] = {0};
	dc_status_t rc = oceanic_vtpro_transfer (device, cmd, sizeof (cmd), ans, sizeof (ans));
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	// Verify the checksum of the answer.
	unsigned char crc = ans[PAGESIZE / 2];
	unsigned char ccrc = checksum_add_uint4 (ans, PAGESIZE / 2, 0x00);
	if (crc != ccrc) {
		ERROR (abstract->context, "Unexpected answer checksum.");
		return DC_STATUS_PROTOCOL;
	}

	// Obtain the device identification string. This string is
	// split over two packets, but we join both parts again.

	for (unsigned int i = 0; i < 2; ++i) {
		unsigned char command[4] = {0x72, 0x03, i * 0x10, 0x00};
		unsigned char answer[PAGESIZE / 2 + 2] = {0};
		rc = oceanic_vtpro_transfer (device, command, sizeof (command), answer, sizeof (answer));
		if (rc != DC_STATUS_SUCCESS)
			return rc;

		// Verify the checksum of the answer.
		unsigned char crc = answer[PAGESIZE / 2];
		unsigned char ccrc = checksum_add_uint4 (answer, PAGESIZE / 2, 0x00);
		if (crc != ccrc) {
			ERROR (abstract->context, "Unexpected answer checksum.");
			return DC_STATUS_PROTOCOL;
		}

		// Verify the last byte of the answer.
		if (answer[PAGESIZE / 2 + 1] != END) {
			ERROR (abstract->context, "Unexpected answer byte.");
			return DC_STATUS_PROTOCOL;
		}

		// Append the answer to the output buffer.
		memcpy (data + i * PAGESIZE / 2, answer, PAGESIZE / 2);
	}

	return DC_STATUS_SUCCESS;
}
Beispiel #7
0
dc_status_t
atomics_cobalt_device_set_simulation (dc_device_t *abstract, unsigned int simulation)
{
	atomics_cobalt_device_t *device = (atomics_cobalt_device_t *) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	device->simulation = simulation;

	return DC_STATUS_SUCCESS;
}
dc_status_t
reefnet_sensus_parser_set_calibration (dc_parser_t *abstract, double atmospheric, double hydrostatic)
{
	reefnet_sensus_parser_t *parser = (reefnet_sensus_parser_t*) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	parser->atmospheric = atmospheric;
	parser->hydrostatic = hydrostatic;

	return DC_STATUS_SUCCESS;
}
Beispiel #9
0
dc_status_t
atomics_cobalt_device_version (dc_device_t *abstract, unsigned char data[], unsigned int size)
{
	atomics_cobalt_device_t *device = (atomics_cobalt_device_t *) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	if (size < SZ_VERSION)
		return DC_STATUS_INVALIDARGS;

#ifdef HAVE_LIBUSB
	// Send the command to the dive computer.
	uint8_t bRequest = 0x01;
	int rc = libusb_control_transfer (device->handle,
		LIBUSB_RECIPIENT_DEVICE | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT,
		bRequest, 0, 0, NULL, 0, TIMEOUT);
	if (rc != LIBUSB_SUCCESS) {
		ERROR (abstract->context, "Failed to send the command.");
		return EXITCODE(rc);
	}

	HEXDUMP (abstract->context, DC_LOGLEVEL_INFO, "Write", &bRequest, 1);

	// Receive the answer from the dive computer.
	int length = 0;
	unsigned char packet[SZ_VERSION + 2] = {0};
	rc = libusb_bulk_transfer (device->handle, 0x82,
		packet, sizeof (packet), &length, TIMEOUT);
	if (rc != LIBUSB_SUCCESS || length != sizeof (packet)) {
		ERROR (abstract->context, "Failed to receive the answer.");
		return EXITCODE(rc);
	}

	HEXDUMP (abstract->context, DC_LOGLEVEL_INFO, "Read", packet, length);

	// Verify the checksum of the packet.
	unsigned short crc = array_uint16_le (packet + SZ_VERSION);
	unsigned short ccrc = checksum_add_uint16 (packet, SZ_VERSION, 0x0);
	if (crc != ccrc) {
		ERROR (abstract->context, "Unexpected answer checksum.");
		return DC_STATUS_PROTOCOL;
	}

	memcpy (data, packet, SZ_VERSION);

	return DC_STATUS_SUCCESS;
#else
	return DC_STATUS_UNSUPPORTED;
#endif
}
dc_status_t
hw_ostc3_device_config_reset (dc_device_t *abstract)
{
	hw_ostc3_device_t *device = (hw_ostc3_device_t *) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	// Send the command.
	dc_status_t rc = hw_ostc3_transfer (device, NULL, RESET, NULL, 0, NULL, 0);
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	return DC_STATUS_SUCCESS;
}
Beispiel #11
0
dc_status_t
hw_ostc_device_reset (dc_device_t *abstract)
{
	hw_ostc_device_t *device = (hw_ostc_device_t *) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	// Send the command.
	dc_status_t rc = hw_ostc_send (device, 'h', 1);
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	return DC_STATUS_SUCCESS;
}
static dc_status_t
shearwater_predator_extract_dives (dc_device_t *abstract, const unsigned char data[], unsigned int size, dc_dive_callback_t callback, void *userdata)
{
	if (abstract && !ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	if (size < SZ_MEMORY)
		return DC_STATUS_DATAFORMAT;

	unsigned int model = data[0x2000D];

	if (model == PETREL) {
		return shearwater_predator_extract_petrel (abstract, data, size, callback, userdata);
	} else {
		return shearwater_predator_extract_predator (abstract, data, size, callback, userdata);
	}
}
Beispiel #13
0
dc_status_t
reefnet_sensus_device_get_handshake (dc_device_t *abstract, unsigned char data[], unsigned int size)
{
	reefnet_sensus_device_t *device = (reefnet_sensus_device_t*) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	if (size < SZ_HANDSHAKE) {
		ERROR (abstract->context, "Insufficient buffer space available.");
		return DC_STATUS_INVALIDARGS;
	}

	memcpy (data, device->handshake, SZ_HANDSHAKE);

	return DC_STATUS_SUCCESS;
}
dc_status_t
hw_ostc3_device_version (dc_device_t *abstract, unsigned char data[], unsigned int size)
{
	hw_ostc3_device_t *device = (hw_ostc3_device_t *) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	if (size != SZ_VERSION)
		return DC_STATUS_INVALIDARGS;

	// Send the command.
	dc_status_t rc = hw_ostc3_transfer (device, NULL, IDENTITY, NULL, 0, data, size);
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	return DC_STATUS_SUCCESS;
}
Beispiel #15
0
dc_status_t
hw_ostc_extract_dives (dc_device_t *abstract, const unsigned char data[], unsigned int size, dc_dive_callback_t callback, void *userdata)
{
	hw_ostc_device_t *device = (hw_ostc_device_t *) abstract;

	if (abstract && !ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	const unsigned char header[2] = {0xFA, 0xFA};
	const unsigned char footer[2] = {0xFD, 0xFD};

	// Initialize the data stream pointers.
	const unsigned char *current  = data + size;
	const unsigned char *previous = data + size;

	// Search the data stream for header markers.
	while ((current = array_search_backward (data + 266, current - data - 266, header, sizeof (header))) != NULL) {
		// Move the pointer to the begin of the header.
		current -= sizeof (header);

		// Once a header marker is found, start searching
		// for the corresponding footer marker. The search is
		// now limited to the start of the previous dive.
		previous = array_search_forward (current, previous - current, footer, sizeof (footer));

		if (previous) {
			// Move the pointer to the end of the footer.
			previous += sizeof (footer);

			if (device && memcmp (current + 3, device->fingerprint, sizeof (device->fingerprint)) == 0)
				return DC_STATUS_SUCCESS;

			if (callback && !callback (current, previous - current, current + 3, 5, userdata))
				return DC_STATUS_SUCCESS;
		}

		// Prepare for the next iteration.
		previous = current;
	}

	return DC_STATUS_SUCCESS;
}
dc_status_t
hw_ostc3_device_config_read (dc_device_t *abstract, unsigned int config, unsigned char data[], unsigned int size)
{
	hw_ostc3_device_t *device = (hw_ostc3_device_t *) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	if (size > SZ_CONFIG) {
		ERROR (abstract->context, "Invalid parameter specified.");
		return DC_STATUS_INVALIDARGS;
	}

	// Send the command.
	unsigned char command[1] = {config};
	dc_status_t rc = hw_ostc3_transfer (device, NULL, READ, command, sizeof (command), data, size);
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	return DC_STATUS_SUCCESS;
}
dc_status_t
hw_ostc3_device_customtext (dc_device_t *abstract, const char *text)
{
	hw_ostc3_device_t *device = (hw_ostc3_device_t *) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	// Pad the data packet with spaces.
	unsigned char packet[SZ_CUSTOMTEXT] = {0};
	if (hw_ostc3_strncpy (packet, sizeof (packet), text) != 0) {
		ERROR (abstract->context, "Invalid parameter specified.");
		return DC_STATUS_INVALIDARGS;
	}

	// Send the command.
	dc_status_t rc = hw_ostc3_transfer (device, NULL, CUSTOMTEXT, packet, sizeof (packet), NULL, 0);
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	return DC_STATUS_SUCCESS;
}
dc_status_t
hw_ostc3_device_clock (dc_device_t *abstract, const dc_datetime_t *datetime)
{
	hw_ostc3_device_t *device = (hw_ostc3_device_t *) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	if (datetime == NULL) {
		ERROR (abstract->context, "Invalid parameter specified.");
		return DC_STATUS_INVALIDARGS;
	}

	// Send the command.
	unsigned char packet[6] = {
		datetime->hour, datetime->minute, datetime->second,
		datetime->month, datetime->day, datetime->year - 2000};
	dc_status_t rc = hw_ostc3_transfer (device, NULL, CLOCK, packet, sizeof (packet), NULL, 0);
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	return DC_STATUS_SUCCESS;
}
Beispiel #19
0
dc_status_t
oceanic_vtpro_device_keepalive (dc_device_t *abstract)
{
	oceanic_vtpro_device_t *device = (oceanic_vtpro_device_t*) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	// Send the command to the dive computer.
	unsigned char answer[1] = {0};
	unsigned char command[4] = {0x6A, 0x08, 0x00, 0x00};
	dc_status_t rc = oceanic_vtpro_transfer (device, command, sizeof (command), answer, sizeof (answer));
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	// Verify the last byte of the answer.
	if (answer[0] != END) {
		ERROR (abstract->context, "Unexpected answer byte(s).");
		return DC_STATUS_PROTOCOL;
	}

	return DC_STATUS_SUCCESS;
}
Beispiel #20
0
int isUnicodeString(PyObject *arg)
{
    return (PyObject_TypeCheck(arg, &UObjectType_) &&
            ISINSTANCE(((t_uobject *) arg)->object, UnicodeString));
}
Beispiel #21
0
dc_status_t
reefnet_sensus_extract_dives (dc_device_t *abstract, const unsigned char data[], unsigned int size, dc_dive_callback_t callback, void *userdata)
{
	reefnet_sensus_device_t *device = (reefnet_sensus_device_t*) abstract;
	dc_context_t *context = (abstract ? abstract->context : NULL);

	if (abstract && !ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	// Search the entire data stream for start markers.
	unsigned int previous = size;
	unsigned int current = (size >= 7 ? size - 7 : 0);
	while (current > 0) {
		current--;
		if (data[current] == 0xFF && data[current + 6] == 0xFE) {
			// Once a start marker is found, start searching
			// for the end of the dive. The search is now
			// limited to the start of the previous dive.
			int found = 0;
			unsigned int nsamples = 0, count = 0;
			unsigned int offset = current + 7; // Skip non-sample data.
			while (offset + 1 <= previous) {
				// Depth (adjusted feet of seawater).
				unsigned char depth = data[offset++];

				// Temperature (degrees Fahrenheit)
				if ((nsamples % 6) == 0) {
					if (offset + 1 > previous)
						break;
					offset++;
				}

				// Current sample is complete.
				nsamples++;

				// The end of a dive is reached when 17 consecutive  
				// depth samples of less than 3 feet have been found.
				if (depth < 13 + 3) {
					count++;
					if (count == 17) {
						found = 1;
						break;
					}
				} else {
					count = 0;
				}
			}

			// Report an error if no end of dive was found.
			if (!found) {
				ERROR (context, "No end of dive found.");
				return DC_STATUS_DATAFORMAT;
			}

			// Automatically abort when a dive is older than the provided timestamp.
			unsigned int timestamp = array_uint32_le (data + current + 2);
			if (device && timestamp <= device->timestamp)
				return DC_STATUS_SUCCESS;

			if (callback && !callback (data + current, offset - current, data + current + 2, 4, userdata))
				return DC_STATUS_SUCCESS;

			// Prepare for the next dive.
			previous = current;
			current = (current >= 7 ? current - 7 : 0);
		}
	}

	return DC_STATUS_SUCCESS;
}
Beispiel #22
0
dc_status_t
hw_ostc_device_screenshot (dc_device_t *abstract, dc_buffer_t *buffer, hw_ostc_format_t format)
{
	hw_ostc_device_t *device = (hw_ostc_device_t *) abstract;

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

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

	// Bytes per pixel (RGB formats only).
	unsigned int bpp = 0;

	if (format == HW_OSTC_FORMAT_RAW) {
		// The RAW format has a variable size, depending on the actual image
		// content. Usually the total size is around 4K, which is used as an
		// initial guess and expanded when necessary.
		if (!dc_buffer_reserve (buffer, 4096)) {
			ERROR (abstract->context, "Insufficient buffer space available.");
			return DC_STATUS_NOMEMORY;
		}
	} else {
		// The RGB formats have a fixed size, depending only on the dimensions
		// and the number of bytes per pixel. The required amount of memory is
		// allocated immediately.
		bpp = (format == HW_OSTC_FORMAT_RGB16) ? 2 : 3;
		if (!dc_buffer_resize (buffer, WIDTH * HEIGHT * bpp)) {
			ERROR (abstract->context, "Insufficient buffer space available.");
			return DC_STATUS_NOMEMORY;
		}
	}

	// Enable progress notifications.
	dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
	progress.maximum = WIDTH * HEIGHT;
	device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);

	// Send the command.
	dc_status_t rc = hw_ostc_send (device, 'l', 1);
	if (rc != DC_STATUS_SUCCESS)
		return rc;

	// Cache the pointer to the image data (RGB formats only).
	unsigned char *image = dc_buffer_get_data (buffer);

	// The OSTC sends the image data in a column by column layout, which is
	// converted on the fly to a more convenient row by row layout as used
	// in the majority of image formats. This conversions requires knowledge
	// of the pixel coordinates.
	unsigned int x = 0, y = 0;

	unsigned int npixels = 0;
	while (npixels < WIDTH * HEIGHT) {
		unsigned char raw[3] = {0};
		int n = serial_read (device->port, raw, 1);
		if (n != 1) {
			ERROR (abstract->context, "Failed to receive the packet.");
			return EXITCODE (n);
		}

		unsigned int nbytes = n;
		unsigned int count = raw[0];
		if ((count & 0x80) == 0x00) {
			// Black pixel.
			raw[1] = raw[2] = BLACK;
			count &= 0x7F;
		} else if ((count & 0xC0) == 0xC0) {
			// White pixel.
			raw[1] = raw[2] = WHITE;
			count &= 0x3F;
		} else {
			// Color pixel.
			n = serial_read (device->port, raw + 1, 2);
			if (n != 2) {
				ERROR (abstract->context, "Failed to receive the packet.");
				return EXITCODE (n);
			}

			nbytes += n;
			count &= 0x3F;
		}
		count++;

		// Check for buffer overflows.
		if (npixels + count > WIDTH * HEIGHT) {
			ERROR (abstract->context, "Unexpected number of pixels received.");
			return DC_STATUS_DATAFORMAT;
		}

		if (format == HW_OSTC_FORMAT_RAW) {
			// Append the raw data to the output buffer.
			dc_buffer_append (buffer, raw, nbytes);
		} else {
			// Store the decompressed data in the output buffer.
			for (unsigned int i = 0; i < count; ++i) {
				// Calculate the offset to the current pixel (row layout)
				unsigned int offset = (y * WIDTH + x) * bpp;

				if (format == HW_OSTC_FORMAT_RGB16) {
					image[offset + 0] = raw[1];
					image[offset + 1] = raw[2];
				} else {
					unsigned int value = (raw[1] << 8) + raw[2];
					unsigned char r = (value & 0xF800) >> 11;
					unsigned char g = (value & 0x07E0) >> 5;
					unsigned char b = (value & 0x001F);
					image[offset + 0] = 255 * r / 31;
					image[offset + 1] = 255 * g / 63;
					image[offset + 2] = 255 * b / 31;
				}

				// Move to the next pixel coordinate (column layout).
				y++;
				if (y == HEIGHT) {
					y = 0;
					x++;
				}
			}
		}

		// Update and emit a progress event.
		progress.current += count;
		device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);

		npixels += count;
	}

	return DC_STATUS_SUCCESS;
}
Beispiel #23
0
/*
 * Think twice before modifying the code for updating the ostc firmware!
 * It has been carefully developed and tested with assistance from
 * Heinrichs-Weikamp, using a special development unit. If you start
 * experimenting with a normal unit and accidentally screw up, you might
 * brick the device permanently and turn it into an expensive
 * paperweight. You have been warned!
 */
dc_status_t
hw_ostc_device_fwupdate (dc_device_t *abstract, const char *filename)
{
	dc_status_t rc = DC_STATUS_SUCCESS;
	hw_ostc_device_t *device = (hw_ostc_device_t *) abstract;
	dc_context_t *context = (abstract ? abstract->context : NULL);

	if (!ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	// Allocate memory for the firmware data.
	hw_ostc_firmware_t *firmware = (hw_ostc_firmware_t *) malloc (sizeof (hw_ostc_firmware_t));
	if (firmware == NULL) {
		ERROR (context, "Failed to allocate memory.");
		return DC_STATUS_NOMEMORY;
	}

	// Read the hex file.
	rc = hw_ostc_firmware_readfile (firmware, context, filename);
	if (rc != DC_STATUS_SUCCESS) {
		ERROR (context, "Failed to read the firmware file.");
		free (firmware);
		return rc;
	}

	// Temporary set a relative short timeout. The command to setup the
	// bootloader needs to be send repeatedly, until the response packet is
	// received. Thus the time between each two attempts is directly controlled
	// by the timeout value.
	serial_set_timeout (device->port, 300);

	// Setup the bootloader.
	const unsigned int baudrates[] = {19200, 115200};
	for (unsigned int i = 0; i < C_ARRAY_SIZE(baudrates); ++i) {
		// Adjust the baudrate.
		if (serial_configure (device->port, baudrates[i], 8, SERIAL_PARITY_NONE, 1, SERIAL_FLOWCONTROL_NONE) == -1) {
			ERROR (abstract->context, "Failed to set the terminal attributes.");
			free (firmware);
			return DC_STATUS_IO;
		}

		// Try to setup the bootloader.
		unsigned int maxretries = (i == 0 ? 1 : MAXRETRIES);
		rc = hw_ostc_firmware_setup (device, maxretries);
		if (rc == DC_STATUS_SUCCESS)
			break;
	}
	if (rc != DC_STATUS_SUCCESS) {
		ERROR (abstract->context, "Failed to setup the bootloader.");
		free (firmware);
		return rc;
	}

	// Increase the timeout again.
	serial_set_timeout (device->port, 1000);

	// Enable progress notifications.
	dc_event_progress_t progress = EVENT_PROGRESS_INITIALIZER;
	progress.maximum = C_ARRAY_SIZE(firmware->bitmap);
	device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);

	for (unsigned int i = 0; i < C_ARRAY_SIZE(firmware->bitmap); ++i) {
		// Skip empty blocks.
		if (firmware->bitmap[i] == 0)
			continue;

		// Create the packet.
		unsigned int address = i * SZ_BLOCK;
		unsigned char packet[4 + SZ_BLOCK + 1] = {
			(address >> 16) & 0xFF,
			(address >>  8) & 0xFF,
			(address      ) & 0xFF,
			SZ_BLOCK
		};
		memcpy (packet + 4, firmware->data + address, SZ_BLOCK);
		packet[sizeof (packet) - 1] = ~checksum_add_uint8 (packet, 4 + SZ_BLOCK, 0x00) + 1;

		// Send the packet.
		rc = hw_ostc_firmware_write (device, packet, sizeof (packet));
		if (rc != DC_STATUS_SUCCESS) {
			ERROR (abstract->context, "Failed to send the packet.");
			free (firmware);
			return rc;
		}

		// Update and emit a progress event.
		progress.current = i + 1;
		device_event_emit (abstract, DC_EVENT_PROGRESS, &progress);
	}

	free (firmware);

	return DC_STATUS_SUCCESS;
}
dc_status_t
diverite_nitekq_extract_dives (dc_device_t *abstract, const unsigned char data[], unsigned int size, dc_dive_callback_t callback, void *userdata)
{
	diverite_nitekq_device_t *device = (diverite_nitekq_device_t *) abstract;
	dc_context_t *context = (abstract ? abstract->context : NULL);

	if (abstract && !ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	if (size < SZ_PACKET + SZ_MEMORY)
		return DC_STATUS_DATAFORMAT;

	// Skip the first packet. We don't need it for anything. It also
	// makes the logic easier because all offsets in the data are
	// relative to the real start of the memory (e.g. excluding this
	// artificial first block).
	data += SZ_PACKET;

	// Allocate memory.
	unsigned char *buffer = (unsigned char *) malloc (RB_PROFILE_END - RB_PROFILE_BEGIN);
	if (buffer == NULL) {
		ERROR (context, "Failed to allocate memory.");
		return DC_STATUS_NOMEMORY;
	}

	// Get the end of profile pointer.
	unsigned int eop = array_uint16_be(data + EOP);
	if (eop < RB_PROFILE_BEGIN || eop >= RB_PROFILE_END) {
		ERROR (context, "Invalid ringbuffer pointer detected.");
		free (buffer);
		return DC_STATUS_DATAFORMAT;
	}

	// When a new dive is added, the device moves all existing logbook
	// and address entries towards the end, such that the most recent
	// one is always the first one. This is not the case for the profile
	// data, which is added at the end.
	unsigned int previous = eop;
	for (unsigned int i = 0; i < 10; ++i) {
		// Get the pointer to the logbook entry.
		const unsigned char *p = data + LOGBOOK + i * SZ_LOGBOOK;

		// Abort if an empty logbook is found.
		if (array_isequal (p, SZ_LOGBOOK, 0x00))
			break;

		// Get the address of the profile data.
		unsigned int address = array_uint16_be(data + ADDRESS + i * 2);
		if (address < RB_PROFILE_BEGIN || address >= RB_PROFILE_END) {
			ERROR (context, "Invalid ringbuffer pointer detected.");
			free (buffer);
			return DC_STATUS_DATAFORMAT;
		}

		// Check the fingerprint data.
		if (device && memcmp (p, device->fingerprint, sizeof (device->fingerprint)) == 0)
			break;

		// Copy the logbook entry.
		memcpy (buffer, p, SZ_LOGBOOK);

		// Copy the profile data.
		unsigned int length = 0;
		if (previous > address) {
			length = previous - address;
			memcpy (buffer + SZ_LOGBOOK, data + address, length);
		} else {
			unsigned int len_a = RB_PROFILE_END - address;
			unsigned int len_b = previous - RB_PROFILE_BEGIN;
			length = len_a + len_b;
			memcpy (buffer + SZ_LOGBOOK, data + address, len_a);
			memcpy (buffer + SZ_LOGBOOK + len_a, data + RB_PROFILE_BEGIN, len_b);
		}

		if (callback && !callback (buffer, length + SZ_LOGBOOK, buffer, SZ_LOGBOOK, userdata)) {
			break;
		}

		previous = address;
	}

	free (buffer);

	return DC_STATUS_SUCCESS;
}
Beispiel #25
0
dc_status_t
cressi_leonardo_extract_dives (dc_device_t *abstract, const unsigned char data[], unsigned int size, dc_dive_callback_t callback, void *userdata)
{
	cressi_leonardo_device_t *device = (cressi_leonardo_device_t *) abstract;
	dc_context_t *context = (abstract ? abstract->context : NULL);

	if (abstract && !ISINSTANCE (abstract))
		return DC_STATUS_INVALIDARGS;

	if (size < SZ_MEMORY)
		return DC_STATUS_DATAFORMAT;

	// Locate the most recent dive.
	// The device maintains an internal counter which is incremented for every
	// dive, and the current value at the time of the dive is stored in the
	// dive header. Thus the most recent dive will have the highest value.
	unsigned int count = 0;
	unsigned int latest = 0;
	unsigned int maximum = 0;
	for (unsigned int i = 0; i < RB_LOGBOOK_COUNT; ++i) {
		unsigned int offset = RB_LOGBOOK_BEGIN + i * RB_LOGBOOK_SIZE;

		// Ignore uninitialized header entries.
		if (array_isequal (data + offset, RB_LOGBOOK_SIZE, 0xFF))
			break;

		// Get the internal dive number.
		unsigned int current = array_uint16_le (data + offset);
		if (current > maximum) {
			maximum = current;
			latest = i;
		}

		count++;
	}

	unsigned char *buffer = (unsigned char *) malloc (RB_LOGBOOK_SIZE + RB_PROFILE_END - RB_PROFILE_BEGIN);
	if (buffer == NULL) {
		ERROR (context, "Failed to allocate memory.");
		return DC_STATUS_NOMEMORY;
	}

	for (unsigned int i = 0; i < count; ++i) {
		unsigned int idx = (latest + RB_LOGBOOK_COUNT - i) % RB_LOGBOOK_COUNT;
		unsigned int offset = RB_LOGBOOK_BEGIN + idx * RB_LOGBOOK_SIZE;

		// Get the ringbuffer pointers.
		unsigned int header = array_uint16_le (data + offset + 2);
		unsigned int footer = array_uint16_le (data + offset + 4);
		if (header < RB_PROFILE_BEGIN || header + 2 > RB_PROFILE_END ||
			footer < RB_PROFILE_BEGIN || footer + 2 > RB_PROFILE_END)
		{
			ERROR (abstract->context, "Invalid ringbuffer pointer detected.");
			free (buffer);
			return DC_STATUS_DATAFORMAT;
		}

		// Get the same pointers from the profile.
		unsigned int header2 = array_uint16_le (data + footer);
		unsigned int footer2 = array_uint16_le (data + header);
		if (header2 != header || footer2 != footer) {
			ERROR (abstract->context, "Invalid ringbuffer pointer detected.");
			free (buffer);
			return DC_STATUS_DATAFORMAT;
		}

		// Calculate the profile address and length.
		unsigned int address = header + 2;
		unsigned int length = RB_PROFILE_DISTANCE (header, footer) - 2;

		// Check the fingerprint data.
		if (device && memcmp (data + offset + 8, device->fingerprint, sizeof (device->fingerprint)) == 0)
			break;

		// Copy the logbook entry.
		memcpy (buffer, data + offset, RB_LOGBOOK_SIZE);

		// Copy the profile data.
		if (address + length > RB_PROFILE_END) {
			unsigned int len_a = RB_PROFILE_END - address;
			unsigned int len_b = length - len_a;
			memcpy (buffer + RB_LOGBOOK_SIZE, data + address, len_a);
			memcpy (buffer + RB_LOGBOOK_SIZE + len_a, data + RB_PROFILE_BEGIN, len_b);
		} else {
			memcpy (buffer + RB_LOGBOOK_SIZE, data + address, length);
		}

		if (callback && !callback (buffer, RB_LOGBOOK_SIZE + length, buffer + 8, sizeof (device->fingerprint), userdata)) {
			break;
		}
	}

	free (buffer);

	return DC_STATUS_SUCCESS;
}