35 #define USB_TIMEOUT 1000 41 #define NUM_TIMEOUTS 2 44 #define CHUNK_SIZE 2048 50 struct libusb_config_descriptor *
config;
51 const struct libusb_interface *interface;
52 const struct libusb_interface_descriptor *desc;
53 const struct libusb_endpoint_descriptor *epdesc;
55 bool found_endpoint_in;
56 bool found_endpoint_out;
59 devh->interface_number = 0;
65 ret = libusb_get_active_config_descriptor(devh->
dev->usb_dev, &config);
67 if (ret != LIBUSB_SUCCESS) {
68 log_err(ctx,
"Failed to get configuration descriptor: %s.",
69 libusb_error_name(ret));
73 found_interface =
false;
75 for (uint8_t i = 0; i < config->bNumInterfaces; i++) {
76 interface = &config->interface[i];
77 desc = &interface->altsetting[0];
79 if (desc->bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC)
82 if (desc->bInterfaceSubClass != LIBUSB_CLASS_VENDOR_SPEC)
85 if (desc->bNumEndpoints < 2)
88 found_interface =
true;
89 devh->interface_number = i;
93 if (!found_interface) {
94 log_err(ctx,
"No suitable interface found.");
95 libusb_free_config_descriptor(config);
99 found_endpoint_in =
false;
100 found_endpoint_out =
false;
102 for (uint8_t i = 0; i < desc->bNumEndpoints; i++) {
103 epdesc = &desc->endpoint[i];
105 if (epdesc->bEndpointAddress & LIBUSB_ENDPOINT_IN) {
106 devh->endpoint_in = epdesc->bEndpointAddress;
107 found_endpoint_in =
true;
109 devh->endpoint_out = epdesc->bEndpointAddress;
110 found_endpoint_out =
true;
114 libusb_free_config_descriptor(config);
116 if (!found_endpoint_in) {
117 log_err(ctx,
"Interface IN endpoint not found.");
121 if (!found_endpoint_out) {
122 log_err(ctx,
"Interface OUT endpoint not found.");
126 log_dbg(ctx,
"Using endpoint %02x (IN) and %02x (OUT).",
127 devh->endpoint_in, devh->endpoint_out);
134 log_err(ctx,
"Transport buffer malloc failed.");
158 struct libusb_device_handle *usb_devh;
163 log_dbg(ctx,
"Trying to open device (bus:address = %03u:%03u).",
164 libusb_get_bus_number(dev->usb_dev),
165 libusb_get_device_address(dev->usb_dev));
170 log_err(ctx,
"Initialize device handle failed.");
174 ret = libusb_open(dev->usb_dev, &usb_devh);
176 if (ret != LIBUSB_SUCCESS) {
177 log_err(ctx,
"Failed to open device: %s.",
178 libusb_error_name(ret));
183 ret = libusb_claim_interface(usb_devh, devh->interface_number);
185 if (ret != LIBUSB_SUCCESS) {
186 log_err(ctx,
"Failed to claim interface: %s.",
187 libusb_error_name(ret));
189 libusb_close(usb_devh);
193 log_dbg(ctx,
"Device opened successfully.");
195 devh->usb_devh = usb_devh;
209 log_dbg(ctx,
"Closing device (bus:address = %03u:%03u).",
210 libusb_get_bus_number(dev->usb_dev),
211 libusb_get_device_address(dev->usb_dev));
213 ret = libusb_release_interface(devh->usb_devh, devh->interface_number);
215 libusb_close(devh->usb_devh);
218 if (ret != LIBUSB_SUCCESS) {
219 log_err(ctx,
"Failed to release interface: %s.",
220 libusb_error_name(ret));
224 log_dbg(ctx,
"Device closed successfully.");
230 size_t length,
bool has_command)
241 log_dbgio(ctx,
"Starting write operation (length = %zu bytes).", length);
244 log_warn(ctx,
"Last write operation left %zu bytes in the " 248 log_warn(ctx,
"Last write operation was not performed.");
266 log_dbgio(ctx,
"Starting read operation (length = %zu bytes).",
270 log_dbg(ctx,
"Last read operation left %zu bytes in the " 274 log_warn(ctx,
"Last read operation left %zu bytes.",
284 size_t read_length,
bool has_command)
290 if (!read_length || !write_length)
295 log_dbgio(ctx,
"Starting write / read operation (length = " 296 "%zu / %zu bytes).", write_length, read_length);
299 log_warn(ctx,
"Last write operation left %zu bytes in the " 303 log_warn(ctx,
"Last write operation was not performed.");
306 log_warn(ctx,
"Last read operation left %zu bytes in the " 310 log_warn(ctx,
"Last read operation left %zu bytes.",
336 while (tries > 0 && !transferred) {
338 ret = libusb_bulk_transfer(devh->usb_devh, devh->endpoint_in,
339 (
unsigned char *)buffer,
CHUNK_SIZE, &transferred,
342 if (ret == LIBUSB_ERROR_TIMEOUT) {
343 log_warn(ctx,
"Failed to receive data from " 344 "device: %s.", libusb_error_name(ret));
347 }
else if (ret != LIBUSB_SUCCESS) {
348 log_err(ctx,
"Failed to receive data from " 349 "device: %s.", libusb_error_name(ret));
353 log_dbgio(ctx,
"Received %i bytes from device.", transferred);
357 if (transferred > 0) {
358 *length = transferred;
362 log_err(ctx,
"Receiving data from device timed out.");
382 buffer = realloc(devh->
buffer, size);
385 log_err(ctx,
"Failed to adjust buffer size to %zu bytes.",
393 log_dbg(ctx,
"Adjusted buffer size to %zu bytes.", size);
409 while (tries > 0 && length > 0) {
411 ret = libusb_bulk_transfer(devh->usb_devh, devh->endpoint_out,
415 if (ret == LIBUSB_SUCCESS) {
417 }
else if (ret == LIBUSB_ERROR_TIMEOUT) {
418 log_warn(ctx,
"Failed to send data to device: %s.",
419 libusb_error_name(ret));
422 log_err(ctx,
"Failed to send data to device: %s.",
423 libusb_error_name(ret));
427 buffer += transferred;
428 length -= transferred;
430 log_dbgio(ctx,
"Sent %i bytes to device.", transferred);
436 log_err(ctx,
"Sending data to device timed out.");
453 log_err(ctx,
"Requested to write %zu bytes but only %zu bytes " 454 "are expected for the write operation.", length,
463 if (length < devh->write_length) {
474 log_dbgio(ctx,
"Wrote %zu bytes into buffer.", length);
486 return usb_send(devh, buffer, length);
501 tmp =
MIN(length, fill_bytes);
509 log_dbgio(ctx,
"Buffer filled up with %zu bytes.", tmp);
523 return usb_send(devh, buffer, length);
531 size_t bytes_received;
537 log_err(ctx,
"Requested to read %zu bytes but only %zu bytes " 538 "are expected for the read operation.", length,
543 if (length <= devh->bytes_available) {
550 log_dbgio(ctx,
"Read %zu bytes from buffer.", length);
562 log_dbgio(ctx,
"Read %zu bytes from buffer to flush it.",
586 tmp =
MIN(bytes_received, length);
587 memcpy(buffer, devh->
buffer, tmp);
593 if (bytes_received > length) {
602 log_dbgio(ctx,
"Read %zu bytes from buffer.", tmp);
604 ret =
usb_recv(devh, buffer, &bytes_received);
609 buffer += bytes_received;
610 length -= bytes_received;
613 log_dbgio(ctx,
"Read %zu bytes from device.",
uint8_t * buffer
Buffer for write and read operations.
JAYLINK_PRIV int transport_usb_read(struct jaylink_device_handle *devh, uint8_t *buffer, size_t length)
size_t buffer_size
Buffer size.
JAYLINK_PRIV int transport_usb_open(struct jaylink_device_handle *devh)
JAYLINK_PRIV void log_err(const struct jaylink_context *ctx, const char *format,...)
size_t bytes_available
Number of bytes available in the buffer to be read.
static int usb_recv(struct jaylink_device_handle *devh, uint8_t *buffer, size_t *length)
Opaque structure representing a device.
JAYLINK_PRIV void log_dbgio(const struct jaylink_context *ctx, const char *format,...)
static bool adjust_buffer(struct jaylink_device_handle *devh, size_t size)
Opaque structure representing a libjaylink context.
#define JAYLINK_PRIV
Macro to mark private libjaylink symbol.
Internal libjaylink header file.
static void cleanup_handle(struct jaylink_device_handle *devh)
static struct device_config config
static int usb_send(struct jaylink_device_handle *devh, const uint8_t *buffer, size_t length)
size_t read_length
Number of bytes left for the read operation.
JAYLINK_PRIV void log_dbg(const struct jaylink_context *ctx, const char *format,...)
struct jaylink_context * ctx
libjaylink context.
JAYLINK_PRIV int transport_usb_write(struct jaylink_device_handle *devh, const uint8_t *buffer, size_t length)
size_t write_pos
Current write position in the buffer.
size_t size
Size of the control block search area.
Opaque structure representing a handle of a device.
JAYLINK_PRIV void log_warn(const struct jaylink_context *ctx, const char *format,...)
Public libjaylink header file to be used by applications.
JAYLINK_PRIV int transport_usb_start_write_read(struct jaylink_device_handle *devh, size_t write_length, size_t read_length, bool has_command)
static struct jaylink_device_handle * devh
#define CHUNK_SIZE
Chunk size in bytes in which data is transferred.
size_t read_pos
Current read position in the buffer.
JAYLINK_PRIV int transport_usb_start_read(struct jaylink_device_handle *devh, size_t length)
JAYLINK_PRIV int transport_usb_start_write(struct jaylink_device_handle *devh, size_t length, bool has_command)
struct jaylink_device * dev
Device instance.
size_t write_length
Number of bytes left to be written before the write operation will be performed.
JAYLINK_PRIV int transport_usb_close(struct jaylink_device_handle *devh)
static int initialize_handle(struct jaylink_device_handle *devh)
#define NUM_TIMEOUTS
Number of consecutive timeouts before an USB transfer will be treated as timed out.
#define USB_TIMEOUT
Timeout of an USB transfer in milliseconds.