// Copyright (c) 2026 Storm Dragon // SPDX-License-Identifier: GPL-3.0-or-later // Private libusb ABI fixture. It never enumerates or opens real USB devices. #include #include #include #include #include typedef struct { int unused; } Context; typedef struct { int unused; } Device; typedef struct { int unused; } Handle; typedef struct { uint8_t length, type; uint16_t usb; uint8_t device_class, subclass, protocol, packet_size; uint16_t vendor, product, device; uint8_t manufacturer, product_name, serial, configurations; } Descriptor; static Context context; static Device device; static Handle handle; static Device *devices[] = {&device, &device, NULL}; static int mode(const char *value) { return strcmp(getenv("USB_FIXTURE_MODE"), value) == 0; } static void record(const char *message) { FILE *log = fopen(getenv("USB_FIXTURE_LOG"), "a"); if (!log) abort(); fprintf(log, "%s\n", message); fclose(log); } int libusb_init(Context **result) { record("init"); *result = &context; return 0; } void libusb_exit(Context *value) { (void)value; record("exit"); } ssize_t libusb_get_device_list(Context *value, Device ***result) { (void)value; record("list"); *result = devices; return mode("multiple") ? 2 : 1; } void libusb_free_device_list(Device **value, int unref) { (void)value; (void)unref; record("free-list"); } int libusb_get_device_descriptor(Device *value, Descriptor *result) { (void)value; memset(result, 0, sizeof(*result)); result->vendor = 0x0dd0; result->product = mode("missing") ? 0x1002 : 0x2001; return 0; } int libusb_open(Device *value, Handle **result) { (void)value; record("open"); if (mode("denied")) return -3; *result = &handle; return 0; } void libusb_close(Handle *value) { (void)value; record("close"); } int libusb_get_configuration(Handle *value, int *result) { (void)value; record("configuration"); *result = mode("unconfigured") ? 0 : 1; return 0; } int libusb_set_configuration(Handle *value, int configuration) { (void)value; if (configuration != 1) abort(); record("set-configuration"); return 0; } int libusb_claim_interface(Handle *value, int interface) { (void)value; if (interface != 0) abort(); record("claim"); return mode("busy") ? -6 : 0; } int libusb_release_interface(Handle *value, int interface) { (void)value; if (interface != 0) abort(); record("release"); return 0; } int libusb_bulk_transfer(Handle *value, unsigned char endpoint, unsigned char *data, int length, int *transferred, unsigned int timeout) { (void)value; if (length > 64 || timeout != 1000) abort(); char message[256]; int offset = snprintf(message, sizeof(message), "write-%02x:", endpoint); for (int index = 0; index < length; index++) offset += snprintf(message + offset, sizeof(message) - offset, "%02x", data[index]); record(message); *transferred = mode("short") ? length - 1 : length; return mode("timeout") ? -7 : 0; }