|
USBIP C library 0.7.0
Virtual USB devices & host drivers over USB/IP
|
Functions, interfaces, and the usbip_device_class vtable. More...
Files | |
| file | usb_class.h |
| Class layer - functions, interfaces, and the usbip_device_class vtable. | |
Data Structures | |
| struct | usbip_device_class |
| A reusable device class: the descriptors it declares, the callbacks that drive it, and the size of its per-instance state. More... | |
Macros | |
| #define | USB_DT_CS_INTERFACE |
| Class-specific descriptor type codes - CDC, UAC and UVC all use these two values. | |
| #define | USB_DT_CS_ENDPOINT |
| class-specific endpoint descriptor | |
Typedefs | |
| typedef struct usbip_function | usbip_function |
| A function: one class instance (>=1 iface) | |
| typedef struct usbip_interface | usbip_interface |
| One USB interface (one bInterfaceNumber) | |
| typedef int(* | usbip_function_control_fn) (usbip_function *func, const usb_setup *setup, uint8_t *buf, uint16_t len) |
| Class/vendor control handler. | |
Functions | |
| usbip_function * | usbip_device_add_function (usbip_device *dev) |
| Low-level: add a bare function you configure yourself, descriptor by descriptor. | |
| int | usbip_function_add_descriptor (usbip_function *func, const void *descriptor) |
| Append a typed descriptor (interface / endpoint / HID / class-specific) to a function, in wire order. | |
| usbip_ep * | usbip_function_add_endpoint (usbip_function *func, const void *ep_descriptor) |
| Append an endpoint descriptor and return the pipe it created. | |
| uint8_t | usbip_function_reserve_endpoint (usbip_function *func, uint8_t want_addr) |
| Claim an endpoint address now, for an endpoint declared later. | |
| usbip_ep * | usbip_function_endpoint (usbip_function *func, uint8_t addr) |
| Fetch one of this function's endpoint pipes by address. | |
| void | usbip_function_on_control (usbip_function *func, usbip_function_control_fn cb) |
| Install the class/vendor control handler for an interface. | |
| int | usbip_function_enable_msos (usbip_function *func, const char *compatible, const char *guid) |
| Advertise Microsoft OS descriptors for one function of a composite device. | |
| int | usbip_function_enable_winusb (usbip_function *func, const char *guid) |
| usbip_function_enable_msos() with the "WINUSB" Compatible ID. | |
| usbip_function * | usbip_device_add_class (usbip_device *dev, const usbip_device_class *cls, const void *params) |
| Instantiate a reusable device class onto a device, adding one function. | |
| void * | usbip_function_state (usbip_function *func) |
| The function's per-instance state block (sized by usbip_device_class::state_size). | |
| usbip_device * | usbip_function_device (usbip_function *func) |
| The device a function belongs to - for device-level setup from a class build (e.g. | |
| int | usbip_function_base_ifnum (usbip_function *func) |
| The bInterfaceNumber of this function's first interface. | |
| int | usbip_function_instance (usbip_function *func) |
| Which instance of its own class this function is, counting from 0 in add order. | |
| usbip_interface * | usbip_function_add_interface (usbip_function *func, uint8_t cls, uint8_t sub, uint8_t proto) |
| Add a USB interface (a fresh bInterfaceNumber, alternate setting 0) to a function. | |
| int | usbip_interface_add_altsetting (usbip_interface *iface, uint8_t alt) |
| Add an alternate setting to an interface (same bInterfaceNumber, new bAlternateSetting). | |
| int | usbip_interface_add_descriptor (usbip_interface *iface, const void *descriptor) |
| Append a class-specific descriptor to an interface's current alternate setting. | |
| usbip_ep * | usbip_interface_add_endpoint (usbip_interface *iface, const void *ep_descriptor) |
| Append an endpoint to an interface's current alternate setting. | |
| int | usbip_interface_number (usbip_interface *iface) |
| An interface's bInterfaceNumber. | |
| void | usbip_interface_set_string (usbip_interface *iface, uint8_t istr) |
| Set the iInterface string index on the interface's current alternate setting. | |
| void | usbip_function_associate (usbip_function *func, uint8_t count, uint8_t cls, uint8_t sub, uint8_t proto, uint8_t iFunction) |
| Emit an Interface Association Descriptor grouping this function's interfaces (opt-in). | |
| void | usbip_class_vlog (void(*emit)(void *user, const char *text), void *user, const char *prefix, const char *fmt, va_list ap) |
| Format a log line and hand it to a class module's on_event-style callback. | |
Functions, interfaces, and the usbip_device_class vtable.
Composes a device out of usbip_function functions, each owning one or more usbip_interface interfaces. Instantiate a reusable class with usbip_device_add_class() or author a bare function with usbip_device_add_function(). The layer sits on the device core, which knows nothing about it.
| #define USB_DT_CS_INTERFACE |
Class-specific descriptor type codes - CDC, UAC and UVC all use these two values.
class-specific interface descriptor
| #define USB_DT_CS_ENDPOINT |
class-specific endpoint descriptor
| typedef struct usbip_function usbip_function |
A function: one class instance (>=1 iface)
| typedef struct usbip_interface usbip_interface |
One USB interface (one bInterfaceNumber)
| typedef int(* usbip_function_control_fn) (usbip_function *func, const usb_setup *setup, uint8_t *buf, uint16_t len) |
Class/vendor control handler.
For an IN request, fill buf with up to len bytes and return the count; for an OUT request, buf holds len bytes and you return >= 0; return a negative value to STALL. Standard requests are handled automatically by the core.
| func | the function. |
| setup | the 8-byte SETUP packet. |
| buf | data buffer (IN: to fill; OUT: incoming data). |
| len | IN: capacity of buf; OUT: number of bytes in buf. |
| usbip_function * usbip_device_add_function | ( | usbip_device * | dev | ) |
Low-level: add a bare function you configure yourself, descriptor by descriptor.
Most code uses a ready-made class (e.g. hid_add()) instead. The interface class triple lives in the interface descriptors you append - the function itself carries none.
| dev | the device. |
NULL when the function table (8) is full or memory ran out. | int usbip_function_add_descriptor | ( | usbip_function * | func, |
| const void * | descriptor | ||
| ) |
Append a typed descriptor (interface / endpoint / HID / class-specific) to a function, in wire order.
bNumEndpoints is auto-counted: leave it 0 in interface descriptors - every endpoint appended afterwards bumps the count in its owning alternate setting.
The bytes are appended as they are, so declare the descriptor USB_PACKED and its little-endian layout is handled for you (USB_U16LE for a raw byte array) - see usbip_device_add_descriptor().
| func | the function. |
| descriptor | pointer to a USB_PACKED descriptor whose first byte is its length. |
| USB_SUCCESS | appended. |
| USB_ERROR_NO_MEM | the device's descriptor buffer is full, or (for an endpoint descriptor) no endpoint number was free in its direction. |
| usbip_ep * usbip_function_add_endpoint | ( | usbip_function * | func, |
| const void * | ep_descriptor | ||
| ) |
Append an endpoint descriptor and return the pipe it created.
Prefer this over usbip_function_add_descriptor() for endpoints: bEndpointAddress is only a preference. It is honoured when the number is free, but if another interface already holds it the endpoint is relocated to the lowest free number in the same direction - so a second instance of a class, or a composite device, gets working pipes instead of a descriptor in which two interfaces claim one address. Pass a zero endpoint number (0x00 OUT / 0x80 IN) to say "any".
Because the address may change, keep the returned pipe rather than looking it up again by the address you asked for.
| func | the function. |
| ep_descriptor | a packed usb_endpoint_descriptor. |
NULL if it could not be added (no free number, or the device's descriptor buffer is full). | uint8_t usbip_function_reserve_endpoint | ( | usbip_function * | func, |
| uint8_t | want_addr | ||
| ) |
Claim an endpoint address now, for an endpoint declared later.
Needed when a class-specific descriptor has to name an endpoint that has not been declared yet - UVC's VideoStreaming input header carries a bEndpointAddress, but must be emitted before the endpoint descriptor, which lives in a later alternate setting. Writing the requested address into that header would be wrong the moment the allocator relocates the endpoint (see usbip_function_add_endpoint()), leaving the class descriptor pointing at some other function's pipe.
Returns the address the endpoint will actually get. Put that in the class descriptor, then pass it as the bEndpointAddress of the endpoint descriptor when you add it: the reservation makes the allocator hand back the same number. Call it after adding the interface that will own the endpoint - the reservation belongs to that interface, so its alternate settings can all use it.
| func | the function. |
| want_addr | the preferred address (direction bit included), e.g. 0x81. |
| usbip_ep * usbip_function_endpoint | ( | usbip_function * | func, |
| uint8_t | addr | ||
| ) |
Fetch one of this function's endpoint pipes by address.
The lookup is scoped to func, so each function in a composite device resolves its own pipes. Note that an endpoint relocated by the allocator (see usbip_function_add_endpoint()) no longer answers to the address originally requested - hold on to the pipe you were given instead.
| func | the function. |
| addr | endpoint address (e.g. 0x81 for IN endpoint 1). |
NULL if this function has none with that address. | void usbip_function_on_control | ( | usbip_function * | func, |
| usbip_function_control_fn | cb | ||
| ) |
Install the class/vendor control handler for an interface.
| func | the function. |
| cb | the handler (see usbip_function_control_fn), or NULL to remove it. |
| int usbip_function_enable_msos | ( | usbip_function * | func, |
| const char * | compatible, | ||
| const char * | guid | ||
| ) |
Advertise Microsoft OS descriptors for one function of a composite device.
On a composite, Windows loads usbccgp and gives each function its own devnode, each binding its own driver. A device-wide Compatible ID cannot express that: it would tell Windows the whole device is (say) WinUSB, taking the COM port of a neighbouring CDC function down with it. This form names the function, so Microsoft OS 1.0 emits a section with the right bFirstInterfaceNumber and Microsoft OS 2.0 wraps the feature in a Function Subset.
Call it from the class's build() or right after adding the class; the interface numbers are resolved later, when the host asks for the descriptors. Bumps bcdUSB to 0x0210 so the host fetches the BOS.
A single-function device may call this too - the emitted bytes are then identical to the device-wide form.
| func | the function to describe. |
| compatible | the Compatible ID string (e.g. "WINUSB", "MTP"). |
| guid | DeviceInterfaceGUID to add, or NULL to omit it. |
| USB_SUCCESS | recorded. |
| USB_ERROR_NO_MEM | the advertisement table is full or memory ran out. |
| USB_ERROR_INVALID_PARAM | func is NULL. |
| int usbip_function_enable_winusb | ( | usbip_function * | func, |
| const char * | guid | ||
| ) |
usbip_function_enable_msos() with the "WINUSB" Compatible ID.
| func | the function to describe. |
| guid | DeviceInterfaceGUID to advertise, or NULL for a built-in default. |
| USB_SUCCESS | recorded. |
| USB_ERROR_NO_MEM | the advertisement table is full or memory ran out. |
| USB_ERROR_INVALID_PARAM | func is NULL. |
| usbip_function * usbip_device_add_class | ( | usbip_device * | dev, |
| const usbip_device_class * | cls, | ||
| const void * | params | ||
| ) |
Instantiate a reusable device class onto a device, adding one function.
| dev | the device. |
| cls | the class to instantiate - a statically-allocated class descriptor, kept by reference (e.g. &usbip_device_hid). |
| params | class-specific build parameters, passed to usbip_device_class::build. |
NULL if cls is NULL or its build failed. | void * usbip_function_state | ( | usbip_function * | func | ) |
The function's per-instance state block (sized by usbip_device_class::state_size).
| func | the function. |
NULL if the class declared none. | usbip_device * usbip_function_device | ( | usbip_function * | func | ) |
The device a function belongs to - for device-level setup from a class build (e.g.
usbip_device_add_string() / usbip_device_enable_winusb()).
| func | the function. |
| int usbip_function_base_ifnum | ( | usbip_function * | func | ) |
The bInterfaceNumber of this function's first interface.
Fixed when the function is created, so it reads the same before and after the function's interfaces are added. A multi-interface class uses it to name its own interfaces from inside a descriptor it emits earlier in the block - a CDC Union or a UVC VideoControl header has to state the interface number of a sibling that does not exist yet, and the function's interfaces are numbered consecutively from this base. Once an interface exists, usbip_interface_number() reports it directly.
| func | the function. |
| int usbip_function_instance | ( | usbip_function * | func | ) |
Which instance of its own class this function is, counting from 0 in add order.
Lets a class label its instances without a global counter - the second cdc_acm_add() on a device answers 1, and the count restarts per device, so several devices in one process stay independent.
| func | the function. |
| usbip_interface * usbip_function_add_interface | ( | usbip_function * | func, |
| uint8_t | cls, | ||
| uint8_t | sub, | ||
| uint8_t | proto | ||
| ) |
Add a USB interface (a fresh bInterfaceNumber, alternate setting 0) to a function.
| func | the function. |
| cls | bInterfaceClass. |
| sub | bInterfaceSubClass. |
| proto | bInterfaceProtocol. |
| int usbip_interface_add_altsetting | ( | usbip_interface * | iface, |
| uint8_t | alt | ||
| ) |
Add an alternate setting to an interface (same bInterfaceNumber, new bAlternateSetting).
Subsequent usbip_interface_add_endpoint() / usbip_interface_add_descriptor() calls land in this alternate setting.
| iface | the interface. |
| alt | the bAlternateSetting value. |
| USB_SUCCESS | added. |
| USB_ERROR_NO_MEM | the device's descriptor buffer is full. |
| int usbip_interface_add_descriptor | ( | usbip_interface * | iface, |
| const void * | descriptor | ||
| ) |
Append a class-specific descriptor to an interface's current alternate setting.
| iface | the interface. |
| descriptor | a packed descriptor whose first byte is its length. |
| usbip_ep * usbip_interface_add_endpoint | ( | usbip_interface * | iface, |
| const void * | ep_descriptor | ||
| ) |
Append an endpoint to an interface's current alternate setting.
| iface | the interface. |
| ep_descriptor | a packed usb_endpoint_descriptor. |
NULL on failure. | int usbip_interface_number | ( | usbip_interface * | iface | ) |
An interface's bInterfaceNumber.
| iface | the interface. |
| void usbip_interface_set_string | ( | usbip_interface * | iface, |
| uint8_t | istr | ||
| ) |
Set the iInterface string index on the interface's current alternate setting.
Does nothing if the interface has no alternate setting yet - call it after usbip_function_add_interface().
| iface | the interface. |
| istr | string descriptor index (from usbip_device_add_string()). |
| void usbip_function_associate | ( | usbip_function * | func, |
| uint8_t | count, | ||
| uint8_t | cls, | ||
| uint8_t | sub, | ||
| uint8_t | proto, | ||
| uint8_t | iFunction | ||
| ) |
Emit an Interface Association Descriptor grouping this function's interfaces (opt-in).
Call before adding the function's interfaces. Needed only for true composite functions (e.g. UVC); most multi-interface classes (CDC, Bluetooth, audio) group their interfaces by class-specific means and must NOT emit an IAD. Pair with usbip_device_set_class(dev, ::USB_CLASS_MISC, ::USB_SUBCLASS_COMMON, ::USB_PROTOCOL_IAD) - or let usbip_device_set_composite() do it for the device.
| func | the function. |
| count | bInterfaceCount (number of interfaces in the association). |
| cls | bFunctionClass. |
| sub | bFunctionSubClass. |
| proto | bFunctionProtocol. |
| iFunction | iFunction string index (0 for none). |
| void usbip_class_vlog | ( | void(*)(void *user, const char *text) | emit, |
| void * | user, | ||
| const char * | prefix, | ||
| const char * | fmt, | ||
| va_list | ap | ||
| ) |
Format a log line and hand it to a class module's on_event-style callback.
The one implementation of the "format into a small buffer, emit, or do nothing when no callback is set" idiom every class module needs.
| emit | the module's event callback, or NULL (then nothing happens). |
| user | the callback's user pointer. |
| prefix | text placed before the formatted message, or NULL for none. |
| fmt | printf format for the message. |
| ap | its arguments. |