USBIP C library 0.7.0
Virtual USB devices & host drivers over USB/IP
Loading...
Searching...
No Matches
Class layer

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_functionusbip_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_epusbip_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_epusbip_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_functionusbip_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_deviceusbip_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_interfaceusbip_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_epusbip_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.
 

Detailed Description

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.

Macro Definition Documentation

◆ USB_DT_CS_INTERFACE

#define USB_DT_CS_INTERFACE

Class-specific descriptor type codes - CDC, UAC and UVC all use these two values.

class-specific interface descriptor

◆ USB_DT_CS_ENDPOINT

#define USB_DT_CS_ENDPOINT

class-specific endpoint descriptor

Typedef Documentation

◆ usbip_function

A function: one class instance (>=1 iface)

◆ usbip_interface

One USB interface (one bInterfaceNumber)

◆ usbip_function_control_fn

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.

Parameters
functhe function.
setupthe 8-byte SETUP packet.
bufdata buffer (IN: to fill; OUT: incoming data).
lenIN: capacity of buf; OUT: number of bytes in buf.
Returns
bytes produced (IN) / consumed-OK (OUT, >= 0), or < 0 to STALL.

Function Documentation

◆ usbip_device_add_function()

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.

Parameters
devthe device.
Returns
the new function, or NULL when the function table (8) is full or memory ran out.

◆ usbip_function_add_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.

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().

Parameters
functhe function.
descriptorpointer to a USB_PACKED descriptor whose first byte is its length.
Return values
USB_SUCCESSappended.
USB_ERROR_NO_MEMthe device's descriptor buffer is full, or (for an endpoint descriptor) no endpoint number was free in its direction.

◆ usbip_function_add_endpoint()

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.

Parameters
functhe function.
ep_descriptora packed usb_endpoint_descriptor.
Returns
the endpoint, or NULL if it could not be added (no free number, or the device's descriptor buffer is full).

◆ usbip_function_reserve_endpoint()

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.

Parameters
functhe function.
want_addrthe preferred address (direction bit included), e.g. 0x81.
Returns
the reserved address, or 0 if no number was free in that direction - or if the function has no interface yet to own the claim.

◆ usbip_function_endpoint()

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.

Parameters
functhe function.
addrendpoint address (e.g. 0x81 for IN endpoint 1).
Returns
the endpoint, or NULL if this function has none with that address.

◆ usbip_function_on_control()

void usbip_function_on_control ( usbip_function func,
usbip_function_control_fn  cb 
)

Install the class/vendor control handler for an interface.

Parameters
functhe function.
cbthe handler (see usbip_function_control_fn), or NULL to remove it.

◆ usbip_function_enable_msos()

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.

Parameters
functhe function to describe.
compatiblethe Compatible ID string (e.g. "WINUSB", "MTP").
guidDeviceInterfaceGUID to add, or NULL to omit it.
Return values
USB_SUCCESSrecorded.
USB_ERROR_NO_MEMthe advertisement table is full or memory ran out.
USB_ERROR_INVALID_PARAMfunc is NULL.

◆ usbip_function_enable_winusb()

int usbip_function_enable_winusb ( usbip_function func,
const char *  guid 
)

usbip_function_enable_msos() with the "WINUSB" Compatible ID.

Parameters
functhe function to describe.
guidDeviceInterfaceGUID to advertise, or NULL for a built-in default.
Return values
USB_SUCCESSrecorded.
USB_ERROR_NO_MEMthe advertisement table is full or memory ran out.
USB_ERROR_INVALID_PARAMfunc is NULL.

◆ usbip_device_add_class()

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.

Parameters
devthe device.
clsthe class to instantiate - a statically-allocated class descriptor, kept by reference (e.g. &usbip_device_hid).
paramsclass-specific build parameters, passed to usbip_device_class::build.
Returns
the new function, or NULL if cls is NULL or its build failed.

◆ usbip_function_state()

void * usbip_function_state ( usbip_function func)

The function's per-instance state block (sized by usbip_device_class::state_size).

Parameters
functhe function.
Returns
a pointer to the zero-initialised state, or NULL if the class declared none.

◆ usbip_function_device()

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()).

Parameters
functhe function.
Returns
the owning device.

◆ usbip_function_base_ifnum()

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.

Parameters
functhe function.
Returns
the bInterfaceNumber of the function's first interface.

◆ usbip_function_instance()

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.

Parameters
functhe function.
Returns
the 0-based instance number among same-class functions on this device.

◆ usbip_function_add_interface()

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.

Parameters
functhe function.
clsbInterfaceClass.
subbInterfaceSubClass.
protobInterfaceProtocol.
Returns
the new interface.

◆ usbip_interface_add_altsetting()

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.

Parameters
ifacethe interface.
altthe bAlternateSetting value.
Return values
USB_SUCCESSadded.
USB_ERROR_NO_MEMthe device's descriptor buffer is full.

◆ usbip_interface_add_descriptor()

int usbip_interface_add_descriptor ( usbip_interface iface,
const void *  descriptor 
)

Append a class-specific descriptor to an interface's current alternate setting.

Parameters
ifacethe interface.
descriptora packed descriptor whose first byte is its length.
Returns
USB_SUCCESS, or a negative USB_ERROR code.

◆ usbip_interface_add_endpoint()

usbip_ep * usbip_interface_add_endpoint ( usbip_interface iface,
const void *  ep_descriptor 
)

Append an endpoint to an interface's current alternate setting.

Parameters
ifacethe interface.
ep_descriptora packed usb_endpoint_descriptor.
Returns
the new endpoint pipe, or NULL on failure.

◆ usbip_interface_number()

int usbip_interface_number ( usbip_interface iface)

An interface's bInterfaceNumber.

Parameters
ifacethe interface.
Returns
its bInterfaceNumber.

◆ usbip_interface_set_string()

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().

Parameters
ifacethe interface.
istrstring descriptor index (from usbip_device_add_string()).

◆ usbip_function_associate()

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.

Parameters
functhe function.
countbInterfaceCount (number of interfaces in the association).
clsbFunctionClass.
subbFunctionSubClass.
protobFunctionProtocol.
iFunctioniFunction string index (0 for none).

◆ usbip_class_vlog()

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.

Parameters
emitthe module's event callback, or NULL (then nothing happens).
userthe callback's user pointer.
prefixtext placed before the formatted message, or NULL for none.
fmtprintf format for the message.
apits arguments.