Skip to content

Commit

Permalink
camera: USB maximum transfer size helper
Browse files Browse the repository at this point in the history
  • Loading branch information
EmmanuelP committed Nov 7, 2024
1 parent 8e1bd27 commit 9e59d2f
Show file tree
Hide file tree
Showing 7 changed files with 89 additions and 29 deletions.
33 changes: 33 additions & 0 deletions src/arvcamera.c
Original file line number Diff line number Diff line change
Expand Up @@ -3880,6 +3880,39 @@ arv_camera_uv_set_usb_mode (ArvCamera *camera, ArvUvUsbMode usb_mode)
#endif
}

/**
* arv_camera_uv_set_maximum_transfer_size:
* @camera: a #ArvCamera
* @size: maximum bulk transfer size, in bytes
*
* Set the maximum size when asking for a USB bulk transfer. The default value should work most of the time, but you may
* have to tweak this setting in order to get reliable transfers.
*
* ::: note "Help needed"
* It would be nice to be able to compute a working value for any OS/driver combination aravis is
* running on. If someone knows how to do that, please open an issue (or event better, a merge request) on
* the aravis [issue tracker]<https://github.com/AravisProject/aravis/issues>.
*
* On linux, there seems to be this kernel parameter that could be used:
* `/sys/module/usbcore/parameters/usbfs_memory_mb`.
*
* Since: 0.10.0
*/

void
arv_camera_uv_set_maximum_transfer_size (ArvCamera *camera, guint64 size)
{
#if ARAVIS_HAS_USB
ArvCameraPrivate *priv = arv_camera_get_instance_private (camera);
#endif

g_return_if_fail (arv_camera_is_uv_device (camera));

#if ARAVIS_HAS_USB
arv_uv_device_set_maximum_transfer_size (ARV_UV_DEVICE (priv->device), size);
#endif
}

/**
* arv_camera_is_gentl_device:
* @camera: a #ArvCamera
Expand Down
1 change: 1 addition & 0 deletions src/arvcamera.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ ARV_API void arv_camera_uv_set_bandwidth (ArvCamera *camera, guint bandwidth,
ARV_API guint arv_camera_uv_get_bandwidth (ArvCamera *camera, GError **error);
ARV_API void arv_camera_uv_get_bandwidth_bounds (ArvCamera *camera, guint *min, guint *max, GError **error);
ARV_API void arv_camera_uv_set_usb_mode (ArvCamera *camera, ArvUvUsbMode usb_mode);
ARV_API void arv_camera_uv_set_maximum_transfer_size (ArvCamera *camera, guint64 size);

ARV_API gboolean arv_camera_is_gentl_device (ArvCamera *camera);

Expand Down
11 changes: 10 additions & 1 deletion src/arvcameratest.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ static char *arv_option_range_check = NULL;
static char *arv_option_access_check = NULL;
static int arv_option_duration_s = -1;
static char *arv_option_uv_usb_mode = NULL;
static guint arv_option_uv_usb_maximum_transfer_size = 0;
static gboolean arv_option_show_version = FALSE;
static gboolean arv_option_gv_allow_broadcast_discovery_ack = FALSE;
static char *arv_option_gv_port_range = NULL;
Expand Down Expand Up @@ -159,6 +160,12 @@ static const GOptionEntry arv_option_entries[] =
&arv_option_uv_usb_mode, "USB device I/O mode",
"{sync|async}"
},
{
"usb-maximum-transfer-size", '\0', 0, G_OPTION_ARG_INT,
&arv_option_uv_usb_maximum_transfer_size,
"USB maximum transfer size",
"<n_bytes>}"
},
{
"chunks", 'u', 0, G_OPTION_ARG_STRING,
&arv_option_chunks, "Chunks",
Expand Down Expand Up @@ -570,8 +577,10 @@ main (int argc, char **argv)
if (arv_camera_is_uv_device (camera)) {
if (error == NULL)
arv_camera_uv_set_usb_mode (camera, usb_mode);
if (error == NULL && arv_option_uv_usb_maximum_transfer_size > 0)
arv_camera_uv_set_maximum_transfer_size (camera, arv_option_uv_usb_maximum_transfer_size);
if (error == NULL && arv_option_bandwidth_limit >= 0)
arv_camera_uv_set_bandwidth (camera, arv_option_bandwidth_limit, &error);
arv_camera_uv_set_bandwidth (camera, arv_option_bandwidth_limit, &error);
}

if (arv_camera_is_gv_device (camera)) {
Expand Down
24 changes: 23 additions & 1 deletion src/arvuvdevice.c
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ typedef struct {
gboolean disconnected;

ArvUvUsbMode usb_mode;
guint64 maximum_transfer_size;

int event_thread_run;
GThread* event_thread;
Expand Down Expand Up @@ -211,7 +212,8 @@ static ArvStream *
arv_uv_device_create_stream (ArvDevice *device, ArvStreamCallback callback, void *user_data, GDestroyNotify destroy, GError **error)
{
ArvUvDevicePrivate *priv = arv_uv_device_get_instance_private (ARV_UV_DEVICE (device));
return arv_uv_stream_new (ARV_UV_DEVICE (device), callback, user_data, destroy, priv->usb_mode, error);
return arv_uv_stream_new (ARV_UV_DEVICE (device), callback, user_data, destroy,
priv->usb_mode, priv->maximum_transfer_size, error);
}

static gboolean
Expand Down Expand Up @@ -940,6 +942,25 @@ arv_uv_device_set_usb_mode (ArvUvDevice *uv_device, ArvUvUsbMode usb_mode)
priv->usb_mode = usb_mode;
}

/**
* arv_uv_device_set_maximum_transfer_size:
* @uv_device: a #ArvUvDevice
* @size: maximum transfer size, in bytes
*
* Set the maximum transfer size for a USB bulk transfer.
*
* Since: 0.10.0
*/

void
arv_uv_device_set_maximum_transfer_size (ArvUvDevice *uv_device, guint64 size)
{
ArvUvDevicePrivate *priv = arv_uv_device_get_instance_private (uv_device);

g_return_if_fail (ARV_IS_UV_DEVICE (uv_device));

priv->maximum_transfer_size = size;
}
/**
* arv_uv_device_new:
* @vendor: USB3 vendor string
Expand Down Expand Up @@ -1085,6 +1106,7 @@ arv_uv_device_constructed (GObject *object)
&priv->hotplug_cb_handle);

priv->usb_mode = ARV_UV_USB_MODE_DEFAULT;
priv->maximum_transfer_size = ARV_UV_STREAM_MAXIMUM_TRANSFER_SIZE_DEFAULT;

priv->event_thread_run = 1;
priv->event_thread = g_thread_new ( "arv_libusb", event_thread_func, priv);
Expand Down
3 changes: 2 additions & 1 deletion src/arvuvdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ ARV_API ArvDevice * arv_uv_device_new (const char *vendor, const char *produc
const char *serial_number, GError **error);
ARV_API ArvDevice * arv_uv_device_new_from_guid (const char *guid, GError **error);

ARV_API void arv_uv_device_set_usb_mode (ArvUvDevice *uv_device, ArvUvUsbMode usb_mode);
ARV_API void arv_uv_device_set_usb_mode (ArvUvDevice *uv_device, ArvUvUsbMode usb_mode);
ARV_API void arv_uv_device_set_maximum_transfer_size (ArvUvDevice *uv_device, guint64 size);

G_END_DECLS

Expand Down
38 changes: 14 additions & 24 deletions src/arvuvstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@
#include <libusb.h>
#include <string.h>

#define ARV_UV_STREAM_MAXIMUM_TRANSFER_SIZE_DEFAULT (1*1024*1024)
#define ARV_UV_STREAM_N_MAXIMUM_SUBMITS 8

#define ARV_UV_STREAM_POP_INPUT_BUFFER_TIMEOUT_MS 10
#define ARV_UV_STREAM_TRANSFER_WAIT_TIMEOUT_MS 10

Expand Down Expand Up @@ -1096,21 +1093,25 @@ arv_uv_stream_create_buffers (ArvStream *stream, guint n_buffers, size_t size,
* @uv_device: a #ArvUvDevice
* @callback: (scope call): image processing callback
* @callback_data: (closure): user data for @callback
* @destroy: callback data destroy function
* @usb_mode: USB mode selection
* @maximum_transfer_size: maximum transfer size, in bytes
* @error: a #GError placeholder, %NULL to ignore
*
* Return Value: (transfer full): a new #ArvStream.
*/

ArvStream *
arv_uv_stream_new (ArvUvDevice *uv_device, ArvStreamCallback callback, void *callback_data, GDestroyNotify destroy,
ArvUvUsbMode usb_mode, GError **error)
ArvUvUsbMode usb_mode, guint64 maximum_transfer_size, GError **error)
{
return g_initable_new (ARV_TYPE_UV_STREAM, NULL, error,
"device", uv_device,
"callback", callback,
"callback-data", callback_data,
"destroy-notify", destroy,
"destroy-notify", destroy,
"usb-mode", usb_mode,
"maximum-transfer-size", maximum_transfer_size,
NULL);
}

Expand Down Expand Up @@ -1255,25 +1256,14 @@ arv_uv_stream_class_init (ArvUvStreamClass *uv_stream_class)
/**
* ArvUvStream:maximum-transfer-size:
*
* Maximum size when asking for a USB bulk transfer. The default value should work most of the time, but you may
* have to tweak this setting in order to get reliable transfers. This property can be changed at any time, but
* it will only have effect the next acquisition start.
*
* ::: note "Help needed"
* It would be nice to be able to compute a working value for any OS/driver combination aravis is
* running on. If someone knows how to do that, please open an issue (or event better, a merge request) on
* the aravis [issue tracker]<https://github.com/AravisProject/aravis/issues>.
*
* On linux, there seems to be this kernel parameter that could be used:
* `/sys/module/usbcore/parameters/usbfs_memory_mb`.
*
* Maximum size when asking for a USB bulk transfer.
*/
g_object_class_install_property (
object_class, ARV_UV_STREAM_PROPERTY_MAXIMUM_TRANSFER_SIZE,
g_param_spec_uint64 ("maximum-transfer-size", "Maximum transfer size",
"USB maximum transfer size",
1024, 1024 * 1024 * 1024,
ARV_UV_STREAM_MAXIMUM_TRANSFER_SIZE_DEFAULT,
G_PARAM_CONSTRUCT | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)
);
object_class, ARV_UV_STREAM_PROPERTY_MAXIMUM_TRANSFER_SIZE,
g_param_spec_uint64 ("maximum-transfer-size", "Maximum transfer size",
"USB maximum transfer size",
1024, 1024 * 1024 * 1024,
ARV_UV_STREAM_MAXIMUM_TRANSFER_SIZE_DEFAULT,
G_PARAM_CONSTRUCT_ONLY | G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS)
);
}
8 changes: 6 additions & 2 deletions src/arvuvstreamprivate.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,12 @@

G_BEGIN_DECLS

ArvStream * arv_uv_stream_new (ArvUvDevice *uv_device, ArvStreamCallback callback, void *user_data, GDestroyNotify destroy,
ArvUvUsbMode usb_mode, GError **error);
#define ARV_UV_STREAM_MAXIMUM_TRANSFER_SIZE_DEFAULT (1*1024*1024)
#define ARV_UV_STREAM_N_MAXIMUM_SUBMITS 8

ArvStream * arv_uv_stream_new (ArvUvDevice *uv_device,
ArvStreamCallback callback, void *user_data, GDestroyNotify destroy,
ArvUvUsbMode usb_mode, guint64 maximum_transfer_size, GError **error);

G_END_DECLS

Expand Down

0 comments on commit 9e59d2f

Please sign in to comment.