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

Adding two classes to one device makes it composite.

examples/device/cdc_hid_device.c is a serial port plus a media-key (HID consumer control) function on one device. Declaring it composite is the whole difference - from there each function is added exactly as it would be on a device of its own:

usbip_device_set_composite(dev); /* EF/02/01: usbccgp splits per IAD */
/* --- function 1: CDC-ACM (interfaces 0+1), grouped by the class's IAD --- */
cdc_acm_opts copts = {
.on_rx = on_rx,
.on_open = on_open,
.on_close = on_close,
.user = &app
};
app.console = cdc_acm_add(dev, &copts);
cdc_port * cdc_acm_add(usbip_device *dev, const cdc_acm_opts *opts)
Add a CDC-ACM serial port to a device.
void usbip_device_set_composite(usbip_device *dev)
Declare the device composite: several independent class functions on one device.
App callbacks and per-port settings.
Definition cdc_acm.h:70
void(* on_rx)(cdc_port *port, void *user, const void *data, int len)
Bytes arrived from the host (optional).
Definition cdc_acm.h:98
/* --- function 2: HID consumer control (interface 2) --------------------
* No subclass or protocol: only a keyboard or a mouse can be a boot device. */
hid_opts hopts = {
.report_desc = RD_CONSUMER,
.report_desc_len = sizeof(RD_CONSUMER),
.in_mps = 2,
.user = &app
};
app.consumer = hid_add(dev, &hopts);
hid_iface * hid_add(usbip_device *dev, const hid_opts *opts)
Add a generic HID interface to a device.
Per-instance configuration for a generic HID interface.
Definition hid.h:171
const uint8_t * report_desc
The Report descriptor bytes (required)
Definition hid.h:172

One plug, and the host binds two of its own drivers: a serial port and a consumer control. Neither class is told it is sharing the device. Interface numbers are handed out as functions are added - CDC-ACM takes 0 and 1, so the HID lands on 2 - and endpoint addresses work the same way, so instances never collide: each class asks for the address it would use alone, the core relocates the later ones onto free numbers, and each keeps the pipe it was handed. You assign neither yourself.

How functions group interfaces, when the EF/02/01 composite triple is required, and per-function Microsoft OS descriptors are covered by the class layer. To author a composite without the classes - writing the IADs and every descriptor by hand - see Vendor Devices & WebUSB, which does exactly that for one function. To serve several SEPARATE devices from one program instead - each with its own identity and attach - see Multiple devices.