Skip to content

Commit 5f88208

Browse files
27CobalterEmmanuelP
authored andcommitted
uvdevice: correct handling of USB3Vision control endpoints
Fixes #500 This change removes the incorrect assumption that endpoint_in == (endpoint_out | LIBUSB_ENDPOINT_IN). This was causing issues with cameras like the Toshiba-Teli BU406M (where OUT=0x01 but IN=0x82). Summary of changes: Stored control OUT and IN endpoints in separate variables with their raw values. Removed the manual bitwise OR flag logic. Updated log messages to show both endpoints in 2-digit hex format (consistent with libusb style).
1 parent afaf46b commit 5f88208

1 file changed

Lines changed: 45 additions & 18 deletions

File tree

src/arvuvdevice.c

Lines changed: 45 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@ typedef struct {
5555
char *serial_number;
5656
char *guid;
5757

58+
unsigned int usb_major_version;
59+
unsigned int usb_minor_version;
60+
5861
libusb_context *usb;
5962
libusb_device_handle *usb_device;
6063

@@ -72,8 +75,9 @@ typedef struct {
7275
guint ack_packet_size_max;
7376
guint control_interface;
7477
guint data_interface;
75-
guint8 control_endpoint;
76-
guint8 data_endpoint;
78+
guint8 control_endpoint_out;
79+
guint8 control_endpoint_in;
80+
guint8 data_endpoint;
7781
gboolean disconnected;
7882

7983
ArvUvUsbMode usb_mode;
@@ -141,9 +145,13 @@ arv_uv_device_fill_bulk_transfer (struct libusb_transfer* transfer, ArvUvDevice
141145
ArvUvDevicePrivate *priv = arv_uv_device_get_instance_private (uv_device);
142146
guint8 endpoint;
143147

144-
endpoint = (endpoint_type == ARV_UV_ENDPOINT_CONTROL) ? priv->control_endpoint : priv->data_endpoint;
148+
if (endpoint_type == ARV_UV_ENDPOINT_CONTROL) {
149+
endpoint = (endpoint_flags == LIBUSB_ENDPOINT_IN) ? priv->control_endpoint_in : priv->control_endpoint_out;
150+
} else {
151+
endpoint = priv->data_endpoint;
152+
}
145153

146-
libusb_fill_bulk_transfer (transfer, priv->usb_device, endpoint | endpoint_flags, data, size,
154+
libusb_fill_bulk_transfer (transfer, priv->usb_device, endpoint, data, size,
147155
callback, callback_data, timeout );
148156
}
149157

@@ -167,9 +175,12 @@ arv_uv_device_bulk_transfer (ArvUvDevice *uv_device, ArvUvEndpointType endpoint_
167175
return FALSE;
168176
}
169177

170-
171-
endpoint = (endpoint_type == ARV_UV_ENDPOINT_CONTROL) ? priv->control_endpoint : priv->data_endpoint;
172-
result = libusb_bulk_transfer (priv->usb_device, endpoint | endpoint_flags, data, size, &transferred,
178+
if (endpoint_type == ARV_UV_ENDPOINT_CONTROL) {
179+
endpoint = (endpoint_flags == LIBUSB_ENDPOINT_IN) ? priv->control_endpoint_in : priv->control_endpoint_out;
180+
} else {
181+
endpoint = priv->data_endpoint;
182+
}
183+
result = libusb_bulk_transfer (priv->usb_device, endpoint, data, size, &transferred,
173184
timeout_ms > 0 ? timeout_ms : priv->timeout_ms);
174185

175186
success = result >= 0;
@@ -708,7 +719,7 @@ arv_uv_device_get_genicam_xml (ArvDevice *device, size_t *size)
708719
}
709720

710721
static void
711-
reset_endpoint (libusb_device_handle *usb_device, guint8 endpoint, guint8 endpoint_flags)
722+
reset_endpoint (libusb_device_handle *usb_device, guint8 endpoint)
712723
{
713724
int errcode;
714725

@@ -717,17 +728,17 @@ reset_endpoint (libusb_device_handle *usb_device, guint8 endpoint, guint8 endpoi
717728
LIBUSB_ENDPOINT_OUT | LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_ENDPOINT,
718729
LIBUSB_REQUEST_SET_FEATURE,
719730
0, /* Value: 0=endpoint_halt */
720-
endpoint | endpoint_flags,
731+
endpoint,
721732
0, 0,
722733
1000);
723734
if (errcode < 0) {
724735
arv_warning_device("Failed to set endpoint %x in halt condition: %s",
725-
endpoint|endpoint_flags, libusb_error_name (errcode));
736+
endpoint, libusb_error_name (errcode));
726737
return;
727738
}
728739

729740
/* Clear halt condtion on the endpoint, effectivelly resetting the pipe */
730-
errcode = libusb_clear_halt(usb_device, endpoint | endpoint_flags);
741+
errcode = libusb_clear_halt(usb_device, endpoint);
731742
if (errcode < 0) {
732743
arv_warning_device("Failed to clear halt contidion on endpoint: %s",
733744
libusb_error_name (errcode));
@@ -742,7 +753,7 @@ arv_uv_device_reset_stream_endpoint (ArvUvDevice *device)
742753

743754
g_return_val_if_fail(ARV_IS_UV_DEVICE(device), FALSE);
744755

745-
reset_endpoint (priv->usb_device, priv->data_endpoint, LIBUSB_ENDPOINT_IN);
756+
reset_endpoint (priv->usb_device, priv->data_endpoint);
746757

747758
return TRUE;
748759
}
@@ -845,6 +856,9 @@ _open_usb_device (ArvUvDevice *uv_device, GError **error)
845856
if (priv->guid == NULL)
846857
priv->guid = g_strdup ((char *) guid);
847858

859+
priv->usb_major_version = ((desc.bcdUSB >> 12) & 0xf) * 10 + ((desc.bcdUSB >> 8) & 0xf);
860+
priv->usb_minor_version = ((desc.bcdUSB >> 4) & 0xf) * 10 + (desc.bcdUSB & 0xf);
861+
848862
result = libusb_set_auto_detach_kernel_driver (usb_device, 1);
849863
if (result != 0) {
850864
arv_warning_device ("Failed to set auto kernel detach feature "
@@ -861,13 +875,19 @@ _open_usb_device (ArvUvDevice *uv_device, GError **error)
861875
if (interdesc->bInterfaceClass == ARV_UV_INTERFACE_INTERFACE_CLASS &&
862876
interdesc->bInterfaceSubClass == ARV_UV_INTERFACE_INTERFACE_SUBCLASS) {
863877
if (interdesc->bInterfaceProtocol == ARV_UV_INTERFACE_CONTROL_PROTOCOL) {
864-
endpoint = interdesc->endpoint[0];
865-
priv->control_endpoint = endpoint.bEndpointAddress & 0x0f;
878+
for (int edx = 0; edx < interdesc->bNumEndpoints; edx++) {
879+
endpoint = interdesc->endpoint[edx];
880+
if ((endpoint.bEndpointAddress & LIBUSB_ENDPOINT_IN) != 0) {
881+
priv->control_endpoint_in = endpoint.bEndpointAddress;
882+
} else {
883+
priv->control_endpoint_out = endpoint.bEndpointAddress;
884+
}
885+
}
866886
priv->control_interface = interdesc->bInterfaceNumber;
867887
}
868888
if (interdesc->bInterfaceProtocol == ARV_UV_INTERFACE_DATA_PROTOCOL) {
869889
endpoint = interdesc->endpoint[0];
870-
priv->data_endpoint = endpoint.bEndpointAddress & 0x0f;
890+
priv->data_endpoint = endpoint.bEndpointAddress;
871891
priv->data_interface = interdesc->bInterfaceNumber;
872892
}
873893
}
@@ -1032,9 +1052,16 @@ arv_uv_device_constructed (GObject *object)
10321052
return;
10331053
}
10341054

1035-
arv_info_device("[UvDevice::new] Using control endpoint %d, interface %d",
1036-
priv->control_endpoint, priv->control_interface);
1037-
arv_info_device("[UvDevice::new] Using data endpoint %d, interface %d",
1055+
if (priv->usb_major_version < 3)
1056+
arv_warning_device ("[UvDevice::new] USB %d.%d (Low bandwidth)",
1057+
priv->usb_major_version, priv->usb_minor_version);
1058+
else
1059+
arv_info_device ("[UvDevice::new] USB %d.%d",
1060+
priv->usb_major_version, priv->usb_minor_version);
1061+
1062+
arv_info_device("[UvDevice::new] Using control endpoint OUT=0x%02x IN=0x%02x, interface %d",
1063+
priv->control_endpoint_out, priv->control_endpoint_in, priv->control_interface);
1064+
arv_info_device("[UvDevice::new] Using data endpoint 0x%02x, interface %d",
10381065
priv->data_endpoint, priv->data_interface);
10391066

10401067
result = libusb_claim_interface (priv->usb_device, priv->control_interface);

0 commit comments

Comments
 (0)