static void * arv_gv_device_heartbeat_thread (void *data) { ArvGvDeviceHeartbeatData *thread_data = data; ArvGvDeviceIOData *io_data = thread_data->io_data; GTimer *timer; guint32 value; timer = g_timer_new (); do { g_usleep (thread_data->period_us); if (io_data->is_controller) { guint counter = 1; /* TODO: Instead of reading the control register, Pylon does write the heartbeat * timeout value, which is interresting, as doing this we could get an error * ack packet which will indicate we lost the control access. */ g_timer_start (timer); while (!_read_register (io_data, ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_OFFSET, &value, NULL) && g_timer_elapsed (timer, NULL) < ARV_GV_DEVICE_HEARTBEAT_RETRY_TIMEOUT_S && !thread_data->cancel) { g_usleep (ARV_GV_DEVICE_HEARTBEAT_RETRY_DELAY_US); counter++; } if (!thread_data->cancel) { arv_log_device ("[GvDevice::Heartbeat] Ack value = %d", value); if (counter > 1) arv_log_device ("[GvDevice::Heartbeat] Tried %u times", counter); if ((value & (ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_CONTROL | ARV_GVBS_CONTROL_CHANNEL_PRIVILEGE_EXCLUSIVE)) == 0) { arv_warning_device ("[GvDevice::Heartbeat] Control access lost"); arv_device_emit_control_lost_signal (ARV_DEVICE (thread_data->gv_device)); io_data->is_controller = FALSE; } } else io_data->is_controller = FALSE; } } while (!thread_data->cancel); g_timer_destroy (timer); return NULL; }
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; }