[aravis/wip/emmanuel/usb3vision: 7/7] wip: load u3v genicam
- From: Emmanuel Pacaud <emmanuel src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [aravis/wip/emmanuel/usb3vision: 7/7] wip: load u3v genicam
- Date: Tue, 17 May 2016 15:45:16 +0000 (UTC)
commit 159cf9bbe7dcca9fd95356fa60b2ba7e8fef2e7c
Author: Emmanuel Pacaud <emmanuel gnome org>
Date: Mon May 16 21:57:25 2016 +0200
wip: load u3v genicam
src/Makefile.am | 6 +
src/arvdeviceprivate.h | 2 +-
src/arvsystem.c | 12 +-
src/arvuvcp.c | 228 ++++++++++++++++++++++++++++++++++++++++++++
src/arvuvcp.h | 249 ++++++++++++++++++++++++++++++++++++++++++++++++
src/arvuvdevice.c | 241 ++++++++++++++++++++++++++++++++++++++++++++--
src/arvuvdevice.h | 2 +-
src/arvuvinterface.c | 103 ++++++++++++++++++--
8 files changed, 816 insertions(+), 27 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 26e2bf5..346d406 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -162,10 +162,16 @@ ARAVIS_SRCS += \
arvuvdevice.c \
arvuvstream.c
+ARAVIS_SRCS_NO_INTRO += \
+ arvuvcp.c
+
ARAVIS_HDRS += \
arvuvinterface.h \
arvuvdevice.h \
arvuvstream.h
+
+ARAVIS_HDRS_NO_INTRO += \
+ arvuvcp.h
endif
arv_fake_cameradir = $(aravis_datadir)
diff --git a/src/arvdeviceprivate.h b/src/arvdeviceprivate.h
index ace2e7d..cc72d72 100644
--- a/src/arvdeviceprivate.h
+++ b/src/arvdeviceprivate.h
@@ -23,7 +23,7 @@
#ifndef ARV_DEVICE_PRIVATE_H
#define ARV_DEVICE_PRIVATE_H
-#include <arvdeviceprivate.h>
+#include <arvdevice.h>
G_BEGIN_DECLS
diff --git a/src/arvsystem.c b/src/arvsystem.c
index 4799155..7f3e7a6 100644
--- a/src/arvsystem.c
+++ b/src/arvsystem.c
@@ -44,18 +44,18 @@ ArvInterfaceInfos interfaces[] = {
.get_interface_instance = arv_fake_interface_get_instance,
.destroy_interface_instance = arv_fake_interface_destroy_instance
},
- { .interface_id = "GigEVision",
- .is_available = TRUE,
- .get_interface_instance = arv_gv_interface_get_instance,
- .destroy_interface_instance = arv_gv_interface_destroy_instance
- },
#ifdef ARAVIS_BUILD_USB
{ .interface_id = "USB3Vision",
.is_available = TRUE,
.get_interface_instance = arv_uv_interface_get_instance,
.destroy_interface_instance = arv_uv_interface_destroy_instance
- }
+ },
#endif
+ { .interface_id = "GigEVision",
+ .is_available = TRUE,
+ .get_interface_instance = arv_gv_interface_get_instance,
+ .destroy_interface_instance = arv_gv_interface_destroy_instance
+ }
};
unsigned int
diff --git a/src/arvuvcp.c b/src/arvuvcp.c
new file mode 100644
index 0000000..f87a52c
--- /dev/null
+++ b/src/arvuvcp.c
@@ -0,0 +1,228 @@
+/* Aravis - Digital camera library
+ *
+ * Copyright © 2009-2016 Emmanuel Pacaud
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Author: Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+/**
+ * SECTION: arvuvcp
+ * @short_description: Uvcp packet handling (control)
+ */
+
+#include <arvuvcp.h>
+#include <arvenumtypes.h>
+#include <arvdebug.h>
+#include <arvstr.h>
+#include <string.h>
+
+#define ARV_UVCP_MAGIC 0x43563355
+
+void
+arv_uvcp_packet_free (ArvUvcpPacket *packet)
+{
+ g_free (packet);
+}
+
+/**
+ * arv_uvcp_packet_new_read_memory_cmd: (skip)
+ * @address: read address
+ * @size: read size, in bytes
+ * @packet_id: packet id
+ * @packet_size: (out): packet size, in bytes
+ * Return value: (transfer full): a new #ArvUvcpPacket
+ *
+ * Create a uvcp packet for a memory read command.
+ */
+
+ArvUvcpPacket *
+arv_uvcp_packet_new_read_memory_cmd (guint32 address, guint32 size, guint16 packet_id, size_t *packet_size)
+{
+ ArvUvcpReadMemoryCmd *packet;
+
+ g_return_val_if_fail (packet_size != NULL, NULL);
+
+ *packet_size = sizeof (ArvUvcpReadMemoryCmd);
+
+ packet = g_malloc (*packet_size);
+
+ packet->header.magic = GUINT32_TO_LE (ARV_UVCP_MAGIC);
+ packet->header.packet_type = GUINT16_TO_LE (ARV_UVCP_PACKET_TYPE_CMD);
+ packet->header.command = GUINT16_TO_LE (ARV_UVCP_COMMAND_READ_MEMORY_CMD);
+ packet->header.size = GUINT16_TO_LE (sizeof (ArvUvcpReadMemoryCmdInfos));
+ packet->header.id = GUINT16_TO_LE (packet_id);
+ packet->infos.address = GUINT64_TO_LE (address);
+ packet->infos.size = GUINT16_TO_LE (size);
+
+ return (ArvUvcpPacket *) packet;
+}
+
+/**
+ * arv_uvcp_packet_new_write_memory_cmd: (skip)
+ * @address: write address
+ * @size: write size, in bytes
+ * @packet_id: packet id
+ * @packet_size: (out): packet size, in bytes
+ * Return value: (transfer full): a new #ArvUvcpPacket
+ *
+ * Create a uvcp packet for a memory write command.
+ */
+
+ArvUvcpPacket *
+arv_uvcp_packet_new_write_memory_cmd (guint32 address, guint32 size, guint16 packet_id, size_t *packet_size)
+{
+ ArvUvcpPacket *packet;
+ guint32 n_address = g_htonl (address);
+
+ g_return_val_if_fail (packet_size != NULL, NULL);
+
+ *packet_size = sizeof (ArvUvcpHeader) + sizeof (guint32) + size;
+
+ packet = g_malloc (*packet_size);
+
+ packet->header.packet_type = g_htons (ARV_UVCP_PACKET_TYPE_CMD);
+ packet->header.command = g_htons (ARV_UVCP_COMMAND_WRITE_MEMORY_CMD);
+ packet->header.size = g_htons (sizeof (guint32) + size);
+ packet->header.id = g_htons (packet_id);
+
+ memcpy (&packet->data, &n_address, sizeof (guint32));
+
+ return packet;
+}
+
+static const char *
+arv_enum_to_string (GType type,
+ guint enum_value)
+{
+ GEnumClass *enum_class;
+ GEnumValue *value;
+ const char *retval = NULL;
+
+ enum_class = g_type_class_ref (type);
+
+ value = g_enum_get_value (enum_class, enum_value);
+ if (value)
+ retval = value->value_nick;
+
+ g_type_class_unref (enum_class);
+
+ return retval;
+}
+
+static const char *
+arv_uvcp_packet_type_to_string (ArvUvcpPacketType value)
+{
+ return arv_enum_to_string (ARV_TYPE_UVCP_PACKET_TYPE, value);
+}
+
+static const char *
+arv_uvcp_command_to_string (ArvUvcpCommand value)
+{
+ return arv_enum_to_string (ARV_TYPE_UVCP_COMMAND, value);
+}
+
+/**
+ * arv_uvcp_packet_to_string:
+ * @packet: a #ArvUvcpPacket
+ *
+ * Converts @packet into a human readable string.
+ *
+ * return value: (transfer full): A newly allocated string.
+ */
+
+char *
+arv_uvcp_packet_to_string (const ArvUvcpPacket *packet)
+{
+ GString *string;
+ char *c_string;
+ int packet_size;
+ guint32 value;
+
+ g_return_val_if_fail (packet != NULL, NULL);
+
+ string = g_string_new ("");
+
+ g_string_append_printf (string, "packet_type = %s\n",
+ arv_uvcp_packet_type_to_string (GUINT16_FROM_LE
(packet->header.packet_type)));
+ g_string_append_printf (string, "command = %s\n",
+ arv_uvcp_command_to_string (GUINT16_FROM_LE (packet->header.command)));
+ g_string_append_printf (string, "size = %d\n", GUINT16_FROM_LE (packet->header.size));
+ g_string_append_printf (string, "id = %d\n", GUINT16_FROM_LE (packet->header.id));
+
+ switch (GUINT16_FROM_LE (packet->header.command)) {
+ case ARV_UVCP_COMMAND_READ_MEMORY_CMD:
+ {
+ ArvUvcpReadMemoryCmd *cmd_packet = (void *) packet;
+
+ value = GUINT64_FROM_LE (cmd_packet->infos.address);
+ g_string_append_printf (string, "address = %10u (0x%08x)\n",
+ value, value);
+ value = GUINT16_FROM_LE (cmd_packet->infos.size);
+ g_string_append_printf (string, "size = %10u (0x%08x)\n",
+ value, value);
+ break;
+ }
+ case ARV_UVCP_COMMAND_READ_MEMORY_ACK:
+ {
+ break;
+ }
+ }
+
+ packet_size = sizeof (ArvUvcpHeader) + GUINT16_FROM_LE (packet->header.size);
+
+ arv_g_string_append_hex_dump (string, packet, packet_size);
+
+ c_string = string->str;
+
+ g_string_free (string, FALSE);
+
+ return c_string;
+}
+
+/**
+ * arv_uvcp_packet_debug:
+ * @packet: a #ArvUvcpPacket
+ * @level: debug level
+ *
+ * Dumps the content of @packet if level is lower or equal to the current debug level for the uvcp debug
category. See arv_debug_enable().
+ */
+
+void
+arv_uvcp_packet_debug (const ArvUvcpPacket *packet, ArvDebugLevel level)
+{
+ char *string;
+
+ if (!arv_debug_check (&arv_debug_category_gvcp, level))
+ return;
+
+ string = arv_uvcp_packet_to_string (packet);
+ switch (level) {
+ case ARV_DEBUG_LEVEL_LOG:
+ arv_log_gvcp ("%s", string);
+ break;
+ case ARV_DEBUG_LEVEL_DEBUG:
+ arv_debug_gvcp ("%s", string);
+ break;
+ case ARV_DEBUG_LEVEL_WARNING:
+ arv_warning_gvcp ("%s", string);
+ break;
+ default:
+ break;
+ }
+ g_free (string);
+}
diff --git a/src/arvuvcp.h b/src/arvuvcp.h
new file mode 100644
index 0000000..cb84b85
--- /dev/null
+++ b/src/arvuvcp.h
@@ -0,0 +1,249 @@
+/* Aravis - Digital camera library
+ *
+ * Copyright © 2009-2016 Emmanuel Pacaud
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Author: Emmanuel Pacaud <emmanuel gnome org>
+ */
+
+#ifndef ARV_UVCP_H
+#define ARV_UVCP_H
+
+#include <arvtypes.h>
+#include <arvdebug.h>
+
+G_BEGIN_DECLS
+
+#define ARV_ABRM_GENCP_VERSION 0x0000
+#define ARV_ABRM_MANUFACTURER_NAME 0x0004
+#define ARV_ABRM_MODEL_NAME 0x0044
+#define ARV_ABRM_FAMILY_NAME 0x0084
+#define ARV_ABRM_DEVICE_VERSION 0x00c4
+#define ARV_ABRM_MANUFACTURER_INFO 0x0104
+#define ARV_ABRM_SERIAL_NUMBER 0x0144
+#define ARV_ABRM_USER_DEFINED_NAME 0x0184
+#define ARV_ABRM_DEVICE_CAPABILITY 0x01c4
+#define ARV_ABRM_MAX_DEVICE_RESPONSE_TIME 0x01cc
+#define ARV_ABRM_MANIFEST_TABLE_ADDRESS 0x01d0
+#define ARV_ABRM_SBRM_ADDRESS 0x01d8
+#define ARV_ABRM_DEVICE_CONFIGURATION 0x01e0
+#define ARV_ABRM_HEARTBEAT_TIMEOUT 0x01e8
+#define ARV_ABRM_MESSAGE_CHANNEL_ID 0x01ec
+#define ARV_ABRM_TIMESTAMP 0x01f0
+#define ARV_ABRM_TIMESTAMP_LATCH 0x01f8
+#define ARV_ABRM_TIMESTAMP_INCREMENT 0x01fc
+#define ARV_ABRM_ACCESS_PRIVILEGE 0x0204
+#define ARV_ABRM_PROTOCOL_ENDIANESS 0x0208
+#define ARV_ABRM_IMPLEMENTATION_ENDIANESS 0x020c
+#define ARV_ABRM_RESERVED 0x0210
+
+#define ARV_SBRM_U3V_VERSION 0x0000
+#define ARV_SBRM_U3VCP_CAPABILITY 0x0004
+#define ARV_SBRM_U3VCP_CONFIGURATION 0x000c
+#define ARV_SBRM_MAX_CMD_TRANSFER 0x0014
+#define ARV_SBRM_MAX_ACK_TRANSFER 0x0018
+#define ARV_SBRM_NUM_STREAM_CHANNELS 0x001c
+#define ARV_SBRM_SIRM_ADDRESS 0x0020
+#define ARV_SBRM_SIRM_LENGTH 0x0028
+#define ARV_SBRM_EIRM_ADDRESS 0x002c
+#define ARV_SBRM_EIRM_LENGTH 0x0034
+#define ARV_SBRM_IIDC2_ADDRESS 0x0038
+#define ARV_SBRM_CURRENT_SPEED 0x0040
+#define ARV_SBRM_RESERVED 0x0044
+
+#define ARV_SI_INFO 0x0000
+#define ARV_SI_CONTROL 0x0004
+#define ARV_SI_REQ_PAYLOAD_SIZE 0x0008
+#define ARV_SI_REQ_LEADER_SIZE 0x0010
+#define ARV_SI_REQ_TRAILER_SIZE 0x0014
+#define ARV_SI_MAX_LEADER_SIZE 0x0018
+#define ARV_SI_PAYLOAD_SIZE 0x001C
+#define ARV_SI_PAYLOAD_COUNT 0x0020
+#define ARV_SI_TRANSFER1_SIZE 0x0024
+#define ARV_SI_TRANSFER2_SIZE 0x0028
+#define ARV_SI_MAX_TRAILER_SIZE 0x002C
+#define ARV_SI_INFO_ALIGNMENT_MASK 0xFF000000
+#define ARV_SI_INFO_ALIGNMENT_SHIFT 0x0018
+
+/**
+ * ArvUvcpPacketType:
+ * @ARV_UVCP_PACKET_TYPE_ACK: acknowledge packet
+ * @ARV_UVCP_PACKET_TYPE_CMD: command packet
+ */
+
+typedef enum {
+ ARV_UVCP_PACKET_TYPE_ERROR = 0xffff,
+ ARV_UVCP_PACKET_TYPE_ACK = 0x0000,
+ ARV_UVCP_PACKET_TYPE_CMD = 0x4000
+} ArvUvcpPacketType;
+
+/**
+ * ArvUvcpCommand:
+ * @ARV_UVCP_COMMAND_READ_MEMORY_CMD: read memory command
+ * @ARV_UVCP_COMMAND_READ_MEMORY_ACK: read memory acknowledge
+ * @ARV_UVCP_COMMAND_WRITE_MEMORY_CMD: write memory command
+ * @ARV_UVCP_COMMAND_WRITE_MEMORY_ACK: write memory acknowledge
+ * @ARV_UVCP_COMMAND_PENDING_ACK: pending command acknowledge
+ */
+
+typedef enum {
+ ARV_UVCP_COMMAND_READ_MEMORY_CMD = 0x0800,
+ ARV_UVCP_COMMAND_READ_MEMORY_ACK = 0x0801,
+ ARV_UVCP_COMMAND_WRITE_MEMORY_CMD = 0x0802,
+ ARV_UVCP_COMMAND_WRITE_MEMORY_ACK = 0x0803,
+ ARV_UVCP_COMMAND_PENDING_ACK = 0x0805
+} ArvUvcpCommand;
+
+#define ARAVIS_PACKED_STRUCTURE __attribute__((__packed__))
+
+/**
+ * ArvUvcpHeader:
+ *
+ * UVCP packet header structure.
+ */
+
+typedef struct ARAVIS_PACKED_STRUCTURE {
+ guint32 magic;
+ guint16 packet_type;
+ guint16 command;
+ guint16 size;
+ guint16 id;
+} ArvUvcpHeader;
+
+typedef struct ARAVIS_PACKED_STRUCTURE {
+ guint64 address;
+ guint16 unknown;
+ guint16 size;
+} ArvUvcpReadMemoryCmdInfos;
+
+typedef struct ARAVIS_PACKED_STRUCTURE {
+ ArvUvcpHeader header;
+ ArvUvcpReadMemoryCmdInfos infos;
+} ArvUvcpReadMemoryCmd;
+
+/**
+ * ArvUvcpPacket:
+ * @header: packet header
+ * @data: variable size byte array
+ *
+ * UVCP packet structure.
+ */
+
+typedef struct ARAVIS_PACKED_STRUCTURE {
+ ArvUvcpHeader header;
+ unsigned char data[];
+} ArvUvcpPacket;
+
+typedef struct ARAVIS_PACKED_STRUCTURE {
+ guint64 unknown0;
+ guint64 address;
+ guint64 size;
+ guint64 unknown3;
+ guint64 unknown4;
+ guint64 unknown5;
+ guint64 unknown6;
+ guint64 unknown7;
+} ArvUvcpManifestEntry;
+
+#undef ARAVIS_PACKED_STRUCTURE
+
+void arv_uvcp_packet_free (ArvUvcpPacket *packet);
+ArvUvcpPacket * arv_uvcp_packet_new_read_memory_cmd (guint32 address, guint32 size,
+ guint16 packet_id, size_t *packet_size);
+ArvUvcpPacket * arv_uvcp_packet_new_write_memory_cmd (guint32 address, guint32 size,
+ guint16 packet_id, size_t *packet_size);
+char * arv_uvcp_packet_to_string (const ArvUvcpPacket *packet);
+void arv_uvcp_packet_debug (const ArvUvcpPacket *packet, ArvDebugLevel
level);
+
+/**
+ * arv_uvcp_packet_get_packet_type:
+ * @packet: a #ArvUvcpPacket
+ *
+ * Return value: The #ArvUvcpPacketType code of @packet.
+ */
+
+static inline ArvUvcpPacketType
+arv_uvcp_packet_get_packet_type (ArvUvcpPacket *packet)
+{
+ if (packet == NULL)
+ return ARV_UVCP_PACKET_TYPE_ERROR;
+
+ return (ArvUvcpPacketType) g_ntohs (packet->header.packet_type);
+}
+
+/**
+ * arv_uvcp_packet_get_command:
+ * @packet: a #ArvUvcpPacket
+ *
+ * Return value: The #ArvUvcpCommand code of @packet.
+ */
+
+static inline ArvUvcpCommand
+arv_uvcp_packet_get_command (ArvUvcpPacket *packet)
+{
+ if (packet == NULL)
+ return (ArvUvcpCommand) 0;
+
+ return (ArvUvcpCommand) g_ntohs (packet->header.command);
+}
+
+static inline void
+arv_uvcp_packet_set_packet_id (ArvUvcpPacket *packet, guint16 id)
+{
+ if (packet != NULL)
+ packet->header.id = g_htons (id);
+}
+
+static inline guint16
+arv_uvcp_packet_get_packet_id (ArvUvcpPacket *packet)
+{
+ if (packet == NULL)
+ return 0;
+
+ return g_ntohs (packet->header.id);
+}
+
+static inline void *
+arv_uvcp_packet_get_read_memory_ack_data (const ArvUvcpPacket *packet)
+{
+ return (char *) packet + sizeof (ArvUvcpHeader);
+}
+
+static inline size_t
+arv_uvcp_packet_get_read_memory_ack_size (size_t data_size)
+{
+ return sizeof (ArvUvcpHeader) + data_size;
+}
+
+static inline void *
+arv_uvcp_packet_get_write_memory_cmd_data (const ArvUvcpPacket *packet)
+{
+ return (char *) packet + sizeof (ArvUvcpPacket);
+}
+
+static inline guint16
+arv_uvcp_next_packet_id (guint16 packet_id)
+{
+ /* packet_id == 0 is an error value */
+ if (packet_id == 0xffff)
+ return 1;
+ return packet_id + 1;
+}
+
+G_END_DECLS
+
+#endif
diff --git a/src/arvuvdevice.c b/src/arvuvdevice.c
index 1e23ad7..eb3a7a4 100644
--- a/src/arvuvdevice.c
+++ b/src/arvuvdevice.c
@@ -25,18 +25,32 @@
* @short_description: Uv camera device
*/
+#include <arvdeviceprivate.h>
#include <arvuvdevice.h>
#include <arvuvstream.h>
#include <arvgc.h>
#include <arvdebug.h>
+#include <arvuvcp.h>
+#include <libusb.h>
+#include <string.h>
+#include <arvstr.h>
static GObjectClass *parent_class = NULL;
struct _ArvUvDevicePrivate {
+ char *vendor;
+ char *product;
+ char *serial_nbr;
+
+ libusb_context *usb;
+ libusb_device_handle *usb_device;
+
ArvGc *genicam;
const char *genicam_xml;
size_t genicam_xml_size;
+
+ guint16 packet_id;
};
/* ArvUvDevice implemenation */
@@ -57,10 +71,89 @@ static const char *
arv_uv_device_get_genicam_xml (ArvDevice *device, size_t *size)
{
ArvUvDevice *uv_device = ARV_UV_DEVICE (device);
+ guint64 offset;
+ guint32 response_time;
+ guint64 manifest_table_address;
+ guint64 device_capability;
+ guint32 max_cmd_transfer;
+ guint32 max_ack_transfer;
+ guint32 u3vcp_capability;
+ guint64 sirm_offset;
+ guint32 si_control;
+ guint32 si_info;
+ guint32 req_payload_size;
+ guint32 req_leader_size;
+ guint32 req_trailer_size;
+ guint64 manifest_n_entries;
+ ArvUvcpManifestEntry entry;
+ GString *string;
+
+ if (uv_device->priv->genicam_xml != NULL) {
+ *size = uv_device->priv->genicam_xml_size;
+ return uv_device->priv->genicam_xml;
+ }
+
+ g_message ("Get genicam");
+
+ arv_device_read_memory (device, ARV_ABRM_SBRM_ADDRESS, sizeof (guint64), &offset, NULL);
+ arv_device_read_memory (device, ARV_ABRM_MAX_DEVICE_RESPONSE_TIME, sizeof (guint32), &response_time,
NULL);
+ arv_device_read_memory (device, ARV_ABRM_DEVICE_CAPABILITY, sizeof (guint64), &device_capability,
NULL);
+ arv_device_read_memory (device, ARV_ABRM_MANIFEST_TABLE_ADDRESS, sizeof (guint64),
&manifest_table_address, NULL);
+
+ g_message ("MAX_DEVICE_RESPONSE_TIME = 0x%08x", response_time);
+ g_message ("DEVICE_CAPABILITY = 0x%016lx", device_capability);
+ g_message ("SRBM_ADDRESS = 0x%016lx", offset);
+ g_message ("MANIFEST_TABLE_ADDRESS = 0x%016lx", manifest_table_address);
+
+ arv_device_read_memory (device, offset + ARV_SBRM_U3VCP_CAPABILITY, sizeof (guint32),
&u3vcp_capability, NULL);
+ arv_device_read_memory (device, offset + ARV_SBRM_MAX_CMD_TRANSFER, sizeof (guint32),
&max_cmd_transfer, NULL);
+ arv_device_read_memory (device, offset + ARV_SBRM_MAX_ACK_TRANSFER, sizeof (guint32),
&max_ack_transfer, NULL);
+ arv_device_read_memory (device, offset + ARV_SBRM_SIRM_ADDRESS, sizeof (guint64), &sirm_offset, NULL);
+
+ g_message ("U3VCP_CAPABILITY = 0x%08x", u3vcp_capability);
+ g_message ("MAX_CMD_TRANSFER = 0x%08x", max_cmd_transfer);
+ g_message ("MAX_ACK_TRANSFER = 0x%08x", max_ack_transfer);
+ g_message ("SIRM_OFFSET = 0x%016lx", sirm_offset);
+
+ arv_device_read_memory (device, sirm_offset + ARV_SI_INFO, sizeof (guint64), &si_info, NULL);
+ arv_device_read_memory (device, sirm_offset + ARV_SI_CONTROL, sizeof (guint64), &si_control, NULL);
+ arv_device_read_memory (device, sirm_offset + ARV_SI_REQ_PAYLOAD_SIZE, sizeof (guint64),
&req_payload_size, NULL);
+ arv_device_read_memory (device, sirm_offset + ARV_SI_REQ_LEADER_SIZE, sizeof (guint64),
&req_leader_size, NULL);
+ arv_device_read_memory (device, sirm_offset + ARV_SI_REQ_TRAILER_SIZE, sizeof (guint64),
&req_trailer_size, NULL);
+
+ g_message ("SI_INFO = 0x%08x", si_info);
+ g_message ("SI_CONTROL = 0x%08x", si_control);
+ g_message ("REQ_PAYLOAD_SIZE = 0x%08x", req_payload_size);
+ g_message ("REQ_LEADER_SIZE = 0x%08x", req_leader_size);
+ g_message ("REQ_TRAILER_SIZE = 0x%08x", req_trailer_size);
+
+ arv_device_read_memory (device, manifest_table_address, sizeof (guint64), &manifest_n_entries, NULL);
+ arv_device_read_memory (device, manifest_table_address + 0x08, sizeof (entry), &entry, NULL);
+
+ g_message ("MANIFEST_N_ENTRIES = 0x%016lx", manifest_n_entries);
+
+ string = g_string_new ("");
+ arv_g_string_append_hex_dump (string, &entry, sizeof (entry));
+ g_message ("MANIFEST ENTRY\n%s", string->str);
+ g_string_free (string, TRUE);
+
+ g_message ("genicam address = 0x%016lx", entry.address);
+ g_message ("genicam address = 0x%016lx", entry.size);
+
+ return NULL;
+}
+
+static void
+arv_gv_device_load_genicam (ArvUvDevice *uv_device)
+{
+ const char *genicam;
+ size_t size;
- *size = uv_device->priv->genicam_xml_size;
+ genicam = arv_uv_device_get_genicam_xml (ARV_DEVICE (uv_device), &size);
+ if (genicam != NULL) {
+ uv_device->priv->genicam = arv_gc_new (ARV_DEVICE (uv_device), genicam, size);
- return uv_device->priv->genicam_xml;
+ }
}
static ArvGc *
@@ -74,8 +167,59 @@ arv_uv_device_get_genicam (ArvDevice *device)
static gboolean
arv_uv_device_read_memory (ArvDevice *device, guint32 address, guint32 size, void *buffer, GError **error)
{
- g_assert_not_reached ();
- return FALSE;
+ ArvUvDevice *uv_device = ARV_UV_DEVICE (device);
+ ArvUvcpPacket *packet;
+ size_t packet_size;
+ size_t answer_size;
+ gboolean success = FALSE;
+
+ answer_size = arv_uvcp_packet_get_read_memory_ack_size (size);
+
+ g_return_val_if_fail (answer_size <= 1024, FALSE);
+
+ packet = arv_uvcp_packet_new_read_memory_cmd (address, size, 0, &packet_size);
+
+ do {
+ int transferred;
+ void *read_packet;
+ size_t read_packet_size;
+
+/* read_packet_size = arv_uvcp_packet_get_read_memory_ack_size (size);*/
+/* read_packet = g_malloc0 (read_packet_size);*/
+
+ read_packet_size = 1024;
+ read_packet = g_malloc0 (read_packet_size);
+
+ 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);
+
+ g_message ("read_packet_size = %d", (int) read_packet_size);
+
+ g_assert (libusb_claim_interface (uv_device->priv->usb_device, 0) >= 0);
+ g_assert (libusb_bulk_transfer (uv_device->priv->usb_device, (0x04 | LIBUSB_ENDPOINT_OUT),
+ (guchar *) packet, packet_size, &transferred, 0) >= 0);
+ g_assert (libusb_bulk_transfer (uv_device->priv->usb_device, (0x84 | LIBUSB_ENDPOINT_IN),
+ (guchar *) read_packet, read_packet_size, &transferred, 0) >=
0);
+ g_assert (libusb_release_interface (uv_device->priv->usb_device, 0) >= 0);
+ success = TRUE;
+
+ memcpy (buffer, arv_uvcp_packet_get_read_memory_ack_data (read_packet), size);
+
+ g_free (read_packet);
+
+ } while (!success);
+
+ arv_uvcp_packet_free (packet);
+
+ if (!success) {
+ if (error != NULL && *error == NULL)
+ *error = g_error_new (ARV_DEVICE_ERROR, ARV_DEVICE_STATUS_TIMEOUT,
+ "[ArvDevice::read_memory] Timeout");
+ }
+
+ return success;
}
static gboolean
@@ -88,26 +232,97 @@ arv_uv_device_write_memory (ArvDevice *device, guint32 address, guint32 size, vo
static gboolean
arv_uv_device_read_register (ArvDevice *device, guint32 address, guint32 *value, GError **error)
{
- g_assert_not_reached ();
- return FALSE;
+ return arv_uv_device_read_memory (device, address, sizeof (guint32), value, error);
}
static gboolean
arv_uv_device_write_register (ArvDevice *device, guint32 address, guint32 value, GError **error)
{
- g_assert_not_reached ();
- return FALSE;
+ return arv_uv_device_write_memory (device, address, sizeof (guint32), &value, error);
+}
+
+static void
+_open_usb_device (ArvUvDevice *uv_device)
+{
+ libusb_device **devices;
+ unsigned i, count;
+
+ count = libusb_get_device_list (uv_device->priv->usb, &devices);
+ if (count < 0)
+ return;
+
+ for (i = 0; i < count && uv_device->priv->usb_device == NULL; i++) {
+ libusb_device_handle *usb_device;
+ struct libusb_device_descriptor desc;
+
+ if (libusb_get_device_descriptor (devices[i], &desc) >= 0 &&
+ libusb_open (devices[i], &usb_device) == LIBUSB_SUCCESS) {
+ unsigned char *manufacturer;
+ unsigned char *product;
+ unsigned char *serial_nbr;
+ int index;
+
+ manufacturer = g_malloc0 (256);
+ product = g_malloc0 (256);
+ serial_nbr = g_malloc0 (256);
+
+ index = desc.iManufacturer;
+ if (index > 0)
+ libusb_get_string_descriptor_ascii (usb_device, index, manufacturer, 256);
+ index = desc.iProduct;
+ if (index > 0)
+ libusb_get_string_descriptor_ascii (usb_device, index, product, 256);
+ index = desc.iSerialNumber;
+ if (index > 0)
+ libusb_get_string_descriptor_ascii (usb_device, index, serial_nbr, 256);
+
+ if (g_strcmp0 ((char * ) manufacturer, uv_device->priv->vendor) == 0 &&
+ g_strcmp0 ((char * ) product, uv_device->priv->product) == 0 &&
+ g_strcmp0 ((char * ) serial_nbr, uv_device->priv->serial_nbr) == 0) {
+ uv_device->priv->usb_device = usb_device;
+ } else
+ libusb_close (usb_device);
+
+ g_free (manufacturer);
+ g_free (product);
+ g_free (serial_nbr);
+ }
+ }
+
+ libusb_free_device_list (devices, 1);
}
ArvDevice *
-arv_uv_device_new (const char *serial_number)
+arv_uv_device_new (const char *vendor, const char *product, const char *serial_nbr)
{
ArvUvDevice *uv_device;
- g_return_val_if_fail (serial_number != NULL, NULL);
+ g_return_val_if_fail (vendor != NULL, NULL);
+ g_return_val_if_fail (product != NULL, NULL);
+ g_return_val_if_fail (serial_nbr != NULL, NULL);
+
+ arv_debug_device ("[UvDevice::new] Vendor = %s", vendor);
+ arv_debug_device ("[UvDevice::new] Product = %s", product);
+ arv_debug_device ("[UvDevice::new] S/N = %s", serial_nbr);
uv_device = g_object_new (ARV_TYPE_UV_DEVICE, NULL);
+ libusb_init (&uv_device->priv->usb);
+ uv_device->priv->vendor = g_strdup (vendor);
+ uv_device->priv->product = g_strdup (product);
+ uv_device->priv->serial_nbr = g_strdup (serial_nbr);
+ uv_device->priv->packet_id = 65300; /* Start near the end of the circular counter */
+
+ _open_usb_device (uv_device);
+
+ arv_gv_device_load_genicam (uv_device);
+
+ if (!ARV_IS_GC (uv_device->priv->genicam)) {
+ arv_warning_device ("[UvDevice::new] Failed to load genicam data");
+ g_object_unref (uv_device);
+ return NULL;
+ }
+
return ARV_DEVICE (uv_device);
}
@@ -124,6 +339,12 @@ arv_uv_device_finalize (GObject *object)
g_object_unref (uv_device->priv->genicam);
+ g_clear_pointer (&uv_device->priv->vendor, g_free);
+ g_clear_pointer (&uv_device->priv->product, g_free);
+ g_clear_pointer (&uv_device->priv->serial_nbr, g_free);
+ libusb_close (uv_device->priv->usb_device);
+ libusb_exit (uv_device->priv->usb);
+
parent_class->finalize (object);
}
diff --git a/src/arvuvdevice.h b/src/arvuvdevice.h
index 922adaf..d0576f5 100644
--- a/src/arvuvdevice.h
+++ b/src/arvuvdevice.h
@@ -50,7 +50,7 @@ struct _ArvUvDeviceClass {
GType arv_uv_device_get_type (void);
-ArvDevice * arv_uv_device_new (const char *serial_number);
+ArvDevice * arv_uv_device_new (const char *vendor, const char *product, const char
*serial_nbr);
G_END_DECLS
diff --git a/src/arvuvinterface.c b/src/arvuvinterface.c
index ac45dd9..5b843a3 100644
--- a/src/arvuvinterface.c
+++ b/src/arvuvinterface.c
@@ -26,6 +26,7 @@
*/
#include <arvuvinterface.h>
+#include <arvuvdevice.h>
#include <arvdebug.h>
#include <arvmisc.h>
#include <arvstr.h>
@@ -45,12 +46,68 @@
static GObjectClass *parent_class = NULL;
+typedef struct {
+ char *name;
+ char *manufacturer;
+ char *product;
+ char *serial_nbr;
+
+ volatile gint ref_count;
+} ArvUvInterfaceDeviceInfos;
+
+static ArvUvInterfaceDeviceInfos *
+arv_uv_interface_device_infos_new (const char *manufacturer,
+ const char *product,
+ const char *serial_nbr)
+{
+ ArvUvInterfaceDeviceInfos *infos;
+
+ g_return_val_if_fail (manufacturer != NULL, NULL);
+ g_return_val_if_fail (product != NULL, NULL);
+ g_return_val_if_fail (serial_nbr != NULL, NULL);
+
+ infos = g_new (ArvUvInterfaceDeviceInfos, 1);
+ infos->manufacturer = g_strdup (manufacturer);
+ infos->name = g_strdup_printf ("%s-%s", manufacturer, serial_nbr);
+ infos->product = g_strdup (product);
+ infos->serial_nbr = g_strdup (serial_nbr);
+ infos->ref_count = 1;
+
+ arv_str_strip (infos->name, ARV_DEVICE_NAME_ILLEGAL_CHARACTERS,
ARV_DEVICE_NAME_REPLACEMENT_CHARACTER);
+
+ return infos;
+}
+
+/*
+static void
+arv_uv_interface_device_infos_ref (ArvUvInterfaceDeviceInfos *infos)
+{
+ g_return_if_fail (infos != NULL);
+ g_return_if_fail (g_atomic_int_get (&infos->ref_count) > 0);
+ g_atomic_int_inc (&infos->ref_count);
+}
+*/
+
+static void
+arv_uv_interface_device_infos_unref (ArvUvInterfaceDeviceInfos *infos)
+{
+ g_return_if_fail (infos != NULL);
+ g_return_if_fail (g_atomic_int_get (&infos->ref_count) > 0);
+
+ if (g_atomic_int_dec_and_test (&infos->ref_count)) {
+ g_clear_pointer (&infos->name, g_free);
+ g_clear_pointer (&infos->manufacturer, g_free);
+ g_clear_pointer (&infos->product, g_free);
+ g_clear_pointer (&infos->serial_nbr, g_free);
+ g_clear_pointer (&infos, g_free);
+ }
+}
+
struct _ArvUvInterfacePrivate {
GHashTable *devices;
libusb_context *usb;
};
-
#if 0
static void
printdev (libusb_device *device)
@@ -91,7 +148,7 @@ printdev (libusb_device *device)
#endif
ArvInterfaceDeviceIds *
-_usb_device_to_device_ids (libusb_device *device)
+_usb_device_to_device_ids (ArvUvInterface *uv_interface, libusb_device *device)
{
ArvInterfaceDeviceIds *device_ids = NULL;
libusb_device_handle *device_handle;
@@ -129,6 +186,7 @@ _usb_device_to_device_ids (libusb_device *device)
return NULL;
if (libusb_open (device, &device_handle) == LIBUSB_SUCCESS) {
+ ArvUvInterfaceDeviceInfos *device_infos;
unsigned char *manufacturer;
unsigned char *product;
unsigned char *serial_nbr;
@@ -150,11 +208,12 @@ _usb_device_to_device_ids (libusb_device *device)
if (index > 0)
libusb_get_string_descriptor_ascii (device_handle, index, serial_nbr, 256);
- device_ids->device = g_strdup_printf ("%s-%s", manufacturer, serial_nbr);
- device_ids->physical = g_strdup_printf ("FIXME");
- device_ids->address = g_strdup_printf ("FIXME");
+ device_infos = arv_uv_interface_device_infos_new ((char *) manufacturer, (char *) product,
(char *) serial_nbr);
+ g_hash_table_replace (uv_interface->priv->devices, device_infos->name, device_infos);
- arv_str_strip (device_ids->device, ARV_DEVICE_NAME_ILLEGAL_CHARACTERS,
ARV_DEVICE_NAME_REPLACEMENT_CHARACTER);
+ device_ids->device = g_strdup (device_infos->name);
+ device_ids->physical = g_strdup ("FIXME-Physical");
+ device_ids->address = g_strdup ("FIXME-Address");
g_free (manufacturer);
g_free (product);
@@ -182,14 +241,14 @@ arv_uv_interface_update_device_list (ArvInterface *interface, GArray *device_ids
for (i = 0; i < count; i++) {
ArvInterfaceDeviceIds *ids;
- ids = _usb_device_to_device_ids (devices[i]);
+ ids = _usb_device_to_device_ids (uv_interface, devices[i]);
if (ids != NULL) {
uv_count++;
g_array_append_val (device_ids, ids);
}
}
- arv_debug_interface ("Found %d USB3Vision device%s (among %d USB device%ss)",
+ arv_debug_interface ("Found %d USB3Vision device%s (among %d USB device%s)",
uv_count , uv_count > 1 ? "s" : "",
count, count > 1 ? "s" : "");
@@ -199,7 +258,27 @@ arv_uv_interface_update_device_list (ArvInterface *interface, GArray *device_ids
static ArvDevice *
arv_uv_interface_open_device (ArvInterface *interface, const char *device_id)
{
- return NULL;
+ ArvUvInterface *uv_interface;
+ ArvDevice *device = NULL;
+ ArvUvInterfaceDeviceInfos *device_infos;
+
+ uv_interface = ARV_UV_INTERFACE (interface);
+
+ if (device_id == NULL) {
+ GList *device_list;
+
+ device_list = g_hash_table_get_values (uv_interface->priv->devices);
+ device_infos = device_list != NULL ? device_list->data : NULL;
+ g_list_free (device_list);
+ } else
+ device_infos = g_hash_table_lookup (uv_interface->priv->devices, device_id);
+
+ if (device_infos == NULL)
+ return NULL;
+
+ device = arv_uv_device_new (device_infos->manufacturer, device_infos->product,
device_infos->serial_nbr);
+
+ return device;
}
static ArvInterface *uv_interface = NULL;
@@ -241,6 +320,9 @@ arv_uv_interface_init (ArvUvInterface *uv_interface)
{
uv_interface->priv = G_TYPE_INSTANCE_GET_PRIVATE (uv_interface, ARV_TYPE_UV_INTERFACE,
ArvUvInterfacePrivate);
libusb_init (&uv_interface->priv->usb);
+
+ uv_interface->priv->devices = g_hash_table_new_full (g_str_hash, g_str_equal, NULL,
+ (GDestroyNotify)
arv_uv_interface_device_infos_unref);
}
static void
@@ -248,7 +330,10 @@ arv_uv_interface_finalize (GObject *object)
{
ArvUvInterface *uv_interface = ARV_UV_INTERFACE (object);
+ g_hash_table_unref (uv_interface->priv->devices);
+
parent_class->finalize (object);
+
libusb_exit (uv_interface->priv->usb);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]