Streams H.264 to the Galahad II LCD via USB (gousb) with: - ffmpeg CLI transcoding (no fragile FFmpeg C-ABI bindings) - pure-Go Annex-B access-unit splitting - framerate pacing with graceful shutdown and USB reconnect - TOML config, cobra CLI, structured slog logging, unit tests
58 lines
1.4 KiB
Go
58 lines
1.4 KiB
Go
package device
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/google/gousb"
|
|
)
|
|
|
|
// Info describes a USB device for the diagnostics listing.
|
|
type Info struct {
|
|
VendorID int
|
|
ProductID int
|
|
Manufacturer string
|
|
Product string
|
|
Serial string
|
|
Bus int
|
|
Address int
|
|
IsLCD bool
|
|
}
|
|
|
|
// ListDevices enumerates all USB devices visible to libusb. Descriptor
|
|
// strings are best-effort: reading them requires device access, which is
|
|
// why failures are ignored.
|
|
func ListDevices(ctx context.Context) ([]Info, error) {
|
|
gctx := gousb.NewContext()
|
|
defer gctx.Close()
|
|
|
|
devs, err := gctx.OpenDevices(func(*gousb.DeviceDesc) bool { return true })
|
|
if err != nil && len(devs) == 0 {
|
|
return nil, fmt.Errorf("enumerate USB devices (run as root or install the udev rule): %w", err)
|
|
}
|
|
defer func() {
|
|
for _, d := range devs {
|
|
_ = d.Close()
|
|
}
|
|
}()
|
|
|
|
infos := make([]Info, 0, len(devs))
|
|
for _, d := range devs {
|
|
info := Info{
|
|
VendorID: int(d.Desc.Vendor),
|
|
ProductID: int(d.Desc.Product),
|
|
Bus: d.Desc.Bus,
|
|
Address: d.Desc.Address,
|
|
IsLCD: d.Desc.Vendor == gousb.ID(0x0416) && d.Desc.Product == gousb.ID(0x7395),
|
|
}
|
|
if info.IsLCD {
|
|
// Only read strings for the device we care about.
|
|
info.Manufacturer, _ = d.Manufacturer()
|
|
info.Product, _ = d.Product()
|
|
info.Serial, _ = d.SerialNumber()
|
|
}
|
|
infos = append(infos, info)
|
|
}
|
|
return infos, err
|
|
}
|