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.