- TesterDriver interface: Connect/Read/Disconnect - StreamingTesterDriver interface: embeds TesterDriver, adds Stream() - TestResult struct: CableType, versions, speed, power, continuity, eMarker, resistance - LiveReading struct: Voltage, CurrentAmps, PowerWatts, PDProtocol, Timestamp - MockUSBDriver: deterministic USB 3.2 Gen 2 result, ErrNotConnected guard - MockDPDriver: deterministic DP 1.4 result - MockHDMIDriver: deterministic HDMI 2.1 result - MockFNB58Driver: 3 LiveReading samples at 100ms, context-cancelled via Disconnect() - KnownDevices: 4 RoleCableTester placeholder entries (dead0:0001-0004)
82 lines
2.7 KiB
Go
82 lines
2.7 KiB
Go
package usb
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
)
|
|
|
|
// DeviceRole classifies what a USB device is used for in HWLab.
|
|
type DeviceRole int
|
|
|
|
const (
|
|
RolePrinter DeviceRole = iota
|
|
RoleCableTester // reserved for Phase 5
|
|
RoleUnknown
|
|
)
|
|
|
|
// DeviceSpec describes a known USB peripheral by VID and PID.
|
|
type DeviceSpec struct {
|
|
VID string // 4-hex-digit vendor ID, e.g. "0525"
|
|
PID string // 4-hex-digit product ID, e.g. "a4a7"
|
|
Name string // human-readable label for logs
|
|
Role DeviceRole
|
|
BaudRate int // serial baud rate; 0 means use 9600 default
|
|
}
|
|
|
|
// VIDPID returns the canonical "VID:PID" key string.
|
|
func (s DeviceSpec) VIDPID() string { return s.VID + ":" + s.PID }
|
|
|
|
// String returns "VID:PID (Name)" format for logging.
|
|
func (s DeviceSpec) String() string { return s.VIDPID() + " (" + s.Name + ")" }
|
|
|
|
// KnownDevices maps "VID:PID" to DeviceSpec for all peripherals HWLab manages.
|
|
// Update VID/PID values after hardware characterization on 2026-04-13.
|
|
var KnownDevices = map[string]DeviceSpec{
|
|
"0525:a4a7": {VID: "0525", PID: "a4a7", Name: "PRT Qutie", Role: RolePrinter, BaudRate: 9600},
|
|
// TODO(hardware): Replace placeholder VID:PIDs after characterization 2026-04-13
|
|
"dead0:0001": {VID: "dead0", PID: "0001", Name: "Treedix USB Tester", Role: RoleCableTester, BaudRate: 115200},
|
|
"dead0:0002": {VID: "dead0", PID: "0002", Name: "Treedix DP Tester", Role: RoleCableTester, BaudRate: 115200},
|
|
"dead0:0003": {VID: "dead0", PID: "0003", Name: "Treedix HDMI Tester", Role: RoleCableTester, BaudRate: 115200},
|
|
// TODO(hardware): BaudRate 0 = HID protocol — replace VID:PID after characterization
|
|
"dead0:0004": {VID: "dead0", PID: "0004", Name: "FNIRSI FNB58", Role: RoleCableTester, BaudRate: 0},
|
|
}
|
|
|
|
// DeviceState represents the current connection status of a managed device.
|
|
type DeviceState int
|
|
|
|
const (
|
|
StateDisconnected DeviceState = iota
|
|
StateConnected
|
|
)
|
|
|
|
// DeviceEvent is emitted on the Manager.Events() channel for any state change.
|
|
type DeviceEvent struct {
|
|
VIDPID string
|
|
Spec DeviceSpec
|
|
State DeviceState
|
|
}
|
|
|
|
// Command is sent to a device goroutine via its command channel.
|
|
type Command struct {
|
|
Type CommandType
|
|
Payload []byte
|
|
Reply chan<- error // caller closes or receives result
|
|
}
|
|
|
|
// CommandType discriminates Command variants.
|
|
type CommandType int
|
|
|
|
const (
|
|
CmdWrite CommandType = iota
|
|
CmdClose
|
|
)
|
|
|
|
// ParseVIDPID splits a "VID:PID" string into its constituent parts.
|
|
// Returns an error if the format is not exactly "xxxx:xxxx".
|
|
func ParseVIDPID(s string) (vid, pid string, err error) {
|
|
parts := strings.SplitN(s, ":", 2)
|
|
if len(parts) != 2 || parts[0] == "" || parts[1] == "" {
|
|
return "", "", errors.New("invalid VID:PID format: expected \"xxxx:xxxx\", got " + s)
|
|
}
|
|
return parts[0], parts[1], nil
|
|
}
|