package libusb import "core:c" import "core:fmt" //TODO: Switch to sys/posix when linux support is finished import "posix" //TODO: Probably want to switch this to being statically linked foreign import lib "system:usb-1.0" /** \ingroup libusb_desc * Device and/or Interface Class codes */ Class_Code :: enum c.int { /** In the context of a \ref libusb_device_descriptor "device descriptor", * this bDeviceClass value indicates that each interface specifies its * own class information and all interfaces operate independently. */ CLASS_PER_INTERFACE = 0x00, /** Audio class */ CLASS_AUDIO = 0x01, /** Communications class */ CLASS_COMM = 0x02, /** Human Interface Device class */ CLASS_HID = 0x03, /** Physical */ CLASS_PHYSICAL = 0x05, /** Image class */ CLASS_IMAGE = 0x06, CLASS_PTP = 0x06, /* legacy name from libusb-0.1 usb.h */ /** Printer class */ CLASS_PRINTER = 0x07, /** Mass storage class */ CLASS_MASS_STORAGE = 0x08, /** Hub class */ CLASS_HUB = 0x09, /** Data class */ CLASS_DATA = 0x0a, /** Smart Card */ CLASS_SMART_CARD = 0x0b, /** Content Security */ CLASS_CONTENT_SECURITY = 0x0d, /** Video */ CLASS_VIDEO = 0x0e, /** Personal Healthcare */ CLASS_PERSONAL_HEALTHCARE = 0x0f, /** Diagnostic Device */ CLASS_DIAGNOSTIC_DEVICE = 0xdc, /** Wireless class */ CLASS_WIRELESS = 0xe0, /** Miscellaneous class */ CLASS_MISCELLANEOUS = 0xef, /** Application class */ CLASS_APPLICATION = 0xfe, /** Class is vendor-specific */ CLASS_VENDOR_SPEC = 0xff, } /** \ingroup libusb_desc * Descriptor types as defined by the USB specification. */ Descriptor_Type :: enum c.int { /** Device descriptor. See libusb_device_descriptor. */ DEVICE = 0x01, /** Configuration descriptor. See libusb_config_descriptor. */ CONFIG = 0x02, /** String descriptor */ STRING = 0x03, /** Interface descriptor. See libusb_interface_descriptor. */ INTERFACE = 0x04, /** Endpoint descriptor. See libusb_endpoint_descriptor. */ ENDPOINT = 0x05, /** Interface Association Descriptor. * See libusb_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, } /* Descriptor sizes per descriptor type */ DT_DEVICE_SIZE :: 18 DT_CONFIG_SIZE :: 9 DT_INTERFACE_SIZE :: 9 DT_ENDPOINT_SIZE :: 7 DT_ENDPOINT_AUDIO_SIZE :: 9 /* Audio extension */ DT_HUB_NONVAR_SIZE :: 7 DT_SS_ENDPOINT_COMPANION_SIZE :: 6 DT_BOS_SIZE :: 5 DT_DEVICE_CAPABILITY_SIZE :: 3 /* BOS descriptor sizes */ BT_USB_2_0_EXTENSION_SIZE :: 7 BT_SS_USB_DEVICE_CAPABILITY_SIZE :: 10 BT_CONTAINER_ID_SIZE :: 20 BT_PLATFORM_DESCRIPTOR_MIN_SIZE :: 20 /* We unwrap the BOS => define its max size */ DT_BOS_MAX_SIZE :: 42 ENDPOINT_ADDRESS_MASK :: 0x0f /* in bEndpointAddress */ ENDPOINT_DIR_MASK :: 0x80 /** \ingroup libusb_desc * Endpoint direction. Values for bit 7 of the * \ref libusb_endpoint_descriptor::bEndpointAddress "endpoint address" scheme. */ Endpoint_Direction :: enum c.int { /** Out: host-to-device */ ENDPOINT_OUT = 0x00, /** In: device-to-host */ ENDPOINT_IN = 0x80, } TRANSFER_TYPE_MASK :: 0x03 /* in bmAttributes */ /** \ingroup libusb_desc * Endpoint transfer type. Values for bits 0:1 of the * \ref libusb_endpoint_descriptor::bmAttributes "endpoint attributes" field. */ Endpoint_Transfer_Type :: enum c.int { /** Control endpoint */ CONTROL = 0x0, /** Isochronous endpoint */ ISOCHRONOUS = 0x1, /** Bulk endpoint */ BULK = 0x2, /** Interrupt endpoint */ INTERRUPT = 0x3, } /** \ingroup libusb_misc * 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, /* 0x02 is reserved */ /** Set or enable a specific feature */ SET_FEATURE = 0x03, /* 0x04 is reserved */ /** Set device address for all future accesses */ 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, } /** \ingroup libusb_misc * Request type bits of the * \ref libusb_control_setup::bmRequestType "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), } /** \ingroup libusb_misc * Recipient bits of the * \ref libusb_control_setup::bmRequestType "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, } ISO_SYNC_TYPE_MASK :: 0x0c /** \ingroup libusb_desc * Synchronization type for isochronous endpoints. Values for bits 2:3 of the * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in * libusb_endpoint_descriptor. */ Iso_Sync_Type :: enum c.int { /** No synchronization */ NONE = 0x0, /** Asynchronous */ ASYNC = 0x1, /** Adaptive */ ADAPTIVE = 0x2, /** Synchronous */ SYNC = 0x3, } ISO_USAGE_TYPE_MASK :: 0x30 /** \ingroup libusb_desc * Usage type for isochronous endpoints. Values for bits 4:5 of the * \ref libusb_endpoint_descriptor::bmAttributes "bmAttributes" field in * libusb_endpoint_descriptor. */ Iso_Usage_Type :: enum c.int { /** Data endpoint */ DATA = 0x0, /** Feedback endpoint */ FEEDBACK = 0x1, /** Implicit feedback Data endpoint */ IMPLICIT = 0x2, } /** \ingroup libusb_desc * Supported speeds (wSpeedSupported) bitfield. Indicates what * speeds the device supports. */ Supported_Speed :: enum c.int { /** Low speed operation supported (1.5MBit/s). */ LOW_SPEED_OPERATION = (1 << 0), /** Full speed operation supported (12MBit/s). */ FULL_SPEED_OPERATION = (1 << 1), /** High speed operation supported (480MBit/s). */ HIGH_SPEED_OPERATION = (1 << 2), /** Superspeed operation supported (5000MBit/s). */ SUPER_SPEED_OPERATION = (1 << 3), } /** \ingroup libusb_desc * Masks for the bits of the * \ref libusb_usb_2_0_extension_descriptor::bmAttributes "bmAttributes" field * of the USB 2.0 Extension descriptor. */ Usb2_Extension_Attributes :: enum c.int { /** Supports Link Power Management (LPM) */ BM_LPM_SUPPORT = (1 << 1), } /** \ingroup libusb_desc * Masks for the bits of the * \ref libusb_ss_usb_device_capability_descriptor::bmAttributes "bmAttributes" field * field of the SuperSpeed USB Device Capability descriptor. */ Ss_Usb_Device_Capability_Attributes :: enum c.int { /** Supports Latency Tolerance Messages (LTM) */ BM_LTM_SUPPORT = (1 << 1), } /** \ingroup libusb_desc * USB capability types */ 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, } /** \ingroup libusb_desc * A structure representing the standard USB device descriptor. This * descriptor is documented in section 9.6.1 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. */ Device_Descriptor :: struct { /** Size of this descriptor (in bytes) */ bLength: u8, /** Descriptor type. Will have value * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE LIBUSB_DT_DEVICE in this * context. */ bDescriptorType: u8, /** USB specification release number in binary-coded decimal. A value of * 0x0200 indicates USB 2.0, 0x0110 indicates USB 1.1, etc. */ bcdUSB: u16, /** USB-IF class code for the device. See \ref libusb_class_code. */ bDeviceClass: u8, /** USB-IF subclass code for the device, qualified by the bDeviceClass * value */ bDeviceSubClass: u8, /** USB-IF protocol code for the device, qualified by the bDeviceClass and * bDeviceSubClass values */ bDeviceProtocol: u8, /** Maximum packet size for endpoint 0 */ bMaxPacketSize0: u8, /** USB-IF vendor ID */ idVendor: u16, /** USB-IF product ID */ idProduct: u16, /** Device release number in binary-coded decimal */ bcdDevice: u16, /** Index of string descriptor describing manufacturer */ iManufacturer: u8, /** Index of string descriptor describing product */ iProduct: u8, /** Index of string descriptor containing device serial number */ iSerialNumber: u8, /** Number of possible configurations */ bNumConfigurations: u8, } /** \ingroup libusb_desc * A structure representing the standard USB endpoint descriptor. This * descriptor is documented in section 9.6.6 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. */ Endpoint_Descriptor :: struct { /** Size of this descriptor (in bytes) */ bLength: u8, /** Descriptor type. Will have value * \ref libusb_descriptor_type::LIBUSB_DT_ENDPOINT LIBUSB_DT_ENDPOINT in * this context. */ bDescriptorType: u8, /** The address of the endpoint described by this descriptor. Bits 0:3 are * the endpoint number. Bits 4:6 are reserved. Bit 7 indicates direction, * see \ref libusb_endpoint_direction. */ bEndpointAddress: u8, /** Attributes which apply to the endpoint when it is configured using * the bConfigurationValue. Bits 0:1 determine the transfer type and * correspond to \ref libusb_endpoint_transfer_type. Bits 2:3 are only used * for isochronous endpoints and correspond to \ref libusb_iso_sync_type. * Bits 4:5 are also only used for isochronous endpoints and correspond to * \ref libusb_iso_usage_type. Bits 6:7 are reserved. */ bmAttributes: u8, /** Maximum packet size this endpoint is capable of sending/receiving. */ wMaxPacketSize: u16, /** Interval for polling endpoint for data transfers. */ bInterval: u8, /** For audio devices only: the rate at which synchronization feedback * is provided. */ bRefresh: u8, /** For audio devices only: the address if the synch endpoint */ bSynchAddress: u8, /** Extra descriptors. If libusb encounters unknown endpoint descriptors, * it will store them here, should you wish to parse them. */ extra: [^]u8, /** Length of the extra descriptors, in bytes. Must be non-negative. */ extra_length: c.int, } /** \ingroup libusb_desc * A structure representing the standard USB interface association descriptor. * This descriptor is documented in section 9.6.4 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. */ Interface_Association_Descriptor :: struct { /** Size of this descriptor (in bytes) */ bLength: u8, /** Descriptor type. Will have value * \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE_ASSOCIATION * LIBUSB_DT_INTERFACE_ASSOCIATION in this context. */ bDescriptorType: u8, /** Interface number of the first interface that is associated * with this function */ bFirstInterface: u8, /** Number of contiguous interfaces that are associated with * this function */ bInterfaceCount: u8, /** USB-IF class code for this function. * A value of zero is not allowed in this descriptor. * If this field is 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 this field is not set to 0xff, all values are reserved * for assignment by the USB-IF */ bFunctionSubClass: u8, /** USB-IF protocol code for this function. * These codes are qualified by the values of the bFunctionClass * and bFunctionSubClass fields. */ bFunctionProtocol: u8, /** Index of string descriptor describing this function */ iFunction: u8, } /** \ingroup libusb_desc * Structure containing an array of 0 or more interface association * descriptors */ Interface_Association_Descriptor_Array :: struct { /** Array of interface association descriptors. The size of this array * is determined by the length field. */ iad: [^]Interface_Association_Descriptor, /** Number of interface association descriptors contained. Read-only. */ length: c.int, } /** \ingroup libusb_desc * A structure representing the standard USB interface descriptor. This * descriptor is documented in section 9.6.5 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. */ Interface_Descriptor :: struct { /** Size of this descriptor (in bytes) */ bLength: u8, /** Descriptor type. Will have value * \ref libusb_descriptor_type::LIBUSB_DT_INTERFACE LIBUSB_DT_INTERFACE * in this context. */ 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 \ref libusb_class_code. */ bInterfaceClass: u8, /** USB-IF subclass code for this interface, qualified by the * bInterfaceClass value */ bInterfaceSubClass: u8, /** USB-IF protocol code for this interface, qualified by the * bInterfaceClass and bInterfaceSubClass values */ bInterfaceProtocol: u8, /** Index of string descriptor describing this interface */ iInterface: u8, /** Array of endpoint descriptors. This length of this array is determined * by the bNumEndpoints field. */ endpoint: [^]Endpoint_Descriptor, /** Extra descriptors. If libusb encounters unknown interface descriptors, * it will store them here, should you wish to parse them. */ extra: [^]u8, /** Length of the extra descriptors, in bytes. Must be non-negative. */ extra_length: c.int, } /** \ingroup libusb_desc * A collection of alternate settings for a particular USB interface. */ Interface :: struct { /** Array of interface descriptors. The length of this array is determined * by the num_altsetting field. */ altsetting: [^]Interface_Descriptor, /** The number of alternate settings that belong to this interface. * Must be non-negative. */ num_altsetting: c.int, } /** \ingroup libusb_desc * A structure representing the standard USB configuration descriptor. This * descriptor is documented in section 9.6.3 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. */ Config_Descriptor :: struct { /** Size of this descriptor (in bytes) */ bLength: u8, /** Descriptor type. Will have value * \ref libusb_descriptor_type::LIBUSB_DT_CONFIG LIBUSB_DT_CONFIG * in this context. */ 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, /** Maximum power consumption of the USB device from this bus in this * configuration when the device is fully operation. Expressed in units * of 2 mA when the device is operating in high-speed mode and in units * of 8 mA when the device is operating in super-speed mode. */ MaxPower: u8, /** Array of interfaces supported by this configuration. The length of * this array is determined by the bNumInterfaces field. */ interface: [^]Interface, /** Extra descriptors. If libusb encounters unknown configuration * descriptors, it will store them here, should you wish to parse them. */ extra: [^]u8, /** Length of the extra descriptors, in bytes. Must be non-negative. */ extra_length: c.int, } /** \ingroup libusb_desc * A structure representing the superspeed endpoint companion * descriptor. This descriptor is documented in section 9.6.7 of * the USB 3.0 specification. All multiple-byte fields are represented in * host-endian format. */ Ss_Endpoint_Companion_Descriptor :: struct { /** Size of this descriptor (in bytes) */ bLength: u8, /** Descriptor type. Will have value * \ref libusb_descriptor_type::LIBUSB_DT_SS_ENDPOINT_COMPANION in * this context. */ 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 represents the maximum number of * streams the EP supports. In isochronous EP: bits 1:0 * represents the Mult - a zero based value that determines * the maximum number of packets within a service interval */ bmAttributes: u8, /** The total number of bytes this EP will transfer every * service interval. Valid only for periodic EPs. */ wBytesPerInterval: u16, } /** \ingroup libusb_desc * A generic representation of a BOS Device Capability descriptor. It is * advised to check bDevCapabilityType and call the matching * libusb_get_*_descriptor function to get a structure fully matching the type. */ Bos_Dev_Capability_Descriptor :: struct { /** Size of this descriptor (in bytes) */ bLength: u8, /** Descriptor type. Will have value * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ bDescriptorType: u8, /** Device Capability type */ bDevCapabilityType: u8, /** Device Capability data (bLength - 3 bytes) */ dev_capability_data: [0]u8, } /** \ingroup libusb_desc * A structure representing the Binary Device Object Store (BOS) descriptor. * This descriptor is documented in section 9.6.2 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. */ Bos_Descriptor :: struct { /** Size of this descriptor (in bytes) */ bLength: u8, /** Descriptor type. Will have value * \ref libusb_descriptor_type::LIBUSB_DT_BOS LIBUSB_DT_BOS * in this context. */ 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, /** bNumDeviceCap Device Capability Descriptors * Isochronous packet descriptors, for isochronous transfers only. * This is a C flexible array member and memory must be handled completely manually if it's used.*/ dev_capability: [0]^Bos_Dev_Capability_Descriptor, } /** \ingroup libusb_desc * A structure representing the USB 2.0 Extension descriptor * This descriptor is documented in section 9.6.2.1 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. */ Usb2_Extension_Descriptor :: struct { /** Size of this descriptor (in bytes) */ bLength: u8, /** Descriptor type. Will have value * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ bDescriptorType: u8, /** Capability type. Will have value * \ref libusb_capability_type::LIBUSB_BT_USB_2_0_EXTENSION * LIBUSB_BT_USB_2_0_EXTENSION in this context. */ bDevCapabilityType: u8, /** Bitmap encoding of supported device level features. * A value of one in a bit location indicates a feature is * supported; a value of zero indicates it is not supported. * See \ref libusb_usb_2_0_extension_attributes. */ bmAttributes: u32, } /** \ingroup libusb_desc * A structure representing the SuperSpeed USB Device Capability descriptor * This descriptor is documented in section 9.6.2.2 of the USB 3.0 specification. * All multiple-byte fields are represented in host-endian format. */ Ss_Usb_Device_Capability_Descriptor :: struct { /** Size of this descriptor (in bytes) */ bLength: u8, /** Descriptor type. Will have value * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ bDescriptorType: u8, /** Capability type. Will have value * \ref libusb_capability_type::LIBUSB_BT_SS_USB_DEVICE_CAPABILITY * LIBUSB_BT_SS_USB_DEVICE_CAPABILITY in this context. */ bDevCapabilityType: u8, /** Bitmap encoding of supported device level features. * A value of one in a bit location indicates a feature is * supported; a value of zero indicates it is not supported. * See \ref libusb_ss_usb_device_capability_attributes. */ bmAttributes: u8, /** Bitmap encoding of the speed supported by this device when * operating in SuperSpeed mode. See \ref libusb_supported_speed. */ wSpeedSupported: u16, /** The lowest speed at which all the functionality supported * by the device is available to the user. For example if the * device supports all its functionality when connected at * full speed and above then it sets this value to 1. */ bFunctionalitySupport: u8, /** U1 Device Exit Latency. */ bU1DevExitLat: u8, /** U2 Device Exit Latency. */ bU2DevExitLat: u16, } /** \ingroup libusb_desc * A structure representing the Container ID descriptor. * This descriptor is documented in section 9.6.2.3 of the USB 3.0 specification. * All multiple-byte fields, except UUIDs, are represented in host-endian format. */ Container_Id_Descriptor :: struct { /** Size of this descriptor (in bytes) */ bLength: u8, /** Descriptor type. Will have value * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ bDescriptorType: u8, /** Capability type. Will have value * \ref libusb_capability_type::LIBUSB_BT_CONTAINER_ID * LIBUSB_BT_CONTAINER_ID in this context. */ bDevCapabilityType: u8, /** Reserved field */ bReserved: u8, /** 128 bit UUID */ ContainerID: u128, } /** \ingroup libusb_desc * A structure representing a Platform descriptor. * This descriptor is documented in section 9.6.2.4 of the USB 3.2 specification. * This struct contains a mandatory C flexible array member all of it's memory must be handled completely manually. */ Platform_Descriptor :: struct { /** Size of this descriptor (in bytes) */ bLength: u8, /** Descriptor type. Will have value * \ref libusb_descriptor_type::LIBUSB_DT_DEVICE_CAPABILITY * LIBUSB_DT_DEVICE_CAPABILITY in this context. */ bDescriptorType: u8, /** Capability type. Will have value * \ref libusb_capability_type::LIBUSB_BT_PLATFORM_DESCRIPTOR * LIBUSB_BT_CONTAINER_ID in this context. */ bDevCapabilityType: u8, /** Reserved field */ bReserved: u8, /** 128 bit UUID */ PlatformCapabilityUUID: u128, /** Capability data (bLength - 20) * This is a C flexible array member and memory must be handled completely manually.*/ CapabilityData: [0]u8, } //TODO: Add `libusb_control_setup` Context :: distinct rawptr Device :: distinct rawptr Device_Handle :: distinct rawptr /** \ingroup libusb_lib * Structure providing the 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. */ nano: u16, /** Library release candidate suffix string, e.g. "-rc4". */ rc: cstring, /** For ABI compatibility only. */ describe: cstring, } /** \ingroup libusb_dev * 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, } /** \ingroup libusb_misc * Error codes. Most libusb functions return 0 on success or one of these * codes on failure. * You can call libusb_error_name() to retrieve a string representation of an * error code or libusb_strerror() to get an end-user suitable description of * an error code. */ 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, /* NB: Remember to update LIBUSB_ERROR_COUNT below as well as the message strings in strerror.c when adding new error codes here. */ /** Other error */ OTHER = -99, } /* Total number of error codes in enum libusb_error */ ERROR_COUNT :: 14 /** \ingroup libusb_asyncio * Transfer type */ TransferType :: enum c.int { /** Control transfer */ CONTROL = 0, /** Isochronous transfer */ ISOCHRONOUS = 1, /** Bulk transfer */ BULK = 2, /** Interrupt transfer */ INTERRUPT = 3, /** Bulk stream transfer */ BULK_STREAM = 4, } /** \ingroup libusb_asyncio * 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, } Transfer_Flag_Bits :: enum u8 { /** Report short frames as errors */ SHORT_NOT_OK, /** Automatically free() transfer buffer during libusb_free_transfer(). * Note that buffers allocated with libusb_dev_mem_alloc() should not * be attempted freed in this way, since free() is not an appropriate * way to release such memory. */ FREE_BUFFER, /** Automatically call libusb_free_transfer() after callback returns. * If this flag is set, it is illegal to call libusb_free_transfer() * from your transfer callback, as this will result in a double-free * when this flag is acted upon. */ FREE_TRANSFER, /** Terminate transfers that are a multiple of the endpoint's * wMaxPacketSize with an extra zero length packet. This is useful * when a device protocol mandates that each logical request is * terminated by an incomplete packet (i.e. the logical requests are * not separated by other means). * * This flag only affects host-to-device transfers to bulk and interrupt * endpoints. In other situations, it is ignored. * * This flag only affects transfers with a length that is a multiple of * the endpoint's wMaxPacketSize. On transfers of other lengths, this * flag has no effect. Therefore, if you are working with a device that * needs a ZLP whenever the end of the logical request falls on a packet * boundary, then it is sensible to set this flag on every * transfer (you do not have to worry about only setting it on transfers * that end on the boundary). * * This flag is currently only supported on Linux. * On other systems, libusb_submit_transfer() will return * \ref LIBUSB_ERROR_NOT_SUPPORTED for every transfer where this * flag is set. * * Available since libusb-1.0.9. */ ADD_ZERO_PACKET, } Transfer_Flag :: bit_set[Transfer_Flag_Bits;u8] /** \ingroup libusb_asyncio * 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, } Transfer_Cb :: #type proc "c" (transfer: ^Transfer) /** \ingroup libusb_asyncio * The generic USB transfer structure. The user populates this structure and * then submits it in order to request a transfer. After the transfer has * completed, the library populates the transfer with the results and passes * it back to the user. */ Transfer :: struct { /** Handle of the device that this transfer will be submitted to */ dev_handle: ^Device_Handle, /** A bitwise OR combination of \ref libusb_transfer_flags. */ flags: Transfer_Flag, /** Address of the endpoint where this transfer will be sent. */ endpoint: c.char, /** Type of the transfer from \ref libusb_transfer_type */ type: c.char, /** Timeout for this transfer in milliseconds. A value of 0 indicates no * timeout. */ timeout: c.uint, /** The status of the transfer. Read-only, and only for use within * transfer callback function. * * If this is an isochronous transfer, this field may read COMPLETED even * if there were errors in the frames. Use the * \ref libusb_iso_packet_descriptor::status "status" field in each packet * to determine if errors occurred. */ status: Transfer_Status, /** Length of the data buffer. Must be non-negative. */ length: c.int, /** Actual length of data that was transferred. Read-only, and only for * use within transfer callback function. Not valid for isochronous * endpoint transfers. */ actual_length: c.int, /** Callback function. This will be invoked when the transfer completes, * fails, or is cancelled. */ callback: Transfer_Cb, /** User context data. Useful for associating specific data to a transfer * that can be accessed from within the callback function. * * This field may be set manually or is taken as the `user_data` parameter * of the following functions: * - libusb_fill_bulk_transfer() * - libusb_fill_bulk_stream_transfer() * - libusb_fill_control_transfer() * - libusb_fill_interrupt_transfer() * - libusb_fill_iso_transfer() */ user_data: rawptr, /** Data buffer */ buffer: [^]c.char, /** Number of isochronous packets. Only used for I/O with isochronous * endpoints. Must be non-negative. */ num_iso_packets: c.int, /** Isochronous packet descriptors, for isochronous transfers only. * This is a C flexible array member and memory must be handled completely manually if it's used.*/ iso_packet_desc: [0]Iso_Packet_Descriptor, } /** \ingroup libusb_misc * Capabilities supported by an instance of libusb on the current running * platform. Test if the loaded library supports a given capability by calling * \ref libusb_has_capability(). */ Capability :: enum c.uint { /** The libusb_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 * \ref libusb_detach_kernel_driver(). */ HAS_HID_ACCESS = 0x0100, /** The library supports detaching of the default USB driver, using * \ref libusb_detach_kernel_driver(), if one is set by the OS kernel */ SUPPORTS_DETACH_KERNEL_DRIVER = 0x0101, } /** \ingroup libusb_lib * Log message levels. */ Log_Level :: enum c.int { /** (0) : No messages ever emitted by the library (default) */ NONE = 0, /** (1) : Error messages are emitted */ ERROR = 1, /** (2) : Warning and error messages are emitted */ WARNING = 2, /** (3) : Informational, warning and error messages are emitted */ INFO = 3, /** (4) : All messages are emitted */ DEBUG = 4, } /** \ingroup libusb_lib * Log callback mode. * * Since version 1.0.23, \ref LIBUSB_API_VERSION >= 0x01000107 * * \see libusb_set_log_cb() */ Log_Cb_Mode :: enum c.int { /** Callback function handling all log messages. */ GLOBAL = (1 << 0), /** Callback function handling context related log messages. */ CONTEXT = (1 << 1), } /** \ingroup libusb_lib * Available option values for libusb_set_option() and libusb_init_context(). */ Option :: enum c.int { /** Set the log message verbosity. * * This option must be provided an argument of type \ref libusb_log_level. * The default level is LIBUSB_LOG_LEVEL_NONE, which means no messages are ever * printed. If you choose to increase the message verbosity level, ensure * that your application does not close the stderr file descriptor. * * You are advised to use level LIBUSB_LOG_LEVEL_WARNING. libusb is conservative * with its message logging and most of the time, will only log messages that * explain error conditions and other oddities. This will help you debug * your software. * * If the LIBUSB_DEBUG environment variable was set when libusb was * initialized, this option does nothing: the message verbosity is fixed * to the value in the environment variable. * * If libusb was compiled without any message logging, this option does * nothing: you'll never get any messages. * * If libusb was compiled with verbose debug message logging, this option * does nothing: you'll always get messages from all levels. */ LOG_LEVEL = 0, /** Use the UsbDk backend for a specific context, if available. * * This option should be set at initialization with libusb_init_context() * otherwise unspecified behavior may occur. * * Only valid on Windows. Ignored on all other platforms. */ USE_USBDK = 1, /** Do not scan for devices * * With this option set, libusb will skip scanning devices in * libusb_init_context(). * * Hotplug functionality will also be deactivated. * * The option is useful in combination with libusb_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. * * This option should only be used with libusb_init_context() * otherwise unspecified behavior may occur. * * Only valid on Linux. Ignored on all other platforms. */ NO_DEVICE_DISCOVERY = 2, /** Set the context log callback function. * * Set the log callback function either on a context or globally. This * option must be provided an argument of type \ref libusb_log_cb. * Using this option with a NULL context is equivalent to calling * libusb_set_log_cb() with mode \ref LIBUSB_LOG_CB_GLOBAL. * Using it with a non-NULL context is equivalent to calling * libusb_set_log_cb() with mode \ref LIBUSB_LOG_CB_CONTEXT. */ LOG_CB = 3, MAX = 4, } Log_Cb :: #type proc "c" (ctx: ^Context, level: Log_Level, str: cstring) Init_Option_Value :: struct #raw_union { ival: c.int, libusb_log_cb: Log_Cb, } Init_Option :: struct { option: Option, value: Init_Option_Value, } /** \ingroup libusb_hotplug * * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 * * Hotplug events */ Hotplug_Event :: enum c.int { /** A device has been plugged in and is ready to use */ DEVICE_ARRIVED = (1 << 0), /** A device has left and is no longer available. * It is the user's responsibility to call libusb_close on any handle associated with a disconnected device. * It is safe to call libusb_get_device_descriptor on a device that has left */ DEVICE_LEFT = (1 << 1), } /** \ingroup libusb_hotplug * * Since version 1.0.16, \ref LIBUSB_API_VERSION >= 0x01000102 * * Hotplug flags */ Hotplug_Flag :: enum c.int { /** Arm the callback and fire it for all matching currently attached devices. */ ENUMERATE = 1, } /** \ingroup libusb_hotplug * Convenience macro when not using any flags */ HOTPLUG_NO_FLAGS :: 0 /** \ingroup libusb_hotplug * Wildcard matching for hotplug events */ HOTPLUG_MATCH_ANY :: -1 Hotplug_Callback_Fn :: #type proc "c" ( ctx: Context, device: ^Device, event: Hotplug_Event, user_date: rawptr, ) -> c.int Callback_Handle :: distinct c.int Transfer_Type :: enum c.int { CONTROL = 0, ISOCHRONOUS = 1, BULK = 2, INTERRUPT = 3, STREAM = 4, } Poll_Fd :: struct { /** Numeric file descriptor */ fd: c.int, /** Event flags to poll for from . POLLIN indicates that you * should monitor this file descriptor for becoming ready to read from, * and POLLOUT indicates that you should monitor this file descriptor for * nonblocking write readiness. */ events: posix.Poll_Event, } Poll_FD_Added_CB :: #type proc "c" (fd: posix.FD, events: posix.Poll_Event, user_data: rawptr) Poll_FD_Removed_CB :: #type proc "c" (fd: posix.FD, user_data: rawptr) @(default_calling_convention = "c", link_prefix = "libusb_") foreign lib { //----- Library initialization/deinitialization ---------------------------------- set_log_cb :: proc(ctx: Context, cb: Log_Cb, mode: Log_Cb_Mode) --- set_option :: proc(ctx: Context, option: Option, args: c.va_list) -> Error --- init :: proc(ctx: ^Context) -> Error --- init_context :: proc(ctx: ^Context, options: [^]Init_Option, num_options: c.int) -> Error --- exit :: proc(ctx: Context) --- //----- Device handling and enumeration ---------------------------------- get_device_list :: proc(ctx: Context, list: ^^[^]Device) -> int --- free_device_list :: proc(device: ^[^]Device, unref_devices: c.int) --- get_bus_number :: proc(dev: ^Device) -> u8 --- get_port_number :: proc(dev: ^Device) -> u8 --- get_port_numbers :: proc(dev: ^Device, port_numbers: [^]u8, port_numbers_len: c.int) -> Error --- get_parent :: proc(dev: ^Device) -> ^Device --- get_device_address :: proc(dev: ^Device) -> u8 --- get_device_speed :: proc(dev: ^Device) -> Speed --- get_max_iso_packet_size :: proc(dev: ^Device, endpoint: c.char) -> c.int --- get_max_alt_packet_size :: proc(dev: ^Device, interface_number: c.int, alternate_setting: c.int, endpoint: u8) -> c.int --- ref_device :: proc(dev: ^Device) -> Device --- unref_device :: proc(dev: ^Device) --- wrap_sys_device :: proc(ctx: Context, sys_dev: rawptr, dev_handle: ^^Device_Handle) -> Error --- open :: proc(dev: ^Device, dev_handle: ^Device_Handle) -> Error --- open_device_with_vid_pid :: proc(ctx: Context, vendor_id: u16, product_id: u16) -> ^Device_Handle --- close :: proc(dev_handle: ^Device_Handle) --- get_device :: proc(dev_handle: ^Device_Handle) -> ^Device --- get_configuration :: proc(dev: ^Device_Handle, config: ^c.int) -> Error --- set_configuration :: proc(dev_handle: ^Device_Handle, configuration: c.int) -> Error --- claim_interface :: proc(dev_handle: ^Device_Handle, interface_number: c.int) -> Error --- release_interface :: proc(dev_handle: ^Device_Handle, interface_number: c.int) -> Error --- interface_alt_setting :: proc(dev_handle: ^Device_Handle, interface_number: c.int, alternate_setting: c.int) -> Error --- clear_halt :: proc(dev_handle: ^Device_Handle, endpoint: u8) -> Error --- reset_device :: proc(dev_handle: ^Device_Handle) -> Error --- kernel_driver_active :: proc(dev_handle: ^Device_Handle, interface_number: c.int) -> Error --- detach_kernel_driver :: proc(dev_handle: ^Device_Handle, interface_number: c.int) -> Error --- 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 --- //----- Miscellaneous ---------------------------------- has_capability :: proc(capability: Capability) -> c.int --- error_name :: proc(errcode: Error) -> cstring --- get_version :: proc() -> Version --- setlocale :: proc(locale: cstring) -> Error --- strerror :: proc(errcode: Error) -> cstring --- //----- USB descriptors ---------------------------------- get_device_descriptor :: proc(dev: ^Device, desc: ^Device_Descriptor) -> Error --- get_active_config_descriptor :: proc(dev: ^Device, config: ^^Config_Descriptor) -> Error --- get_config_descriptor :: proc(dev: ^Device, config_index: u8, config_descriptor: ^^Config_Descriptor) -> Error --- get_config_descriptor_by_value :: proc(dev: ^Device, bConfigurationValue: u8, config: ^^Config_Descriptor) -> Error --- free_config_descriptor :: proc(config: ^Config_Descriptor) --- get_ss_endpoint_companion_descriptor :: proc(ctx: Context, endpoint: ^Endpoint_Direction, ep_comp: ^^Ss_Endpoint_Companion_Descriptor) -> Error --- free_ss_endpoint_companion_descriptor :: proc(ep_comp: ^Ss_Endpoint_Companion_Descriptor) --- get_bos_descriptor :: proc(dev_handle: ^Device_Handle, bos: ^^Bos_Descriptor) -> Error --- free_bos_descriptor :: proc(bos: ^Bos_Descriptor) --- get_usb2_extension_descriptor :: proc(ctx: Context, dev_cap: ^Bos_Dev_Capability_Descriptor, usb2_extension: ^^Usb2_Extension_Descriptor) -> Error --- free_usb2_extension_descriptor :: proc(usb2_extension: ^Usb2_Extension_Descriptor) --- 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_ss_usb_device_capability_descriptor :: proc(ss_usb_device_cap: ^Ss_Usb_Device_Capability_Descriptor) --- get_container_id_descriptor :: proc(ctx: Context, dev_cap: ^Bos_Dev_Capability_Descriptor, container_id: ^^Container_Id_Descriptor) -> Error --- free_container_id_descriptor :: proc(container_id: ^Container_Id_Descriptor) --- get_platform_descriptor :: proc(ctx: Context, dev_cap: ^Bos_Dev_Capability_Descriptor, platform_descriptor: ^^Platform_Descriptor) -> Error --- free_platform_descriptor :: proc(platform_descriptor: ^Platform_Descriptor) --- get_string_descriptor_ascii :: proc(dev_handle: ^Device_Handle, desc_index: u8, data: cstring, length: c.int) -> c.int --- get_interface_association_descriptors :: proc(dev: ^Device, config_index: u8, iad_array: ^^Interface_Association_Descriptor_Array) -> Error --- get_active_interface_association_descriptors :: proc(dev: ^Device, iad_array: ^^Interface_Association_Descriptor_Array) -> Error --- free_interface_association_descriptors :: proc(iad_array: ^Interface_Association_Descriptor_Array) -> Error --- //----- Device hotplug event notification ---------------------------------- hotplug_register_callback :: proc(ctx: Context, events: c.int, flags: c.int, vendor_id: c.int, product_id: c.int, dev_class: c.int, cb_fn: Hotplug_Callback_Fn, callback_handle: Callback_Handle) -> Error --- hotplug_deregister_callback :: proc(ctx: Context, hotplug_callback_handle: Callback_Handle) --- hotplug_get_user_data :: proc(ctx: Context, hotplug_callback_handle: Callback_Handle) -> rawptr --- //----- Asynchronous device I/O ---------------------------------- alloc_streams :: proc(dev_handle: Device_Handle, num_streams: u32, endpoints: [^]u8, num_endpoints: c.int) -> c.int --- free_streams :: proc(dev_handle: Device_Handle, endpoints: [^]u8, num_endpoints: c.int) -> Error --- dev_mem_alloc :: proc(dev_handle: Device_Handle, length: c.size_t) -> [^]u8 --- dev_mem_free :: proc(dev_handle: Device_Handle, buffer: [^]u8, length: c.size_t) -> Error --- alloc_transfer :: proc(iso_packets: c.int = 0) -> ^Transfer --- free_transfer :: proc(transfer: ^Transfer) --- submit_transfer :: proc(transfer: ^Transfer) -> Error --- cancel_transfer :: proc(transfer: ^Transfer) -> Error --- transfer_set_stream_id :: proc(transfer: ^Transfer, stream_id: u32) --- transfer_get_stream_id :: proc(transfer: ^Transfer) -> u32 --- //----- Polling and timing ---------------------------------- try_lock_events :: proc(ctx: Context) -> c.int --- lock_events :: proc(ctx: Context) --- unlock_events :: proc(ctx: Context) --- event_handling_ok :: proc(ctx: Context) -> c.int --- event_handler_active :: proc(ctx: Context) -> c.int --- interrupt_event_handler :: proc(ctx: Context) --- lock_event_waiters :: proc(ctx: Context) --- unlock_event_waiters :: proc(ctx: Context) --- wait_for_event :: proc(ctx: Context, tv: ^posix.timeval) -> c.int --- handle_events_timeout_completed :: proc(ctx: Context, tv: ^posix.timeval, completed: ^c.int) -> Error --- handle_events_completed :: proc(ctx: Context, completed: ^c.int) -> Error --- handle_events_locked :: proc(ctx: Context, tv: ^posix.timeval) -> Error --- pollfds_handle_timeouts :: proc(ctx: Context) -> c.int --- get_next_timeout :: proc(ctx: Context, tv: ^posix.timeval) --- set_pollfd_notifiers :: proc(ctx: Context, added_cb: Poll_FD_Added_CB, removed_cb: Poll_FD_Removed_CB, user_data: rawptr) --- get_pollfds :: proc(ctx: Context) -> [^][^]Poll_Fd --- free_fds :: proc(pollfds: [^][^]Poll_Fd) --- //----- Synchronous device I/O ---------------------------------- control_transfer :: proc(dev_handle: ^Device_Handle, bmRequestType: u8, bRequest: u8, wValue: u16, wIndex: u16, data: [^]u8, wLength: u16, timeout: c.uint) -> Error --- bulk_transfer :: proc(dev_handle: ^Device_Handle, endpoint: u8, data: [^]u8, length: c.int, transferred: ^c.int, timeout: c.uint) -> Error --- interrupt_transfer :: proc(dev_handle: ^Device_Handle, endpoint: u8, data: [^]u8, length: c.int, transferred: ^c.int, timeout: c.uint) -> Error --- } // --------------------------------------------------------------------------------------------------------------------- // ----- Tests ------------------------ // --------------------------------------------------------------------------------------------------------------------- import "core:testing" @(test) init_test :: proc(t: ^testing.T) { result := init(nil) testing.expect_value(t, result, Error.SUCCESS) }