Files

59 lines
2.9 KiB
C

// 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 <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
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;
}