[aravis/wip/emmanuel/usb3vision: 7/7] wip: load u3v genicam



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]