Пример #1
0
static gboolean
_write_memory (ArvUvDevice *uv_device, guint64 address, guint32 size, void *buffer, GError **error)
{
	ArvUvcpPacket *packet;
	void *read_packet;
	size_t packet_size;
	size_t read_packet_size;
	gboolean success = FALSE;
	unsigned n_tries = 0;
	guint32 timeout_ms = 0;

	read_packet_size = arv_uvcp_packet_get_write_memory_ack_size ();
	if (read_packet_size > uv_device->priv->ack_packet_size_max) {
		arv_debug_device ("Invalid acknowledge packet size (%d / max: %d)",
				  read_packet_size, uv_device->priv->ack_packet_size_max);
		return FALSE;
	}

	packet = arv_uvcp_packet_new_write_memory_cmd (address, size, 0, &packet_size);
	if (packet_size > uv_device->priv->cmd_packet_size_max) {
		arv_debug_device ("Invalid command packet size (%d / max: %d)", packet_size, uv_device->priv->cmd_packet_size_max);
		arv_uvcp_packet_free (packet);
		return FALSE;
	}

	memcpy (arv_uvcp_packet_get_write_memory_cmd_data (packet), buffer, size);
	read_packet = g_malloc (read_packet_size);

	do {
		GError *error = NULL;
		size_t transferred;

		uv_device->priv->packet_id = arv_uvcp_next_packet_id (uv_device->priv->packet_id);
		arv_uvcp_packet_set_packet_id (packet, uv_device->priv->packet_id);

		arv_uvcp_packet_debug (packet, ARV_DEBUG_LEVEL_LOG);

		success = TRUE;
		success = success && arv_uv_device_bulk_transfer (uv_device, ARV_UV_ENDPOINT_CONTROL, LIBUSB_ENDPOINT_OUT,
								  packet, packet_size, NULL, 0, &error);
		if (success ) {
			gboolean expected_answer;

			do {
				success = TRUE;
				success = success && arv_uv_device_bulk_transfer (uv_device, ARV_UV_ENDPOINT_CONTROL, LIBUSB_ENDPOINT_IN,
										  read_packet, read_packet_size, &transferred,
										  timeout_ms, &error);

				if (success) {
					ArvUvcpPacketType packet_type;
					ArvUvcpCommand command;
					guint16 packet_id;

					packet_type = arv_uvcp_packet_get_packet_type (read_packet);
					command = arv_uvcp_packet_get_command (read_packet);
					packet_id = arv_uvcp_packet_get_packet_id (read_packet);

					if (command == ARV_UVCP_COMMAND_PENDING_ACK) {
						expected_answer = FALSE;
						timeout_ms = arv_uvcp_packet_get_pending_ack_timeout (read_packet);

						arv_log_device ("[UvDevice::write_memory] Pending ack timeout = %d", timeout_ms);
					} else
						expected_answer = packet_type == ARV_UVCP_PACKET_TYPE_ACK &&
							command == ARV_UVCP_COMMAND_WRITE_MEMORY_ACK &&
							packet_id == uv_device->priv->packet_id;
				} else {
					expected_answer = FALSE;
					if (error != NULL)
						g_warning ("[UvDevice::write_memory] Ack reception error: %s", error->message);
					g_clear_error (&error);
				}

			} while (success && !expected_answer);

			success = success && expected_answer;

			if (success)
				arv_uvcp_packet_debug (read_packet, ARV_DEBUG_LEVEL_LOG);
		} else {
			if (error != NULL)
				g_warning ("[UvDevice::write_memory] Command sending error: %s", error->message);
			g_clear_error (&error);
		}

		n_tries++;
	} while (!success && n_tries < ARV_UV_DEVICE_N_TRIES_MAX);

	g_free (read_packet);
	arv_uvcp_packet_free (packet);

	if (!success) {
		if (error != NULL && *error == NULL)
			*error = g_error_new (ARV_DEVICE_ERROR, ARV_DEVICE_STATUS_TIMEOUT,
					      "[ArvDevice::write_memory] Timeout");
	}

	return success;
}
Пример #2
0
static void *
arv_uv_stream_thread (void *data)
{
	ArvUvStreamThreadData *thread_data = data;
	ArvUvspPacket *packet;
	ArvBuffer *buffer = NULL;
	void *incoming_buffer;
	guint64 offset;
	size_t transferred;

	arv_log_stream_thread ("Start USB3Vision stream thread");

	incoming_buffer = g_malloc (MAXIMUM_TRANSFER_SIZE);

	if (thread_data->callback != NULL)
		thread_data->callback (thread_data->user_data, ARV_STREAM_CALLBACK_TYPE_INIT, NULL);

	offset = 0;

	while (!thread_data->cancel) {
		size_t size;
		transferred = 0;

		if (buffer == NULL)
			size = thread_data->leader_size;
		else {
			if (offset < buffer->priv->size)
				size = MIN (thread_data->payload_size, buffer->priv->size - offset);
			else
				size = thread_data->trailer_size;
		}

		/* Avoid unnecessary memory copy by transferring data directly to the image buffer */
		if (buffer != NULL &&
		    buffer->priv->status == ARV_BUFFER_STATUS_FILLING &&
		    offset + size <= buffer->priv->size)
			packet = buffer->priv->data + offset;
		else
			packet = incoming_buffer;

		arv_uv_device_bulk_transfer (thread_data->uv_device, 0x81 | LIBUSB_ENDPOINT_IN,
					     packet, size, &transferred, 0, NULL);

		if (transferred > 0) {
			ArvUvspPacketType packet_type;

			arv_log_sp ("Received %d bytes", transferred);
			arv_uvsp_packet_debug (packet, ARV_DEBUG_LEVEL_LOG);

			packet_type = arv_uvsp_packet_get_packet_type (packet);
			switch (packet_type) {
				case ARV_UVSP_PACKET_TYPE_LEADER:
					if (buffer != NULL) {
						arv_debug_stream_thread ("New leader received while a buffer is still open");
						buffer->priv->status = ARV_BUFFER_STATUS_MISSING_PACKETS;
						arv_stream_push_output_buffer (thread_data->stream, buffer);
						thread_data->n_failures++;
						buffer = NULL;
					}
					buffer = arv_stream_pop_input_buffer (thread_data->stream);
					if (buffer != NULL) {
						buffer->priv->status = ARV_BUFFER_STATUS_FILLING;
						buffer->priv->gvsp_payload_type = ARV_GVSP_PAYLOAD_TYPE_IMAGE;
						arv_uvsp_packet_get_region (packet,
									    &buffer->priv->width,
									    &buffer->priv->height,
									    &buffer->priv->x_offset,
									    &buffer->priv->y_offset);
						buffer->priv->frame_id = arv_uvsp_packet_get_frame_id (packet);
						buffer->priv->timestamp_ns = arv_uvsp_packet_get_timestamp (packet);
						offset = 0;
					} else
						thread_data->n_underruns++;
					break;
				case ARV_UVSP_PACKET_TYPE_TRAILER:
					if (buffer != NULL) {
						arv_log_stream_thread ("Received %" G_GUINT64_FORMAT
								       " bytes - expected %" G_GUINT64_FORMAT,
								       offset, buffer->priv->size);
						buffer->priv->status = ARV_BUFFER_STATUS_SUCCESS;
						arv_stream_push_output_buffer (thread_data->stream, buffer);
						thread_data->n_completed_buffers++;
						buffer = NULL;
					}
					break;
				case ARV_UVSP_PACKET_TYPE_DATA:
					if (buffer != NULL && buffer->priv->status == ARV_BUFFER_STATUS_FILLING) {
						if (offset + transferred <= buffer->priv->size) {
							if (packet == incoming_buffer)
								memcpy (((char *) buffer->priv->data) + offset, packet, transferred);
							offset += transferred;
						} else
							buffer->priv->status = ARV_BUFFER_STATUS_SIZE_MISMATCH;
					}
					break;
				default:
					arv_debug_stream_thread ("Unkown packet type");
					break;
			}
		}
	}

	if (thread_data->callback != NULL)
		thread_data->callback (thread_data->user_data, ARV_STREAM_CALLBACK_TYPE_EXIT, NULL);

	g_free (incoming_buffer);

	arv_log_stream_thread ("Stop USB3Vision stream thread");

	return NULL;
}