# Raw USB Driver (Pro)

The Raw USB driver talks to USB devices directly through **libusb**, bypassing the operating system's class drivers. It is the right driver when a device exposes vendor-specific bulk, control, or isochronous endpoints rather than presenting itself as a serial port (CDC), an HID device, or a mass-storage volume.

If the device shows up as a virtual COM port, use the [UART driver](https://serial-studio.com/help/drivers-uart.md). For gamepads, joysticks, or HID firmware, use the [HID driver](https://serial-studio.com/help/drivers-hid.md). This page covers everything else: logic analysers, oscilloscopes, custom data-acquisition boards, vendor-specific scientific instruments, and any device whose datasheet says "uses bulk endpoints".

## What is USB, really?

USB is layered. From the bottom up:

- **Physical layer.** Differential pair (D+/D-) plus power and ground. Speeds: 1.5 Mbps (Low Speed), 12 Mbps (Full Speed), 480 Mbps (High Speed), 5 Gbps (USB 3.0 SuperSpeed), and faster.
- **Packet layer.** A host-driven token/data/handshake protocol. Devices never initiate transfers; the host always polls.
- **Transfer layer.** Four transfer types (control, bulk, interrupt, isochronous) sit on top of packets.
- **Class layer.** Standard classes (HID, CDC, Mass Storage, Audio, Video) define the device category.

Almost every consumer USB device implements one of the standard classes. The OS bundles a generic driver for each class, so plugging in a USB-CDC microcontroller exposes a COM port without any extra install.

Vendor-specific USB devices skip the standard classes. They expose endpoints with custom semantics that the OS does not know how to interpret. libusb is a userspace library that lets an application open such a device and talk to its endpoints directly.

### Endpoints and transfer types

Every USB device has at least one **endpoint** (endpoint 0, the control endpoint). Most devices have several. Endpoints are unidirectional buffers identified by a number and a direction (IN = device to host, OUT = host to device).

Each endpoint is configured for one of four **transfer types**:

```mermaid
flowchart TB
    USB[USB transfer types]
    USB --> CTRL[Control<br/>EP0 always; bidirectional<br/>config, descriptors, setup]
    USB --> BULK[Bulk<br/>large data, no timing guarantee<br/>guaranteed delivery]
    USB --> INT[Interrupt<br/>small periodic data<br/>guaranteed latency]
    USB --> ISO[Isochronous<br/>continuous streaming<br/>no retransmission, no checksum]
```

- **Control transfers (Endpoint 0)** carry configuration data: reading device descriptors, selecting interfaces, sending vendor commands. Always bidirectional through the same endpoint pair.
- **Bulk transfers** carry large amounts of data with error detection (CRC) and guaranteed delivery but no bandwidth guarantee. Used for printers, mass storage, and most raw data-acquisition devices. The host fits bulk transfers around higher-priority traffic.
- **Interrupt transfers** carry small amounts of data with a guaranteed maximum latency (the polling interval set in the endpoint descriptor). Used for HID devices and other small periodic data. Despite the name there are no real hardware interrupts; the host polls.
- **Isochronous transfers** carry time-sensitive streaming data (audio, video) with guaranteed bandwidth but no retransmission. A corrupted packet is lost. Used for USB audio interfaces and webcams.

For Serial Studio's USB driver, the relevant types are **bulk** (the default, for streaming captured data), **isochronous** (for high-rate continuous streams where dropped frames are acceptable), and **control** (vendor-specific commands, available in Advanced mode).

### Descriptors

A USB device describes itself through a tree of **descriptors**:

```mermaid
flowchart TD
    Device[Device Descriptor<br/>VID, PID, USB version]
    Device --> Cfg[Configuration Descriptor<br/>power requirements]
    Cfg --> If1[Interface Descriptor<br/>logical function]
    If1 --> EP1[Endpoint Descriptor<br/>EP1 IN, bulk, 64 bytes]
    If1 --> EP2[Endpoint Descriptor<br/>EP2 OUT, bulk, 64 bytes]
    Cfg --> If2[Interface Descriptor<br/>another function]
    If2 --> EP3[Endpoint Descriptor<br/>EP3 IN, interrupt, 8 bytes]
```

The host queries the device for its descriptor tree on enumeration, decides what to do with it, and binds drivers accordingly. A vendor-specific bulk device usually has one configuration, one interface, and a couple of endpoints (one IN for reading, one OUT for writing).

### VID and PID

Every USB device has a **Vendor ID (VID)** and **Product ID (PID)**, both 16-bit. VIDs are assigned by the USB-IF; PIDs are chosen by the vendor. Together they uniquely identify a device model. Serial Studio lists USB devices as `VID:PID`, followed by the manufacturer and product strings when the device reports them (for example `1234:5678 – Acme Logic Analyzer`).

## How Serial Studio uses it

The USB driver wraps libusb. The setup flow is:

1. Pick a device from the **USB Device** dropdown. The list updates on libusb hotplug events, with a 2-second rescan fallback on platforms without hotplug support.
2. Pick a **Transfer Mode**:
   - **Bulk Stream** (default): synchronous bulk IN/OUT. Works for most devices.
   - **Advanced (Bulk + Control)**: bulk transfers plus vendor-specific control transfers. A confirmation dialog appears before enabling this, because vendor-specific control writes can do anything the device firmware allows, up to and including bricking the device.
   - **Isochronous**: asynchronous isochronous transfers for fixed-rate streaming.
3. Connect. The **IN Endpoint** and **OUT Endpoint** dropdowns appear once connected, read from the device's active configuration descriptor and labeled like `EP 0x81 – Bulk IN (IF0, max 64 B)`. The first endpoint matching the transfer mode is selected automatically; **OUT Endpoint** defaults to **None (Read-only)** when no matching OUT endpoint exists.
4. In Isochronous mode, a **Max Packet Size** field (1 to 49152 bytes, default 1024) also appears once connected. Serial Studio pre-fills it with the endpoint's reported maximum packet size; override it only when the device datasheet says otherwise.

### Threading

The USB driver runs two dedicated threads:

- **Event thread.** Pumps libusb's event loop. Required by libusb's async API and hotplug callbacks.
- **Read thread.** Issues synchronous bulk reads (64 KB buffer, 100 ms timeout) in Bulk Stream and Advanced modes. In Isochronous mode, data arrives instead through a pool of eight async transfers (eight packets each) whose completion callbacks run on the event thread.

Each completed transfer carries a timestamp captured at completion time and is queued to the main thread for FrameReader processing. See [Threading and Timing Guarantees](https://serial-studio.com/help/threading-and-timing.md).

### Permissions and OS specifics

USB device access is permission-controlled differently on each OS:

- **Linux.** By default only `root` can open arbitrary USB devices. Add a `udev` rule granting the user access to a specific VID:PID:
  ```
  /etc/udev/rules.d/99-myusbdevice.rules:
  SUBSYSTEM=="usb", ATTR{idVendor}=="1234", ATTR{idProduct}=="5678", MODE="0666"
  ```
  Then run `sudo udevadm control --reload-rules && sudo udevadm trigger`. Serial Studio enables libusb's auto-detach on Linux, so a kernel class driver bound to the interface (for example `cdc_acm`) is detached automatically when the interface is claimed and re-attached on release.
- **Windows.** A WinUSB driver must be installed for the device. The standard Windows class drivers (HID, CDC, and so on) hold the device open and prevent libusb from claiming it. Use **Zadig** to replace the driver with WinUSB for the target VID:PID.
- **macOS.** Devices that are not already claimed by an OS class driver can be opened directly. When macOS has bound a kernel driver, opening or claiming the interface fails; Serial Studio does not attempt to detach system drivers.

For step-by-step setup, see the [Protocol Setup Guides, Raw USB section](https://serial-studio.com/help/protocol-setup-guides.md).

### Remote API commands

The TCP API and the in-app AI assistant configure this driver through the `io.usb.*` scope:

| Command | Parameters | Notes |
|---------|------------|-------|
| `io.usb.listDevices` | none | Returns `devices` array and `selectedIndex` (index 0 is the "Select Device" placeholder) |
| `io.usb.setDeviceIndex` | `deviceIndex` (integer) | Selects a device by list index |
| `io.usb.setTransferMode` | `mode` (0 = Bulk Stream, 1 = Advanced, 2 = Isochronous) | |
| `io.usb.setInEndpointIndex` | `endpointIndex` (integer) | Endpoint lists populate when the device connects |
| `io.usb.setOutEndpointIndex` | `endpointIndex` (integer) | Index 0 is "None (Read-only)" |
| `io.usb.setIsoPacketSize` | `size` (1 to 49152 bytes) | |
| `io.usb.getConfig` | none | Returns mode, indices, packet size, and both endpoint lists |

Transport details and command safety tiers are in the [API Reference](https://serial-studio.com/help/api-reference.md).

## Common pitfalls

- **Device not listed.** On Linux, the udev rule is missing or has not taken effect. `lsusb` shows the device; `lsusb -v -d VID:PID` shows its descriptor. If `lsusb` works but Serial Studio does not see the device, it is a permissions problem.
- **Device is listed but will not open.** Another driver or application has already claimed it. On Windows, switch to WinUSB through Zadig. On Linux, kernel class drivers are detached automatically when the interface is claimed; if open still fails, check `dmesg | grep usb` for hints and close other applications using the device.
- **No data on the IN endpoint.** Confirm the endpoint number. Vendor documentation always specifies which endpoint streams data; pick the matching one in the dropdown. Also confirm the device is streaming; some devices need a vendor-specific control write to start.
- **Bulk reads time out.** Timeouts are not errors: the read loop retries every 100 ms and forwards whatever the device delivers. A connection that stays open with nothing arriving means the device is not sending on the selected IN endpoint.
- **Isochronous mode drops samples.** Some hardware/OS combinations cap isochronous bandwidth. Match Max Packet Size to the endpoint's reported maximum; typical values are 192 B for full-speed audio and 1024 B for high-speed devices.
- **Advanced (Bulk + Control) mode warning.** Take it seriously. Vendor-specific control transfers can issue any command the firmware understands, including writing to flash, changing calibration, and arbitrary memory writes. Only enable this mode with a full understanding of what is being sent.
- **Permission denied on Linux, even with udev.** The udev rule did not reload, or the device was not unplugged and replugged after the rule was added. Trigger a re-enumeration with `sudo udevadm trigger`.

## Further reading

- [Beyond Logic: USB primer](https://www.beyondlogic.org/usbnutshell/usb1.shtml): introduction to USB.
- [USB Endpoint Types (Beyond Logic Chapter 4)](https://www.beyondlogic.org/usbnutshell/usb4.shtml)
- [USB Descriptors (Beyond Logic Chapter 5)](https://www.beyondlogic.org/usbnutshell/usb5.shtml)
- [libusb-1.0 API Reference](https://libusb.sourceforge.io/api-1.0/)
- [Asynchronous Device I/O (libusb docs)](https://libusb.sourceforge.io/api-1.0/group__libusb__asyncio.html)

## See also

- [Protocol Setup Guides](https://serial-studio.com/help/protocol-setup-guides.md): step-by-step Raw USB setup.
- [Data Sources](https://serial-studio.com/help/data-sources.md): driver capability summary across all transports.
- [Communication Protocols](https://serial-studio.com/help/communication-protocols.md): overview of all supported transports.
- [Use Cases](https://serial-studio.com/help/use-cases.md): logic analyzers, scientific instruments, and bulk-endpoint devices.
- [Troubleshooting](https://serial-studio.com/help/troubleshooting.md): WinUSB, udev, and permission diagnostics.
- [Drivers: UART](https://serial-studio.com/help/drivers-uart.md): for USB-CDC virtual serial ports.
- [Drivers: HID](https://serial-studio.com/help/drivers-hid.md): for HID-class devices.
