gousb Documentation

repository·master·Indexed 21 days ago

https://github.com/google/gousb

A Go binding for the libusb-1.0 library that enables Go developers to interact with USB devices on Linux, Darwin, and Windows. It provides types for managing USB devices, configurations, and interfaces, as well as support for control transfers and high-throughput read/write streams via InEndpoint and OutEndpoint. The project includes the usbid package for human-readable vendor and product codes and an lsusb example binary for listing connected devices.

Tokens
9.5K
Snippets
31
Records
50
Agent score
75%

What's inside gousb

  1. Install gousb on Windows

    master

    To use gousb on Windows, ensure you have the following installed and configured:

    1. GCC: Tested on Win-Builds and MSYS/MINGW.
    2. pkg-config: Required for Cgo to find dependencies.
    3. libusb-1.0: Must be installed.

    Verification Step: Ensure the libusb-1.0.pc pkg-config file is installed. You can verify that the include paths are correct by running:

    pkg-config --cflags libusb-1.0

    Once these are configured, you can proceed with the standard go get installation commands.

  2. Configure libusb-1.0 dependencies

    master

    The gousb package requires libusb-1.0 to be installed on your system. Cgo should be able to locate it if installed via a package manager or in a default location.

    Darwin (macOS) Note

    If you are on Darwin, you may need to run the provided fix script due to an LLVM incompatibility:

    ./fixlibusb_darwin.sh /usr/local/lib/libusb-1.0/libusb.h
  3. Install the usbid package

    master

    The usbid package provides human-readable vendor and product codes for detected hardware. It is not included in the primary gousb installation by default to keep binary sizes smaller. To install both gousb and usbid simultaneously, use:

    go get -v github.com/google/gousb{,/usbid}
  4. How USB device hierarchy works in gousb

    master

    The library follows the standard USB hierarchy to manage device access:

    1. Context: The root object managing all USB resources.
    2. Device: Represents a physical USB device. It contains a Desc (Device Descriptor) with Vendor/Product IDs.
    3. Config: A device can have multiple mutually exclusive configurations. You select one using Device.Config(num). Switching configs performs a lightweight device reset.
    4. Interface: Within a configuration, a device has multiple interfaces. You select one using Config.Interface(num, altNum). Each interface can have multiple alternate settings.
    5. Endpoint: Interfaces contain endpoints for data transfer.
      • InEndpoints (device-to-host) implement io.Reader and are accessed via Interface.InEndpoint(epNum).
      • OutEndpoints (host-to-device) implement io.Writer and are accessed via Interface.OutEndpoint(epNum).
    6. Control Endpoint: A special endpoint available on all devices for issuing commands via Device.Control(), regardless of active configs or interfaces.
  5. Understand InterfaceDesc and InterfaceSetting descriptors

    master

    USB device structures are represented by two hierarchical descriptor types:

    InterfaceDesc

    Contains information about a specific USB interface, including its interface number and a list of supported alternate settings.

    • Number int: The interface number.
    • AltSettings []InterfaceSetting: A list of available InterfaceSetting objects for this interface.

    InterfaceSetting

    Contains information about a specific alternate setting of an interface.

    • Number int: The interface number (matches the parent InterfaceDesc).
    • Alternate int: The alternate setting number.
    • Class Class, SubClass Class, Protocol Protocol: USB-IF class, subclass, and protocol codes.
    • Endpoints map[EndpointAddress]EndpointDesc: A map of available endpoints on this specific setting, keyed by their EndpointAddress.
  6. Handle context cancellation in USB transfers

    master
    When performing I/O operations on endpoints, use the Context variants of the methods (ReadContext and WriteContext) to manage timeouts or cancellations. If the passed context.Context is cancelled, the underlying USB transfers will be cancelled, and the method will return a TransferCancelled error.
  7. Initialize a gousb Context

    master

    A Context manages all resources necessary for communicating with USB devices and handles device discovery. You can create a context using NewContext() for default settings or ContextOptions{}.New() to customize behavior.

    To use OpenDeviceWithFileDescriptor (useful for Android integration), you must disable automatic device discovery during context initialization using DisableDeviceDiscovery.

    // Default context
    ctx := gousb.NewContext()
    
    // Custom context with discovery disabled
    ctx := gousb.ContextOptions{DeviceDiscovery: gousb.DisableDeviceDiscovery}.New()
  8. Install the lsusb example

    master

    The project includes an lsusb binary that lists connected USB devices and their details (configurations, endpoints, etc.). You can install it using:

    go get -v github.com/google/gousb/lsusb
  9. Use the rawread CLI tool to read USB data

    master

    The rawread tool is a command-line utility used to read raw data from a specific USB device. It allows you to target a device using either its VID:PID or its bus:address. You can specify the configuration, interface, alternate setting, and endpoint to read from, and optionally use streams for prefetching data via multiple buffer transfers.

    Usage Pattern

    1. Identify the device: Use --vidpid (e.g., 1d6b:0002) or --busaddr (e.g., 1:1).
    2. Configure the connection: Specify --config, --interface, --alternate, and --endpoint (the number without the leading 0x8).
    3. Set read parameters: Use --read_size for transaction size, --buffer_size for prefetching (enables streaming), and --read_num for the number of transactions (0 for infinite).
    4. Set timeouts: Use --timeout to limit the execution duration.
    # Example: Read from a device with VID 1d6b and PID 0002, using interface 0, endpoint 1, with a 1024 byte read size
    ./rawread --vidpid 1d6b:0002 --interface 0 --endpoint 1 --read_size 1024
    
    # Example: Read using bus:address with prefetching (buffer_size > 1)
    ./rawread --busaddr 1:5 --buffer_size 4 --read_size 512
  10. Configure libusb debugging level

    master

    You can enable debugging for the underlying libusb library by calling ctx.Debug(level) on your gousb.Context. This is useful for inspecting the inner workings of the USB communication stack.

    • Parameter: level (int) representing the debug level (typically 0..3).
    ctx := gousb.NewContext()
    // Set debug level (e.g., 1)
    ctx.Debug(1)
    defer ctx.Close()
  11. Read data from USB endpoints using ReadStream

    master

    A ReadStream is a buffer that prefetches data from a USB IN endpoint to reduce latency between subsequent Read() calls. It maintains a pool of transfers and keeps prefetching until Close() is called or an error occurs.

    Key Behaviors:

    • Prefetching: It automatically manages multiple USB transfers to ensure data is ready for the next read.
    • EOF Handling: After calling Close(), Read() will continue to return any data remaining in transfers that were initiated before the close, eventually returning io.EOF when no data is left.
    • Error Handling: If a non-nil error is encountered, subsequent reads will return io.ErrClosedPipe.
    • Concurrency: Read, ReadContext, and Close cannot be called concurrently.
    // Example usage pattern for ReadStream (conceptual based on API)
    // stream := ... (obtained from an Endpoint)
    // reader := gousb.ReadStream{s: stream}
    // 
    // buf := make([]byte, 512)
    // n, err := reader.Read(buf)
    // if err == io.EOF {
    //     // End of stream
    // }
    // if err != nil {
    //     // Handle error
    // }