LIBUSB(3)

๐Ÿ“ฆ
version 15.1 ยท 2 versions
, in freebsd 15.1

libusb(3) โ€” USB access library, but make it a group-chat moment ๐Ÿ’…

๐ŸŽ€ NAME ๐ŸŽ€

libusb โ€” USB access library

๐Ÿ“š LIBRARY ๐Ÿ“š

USB access library (libusb, -lusb)

โœจ SYNOPSIS โœจ

#include <libusb.h>

๐Ÿฆ‹ DESCRIPTION ๐Ÿฆ‹

The libusb library contains interfaces for directly managing a usb device. The current implementation supports v1.0 of the libusb API.

๐Ÿ’– LIBRARY INITIALISATION AND DEINITIALISATION ๐Ÿ’–

Okay bestie, this is the setup-and-cleanup era. Do it in the right order or the USB vibes will be off, no cap.

๐ŸŒŸ libusb_get_version

const struct libusb_version * libusb_get_version(void)

This function returns version information about LibUSB.

๐Ÿš€ libusb_init

int libusb_init(libusb_context **ctx)

Call this function before any other libusb v1.0 API function, to initialise a valid libusb v1.0 context. If the ctx argument is non-NULL, a pointer to the libusb context is stored at the given location. This function returns 0 upon success or LIBUSB_ERROR on failure.

๐Ÿงš libusb_init_context

int libusb_init_context(libusb_context **ctx, const struct libusb_init_option [], int num_options)

Call this function before any other libusb v1.0 API function, to initialise a valid libusb v1.0 context. If the ctx argument is non-NULL, a pointer to the libusb context is stored at the given location. Additional options, like the USB debug level, may be given using the second and third argument. If no options are needed, simply use libusb_init(). This function returns 0 upon success or a LIBUSB_ERROR value on failure.

๐Ÿซถ libusb_exit

void libusb_exit(libusb_context *ctx)

Deinitialise libusb. Must be called at the end of the application. Other libusb routines may not be called after this function. Like, thatโ€™s the final goodbye โ€” respect it ๐Ÿ’€

๐Ÿ”ฅ libusb_has_capability

int libusb_has_capability(uint32_t capability)

This function checks the runtime capabilities of libusb. This function will return non-zero if the given capability is supported, 0 if it is not supported. The valid values for capability are:

  • LIBUSB_CAP_HAS_CAPABILITY โ€” libusb supports libusb_has_capability().
  • LIBUSB_CAP_HAS_HOTPLUG โ€” libusb supports hotplug notifications.
  • LIBUSB_CAP_HAS_HID_ACCESS โ€” libusb can access HID devices without requiring user intervention.
  • LIBUSB_CAP_SUPPORTS_DETACH_KERNEL_DRIVER โ€” libusb supports detaching of the default USB driver with libusb_detach_kernel_driver().

๐Ÿ’ฌ libusb_strerror

const char * libusb_strerror(int code)

Get the ASCII representation of the error given by the code argument. This function does not return NULL. Iconic of it, honestly.

๐ŸŒˆ libusb_setlocale

int libusb_setlocale(const char *locale)

Set locale for the error message when using libusb_strerror() to locale. Note other libusb implementations only support the first two bytes, that means โ€˜en-USโ€™ is equivalent to โ€˜en-CAโ€™.

๐Ÿ‘‘ libusb_error_name

const char * libusb_error_name(int code)

Get the ASCII representation of the error enum given by the code argument. This function does not return NULL.

๐Ÿ’… libusb_set_debug

void libusb_set_debug(libusb_context *ctx, int level)

Set the debug level to level.

๐ŸŒˆ getting the device list ๐ŸŒˆ

  • ssize_t libusb_get_device_list(libusb_context *ctx, libusb_device ***list) โ€” fills in list with every USB device it can find, and adds a reference to each device in that list โœจ. It returns the number of devices in the list, or a LIBUSB_ERROR code.
โš ๏ธ bestie, this one comes with homework: every entry this function makes has to have its reference counter decremented when you're done with it, and the list itself has to be freed. Do not just walk away from it, I'm begging ๐Ÿ˜ญ๐Ÿ’€
  • void libusb_free_device_list(libusb_device **list, int unref_devices) โ€” frees the list of devices that libusb_get_device_list found for you. If unref_device is set to 1, every device in the list gets its reference counter decremented once ๐Ÿ’…

๐ŸšŒ bus, port, and address vibes ๐ŸšŒ

  • uint8_t libusb_get_bus_number(libusb_device *dev) โ€” returns the number of the bus that device dev lives on ๐ŸšŒ
  • uint8_t libusb_get_port_number(libusb_device *dev) โ€” returns the port number that dev is attached to ๐Ÿ”Œ
  • int libusb_get_port_numbers(libusb_device *dev, uint8_t *buf, uint8_t bufsize) โ€” stashes the whole list of port numbers, from the root down to dev, into the buffer buf (which is bufsize big) ๐Ÿ“ฆ
  • int libusb_get_port_path(libusb_context *ctx, libusb_device *dev, uint8_t *buf, uint8_t bufsize) โ€” the deprecated girlie ๐Ÿ’€ she's equivalent to libusb_get_port_numbers
  • uint8_t libusb_get_device_address(libusb_device *dev) โ€” returns the device_address that device dev is holding ๐Ÿ 

โšก speed and packet sizes โšก

  • enum libusb_speed libusb_get_device_speed(libusb_device *dev) โ€” tells you the wire speed the device is connected at. Peep the LIBUSB_SPEED_XXX enums for the deets ๐Ÿ‘€ and if the wire speed is a mystery, you get LIBUSB_SPEED_UNKNOWN back ๐Ÿซ 
  • int libusb_get_max_packet_size(libusb_device *dev, unsigned char endpoint) โ€” returns the wMaxPacketSize value on success, LIBUSB_ERROR_NOT_FOUND if that endpoint doesn't exist, and LIBUSB_ERROR_OTHERS on any other failure ๐Ÿ˜ฎโ€๐Ÿ’จ
  • int libusb_get_max_iso_packet_size(libusb_device *dev, unsigned char endpoint) โ€” returns the packet size multiplied by the packet multiplier on success, LIBUSB_ERROR_NOT_FOUND if the endpoint doesn't exist, and LIBUSB_ERROR_OTHERS on other failure โœจ

๐Ÿซถ reference counting, the iconic duo ๐Ÿซถ

  • libusb_device * libusb_ref_device(libusb_device *dev) โ€” bumps up the reference counter of device dev โฌ†๏ธ
  • void libusb_unref_device(libusb_device *dev) โ€” brings the reference counter of device dev down โฌ‡๏ธ

๐Ÿšช wrapping and opening ๐Ÿšช

  • int libusb_wrap_sys_device(libusb_context *ctx, intptr_t sys_dev, libusb_device_handle **dev_handle) โ€” supposed to make a libusb handler out of an already-opened fd, sys_dev. She's here for compatibility only and is currently unimplemented โ€” always returns LIBUSB_ERROR_NOT_SUPPORTED ๐Ÿ™ˆ
  • int libusb_open(libusb_device *dev, libusb_device_handle **devh) โ€” opens a device and hands you a device_handle. Returns 0 on success, LIBUSB_ERROR_NO_MEM if memory allocation goes sideways, LIBUSB_ERROR_ACCESS on permission problems, LIBUSB_ERROR_NO_DEVICE if the device got disconnected, and a LIBUSB_ERROR code on other errors ๐Ÿซก
  • libusb_device_handle * libusb_open_device_with_vid_pid(libusb_context *ctx, uint16_t vid, uint16_t pid) โ€” the convenience queen ๐Ÿ‘‘ opens a device by its vendor and product IDs, vid and pid. Returns NULL on error ๐Ÿฅฒ

โœจ closing and looking things up โœจ

  • void libusb_close(libusb_device_handle *devh) โ€” closes a device handle, doors shut, lights off ๐Ÿšช
  • libusb_device * libusb_get_device(libusb_device_handle *devh) โ€” gets the device that devh is holding. Returns NULL on error ๐Ÿ˜ฌ
  • libusb_device * libusb_get_parent(libusb_device *dev) โ€” gets dev's parent device. Returns NULL if the device has no parent (i.e. it's a root device) ๐ŸŒณ

๐ŸŽ€ configurations ๐ŸŽ€

  • int libusb_get_configuration(libusb_device_handle *devh, int *config) โ€” returns the value of the current configuration. Returns 0 on success, LIBUSB_ERROR_NO_DEVICE if the device has been disconnected, and a LIBUSB_ERROR code on error ๐Ÿ’…
  • int libusb_set_configuration(libusb_device_handle *devh, int config) โ€” sets the active configuration to config for the device that devh is holding. Returns 0 on success, LIBUSB_ERROR_NOT_FOUND if the configuration you asked for doesn't exist, LIBUSB_ERROR_BUSY if the interfaces are currently claimed, LIBUSB_ERROR_NO_DEVICE if the device has been disconnected, and a LIBUSB_ERROR code on failure ๐Ÿ˜ฎโ€๐Ÿ’จ

๐Ÿฆ‹ interfaces, claiming and releasing ๐Ÿฆ‹

  • int libusb_claim_interface(libusb_device_handle *devh, int interface_number) โ€” claims an interface on the given libusb_handle devh. She's a non-blocking function, okurrr ๐Ÿ’… Returns 0 on success, LIBUSB_ERROR_NOT_FOUND if the requested interface doesn't exist, LIBUSB_ERROR_BUSY if a program or driver already claimed it, LIBUSB_ERROR_NO_DEVICE if the device has been disconnected, and a LIBUSB_ERROR code on failure โœจ
  • int libusb_release_interface(libusb_device_handle *devh, int interface_number) โ€” releases an interface. All the claimed interfaces on a device have to be released before you close the device โ€” yes, all of them, I said what I said ๐Ÿ—ฃ๏ธ Returns 0 on success, LIBUSB_ERROR_NOT_FOUND if the interface wasn't claimed, LIBUSB_ERROR_NO_DEVICE if the device has been disconnected, and LIBUSB_ERROR on failure ๐Ÿ’€
  • int libusb_set_interface_alt_setting(libusb_device_handle *dev, int interface_number, int alternate_setting) โ€” activates an alternate setting for an interface. Returns 0 on success, LIBUSB_ERROR_NOT_FOUND if the interface wasn't claimed or the requested setting doesn't exist, LIBUSB_ERROR_NO_DEVICE if the device has been disconnected, and a LIBUSB_ERROR code on failure ๐ŸŒ€

๐Ÿ”ฅ halts, resets, and is-it-still-there checks ๐Ÿ”ฅ

  • int libusb_clear_halt(libusb_device_handle *devh, unsigned char endpoint) โ€” clears a halt/stall on an endpoint. Returns 0 on success, LIBUSB_ERROR_NOT_FOUND if the endpoint doesn't exist, LIBUSB_ERROR_NO_DEVICE if the device has been disconnected, and a LIBUSB_ERROR code on failure ๐Ÿšฟ
  • int libusb_reset_device(libusb_device_handle *devh) โ€” does a USB port reset on a USB device. Returns 0 on success, LIBUSB_ERROR_NOT_FOUND if re-enumeration is required or if the device has been disconnected, and a LIBUSB_ERROR code on failure ๐Ÿ”„
  • int libusb_check_connected(libusb_device_handle *devh) โ€” vibe checks whether the USB device is still connected ๐Ÿซถ Returns 0 on success, LIBUSB_ERROR_NO_DEVICE if it has been disconnected, and a LIBUSB_ERROR code on failure ๐Ÿ˜ญ

๐Ÿงš kernel drivers, the whole saga ๐Ÿงš

  • int libusb_kernel_driver_active(libusb_device_handle *devh, int interface) โ€” finds out if a driver is active on an interface. Returns 0 if no kernel driver is active, 1 if a kernel driver is active, LIBUSB_ERROR_NO_DEVICE if the device has been disconnected, and a LIBUSB_ERROR code on failure ๐Ÿ‘€
  • int libusb_get_driver(libusb_device_handle *devh, int interface, char *name, int namelen) or int libusb_get_driver_np(libusb_device_handle *devh, int interface, char *name, int namelen) โ€” copies the name of the driver attached to the given device and interface into the buffer name, which is namelen long. Returns 0 on success, LIBUSB_ERROR_NOT_FOUND if no kernel driver is attached to the given interface, and LIBUSB_ERROR_INVALID_PARAM if the interface doesn't exist. Heads up: this function is non-portable ๐Ÿšฉ and the buffer name points to is only zero-terminated on success
  • int libusb_detach_kernel_driver(libusb_device_handle *devh, int interface) or int libusb_detach_kernel_driver_np(libusb_device_handle *devh, int interface) โ€” detaches a kernel driver from an interface. You need this to claim an interface that a kernel driver already claimed, no cap ๐Ÿ”“ Returns 0 on success, LIBUSB_ERROR_NOT_FOUND if no kernel driver was active, LIBUSB_ERROR_INVALID_PARAM if the interface doesn't exist, LIBUSB_ERROR_NO_DEVICE if the device has been disconnected, and a LIBUSB_ERROR code on failure. Also non-portable ๐Ÿšฉ
  • int libusb_attach_kernel_driver(libusb_device_handle *devh, int interface) โ€” re-attaches an interface's kernel driver that you previously detached ๐Ÿ” Returns 0 on success, LIBUSB_ERROR_INVALID_PARAM if the interface doesn't exist, LIBUSB_ERROR_NO_DEVICE if the device has been disconnected, LIBUSB_ERROR_BUSY if the driver can't be attached because the interface is claimed by a program or driver, and a LIBUSB_ERROR code on failure ๐Ÿ˜ฎโ€๐Ÿ’จ
  • int libusb_set_auto_detach_kernel_driver(libusb_device_handle *devh, int enable) โ€” turns on automatic kernel interface driver detaching for when an interface gets claimed, and when the interface is restored the kernel driver is allowed to be re-attached ๐Ÿช„ If enable is non-zero the feature is enabled. Else disabled. Returns 0 on success and a LIBUSB_ERROR code on failure โœจ

๐Ÿ’œ DMA memory (allegedly) ๐Ÿ’œ

  • unsigned char * libusb_dev_mem_alloc(libusb_device_handle *devh) โ€” tries to allocate a DMA memory block from the given devh so we can enjoy that zero-copy transfer from the kernel ๐Ÿ˜Œ She's provided for compatibility, is currently unimplemented, and always returns NULL ๐Ÿ™ˆ
  • int libusb_dev_mem_free(libusb_device_handle *devh, unsigned char *buffer, size_t size) โ€” frees the DMA memory in devh from the given buffer with size. Also unimplemented, always returns LIBUSB_ERROR_NOT_SUPPORTED ๐Ÿ’€

๐Ÿฆ‹ USB DESCRIPTORS ๐Ÿฆ‹

okay so descriptors are literally the device's little info cards โ€” its whole personality, its whole resume ๐Ÿ˜Œ and these are the functions that go get them for you. Buckle up bestie, there's a bunch:

  • int libusb_get_device_descriptor(libusb_device *dev, libusb_device_descriptor *desc) โ€” grabs the USB device descriptor for the device dev. This one is non-blocking, it does not sit there waiting on anything ๐Ÿ’… Returns 0 on success and a LIBUSB_ERROR code on failure.
  • int libusb_get_active_config_descriptor(libusb_device *dev, struct libusb_config_descriptor **config) โ€” gets the USB configuration descriptor for the active configuration. Returns 0 on success, LIBUSB_ERROR_NOT_FOUND if the device is in an unconfigured state, and a LIBUSB_ERROR code on error.
  • int libusb_get_config_descriptor(libusb_device *dev, uint8_t config_index, libusb_config_descriptor **config) โ€” gets a USB configuration descriptor based on its index idx. Returns 0 on success, LIBUSB_ERROR_NOT_FOUND if the configuration does not exist, and a LIBUSB_ERROR code on error.
  • int libusb_get_config_descriptor_by_value(libusb_device *dev, uint8 bConfigurationValue, libusb_config_descriptor **config) โ€” gets a USB configuration descriptor with a specific bConfigurationValue. This is a non-blocking function which does not send a request through the device ๐Ÿซถ Returns 0 on success, LIBUSB_ERROR_NOT_FOUND if the configuration does not exist, and a LIBUSB_ERROR code on failure.
  • void libusb_free_config_descriptor(libusb_config_descriptor *config) โ€” frees a configuration descriptor. bye bestie ๐Ÿ‘‹
  • int libusb_get_string_descriptor(libusb_device_handle *devh, uint8_t desc_idx, uint16_t langid, unsigned char *data, int length) โ€” retrieves a string descriptor in raw format. Returns the number of bytes actually transferred on success, or a negative LIBUSB_ERROR code on failure.
  • int libusb_get_string_descriptor_ascii(libusb_device_handle *devh, uint8_t desc_idx, unsigned char *data, int length) โ€” retrieves a string descriptor in C style ASCII, so it's actually readable instead of raw bytes โœจ Returns the positive number of bytes in the resulting ASCII string on success and a LIBUSB_ERROR code on failure.
  • int libusb_parse_ss_endpoint_comp(const void *buf, int len, libusb_ss_endpoint_companion_descriptor **ep_comp) โ€” parses the USB 3.0 endpoint companion descriptor in host endian format pointed to by buf and having a length of len. Typically these arguments are the extra and extra_length fields of the endpoint descriptor, iykyk. On success the pointer to the resulting descriptor is stored at the location given by ep_comp. Returns zero on success and a LIBUSB_ERROR code on failure. On success the parsed USB 3.0 endpoint companion descriptor must be freed using the libusb_free_ss_endpoint_comp function โ€” don't leave it hanging, that's not the vibe ๐Ÿ™ˆ
  • void libusb_free_ss_endpoint_comp(libusb_ss_endpoint_companion_descriptor *ep_comp) โ€” this function is NULL safe and frees a parsed USB 3.0 endpoint companion descriptor given by ep_comp.
  • int libusb_get_ss_endpoint_companion_descriptor(struct libusb_context *ctx, const struct libusb_endpoint_descriptor *endpoint, struct libusb_ss_endpoint_companion_descriptor **ep_comp) โ€” finds and parses the USB 3.0 endpoint companion descriptor given by endpoint. Returns zero on success and a LIBUSB_ERROR code on failure. On success the parsed USB 3.0 endpoint companion descriptor must be freed using the libusb_free_ss_endpoint_companion_descriptor function.
  • void libusb_free_ss_endpoint_companion_descriptor(struct libusb_ss_endpoint_companion_descriptor *ep_comp) โ€” NULL safe, frees a parsed USB 3.0 endpoint companion descriptor given by ep_comp. ๐Ÿ’…
  • int libusb_get_bos_descriptor(libusb_device_handle *handle, struct libusb_bos_descriptor **bos) โ€” queries the USB device given by handle and stores a pointer to a parsed BOS descriptor into bos. Returns zero on success and a LIBUSB_ERROR code on failure. On success the parsed BOS descriptor must be freed using the libusb_free_bos_descriptor function.
  • int libusb_parse_bos_descriptor(const void *buf, int len, libusb_bos_descriptor **bos) โ€” parses a Binary Object Store, BOS, descriptor into host endian format pointed to by buf and having a length of len. On success the pointer to the resulting descriptor is stored at the location given by bos. Returns zero on success and a LIBUSB_ERROR code on failure. On success the parsed BOS descriptor must be freed using the libusb_free_bos_descriptor function.
  • void libusb_free_bos_descriptor(libusb_bos_descriptor *bos) โ€” NULL safe, frees a parsed BOS descriptor given by bos. ๐ŸŽ€
  • int libusb_get_usb_2_0_extension_descriptor(struct libusb_context *ctx, struct libusb_bos_dev_capability_descriptor *dev_cap, struct libusb_usb_2_0_extension_descriptor **usb_2_0_extension) โ€” parses the USB 2.0 extension descriptor from the descriptor given by dev_cap and stores a pointer to the parsed descriptor into usb_2_0_extension. Returns zero on success and a LIBUSB_ERROR code on failure. On success the parsed USB 2.0 extension descriptor must be freed using the libusb_free_usb_2_0_extension_descriptor function.
  • void libusb_free_usb_2_0_extension_descriptor(struct libusb_usb_2_0_extension_descriptor *usb_2_0_extension) โ€” NULL safe, frees a parsed USB 2.0 extension descriptor given by usb_2_0_extension.
  • int libusb_get_ss_usb_device_capability_descriptor(struct libusb_context *ctx, struct libusb_bos_dev_capability_descriptor *dev_cap, struct libusb_ss_usb_device_capability_descriptor **ss_usb_device_capability) โ€” parses the SuperSpeed device capability descriptor from the descriptor given by dev_cap and stores a pointer to the parsed descriptor into ss_usb_device_capability. Returns zero on success and a LIBUSB_ERROR code on failure. On success the parsed SuperSpeed device capability descriptor must be freed using the libusb_free_ss_usb_device_capability_descriptor function. SuperSpeed, literally in the name ๐Ÿ”ฅ
  • void libusb_free_ss_usb_device_capability_descriptor(struct libusb_ss_usb_device_capability_descriptor *ss_usb_device_capability) โ€” NULL safe, frees a parsed SuperSpeed device capability descriptor given by ss_usb_device_capability.
  • int libusb_get_container_id_descriptor(struct libusb_context *ctx, struct libusb_bos_dev_capability_descriptor *dev_cap, struct libusb_container_id_descriptor **container_id) โ€” parses the container ID descriptor from the descriptor given by dev_cap and stores a pointer to the parsed descriptor into container_id. Returns zero on success and a LIBUSB_ERROR code on failure. On success the parsed container ID descriptor must be freed using the libusb_free_container_id_descriptor function.
  • void libusb_free_container_id_descriptor(struct libusb_container_id_descriptor *container_id) โ€” NULL safe, frees a parsed container ID descriptor given by container_id. ๐Ÿ“
  • int libusb_get_platform_descriptor(struct libusb_context *ctx, struct libusb_bos_dev_capability_descriptor *dev_cap, struct libusb_platform_descriptor **platform_descriptor) โ€” parses the platform descriptor from the descriptor given by dev_cap and stores a pointer to the parsed descriptor into platform_descriptor. Returns zero on success and a LIBUSB_ERROR code on failure. On success the parsed platform descriptor must be freed using the libusb_free_platform_descriptor function.
  • void libusb_free_platform_descriptor(struct libusb_platform_descriptor *platform_descriptor) โ€” NULL safe, frees a parsed platform descriptor given by platform_descriptor. ๐Ÿงš

โšก USB ASYNCHRONOUS I/O โšก

async I/O is the "don't wait around, go live your life" era of USB โ€” you hand off the transfer and the library hits you back later. main character energy fr fr ๐Ÿ’ซ

  • struct libusb_transfer * libusb_alloc_transfer(int iso_packets) โ€” allocates a transfer with the number of isochronous packet descriptors specified by iso_packets. Returns NULL on error ๐Ÿ˜ญ
  • void libusb_free_transfer(struct libusb_transfer *tr) โ€” frees a transfer.
  • int libusb_submit_transfer(struct libusb_transfer *tr) โ€” submits a transfer and returns immediately, no waiting, no blocking, we love to see it. Returns 0 on success, LIBUSB_ERROR_NO_DEVICE if the device has been disconnected, and a LIBUSB_ERROR code on other failure.
  • int libusb_cancel_transfer(struct libusb_transfer *tr) โ€” asynchronously cancels a transfer. Returns 0 on success and a LIBUSB_ERROR code on failure.

๐Ÿงธ USB SYNCHRONOUS I/O ๐Ÿงธ

the chill, old-school way: you ask, you wait, you get your answer. no cap, sometimes that's exactly what you want ๐Ÿ˜Œ

  • int libusb_control_transfer(libusb_device_handle *devh, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, unsigned char *data, uint16_t wLength, unsigned int timeout) โ€” performs a USB control transfer. Returns the actual number of bytes transferred on success, in the range from and including zero up to and including wLength. On error a LIBUSB_ERROR code is returned โ€” for example LIBUSB_ERROR_TIMEOUT if the transfer timed out, LIBUSB_ERROR_PIPE if the control request was not supported, LIBUSB_ERROR_NO_DEVICE if the device has been disconnected, and another LIBUSB_ERROR code on other failures. The LIBUSB_ERROR codes are all negative ๐Ÿ‘‘
watch the sign bestie โ€” success is >= 0, errors are negative. don't go reading a negative error like it's a byte count ๐Ÿ’€
  • int libusb_bulk_transfer(libusb_device_handle *devh, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout) โ€” performs an USB bulk transfer. A timeout value of zero means no timeout. The timeout value is given in milliseconds. Returns 0 on success, LIBUSB_ERROR_TIMEOUT if the transfer timed out, LIBUSB_ERROR_PIPE if the control request was not supported, LIBUSB_ERROR_OVERFLOW if the device offered more data, LIBUSB_ERROR_NO_DEVICE if the device has been disconnected and a LIBUSB_ERROR code on other failure.
  • int libusb_interrupt_transfer(libusb_device_handle *devh, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout) โ€” performs an USB Interrupt transfer. A timeout value of zero means no timeout. The timeout value is given in milliseconds. Returns 0 on success, LIBUSB_ERROR_TIMEOUT if the transfer timed out, LIBUSB_ERROR_PIPE if the control request was not supported, LIBUSB_ERROR_OVERFLOW if the device offered more data, LIBUSB_ERROR_NO_DEVICE if the device has been disconnected and a LIBUSB_ERROR code on other failure. ๐ŸŒˆ

๐Ÿฆ‹ USB STREAMS SUPPORT ๐Ÿฆ‹

okay so streams!! this is the โœจfancyโœจ multiqueue-ish stuff, and bestie, there's a catch โ€” it's lowkey simplified rn:

  • int libusb_alloc_streams(libusb_device_handle *dev, uint32_t num_streams, unsigned char *endpoints, int num_endpoints) โ€” this one does a vibe check on your request: it verifies that the given number of streams using the given number of endpoints is actually allowed, then allocates all the resources you need to use so-called USB streams. but heads up: currently only a single stream per endpoint is supported, to simplify the internals of LibUSB. so likeโ€ฆ don't get too ambitious ๐Ÿ˜ญ. returns 0 on success or a LIBUSB_ERROR code on failure.
  • int libusb_free_streams(libusb_device_handle *dev, unsigned char *endpoints, int num_endpoints) โ€” the cleanup era ๐Ÿ’… releases the resources needed for streams usage. returns 0 on success or a LIBUSB_ERROR code on failure.
  • void libusb_transfer_set_stream_id(struct libusb_transfer *transfer, uint32_t stream_id) โ€” sets the stream ID for the given USB transfer. that's it, that's the whole job ๐ŸŽ€
  • uint32_t libusb_transfer_get_stream_id(struct libusb_transfer *transfer) โ€” hands you back the stream ID for the given USB transfer. and if no stream ID is used? you get a value of 0. zero. nada. the void ๐ŸŒˆ

๐Ÿ’… USB EVENTS ๐Ÿ’…

this is the whole threading-and-locking saga, and honestly it's giving "group project where only one person is allowed to touch the doc at a time". let's get into it ๐Ÿซถ

  • int libusb_try_lock_events(libusb_context *ctx) โ€” tries to acquire the event handling lock (note the "try" โ€” she's not gonna wait around for you, queen). returns 0 if the lock was obtained and 1 if not.
  • void libusb_lock_events(libusb_context *ctx) โ€” actually acquires the event handling lock. this function is blocking, so yeah, you're gonna sit there until it's your turn. no cap.
  • void libusb_unlock_events(libusb_context *ctx) โ€” releases the event handling lock. this will wake up any thread blocked on libusb_wait_for_event(). you're literally the main character doing a dramatic exit that frees everyone ๐ŸŒธ
  • int libusb_event_handling_ok(libusb_context *ctx) โ€” determines if it's still OK for this thread to be doing event handling. returns 1 if event handling can start or continue. returns 0 if this thread must give up the events lock. iykyk, that 0 is your cue to leave ๐Ÿ’€
  • int libusb_event_handler_active(libusb_context *ctx) โ€” determines if an active thread is handling events. returns 1 if there is a thread handling events and 0 if there are no threads currently handling events. it's a "is anyone home" check ๐ŸŽ€
  • void libusb_interrupt_event_handler(libusb_context *ctx) โ€” causes the libusb_handle_events() family of functions to return to the caller one time. and the good news? the libusb_handle_events() functions may be called again after calling this function. so it's a nudge, not a breakup ๐Ÿ’–
  • void libusb_lock_event_waiters(libusb_context *ctx) โ€” acquires the event_waiters lock. this lock is designed to be obtained in the situation where you want to be aware when events are completed, but some other thread is event handling so calling libusb_handle_events() is not allowed. it's the "i'm just watching, not touching" lock ๐Ÿ™ˆ
  • void libusb_unlock_event_waiters(libusb_context *ctx) โ€” releases the event_waiters lock. slay, you're done observing ๐Ÿ‘‘
  • int libusb_wait_for_event(libusb_context *ctx, struct timeval *tv) โ€” waits for another thread to signal completion of an event. must be called with the event waiters lock held, see libusb_lock_event_waiters(). this will block until the timeout expires or a transfer completes or a thread releases the event handling lock through libusb_unlock_events(). returns 0 after a transfer completes or another thread stops event handling, and 1 if the timeout expired. so 0 = something happened, 1 = you waited for nothing bestie ๐Ÿ˜ญ
  • int libusb_handle_events_timeout_completed(libusb_context *ctx, struct timeval *tv, int *completed) โ€” handles any pending events by checking if timeouts have expired and by checking the set of file descriptors for activity. if the completed argument is not equal to NULL, this function will loop until a transfer completion callback sets the variable pointed to by the completed argument to non-zero. if the tv argument is not equal to NULL, this function will return LIBUSB_ERROR_TIMEOUT after the given timeout. returns 0 on success, or a LIBUSB_ERROR code on failure or timeout. she does a lot, okay, she's booked and busy โญ
  • int libusb_handle_events_completed(libusb_context *ctx, int *completed) โ€” handles any pending events by checking the set of file descriptors for activity. if the completed argument is not equal to NULL, this function will loop until a transfer completion callback sets the variable pointed to by the completed argument to non-zero. returns 0 on success, or a LIBUSB_ERROR code on failure. same energy, minus the timer drama ๐Ÿ’œ
  • int libusb_handle_events_timeout(libusb_context *ctx, struct timeval *tv) โ€” handles any pending events by checking if timeouts have expired and by checking the set of file descriptors for activity. returns 0 on success, or a LIBUSB_ERROR code on failure or timeout. the classic โœจ
  • int libusb_handle_events(libusb_context *ctx) โ€” handles any pending events in blocking mode with a sensible timeout. "sensible" is doing so much work in that sentence and i respect it. returns 0 on success and a LIBUSB_ERROR code on failure ๐ŸŒˆ
  • int libusb_handle_events_locked(libusb_context *ctx, struct timeval *tv) โ€” handles any pending events by polling file descriptors, without checking if another thread is already doing so. must be called with the event lock held. like, fr fr, do not skip that part ๐Ÿ™
  • int libusb_pollfds_handle_timeouts(libusb_context *ctx) โ€” this function determines whether applications maintaining libusb events using libusb_get_pollfds() are responsible for handling timeout events themselves. returns 1 if libusb handles the timeout internally, 0 if the application needs to set a dedicated timer to handle it. so: 1 = she's got it covered, 0 = you're on your own, bestie ๐ŸŽ€
  • int libusb_get_next_timeout(libusb_context *ctx, struct timeval *tv) โ€” determines the next internal timeout that libusb needs to handle. returns 0 if there are no pending timeouts, 1 if a timeout was returned, or a LIBUSB_ERROR code on failure or timeout. three outcomes, three moods ๐Ÿ’ซ
  • void libusb_set_pollfd_notifiers(libusb_context *ctx, libusb_pollfd_added_cb added_cb, libusb_pollfd_removed_cb remove_cb, void *user_data) โ€” registers notification functions for file descriptor additions/removals. these functions will be invoked for every new or removed file descriptor that libusb uses as an event source. it's giving "notify me when the group chat changes" ๐Ÿฆ‹
  • const struct libusb_pollfd ** libusb_get_pollfds(libusb_context *ctx) โ€” retrieves a list of file descriptors that should be polled by your main loop as libusb event sources. returns a NULL-terminated list on success or NULL on failure. terminated by NULL specifically โ€” don't go walking past the end, that's not the vibe ๐Ÿ’€
  • int libusb_hotplug_register_callback(libusb_context *ctx, libusb_hotplug_event events, libusb_hotplug_flag flags, int vendor_id, int product_id, int dev_class, libusb_hotplug_callback_fn cb_fn, void *user_data, libusb_hotplug_callback_handle *handle) โ€” this function registers a hotplug filter. the events argument selects which events make the hotplug filter trigger. available event values are LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED and LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT. one or more events must be specified. the vendor_id, product_id and dev_class arguments can be set to LIBUSB_HOTPLUG_MATCH_ANY to match any value in the USB device descriptor โ€” else the specified value is used for matching. if the flags argument is set to LIBUSB_HOTPLUG_ENUMERATE, all currently attached and matching USB devices will be passed to the hotplug filter, given by the cb_fn argument. else the flags argument should be set to LIBUSB_HOTPLUG_NO_FLAGS. this function returns 0 upon success or a LIBUSB_ERROR code on failure. plug-and-play but make it โœจfashionโœจ ๐Ÿ‘‘
  • int libusb_hotplug_callback_fn(libusb_context *ctx, libusb_device *device, libusb_hotplug_event event, void *user_data) โ€” the hotplug filter function itself. if this function returns non-zero, the filter is removed. else the filter is kept and can receive more events. the user_data argument is the same as given when the filter was registered. the event argument can be either of LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED or LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT. so returning non-zero is literally you saying "i'm done here" ๐Ÿ’…
  • void libusb_hotplug_deregister_callback(libusb_context *ctx, libusb_hotplug_callback_handle handle) โ€” this function unregisters a hotplug filter. bye bestie ๐Ÿซถ
  • void libusb_free_pollfds(const struct libusb_pollfd **pollfds) โ€” this function releases the memory storage in pollfds, and is safe to call when the argument is NULL. grab the free win, we love a defensive function ๐ŸŒธ
  • libusb_hotplug_get_user_data(struct libusb_context *ctx, libusb_hotplug_callback_handle callback_handle) โ€” this function returns the user data from the opaque callback_handle, or returns NULL if no matching handle is found. (yes the signature in the docs has no return type written and we're not gonna invent one, that's between you and the header ๐Ÿ˜Œ)

๐Ÿงš LIBUSB VERSION 0.1 COMPATIBILITY ๐Ÿงš

the library is also compliant with LibUSB version 0.1.12. yes, the old stuff still works โ€” legacy icons stay iconic ๐Ÿ’–

usb_open() usb_close() usb_get_string() usb_get_string_simple()
usb_get_descriptor_by_endpoint() usb_get_descriptor()
usb_parse_descriptor() usb_parse_configuration()
usb_destroy_configuration() usb_fetch_and_parse_descriptors()
usb_bulk_write() usb_bulk_read() usb_interrupt_write()
usb_interrupt_read() usb_control_msg() usb_set_configuration()
usb_claim_interface() usb_release_interface() usb_set_altinterface()
usb_resetep() usb_clear_halt() usb_reset() usb_strerror() usb_init()
usb_set_debug() usb_find_busses() usb_find_devices() usb_device()
usb_get_busses() usb_check_connected() usb_get_driver_np()
usb_detach_kernel_driver_np()

๐Ÿ”ฅ SEE ALSO ๐Ÿ”ฅ

go read these next, bestie, they're required reading for the lore:

and the official website, which we're allowed to just print as a string here:

https://libusb.info/

๐ŸŒŸ HISTORY ๐ŸŒŸ

libusb support first appeared in FreeBSD 8.0. a true icon since day one, no cap ๐Ÿ’œ


and that's the whole page, bestie!! you made it to the end, which means you're officially a libusb girlie now ๐ŸŽ€ This gorgeous thing came from Debian, dated July 9, 2025, filed under LIBUSB(3) โ€” go forth and poll some file descriptors, you absolute queen ๐Ÿ‘‘๐Ÿ’–

๐Ÿ“ฆ where this page comes from
  • freebsd 15.1: base 15.1
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms