From 271ff3fa1d2a43d2c6f04cf2549b1fee8d6ff88d Mon Sep 17 00:00:00 2001 From: Zachary Levy Date: Thu, 25 Jun 2026 22:06:06 +0000 Subject: [PATCH] Libusb bool / docs Co-authored-by: Zachary Levy Reviewed-on: https://git.bfpower.io/BFPOWER/levlib/pulls/37 --- vendor/libusb/libusb.odin | 658 +++++++++++++++++++++++++++++++++++--- 1 file changed, 617 insertions(+), 41 deletions(-) diff --git a/vendor/libusb/libusb.odin b/vendor/libusb/libusb.odin index 93fbb95..c30026e 100644 --- a/vendor/libusb/libusb.odin +++ b/vendor/libusb/libusb.odin @@ -11,6 +11,7 @@ import "core:c" // available; use pkg-config or linker flags to control it externally. LIBUSB_SHARED :: #config(LIBUSB_SHARED, true) +//odinfmt: disable when ODIN_OS == .Windows { when ODIN_ARCH == .amd64 { when LIBUSB_SHARED { @@ -42,6 +43,7 @@ when ODIN_OS == .Windows { // Install via: apt install libusb-1.0-0-dev / brew install libusb / etc. foreign import lib "system:usb-1.0" } +//odinfmt: enable // libusb API version (1.0.30). API_VERSION :: 0x0100010C @@ -104,30 +106,57 @@ POLLHUP :: c.short(0x0010) // Device and/or Interface Class codes. Class_Code :: enum c.int { + // In the context of a device descriptor, this bDeviceClass value indicates + // that each interface specifies its own class information and all interfaces + // operate independently. PER_INTERFACE = 0x00, + // Audio class. AUDIO = 0x01, + // Communications class. COMM = 0x02, + // Human Interface Device class. HID = 0x03, + // Physical. PHYSICAL = 0x05, + // Image class. IMAGE = 0x06, + // Printer class. PRINTER = 0x07, + // Mass storage class. MASS_STORAGE = 0x08, + // Hub class. HUB = 0x09, + // Data class. DATA = 0x0a, + // Smart Card. SMART_CARD = 0x0b, + // Content Security. CONTENT_SECURITY = 0x0d, + // Video. VIDEO = 0x0e, + // Personal Healthcare. PERSONAL_HEALTHCARE = 0x0f, + // Audio & Video. AUDIO_VIDEO = 0x10, + // Billboard. BILLBOARD = 0x11, + // USB Type-C Bridge class. TYPE_C_BRIDGE = 0x12, + // Bulk Display Protocol. BULK_DISPLAY = 0x13, + // Management Component Transport Protocol. MCTP = 0x14, + // I3C class. I3C = 0x3c, + // Diagnostic Device. DIAGNOSTIC_DEVICE = 0xdc, + // Wireless class. WIRELESS = 0xe0, + // Miscellaneous class. MISCELLANEOUS = 0xef, + // Application class. APPLICATION = 0xfe, + // Class is vendor-specific. VENDOR_SPEC = 0xff, } @@ -136,126 +165,197 @@ CLASS_PTP :: Class_Code.IMAGE // Descriptor types as defined by the USB specification. Descriptor_Type :: enum c.int { + // Device descriptor. See `Device_Descriptor`. DEVICE = 0x01, + // Configuration descriptor. See `Config_Descriptor`. CONFIG = 0x02, + // String descriptor. STRING = 0x03, + // Interface descriptor. See `Interface_Descriptor`. INTERFACE = 0x04, + // Endpoint descriptor. See `Endpoint_Descriptor`. ENDPOINT = 0x05, + // Interface Association Descriptor. See `Interface_Association_Descriptor`. INTERFACE_ASSOCIATION = 0x0b, + // BOS descriptor. BOS = 0x0f, + // Device Capability descriptor. DEVICE_CAPABILITY = 0x10, + // HID descriptor. HID = 0x21, + // HID report descriptor. REPORT = 0x22, + // Physical descriptor. PHYSICAL = 0x23, + // Hub descriptor. HUB = 0x29, + // SuperSpeed Hub descriptor. SUPERSPEED_HUB = 0x2a, + // SuperSpeed Endpoint Companion descriptor. SS_ENDPOINT_COMPANION = 0x30, } // Endpoint direction. Values for bit 7 of the endpoint address. Endpoint_Direction :: enum c.int { + // Out: host-to-device. OUT = 0x00, + // In: device-to-host. IN = 0x80, } // Endpoint transfer type. Values for bits 0:1 of bmAttributes. Endpoint_Transfer_Type :: enum c.int { + // Control endpoint. CONTROL = 0x0, + // Isochronous endpoint. ISOCHRONOUS = 0x1, + // Bulk endpoint. BULK = 0x2, + // Interrupt endpoint. INTERRUPT = 0x3, } // Standard requests, as defined in table 9-5 of the USB 3.0 specifications. Standard_Request :: enum c.int { + // Request status of the specific recipient. GET_STATUS = 0x00, + // Clear or disable a specific feature. CLEAR_FEATURE = 0x01, + // Set or enable a specific feature. (0x02 is reserved.) SET_FEATURE = 0x03, + // Set device address for all future accesses. (0x04 is reserved.) SET_ADDRESS = 0x05, + // Get the specified descriptor. GET_DESCRIPTOR = 0x06, + // Used to update existing descriptors or add new descriptors. SET_DESCRIPTOR = 0x07, + // Get the current device configuration value. GET_CONFIGURATION = 0x08, + // Set device configuration. SET_CONFIGURATION = 0x09, + // Return the selected alternate setting for the specified interface. GET_INTERFACE = 0x0a, + // Select an alternate interface for the specified interface. SET_INTERFACE = 0x0b, + // Set then report an endpoint's synchronization frame. SYNCH_FRAME = 0x0c, + // Sets both the U1 and U2 Exit Latency. SET_SEL = 0x30, + // Delay from the time a host transmits a packet to the time it is + // received by the device. SET_ISOCH_DELAY = 0x31, } // Request type bits of the bmRequestType field in control transfers. Request_Type :: enum c.int { + // Standard. STANDARD = 0x00 << 5, + // Class. CLASS = 0x01 << 5, + // Vendor. VENDOR = 0x02 << 5, + // Reserved. RESERVED = 0x03 << 5, } // Recipient bits of the bmRequestType field in control transfers. // Values 4 through 31 are reserved. Request_Recipient :: enum c.int { + // Device. DEVICE = 0x00, + // Interface. INTERFACE = 0x01, + // Endpoint. ENDPOINT = 0x02, + // Other. OTHER = 0x03, } // Synchronization type for isochronous endpoints. // Values for bits 2:3 of bmAttributes. Iso_Sync_Type :: enum c.int { + // No synchronization. NONE = 0x0, + // Asynchronous. ASYNC = 0x1, + // Adaptive. ADAPTIVE = 0x2, + // Synchronous. SYNC = 0x3, } // Usage type for isochronous endpoints. // Values for bits 4:5 of bmAttributes. Iso_Usage_Type :: enum c.int { + // Data endpoint. DATA = 0x0, + // Feedback endpoint. FEEDBACK = 0x1, + // Implicit feedback data endpoint. IMPLICIT = 0x2, } // Supported speeds (wSpeedSupported) — bitmask flags. +// Indicates what speeds the device supports. Supported_Speed_Bit :: enum u16 { + // Low speed operation supported (1.5MBit/s). LOW = 0, + // Full speed operation supported (12MBit/s). FULL = 1, + // High speed operation supported (480MBit/s). HIGH = 2, + // Superspeed operation supported (5000MBit/s). SUPER = 3, } Supported_Speeds :: bit_set[Supported_Speed_Bit;u16] -// USB 2.0 Extension bmAttributes flags. +// Masks for the bits of the bmAttributes field of the USB 2.0 Extension +// descriptor. Usb2_Ext_Attribute_Bit :: enum u32 { + // Supports Link Power Management (LPM). LPM_SUPPORT = 1, } Usb2_Ext_Attributes :: bit_set[Usb2_Ext_Attribute_Bit;u32] -// SuperSpeed USB Device Capability bmAttributes flags. +// Masks for the bits of the bmAttributes field of the SuperSpeed USB Device +// Capability descriptor. Ss_Dev_Cap_Attribute_Bit :: enum u8 { + // Supports Latency Tolerance Messages (LTM). LTM_SUPPORT = 1, } Ss_Dev_Cap_Attributes :: bit_set[Ss_Dev_Cap_Attribute_Bit;u8] // USB capability types (BOS). Bos_Type :: enum c.int { + // Wireless USB device capability. WIRELESS_USB_DEVICE_CAPABILITY = 0x01, + // USB 2.0 extensions. USB_2_0_EXTENSION = 0x02, + // SuperSpeed USB device capability. SS_USB_DEVICE_CAPABILITY = 0x03, + // Container ID type. CONTAINER_ID = 0x04, + // Platform descriptor. PLATFORM_DESCRIPTOR = 0x05, + // SuperSpeedPlus device capability. SUPERSPEED_PLUS_CAPABILITY = 0x0A, } // Speed codes. Indicates the speed at which the device is operating. Speed :: enum c.int { + // The OS doesn't report or know the device speed. UNKNOWN = 0, + // The device is operating at low speed (1.5MBit/s). LOW = 1, + // The device is operating at full speed (12MBit/s). FULL = 2, + // The device is operating at high speed (480MBit/s). HIGH = 3, + // The device is operating at super speed (5000MBit/s). SUPER = 4, + // The device is operating at super speed plus (10000MBit/s). SUPER_PLUS = 5, + // The device is operating at super speed plus x2 (20000MBit/s). SUPER_PLUS_X2 = 6, } @@ -263,40 +363,68 @@ Speed :: enum c.int { // codes on failure. Use `error_name()` for a string representation or // `strerror()` for an end-user description. Error :: enum c.int { + // Success (no error). SUCCESS = 0, + // Input/output error. IO = -1, + // Invalid parameter. INVALID_PARAM = -2, + // Access denied (insufficient permissions). ACCESS = -3, + // No such device (it may have been disconnected). NO_DEVICE = -4, + // Entity not found. NOT_FOUND = -5, + // Resource busy. BUSY = -6, + // Operation timed out. TIMEOUT = -7, + // Overflow. OVERFLOW = -8, + // Pipe error. PIPE = -9, + // System call interrupted (perhaps due to signal). INTERRUPTED = -10, + // Insufficient memory. NO_MEM = -11, + // Operation not supported or unimplemented on this platform. NOT_SUPPORTED = -12, + // Other error. OTHER = -99, } // Transfer type (for the Transfer struct's `type` field). // Stored as u8 to match libusb_transfer.type which is `unsigned char`. Transfer_Type :: enum u8 { + // Control transfer. CONTROL = 0, + // Isochronous transfer. ISOCHRONOUS = 1, + // Bulk transfer. BULK = 2, + // Interrupt transfer. INTERRUPT = 3, + // Bulk stream transfer. BULK_STREAM = 4, } // Transfer status codes. Transfer_Status :: enum c.int { + // Transfer completed without error. Note that this does not indicate that + // the entire amount of requested data was transferred. COMPLETED, + // Transfer failed. ERROR, + // Transfer timed out. TIMED_OUT, + // Transfer was cancelled. CANCELLED, + // For bulk/interrupt endpoints: halt condition detected (endpoint stalled). + // For control endpoints: control request not supported. STALL, + // Device was disconnected. NO_DEVICE, + // Device sent more data than requested. OVERFLOW, } @@ -317,27 +445,42 @@ Transfer_Flag_Bit :: enum u8 { } Transfer_Flags :: bit_set[Transfer_Flag_Bit;u8] -// Capabilities supported by this instance of libusb. -// Test with `has_capability()`. +// Capabilities supported by an instance of libusb on the current running +// platform. Test with `has_capability()`. Capability :: enum u32 { + // The `has_capability()` API is available. HAS_CAPABILITY = 0x0000, + // Hotplug support is available on this platform. HAS_HOTPLUG = 0x0001, + // The library can access HID devices without requiring user intervention. + // Note that before being able to actually access an HID device, you may + // still have to call additional libusb functions such as + // `detach_kernel_driver()`. HAS_HID_ACCESS = 0x0100, + // The library supports detaching of the default USB driver, using + // `detach_kernel_driver()`, if one is set by the OS kernel. SUPPORTS_DETACH_KERNEL_DRIVER = 0x0101, } // Log message levels. Log_Level :: enum c.int { + // No messages ever emitted by the library (default). NONE = 0, + // Error messages are emitted. ERROR = 1, + // Warning and error messages are emitted. WARNING = 2, + // Informational, warning and error messages are emitted. INFO = 3, + // All messages are emitted. DEBUG = 4, } // Log callback mode bits. Since version 1.0.23. Log_Cb_Mode_Bit :: enum c.int { + // Callback function handling all log messages. GLOBAL = 0, + // Callback function handling context related log messages. CONTEXT = 1, } Log_Cb_Mode :: bit_set[Log_Cb_Mode_Bit;c.int] @@ -345,13 +488,37 @@ Log_Cb_Mode :: bit_set[Log_Cb_Mode_Bit;c.int] // Available option values for `set_option()` and `init_context()`. Option :: enum c.int { // Set the log message verbosity. Argument: `Log_Level` (as c.int). + // + // The default level is NONE, which means no messages are ever printed. If + // you choose to increase the verbosity, ensure your application does not + // close the stderr file descriptor. Level WARNING is advised. + // + // If the LIBUSB_DEBUG environment variable was set when libusb was + // initialized, this option does nothing. If libusb was compiled without + // message logging, or with verbose debug logging, this option does nothing. LOG_LEVEL = 0, - // Use the UsbDk backend (Windows only, ignored elsewhere). + // Use the UsbDk backend for a specific context, if available. + // + // This option should be set at initialization with `init_context()`, + // otherwise unspecified behavior may occur. Only valid on Windows; ignored + // on all other platforms. USE_USBDK = 1, - // Do not scan for devices in `init_context()` (Linux only). + // Do not scan for devices. + // + // With this option set, libusb will skip scanning devices in + // `init_context()`, and hotplug functionality will be deactivated. Useful + // in combination with `wrap_sys_device()`, which can access a device + // directly without prior device scanning. This is typically needed on + // Android, where access to USB devices is limited. + // + // Should only be used with `init_context()`, otherwise unspecified behavior + // may occur. Only valid on Linux; ignored on all other platforms. // Alias: WEAK_AUTHORITY. NO_DEVICE_DISCOVERY = 2, - // Set the context log callback. Argument: `Log_Cb`. + // Set the context log callback function, on a context or globally. + // Argument: `Log_Cb`. Using this option with a nil context is equivalent + // to calling `set_log_cb()` with mode GLOBAL; with a non-nil context, it is + // equivalent to mode CONTEXT. LOG_CB = 3, MAX = 4, } @@ -381,29 +548,44 @@ Device_String_Type :: enum c.int { MANUFACTURER, PRODUCT, SERIAL_NUMBER, + // The total number of string types. COUNT, } -// SuperSpeedPlus sublink attribute enums (libusb 1.0.28+). +// Whether a sublink speed attribute defines a symmetric or asymmetric bit +// rate (libusb 1.0.28+). Ssplus_Sublink_Type :: enum c.int { + // Symmetric. SYM = 0, + // Asymmetric. ASYM = 1, } +// Whether a sublink speed attribute defines the receive or transmit bit rate. Ssplus_Sublink_Direction :: enum c.int { + // Receive. RX = 0, + // Transmit. TX = 1, } +// Base-10 exponent (times 3) applied to the sublink mantissa. Ssplus_Sublink_Exponent :: enum c.int { + // Bits per second. BPS = 0, + // Kbps. KBS = 1, + // Mbps. MBS = 2, + // Gbps. GBS = 3, } +// Protocol supported by a sublink. Ssplus_Sublink_Protocol :: enum c.int { + // SuperSpeed. SS = 0, + // SuperSpeedPlus. SSPLUS = 1, } @@ -411,10 +593,19 @@ Ssplus_Sublink_Protocol :: enum c.int { // Use `fill_control_setup()` to populate. The 16-bit fields // are stored in little-endian byte order on the wire. Control_Setup :: struct #packed { + // Request type. Bits 0:4 determine recipient (`Request_Recipient`), bits + // 5:6 determine type (`Request_Type`), bit 7 determines data transfer + // direction (`Endpoint_Direction`). bmRequestType: u8, + // Request. If the type bits of bmRequestType are STANDARD then this field + // refers to `Standard_Request`. Otherwise its use is application-specific. bRequest: u8, + // Value. Varies according to request. wValue: u16, + // Index. Varies according to request, typically used to pass an index or + // offset. wIndex: u16, + // Number of bytes to transfer. wLength: u16, } @@ -478,37 +669,65 @@ Endpoint_Descriptor :: struct { } // Standard USB interface association descriptor (USB 3.0, section 9.6.4). +// All multi-byte fields in host-endian format. Interface_Association_Descriptor :: struct { + // Size of this descriptor (in bytes). bLength: u8, + // Descriptor type (`Descriptor_Type.INTERFACE_ASSOCIATION`). bDescriptorType: u8, + // Interface number of the first interface associated with this function. bFirstInterface: u8, + // Number of contiguous interfaces associated with this function. bInterfaceCount: u8, + // USB-IF class code for this function. A value of zero is not allowed. If + // 0xff, the function class is vendor-specific. All other values are + // reserved for assignment by the USB-IF. bFunctionClass: u8, + // USB-IF subclass code for this function. If not 0xff, all values are + // reserved for assignment by the USB-IF. bFunctionSubClass: u8, + // USB-IF protocol code for this function, qualified by bFunctionClass and + // bFunctionSubClass. bFunctionProtocol: u8, + // Index of string descriptor describing this function. iFunction: u8, } // Array of 0 or more interface association descriptors. Interface_Association_Descriptor_Array :: struct { + // Array of interface association descriptors. Size determined by `length`. iad: [^]Interface_Association_Descriptor, + // Number of interface association descriptors contained. Read-only. length: c.int, } // Standard USB interface descriptor (USB 3.0, section 9.6.5). +// All multi-byte fields in host-endian format. Interface_Descriptor :: struct { + // Size of this descriptor (in bytes). bLength: u8, + // Descriptor type (`Descriptor_Type.INTERFACE`). bDescriptorType: u8, + // Number of this interface. bInterfaceNumber: u8, + // Value used to select this alternate setting for this interface. bAlternateSetting: u8, + // Number of endpoints used by this interface (excluding the control + // endpoint). bNumEndpoints: u8, + // USB-IF class code for this interface. See `Class_Code`. bInterfaceClass: u8, + // USB-IF subclass code, qualified by bInterfaceClass. bInterfaceSubClass: u8, + // USB-IF protocol code, qualified by class and subclass. bInterfaceProtocol: u8, + // Index of string descriptor describing this interface. iInterface: u8, // Array of endpoint descriptors (length = bNumEndpoints). endpoint: [^]Endpoint_Descriptor, + // Extra descriptors. Stored here if libusb encounters unknown descriptors. extra: [^]u8, + // Length of the extra descriptors, in bytes. extra_length: c.int, } @@ -516,85 +735,131 @@ Interface_Descriptor :: struct { Interface :: struct { // Array of interface descriptors (length = num_altsetting). altsetting: [^]Interface_Descriptor, + // Number of alternate settings that belong to this interface. num_altsetting: c.int, } // Standard USB configuration descriptor (USB 3.0, section 9.6.3). +// All multi-byte fields in host-endian format. Config_Descriptor :: struct { + // Size of this descriptor (in bytes). bLength: u8, + // Descriptor type (`Descriptor_Type.CONFIG`). bDescriptorType: u8, + // Total length of data returned for this configuration. wTotalLength: u16, + // Number of interfaces supported by this configuration. bNumInterfaces: u8, + // Identifier value for this configuration. bConfigurationValue: u8, + // Index of string descriptor describing this configuration. iConfiguration: u8, + // Configuration characteristics. bmAttributes: u8, // Max power consumption. Units of 2 mA (high-speed) or 8 mA (super-speed). MaxPower: u8, // Array of interfaces (length = bNumInterfaces). interface: [^]Interface, + // Extra descriptors. Stored here if libusb encounters unknown descriptors. extra: [^]u8, + // Length of the extra descriptors, in bytes. extra_length: c.int, } // SuperSpeed endpoint companion descriptor (USB 3.0, section 9.6.7). +// All multi-byte fields in host-endian format. Ss_Endpoint_Companion_Descriptor :: struct { + // Size of this descriptor (in bytes). bLength: u8, + // Descriptor type (`Descriptor_Type.SS_ENDPOINT_COMPANION`). bDescriptorType: u8, + // The maximum number of packets the endpoint can send or receive as part + // of a burst. bMaxBurst: u8, + // In bulk EP: bits 4:0 represent the maximum number of streams the EP + // supports. In isochronous EP: bits 1:0 represent the Mult. bmAttributes: u8, + // The total number of bytes this EP will transfer every service interval. + // Valid only for periodic EPs. wBytesPerInterval: u16, } // Generic BOS Device Capability descriptor. Check bDevCapabilityType and // call the matching get_*_descriptor function for a fully-typed struct. Bos_Dev_Capability_Descriptor :: struct { + // Size of this descriptor (in bytes). bLength: u8, + // Descriptor type (`Descriptor_Type.DEVICE_CAPABILITY`). bDescriptorType: u8, + // Device Capability type. See `Bos_Type`. bDevCapabilityType: u8, // Device Capability data (bLength - 3 bytes). Flexible array member. dev_capability_data: [0]u8, } // Binary Device Object Store (BOS) descriptor (USB 3.0, section 9.6.2). +// All multi-byte fields in host-endian format. Bos_Descriptor :: struct { + // Size of this descriptor (in bytes). bLength: u8, + // Descriptor type (`Descriptor_Type.BOS`). bDescriptorType: u8, + // Length of this descriptor and all of its sub descriptors. wTotalLength: u16, + // The number of separate device capability descriptors in the BOS. bNumDeviceCaps: u8, // Flexible array of device capability descriptor pointers. dev_capability: [0]^Bos_Dev_Capability_Descriptor, } // USB 2.0 Extension descriptor (USB 3.0, section 9.6.2.1). +// All multi-byte fields in host-endian format. Usb2_Extension_Descriptor :: struct { + // Size of this descriptor (in bytes). bLength: u8, + // Descriptor type (`Descriptor_Type.DEVICE_CAPABILITY`). bDescriptorType: u8, + // Capability type (`Bos_Type.USB_2_0_EXTENSION`). bDevCapabilityType: u8, - // Bitmap of supported device level features. - // See `Usb2_Ext_Attributes`. + // Bitmap of supported device level features. A value of one in a bit + // location indicates the feature is supported. See `Usb2_Ext_Attributes`. bmAttributes: u32, } // SuperSpeed USB Device Capability descriptor (USB 3.0, section 9.6.2.2). +// All multi-byte fields in host-endian format. Ss_Usb_Device_Capability_Descriptor :: struct { + // Size of this descriptor (in bytes). bLength: u8, + // Descriptor type (`Descriptor_Type.DEVICE_CAPABILITY`). bDescriptorType: u8, + // Capability type (`Bos_Type.SS_USB_DEVICE_CAPABILITY`). bDevCapabilityType: u8, - // See `Ss_Dev_Cap_Attributes`. + // Bitmap of supported device level features. A value of one in a bit + // location indicates the feature is supported. See `Ss_Dev_Cap_Attributes`. bmAttributes: u8, - // Bitmap of supported speeds. See `Supported_Speeds`. + // Bitmap of the speeds supported by this device when operating in + // SuperSpeed mode. See `Supported_Speeds`. wSpeedSupported: u16, - // Lowest speed at which full functionality is available. + // The lowest speed at which all the functionality supported by the device + // is available to the user. bFunctionalitySupport: u8, + // U1 Device Exit Latency. bU1DevExitLat: u8, + // U2 Device Exit Latency. bU2DevExitLat: u16, } // Container ID descriptor (USB 3.0, section 9.6.2.3). +// All multi-byte fields, except UUIDs, in host-endian format. Container_Id_Descriptor :: struct { + // Size of this descriptor (in bytes). bLength: u8, + // Descriptor type (`Descriptor_Type.DEVICE_CAPABILITY`). bDescriptorType: u8, + // Capability type (`Bos_Type.CONTAINER_ID`). bDevCapabilityType: u8, + // Reserved field. bReserved: u8, // 128-bit UUID as a byte array. ContainerID: [16]u8, @@ -603,9 +868,13 @@ Container_Id_Descriptor :: struct { // Platform descriptor (USB 3.2, section 9.6.2.4). // Contains a flexible array member — all memory must be managed manually. Platform_Descriptor :: struct { + // Size of this descriptor (in bytes). bLength: u8, + // Descriptor type (`Descriptor_Type.DEVICE_CAPABILITY`). bDescriptorType: u8, + // Capability type (`Bos_Type.PLATFORM_DESCRIPTOR`). bDevCapabilityType: u8, + // Reserved field. bReserved: u8, // 128-bit UUID as a byte array. PlatformCapabilityUUID: [16]u8, @@ -615,21 +884,33 @@ Platform_Descriptor :: struct { // SuperSpeedPlus sublink attribute (libusb 1.0.28+, USB 3.1, section 9.6.2.5). Ssplus_Sublink_Attribute :: struct { + // Sublink Speed Attribute ID (SSID). Uniquely identifies the speed of this + // sublink. ssid: u8, + // Base-10 exponent (times 3) applied to the mantissa. exponent: Ssplus_Sublink_Exponent, + // Whether the attribute defines a symmetric or asymmetric bit rate. type: Ssplus_Sublink_Type, + // Whether the attribute defines the receive or transmit bit rate. direction: Ssplus_Sublink_Direction, + // The protocol supported by the link. protocol: Ssplus_Sublink_Protocol, + // Mantissa applied to the exponent when calculating the maximum bit rate. mantissa: u16, } // SuperSpeedPlus USB Device Capability descriptor (libusb 1.0.28+). // This is a parsed/computed representation, not the raw USB descriptor. Ssplus_Usb_Device_Capability_Descriptor :: struct { + // Sublink Speed Attribute Count. numSublinkSpeedAttributes: u8, + // Sublink Speed ID Count. numSublinkSpeedIDs: u8, + // Unique ID to indicate the minimum lane speed. ssid: u8, + // Minimum receive lane count. minRxLaneCount: u8, + // Minimum transmit lane count. minTxLaneCount: u8, // Flexible array of sublink attributes (length = numSublinkSpeedAttributes). sublinkSpeedAttributes: [0]Ssplus_Sublink_Attribute, @@ -637,20 +918,30 @@ Ssplus_Usb_Device_Capability_Descriptor :: struct { // Version of the libusb runtime. Version :: struct { + // Library major version. major: u16, + // Library minor version. minor: u16, + // Library micro version. micro: u16, + // Library nano version. Deprecated since 1.0.31: this value is frozen and + // no longer updated per build. Use `describe` for a unique-per-build + // identifier. nano: u16, - // Release candidate suffix, e.g. "-rc4". + // Library release candidate suffix string, e.g. "-rc4". rc: cstring, - // For ABI compatibility only. + // Human-readable build identifier (never nil). Intended for display, logs, + // and bug reports; the overall format is not stable, do not parse. describe: cstring, } // Isochronous packet descriptor. Iso_Packet_Descriptor :: struct { + // Length of data to request in this packet. length: c.uint, + // Amount of data that was actually transferred. actual_length: c.uint, + // Status code for this packet. status: Transfer_Status, } @@ -707,13 +998,17 @@ Poll_Fd :: struct { // Option value union for `Init_Option`. Init_Option_Value :: struct #raw_union { + // An integer value used by the option (if applicable). ival: c.int, + // A log callback value used by the option (if applicable). log_cb: Log_Cb, } // Option structure for `init_context()`. Init_Option :: struct { + // Which option to set. option: Option, + // The value to set the option to (if the option takes one). value: Init_Option_Value, } @@ -728,24 +1023,37 @@ Callback_Handle :: distinct c.int //----- Callback types ---------------------------------- -// Asynchronous transfer completion callback. +// Asynchronous transfer callback. When submitting asynchronous transfers, you +// pass a pointer to a callback of this type via the `callback` member of the +// `Transfer`. libusb calls this later, when the transfer has completed or +// failed. Transfer_Cb :: #type proc "c" (transfer: ^Transfer) -// Log message callback. Since version 1.0.23. +// Callback function for handling log messages. `ctx` is the context related to +// the message, or nil for a global message. `level` is the log level and `str` +// is the message. Since version 1.0.23. Log_Cb :: #type proc "c" (ctx: Context, level: Log_Level, str: cstring) -// Hotplug event callback. Return 1 to deregister this callback. +// Hotplug event callback. When requesting hotplug notifications, you pass a +// pointer to a callback of this type. It may be called by an internal event +// thread, so it is recommended to do minimal processing before returning. It +// is safe to call `hotplug_register_callback()` or +// `hotplug_deregister_callback()` from within the callback. Return true to +// indicate this callback is finished processing events (deregistering it). +// Since version 1.0.16. Hotplug_Callback_Fn :: #type proc "c" ( ctx: Context, device: Device, event: Hotplug_Events, user_data: rawptr, -) -> c.int +) -> b32 -// Callback invoked when a new file descriptor should be monitored for events. +// Callback invoked when a new file descriptor should be added to the set of +// file descriptors monitored for events. Pollfd_Added_Cb :: #type proc "c" (fd: c.int, events: c.short, user_data: rawptr) -// Callback invoked when a file descriptor should no longer be monitored. +// Callback invoked when a file descriptor should be removed from the set being +// monitored for events. After returning, do not use that file descriptor again. Pollfd_Removed_Cb :: #type proc "c" (fd: c.int, user_data: rawptr) @(default_calling_convention = "c", link_prefix = "libusb_") @@ -753,10 +1061,29 @@ foreign lib { // ---- Library initialization/deinitialization ---- + // Set the log handler. libusb redirects its log messages to `cb`. Per-context + // and global messages are supported; context messages also go to the global + // handler. `ctx` may be nil for the default context (ignored when only the + // GLOBAL mode is requested). Pass a nil `cb` to stop redirection. + // Since version 1.0.23. set_log_cb :: proc(ctx: Context, cb: Log_Cb, mode: Log_Cb_Mode) --- + // Set an option in the library. Some options require arguments; consult each + // `Option`. If `ctx` is nil, the option is added to a list of defaults + // applied to all subsequently created contexts. Returns SUCCESS, or + // INVALID_PARAM / NOT_SUPPORTED / NOT_FOUND. Since version 1.0.22. set_option :: proc(ctx: Context, option: Option, #c_vararg args: ..any) -> Error --- + // Deprecated initialization function, equivalent to `init_context(ctx, nil, 0)`. + // Must be called before any other libusb function. If `ctx` is nil, a default + // context is created (or reused). init :: proc(ctx: ^Context) -> Error --- + // Initialize libusb. Must be called before any other libusb function. If you + // do not provide an output location for a context pointer, a default context + // is created (and reused if one already exists). If `num_options` is 0 then + // `options` is ignored and may be nil. Returns SUCCESS or an Error. + // Since version 1.0.27. init_context :: proc(ctx: ^Context, options: [^]Init_Option, num_options: c.int) -> Error --- + // Deinitialize libusb. Should be called after closing all open devices and + // before your application terminates. `ctx` may be nil for the default context. exit :: proc(ctx: Context) --- // Deprecated: use `set_option(.LOG_LEVEL, level)` instead. @@ -764,141 +1091,390 @@ foreign lib { // ---- Device handling and enumeration ---- - // Returns device count (positive) or a negative Error code. + // Returns a list of USB devices currently attached to the system. You must + // later free the list with `free_device_list()` (which can optionally unref + // the devices). Be careful not to unref a device you are about to open until + // after you have opened it. Returns the number of devices in the list (the + // list is NULL-terminated, so it is actually one element larger), or a + // negative Error code. get_device_list :: proc(ctx: Context, list: ^[^]Device) -> int --- - free_device_list :: proc(list: [^]Device, unref_devices: c.int) --- + // Free a list of devices obtained from `get_device_list()`. If `unref_devices` + // is true, the reference count of each device in the list is decremented by 1. + free_device_list :: proc(list: [^]Device, unref_devices: b32) --- + // Get the number of the bus that a device is connected to. get_bus_number :: proc(dev: Device) -> u8 --- + // Get the number of the port that a device is connected to. Usually uniquely + // tied to a physical port. Returns 0 if not available. get_port_number :: proc(dev: Device) -> u8 --- - // Returns number of elements filled or negative Error code. + // Get the list of all port numbers from root for the specified device. + // `port_numbers_len` is the max length of the array (max depth is 7 per the + // USB 3.0 spec). Returns the number of elements filled, or OVERFLOW if the + // array is too small. Since version 1.0.16. get_port_numbers :: proc(dev: Device, port_numbers: [^]u8, port_numbers_len: c.int) -> c.int --- // Deprecated: use `get_port_numbers()` instead. get_port_path :: proc(ctx: Context, dev: Device, path: [^]u8, path_length: u8) -> c.int --- + // Get the parent of the specified device. Returns the parent, or nil if not + // available. Only valid between a `get_device_list()` / `free_device_list()` + // pair. get_parent :: proc(dev: Device) -> Device --- + // Get the address of the device on the bus it is connected to. get_device_address :: proc(dev: Device) -> u8 --- + // Get the negotiated connection speed for a device. Returns a `Speed` code; + // UNKNOWN means the OS doesn't know or doesn't support reporting it. get_device_speed :: proc(dev: Device) -> Speed --- + // Returns the backend-specific identifier of the underlying system device + // tree node. Since version 1.0.30. get_session_data :: proc(dev: Device) -> c.ulong --- - // Returns max packet size or negative Error code. + // Convenience function to retrieve the wMaxPacketSize value for an endpoint + // in the active device configuration. Returns the wMaxPacketSize value, or + // NOT_FOUND / OTHER. For iso transfers prefer `get_max_iso_packet_size()`. get_max_packet_size :: proc(dev: Device, endpoint: u8) -> c.int --- - // Returns max iso packet size or negative Error code. + // Calculate the maximum packet size an endpoint is capable of sending or + // receiving in 1 microframe. Useful when setting up isochronous transfers. + // Returns the max packet size, or NOT_FOUND / OTHER. get_max_iso_packet_size :: proc(dev: Device, endpoint: u8) -> c.int --- + // Like `get_max_iso_packet_size()` but for a specific interface and alternate + // setting rather than the first one. Since version 1.0.27. get_max_alt_packet_size :: proc(dev: Device, interface_number: c.int, alternate_setting: c.int, endpoint: u8) -> c.int --- + // Increment the reference count of a device. Returns the same device. ref_device :: proc(dev: Device) -> Device --- + // Decrement the reference count of a device. The device is destroyed when its + // reference count reaches 0. unref_device :: proc(dev: Device) --- + // Wrap a platform-specific system device handle to obtain a libusb device + // handle. On Linux, `sys_dev` must be a valid file descriptor opened on the + // device node. The system handle must remain open until `close()` and is not + // closed by `close()`. Since version 1.0.23. wrap_sys_device :: proc(ctx: Context, sys_dev: c.intptr_t, dev_handle: ^Device_Handle) -> Error --- + // Open a device and obtain a device handle, which allows you to perform I/O. + // Adds a reference to the device (removed by `close()`). Returns SUCCESS, or + // NO_MEM / ACCESS / NO_DEVICE. open :: proc(dev: Device, dev_handle: ^Device_Handle) -> Error --- + // Convenience function to open the first device with the given vendor/product + // IDs. Not intended for real applications (e.g. it only returns the first + // match). Returns a device handle, or nil on error / if not found. open_device_with_vid_pid :: proc(ctx: Context, vendor_id: u16, product_id: u16) -> Device_Handle --- + // Close a device handle. Should be called on all open handles before your + // application exits. Destroys the reference added by `open()`. close :: proc(dev_handle: Device_Handle) --- + // Get the underlying device for a device handle. Does not modify the device's + // reference count, so you need not unref the result. get_device :: proc(dev_handle: Device_Handle) -> Device --- + // Determine the bConfigurationValue of the currently active configuration. + // May use OS caches (no I/O) or block on a control transfer. Writes 0 to + // `config` if the device is unconfigured. Returns SUCCESS or NO_DEVICE. get_configuration :: proc(dev_handle: Device_Handle, config: ^c.int) -> Error --- + // Set the active configuration for a device. A value of -1 puts the device in + // an unconfigured state. Calling with the already-active value acts as a + // lightweight reset. Cannot change configuration while interfaces are claimed. + // Blocking. Returns SUCCESS, or NOT_FOUND / BUSY / NOT_SUPPORTED / NO_DEVICE. set_configuration :: proc(dev_handle: Device_Handle, configuration: c.int) -> Error --- + // Claim an interface on a device handle. Must be claimed before performing + // I/O on any of its endpoints. Purely logical (no bus I/O). Returns SUCCESS, + // or NOT_FOUND / BUSY / NO_DEVICE. claim_interface :: proc(dev_handle: Device_Handle, interface_number: c.int) -> Error --- + // Release a previously claimed interface. Release all claimed interfaces + // before closing a handle. Blocking (sends a SET_INTERFACE request). Returns + // SUCCESS, or NOT_FOUND / NO_DEVICE. release_interface :: proc(dev_handle: Device_Handle, interface_number: c.int) -> Error --- + // Activate an alternate setting for an interface (which must be claimed). + // Blocking. Returns SUCCESS, or NOT_FOUND / NO_DEVICE. set_interface_alt_setting :: proc(dev_handle: Device_Handle, interface_number: c.int, alternate_setting: c.int) -> Error --- + // Clear the halt/stall condition for an endpoint. Cancel all pending + // transfers on the endpoint first. Blocking. Returns SUCCESS, or NOT_FOUND / + // NO_DEVICE. clear_halt :: proc(dev_handle: Device_Handle, endpoint: u8) -> Error --- + // Perform a USB port reset to reinitialize a device. If the reset fails or + // the descriptors change, returns NOT_FOUND — close the handle and + // re-enumerate. Blocking, usually with a noticeable delay. reset_device :: proc(dev_handle: Device_Handle) -> Error --- - // Returns 0 if no kernel driver active, 1 if active, or negative Error code. + // Determine if a kernel driver is active on an interface. If active, you + // cannot claim the interface. Not available on Windows. Returns 0 if no + // kernel driver is active, 1 if active, or a negative Error code. kernel_driver_active :: proc(dev_handle: Device_Handle, interface_number: c.int) -> c.int --- + // Detach a kernel driver from an interface, allowing you to claim it. Not + // available on Windows. Returns SUCCESS, or NOT_FOUND / INVALID_PARAM / + // NO_DEVICE / NOT_SUPPORTED. detach_kernel_driver :: proc(dev_handle: Device_Handle, interface_number: c.int) -> Error --- + // Re-attach an interface's kernel driver previously detached with + // `detach_kernel_driver()`. Not available on Windows. Returns SUCCESS, or + // NOT_FOUND / INVALID_PARAM / NO_DEVICE / NOT_SUPPORTED / BUSY. attach_kernel_driver :: proc(dev_handle: Device_Handle, interface_number: c.int) -> Error --- - set_auto_detach_kernel_driver :: proc(dev_handle: Device_Handle, enable: c.int) -> Error --- + // Enable/disable libusb's automatic kernel driver detachment. When enabled, + // libusb detaches the kernel driver on `claim_interface()` and re-attaches it + // on `release_interface()`. Returns SUCCESS, or NOT_SUPPORTED on platforms + // without this capability. + set_auto_detach_kernel_driver :: proc(dev_handle: Device_Handle, enable: b32) -> Error --- // ---- Miscellaneous ---- + // Check at runtime if the loaded library has a given capability. Should be + // performed after `init_context()`, so the backend has updated its capability + // set. Returns nonzero if the capability is supported, 0 otherwise. has_capability :: proc(capability: Capability) -> c.int --- + // Returns a constant string with the ASCII name of an Error or transfer + // status code (e.g. "LIBUSB_ERROR_IO"). Must not be freed. error_name :: proc(errcode: Error) -> cstring --- + // Returns a pointer to a `Version` with the version of the running library. get_version :: proc() -> ^Version --- + // Set the language used for translatable libusb messages (see `strerror()`). + // `locale` is a 2-letter ISO 639-1 code, optionally followed by region. + // Returns SUCCESS, or INVALID_PARAM / NOT_FOUND. Since version 1.0.21. setlocale :: proc(locale: cstring) -> Error --- + // Returns a constant UTF-8 string describing an Error code, suitable for + // display to an end user. Must not be freed. strerror :: proc(errcode: Error) -> cstring --- // ---- USB descriptors ---- + // Get the USB device descriptor for a device. Non-blocking; the descriptor is + // cached. Returns SUCCESS or an Error. get_device_descriptor :: proc(dev: Device, desc: ^Device_Descriptor) -> Error --- + // Get the configuration descriptor for the currently active configuration. + // Free with `free_config_descriptor()`. Returns SUCCESS, or NOT_FOUND if the + // device is in an unconfigured state. get_active_config_descriptor :: proc(dev: Device, config: ^^Config_Descriptor) -> Error --- + // Get a configuration descriptor by its index. Free with + // `free_config_descriptor()`. Returns SUCCESS, or NOT_FOUND. get_config_descriptor :: proc(dev: Device, config_index: u8, config: ^^Config_Descriptor) -> Error --- + // Get a configuration descriptor with a specific bConfigurationValue. Free + // with `free_config_descriptor()`. Returns SUCCESS, or NOT_FOUND. get_config_descriptor_by_value :: proc(dev: Device, bConfigurationValue: u8, config: ^^Config_Descriptor) -> Error --- + // Free a configuration descriptor obtained from `get_active_config_descriptor()` + // or `get_config_descriptor()`. Safe to call with nil. free_config_descriptor :: proc(config: ^Config_Descriptor) --- + // Get the SuperSpeed endpoint companion descriptor for an endpoint. Free with + // `free_ss_endpoint_companion_descriptor()`. Returns SUCCESS, NOT_FOUND if not + // present, or another Error. get_ss_endpoint_companion_descriptor :: proc(ctx: Context, endpoint: ^Endpoint_Descriptor, ep_comp: ^^Ss_Endpoint_Companion_Descriptor) -> Error --- + // Free an SS endpoint companion descriptor. Safe to call with nil. free_ss_endpoint_companion_descriptor :: proc(ep_comp: ^Ss_Endpoint_Companion_Descriptor) --- + // Get a Binary Object Store (BOS) descriptor. Free with `free_bos_descriptor()`. + // Returns SUCCESS, NOT_FOUND if not present, or another Error. get_bos_descriptor :: proc(dev_handle: Device_Handle, bos: ^^Bos_Descriptor) -> Error --- + // Free a BOS descriptor. Safe to call with nil. free_bos_descriptor :: proc(bos: ^Bos_Descriptor) --- + // Get a USB 2.0 Extension descriptor from a BOS device capability. Free with + // `free_usb2_extension_descriptor()`. Returns SUCCESS or an Error. get_usb2_extension_descriptor :: proc(ctx: Context, dev_cap: ^Bos_Dev_Capability_Descriptor, usb2_extension: ^^Usb2_Extension_Descriptor) -> Error --- + // Free a USB 2.0 Extension descriptor. Safe to call with nil. free_usb2_extension_descriptor :: proc(usb2_extension: ^Usb2_Extension_Descriptor) --- + // Get a SuperSpeed USB Device Capability descriptor from a BOS device + // capability. Free with `free_ss_usb_device_capability_descriptor()`. Returns + // SUCCESS or an Error. get_ss_usb_device_capability_descriptor :: proc(ctx: Context, dev_cap: ^Bos_Dev_Capability_Descriptor, ss_usb_device_cap: ^^Ss_Usb_Device_Capability_Descriptor) -> Error --- + // Free a SuperSpeed USB Device Capability descriptor. Safe to call with nil. free_ss_usb_device_capability_descriptor :: proc(ss_usb_device_cap: ^Ss_Usb_Device_Capability_Descriptor) --- + // Get a SuperSpeedPlus USB Device Capability descriptor from a BOS device + // capability. Free with `free_ssplus_usb_device_capability_descriptor()`. + // Since version 1.0.27. get_ssplus_usb_device_capability_descriptor :: proc(ctx: Context, dev_cap: ^Bos_Dev_Capability_Descriptor, ssplus_usb_device_cap: ^^Ssplus_Usb_Device_Capability_Descriptor) -> Error --- + // Free a SuperSpeedPlus USB Device Capability descriptor. Safe to call with + // nil. Since version 1.0.27. free_ssplus_usb_device_capability_descriptor :: proc(ssplus_usb_device_cap: ^Ssplus_Usb_Device_Capability_Descriptor) --- + // Get a Container ID descriptor from a BOS device capability. Free with + // `free_container_id_descriptor()`. Returns SUCCESS or an Error. get_container_id_descriptor :: proc(ctx: Context, dev_cap: ^Bos_Dev_Capability_Descriptor, container_id: ^^Container_Id_Descriptor) -> Error --- + // Free a Container ID descriptor. Safe to call with nil. free_container_id_descriptor :: proc(container_id: ^Container_Id_Descriptor) --- + // Get a Platform descriptor from a BOS device capability. Free with + // `free_platform_descriptor()`. Since version 1.0.27. get_platform_descriptor :: proc(ctx: Context, dev_cap: ^Bos_Dev_Capability_Descriptor, platform_descriptor: ^^Platform_Descriptor) -> Error --- + // Free a Platform descriptor. Safe to call with nil. Since version 1.0.27. free_platform_descriptor :: proc(platform_descriptor: ^Platform_Descriptor) --- - // Returns number of bytes written or negative Error code. `data` is an output buffer. + // Retrieve a string descriptor in C-style ASCII. `data` is an output buffer + // of size `length`. Returns the number of bytes written, or a negative Error + // code. get_string_descriptor_ascii :: proc(dev_handle: Device_Handle, desc_index: u8, data: [^]u8, length: c.int) -> c.int --- + // Get an array of interface association descriptors (IADs) for a given + // configuration index. Free with `free_interface_association_descriptors()`. + // Since version 1.0.27. get_interface_association_descriptors :: proc(dev: Device, config_index: u8, iad_array: ^^Interface_Association_Descriptor_Array) -> Error --- + // Get an array of IADs for the currently active configuration. Free with + // `free_interface_association_descriptors()`. Since version 1.0.27. get_active_interface_association_descriptors :: proc(dev: Device, iad_array: ^^Interface_Association_Descriptor_Array) -> Error --- + // Free an array of interface association descriptors. Safe to call with nil. + // Since version 1.0.27. free_interface_association_descriptors :: proc(iad_array: ^Interface_Association_Descriptor_Array) --- // ---- Device string (libusb 1.0.30+) ---- - // Retrieve a device string descriptor as UTF-8. - // Returns number of bytes written or negative Error code. + // Retrieve a device string descriptor (manufacturer, product, or serial + // number) as UTF-8. `data` is an output buffer of size `length`. Returns the + // number of bytes written (including the null terminator), or a negative + // Error code. Since version 1.0.30. get_device_string :: proc(dev: Device, string_type: Device_String_Type, data: [^]u8, length: c.int) -> c.int --- // ---- Raw I/O (libusb 1.0.30+) ---- - // Returns 1 if supported, 0 if not, or negative Error code. + // Check whether an endpoint supports WinUSB RAW_IO. Only endpoints using the + // WinUSB driver support it; all other backends return 0. The interface must + // be claimed. Returns 1 if supported, 0 if not, or a negative Error code. + // Since version 1.0.30. endpoint_supports_raw_io :: proc(dev_handle: Device_Handle, endpoint: u8) -> c.int --- - endpoint_set_raw_io :: proc(dev_handle: Device_Handle, endpoint: u8, enable: c.int) -> c.int --- + // Enable/disable WinUSB RAW_IO for an endpoint on an open device. Can greatly + // improve throughput. While enabled, transfers must obey alignment rules: the + // buffer length must be a multiple of the endpoint's max packet size and + // `<= get_max_raw_io_transfer_size()`. Returns 0 (SUCCESS), or a negative + // Error code (NOT_SUPPORTED if the backend lacks RAW_IO). Since version 1.0.30. + endpoint_set_raw_io :: proc(dev_handle: Device_Handle, endpoint: u8, enable: b32) -> c.int --- + // Retrieve the maximum transfer size in bytes supported for WinUSB RAW_IO on + // an inbound bulk or interrupt endpoint. Returns a positive maximum transfer + // size, or a negative Error code (NOT_SUPPORTED if unsupported). Since version + // 1.0.30. get_max_raw_io_transfer_size :: proc(dev_handle: Device_Handle, endpoint: u8) -> c.int --- // ---- Device hotplug event notification ---- + // Register a hotplug callback. It fires when a matching event occurs on a + // matching device, until deregistered or until the callback returns true. + // Pass `HOTPLUG_MATCH_ANY` for vendor_id / product_id / dev_class to match + // anything. If `flags` includes ENUMERATE, the callback also fires for all + // currently attached matching devices. `callback_handle` may be nil. Returns + // SUCCESS or an Error. Since version 1.0.16. hotplug_register_callback :: proc(ctx: Context, events: Hotplug_Events, flags: Hotplug_Flags, vendor_id: c.int, product_id: c.int, dev_class: c.int, cb_fn: Hotplug_Callback_Fn, user_data: rawptr, callback_handle: ^Callback_Handle) -> Error --- + // Deregister a hotplug callback. Safe to call from within a hotplug callback. + // Since version 1.0.16. hotplug_deregister_callback :: proc(ctx: Context, callback_handle: Callback_Handle) --- + // Get the user_data associated with a hotplug callback. Since version 1.0.24. hotplug_get_user_data :: proc(ctx: Context, callback_handle: Callback_Handle) -> rawptr --- // ---- Asynchronous device I/O ---- - // Returns number of streams allocated or negative Error code. + // Allocate up to `num_streams` USB bulk streams on the specified endpoints + // (which must all belong to the same interface). Stream id 0 is reserved; if + // N streams are allocated you may use ids 1..=N. Returns the number of streams + // allocated, or a negative Error code. Since version 1.0.19. alloc_streams :: proc(dev_handle: Device_Handle, num_streams: u32, endpoints: [^]u8, num_endpoints: c.int) -> c.int --- + // Free bulk streams allocated with `alloc_streams()`. Streams are also freed + // automatically when releasing an interface. Returns SUCCESS or an Error. + // Since version 1.0.19. free_streams :: proc(dev_handle: Device_Handle, endpoints: [^]u8, num_endpoints: c.int) -> Error --- + // Attempt to allocate a block of persistent DMA memory suitable for transfers + // against the device, allowing zero-copy. Returns nil on failure (many systems + // do not support this). Free with `dev_mem_free()`; do not use the FREE_BUFFER + // flag on such buffers. Since version 1.0.21. dev_mem_alloc :: proc(dev_handle: Device_Handle, length: c.size_t) -> [^]u8 --- + // Free device memory allocated with `dev_mem_alloc()`. Returns SUCCESS or an + // Error. dev_mem_free :: proc(dev_handle: Device_Handle, buffer: [^]u8, length: c.size_t) -> Error --- + // Allocate a transfer with the given number of isochronous packet descriptors + // (0 for control/bulk/interrupt). The returned transfer is pre-initialized. + // Free with `free_transfer()`. Returns nil on error. alloc_transfer :: proc(iso_packets: c.int) -> ^Transfer --- + // Free a transfer allocated with `alloc_transfer()`. If the FREE_BUFFER flag + // is set and the buffer is non-nil, the buffer is also freed. Safe to call + // with nil. It is illegal to free an active (submitted, incomplete) transfer. free_transfer :: proc(transfer: ^Transfer) --- + // Submit a transfer. Fires off the transfer and returns immediately. Returns + // SUCCESS, or NO_DEVICE / BUSY / NOT_SUPPORTED / INVALID_PARAM / another Error. submit_transfer :: proc(transfer: ^Transfer) -> Error --- + // Asynchronously cancel a previously submitted transfer. Returns immediately; + // the callback is invoked later with status CANCELLED. Returns SUCCESS, or + // NOT_FOUND if the transfer is not in progress / already complete / already + // cancelled. cancel_transfer :: proc(transfer: ^Transfer) -> Error --- + // Set a transfer's bulk stream id. Prefer `fill_bulk_stream_transfer()`. + // Since version 1.0.19. transfer_set_stream_id :: proc(transfer: ^Transfer, stream_id: u32) --- + // Get a transfer's bulk stream id. Since version 1.0.19. transfer_get_stream_id :: proc(transfer: ^Transfer) -> u32 --- // ---- Polling and timing ---- + // Attempt to acquire the event handling lock, which ensures only one thread + // monitors libusb's event sources at a time. Only needed if you poll()/select() + // on libusb's file descriptors directly. Returns 0 if the lock was obtained, + // 1 if it was not. try_lock_events :: proc(ctx: Context) -> c.int --- + // Acquire the event handling lock, blocking until it is obtained. Only needed + // if you poll()/select() on libusb's file descriptors directly. lock_events :: proc(ctx: Context) --- + // Release the lock acquired with `try_lock_events()` or `lock_events()`. Wakes + // up any threads blocked on `wait_for_event()`. unlock_events :: proc(ctx: Context) --- - event_handling_ok :: proc(ctx: Context) -> c.int --- - event_handler_active :: proc(ctx: Context) -> c.int --- + // Determine if it is still OK for this thread to be doing event handling. Call + // before polling; if it returns false, give up the events lock and retry the + // cycle. Returns true if event handling can start or continue, false if this + // thread must give up the events lock. + event_handling_ok :: proc(ctx: Context) -> b32 --- + // Determine if an active thread is handling events (i.e. holds the event + // handling lock). Returns true if a thread is handling events, false if none. + event_handler_active :: proc(ctx: Context) -> b32 --- + // Interrupt any active thread that is handling events. Mainly useful for + // interrupting a dedicated event-handling thread before calling `exit()`. + // Since version 1.0.21. interrupt_event_handler :: proc(ctx: Context) --- + // Acquire the event waiters lock. Use when you want to be notified of event + // completion but another thread is handling events. lock_event_waiters :: proc(ctx: Context) --- + // Release the event waiters lock. unlock_event_waiters :: proc(ctx: Context) --- + // Wait for another thread to signal completion of an event. Must be called + // with the event waiters lock held. Blocks until the timeout expires, a + // transfer completes, or a thread releases the event handling lock. `tv` may + // be nil for an unlimited wait. Returns 0 after a transfer completes or + // another thread stops handling events, 1 if the timeout expired, or + // INVALID_PARAM. wait_for_event :: proc(ctx: Context, tv: ^Timeval) -> c.int --- + // Handle any pending events in blocking mode (60s internal timeout). Kept + // mainly for backwards compatibility; prefer `handle_events_completed()`. + // Returns SUCCESS or an Error. handle_events :: proc(ctx: Context) -> Error --- + // Handle any pending events, blocking up to `tv` (an all-zero timeval gives + // non-blocking behavior). Kept for backwards compatibility; prefer + // `handle_events_timeout_completed()`. Returns SUCCESS or an Error. handle_events_timeout :: proc(ctx: Context, tv: ^Timeval) -> Error --- - handle_events_timeout_completed :: proc(ctx: Context, tv: ^Timeval, completed: ^c.int) -> Error --- - handle_events_completed :: proc(ctx: Context, completed: ^c.int) -> Error --- + // Like `handle_events_timeout()`, but if `completed` is non-nil this returns + // immediately (after obtaining the event lock) once the pointed-to flag is + // set, allowing race-free waiting for a specific transfer. The flag should be + // set from within the transfer callback. Returns SUCCESS, or INVALID_PARAM / + // another Error. + handle_events_timeout_completed :: proc(ctx: Context, tv: ^Timeval, completed: ^b32) -> Error --- + // Like `handle_events()`, with a `completed` flag for race-free waiting on a + // specific transfer (see `handle_events_timeout_completed()`). Returns SUCCESS + // or an Error. + handle_events_completed :: proc(ctx: Context, completed: ^b32) -> Error --- + // Handle pending events by polling file descriptors, without checking whether + // other threads are already doing so. Must be called with the event lock held. + // Returns SUCCESS, or INVALID_PARAM / another Error. handle_events_locked :: proc(ctx: Context, tv: ^Timeval) -> Error --- + // Determine whether your application must apply special timing considerations + // when monitoring libusb's file descriptors. Returns 0 if you must call into + // libusb at times determined by `get_next_timeout()`, or 1 if all timeout + // events are handled internally or through regular file-descriptor activity. pollfds_handle_timeouts :: proc(ctx: Context) -> c.int --- - // Returns 0 if no timeout, 1 if a timeout was returned, or negative Error code. + // Determine the next internal timeout that libusb needs to handle. Only needed + // if you poll()/select() on libusb's file descriptors yourself; use the result + // as an upper bound for your poll timeout. Returns 0 if there are no pending + // timeouts, 1 if a timeout was returned, or a negative Error code. get_next_timeout :: proc(ctx: Context, tv: ^Timeval) -> c.int --- + // Register notification functions for file-descriptor additions/removals as + // libusb's event sources change. Pass nil function pointers to remove the + // notifiers. Note that descriptors may already have been added before you + // register (e.g. at `init_context()` time). set_pollfd_notifiers :: proc(ctx: Context, added_cb: Pollfd_Added_Cb, removed_cb: Pollfd_Removed_Cb, user_data: rawptr) --- - // Returns a NULL-terminated list of `Poll_Fd` pointers. Free with `free_pollfds()`. + // Retrieve the list of file descriptors that should be polled as libusb event + // sources. Returns a NULL-terminated list of `Poll_Fd` pointers; free with + // `free_pollfds()`. Not available on Windows (returns nil). get_pollfds :: proc(ctx: Context) -> [^]^Poll_Fd --- + // Free a pollfd list obtained from `get_pollfds()`. Safe to call with nil. + // Since version 1.0.20. free_pollfds :: proc(pollfds: [^]^Poll_Fd) --- // ---- Synchronous device I/O ---- - // Returns number of bytes transferred or negative Error code. + // Perform a USB control transfer. `data` must point to a buffer of `wLength` + // bytes for the data stage (direction per bit 7 of `bmRequestType`). `timeout` + // is in milliseconds (0 = unlimited). Returns the number of bytes actually + // transferred, or a negative Error code. control_transfer :: proc(dev_handle: Device_Handle, bmRequestType: u8, bRequest: u8, wValue: u16, wIndex: u16, data: [^]u8, wLength: u16, timeout: c.uint) -> c.int --- + // Perform a USB bulk transfer. `transferred`, if non-nil, receives the number + // of bytes actually transferred. `timeout` is in milliseconds (0 = unlimited). + // Returns SUCCESS, or TIMEOUT / PIPE / OVERFLOW / NO_DEVICE / another Error. bulk_transfer :: proc(dev_handle: Device_Handle, endpoint: u8, data: [^]u8, length: c.int, transferred: ^c.int, timeout: c.uint) -> Error --- + // Perform a USB interrupt transfer. Behaves like `bulk_transfer()` but for + // interrupt endpoints. Returns SUCCESS or an Error. interrupt_transfer :: proc(dev_handle: Device_Handle, endpoint: u8, data: [^]u8, length: c.int, transferred: ^c.int, timeout: c.uint) -> Error --- }