Skip to main content

USB

USB Logo

Endpoint uses USB in two ways: the USB-C connection to your PC is the debug and deploy channel (no user code involved, the IDE drives it), and a separate USB host port supports standard USB peripherals like keyboards, mice, joysticks, printers and mass-storage drives.

USB host: detecting devices​

Open the host controller, subscribe to ConnectionChanged, and Enable() it. The event fires for every device plugged in now and in the future (and again when a device is unplugged). The devices already connected at Enable() time are reported too.

using GHIElectronics.Endpoint.Core;
using GHIElectronics.Endpoint.Devices.UsbHost;

var usb = UsbHostController.GetDefault();

usb.ConnectionChanged += (sender, e) => {
Console.WriteLine($"{e.DeviceStatus} id={e.Id} type={e.Type} name={e.DeviceName}");
Console.WriteLine($" VID={e.VendorId:X4} PID={e.ProductId:X4} '{e.Manufacturer}' '{e.Product}'");
};

usb.Enable();

e.Type is a DeviceType value (Hub, Keyboard, Mouse, Joystick, MassStorage, Printer, Serial, Webcam, Audio, Network, Bluetooth, Touch, HID, Unknown); use it to decide what to open the device with. e.DeviceName is the string you pass to the device-specific class ("/dev/input/event1", "/dev/ttyUSB0", etc.).

One USB device may show up as several types. A webcam with a microphone fires both Webcam and Audio, and a keyboard with a built-in touchpad fires both Keyboard and Mouse. Handle each as a separate event.

Keyboards, mice, joysticks​

Each peripheral type has a small wrapper class in GHIElectronics.Endpoint.Devices.UsbHost. Create one from the DeviceName the ConnectionChanged event gave you.

usb.ConnectionChanged += (sender, e) => {
if (e.DeviceStatus != DeviceConnectionStatus.Connected) return;

switch (e.Type) {
case DeviceType.Keyboard:
var kb = new Keyboard(e.DeviceName);
kb.CharDown += (s, a) => Console.Write(a.Ascii);
kb.KeyDown += (s, a) => { if (a.Which == Key.Escape) Console.WriteLine("Esc"); };
break;

case DeviceType.Mouse:
var mouse = new Mouse(e.DeviceName);
mouse.SetCursorBounds(new Position { X = 0, Y = 0 },
new Position { X = 799, Y = 479 });
mouse.CursorMoved += (s, a) => Console.WriteLine($"({a.NewPosition.X}, {a.NewPosition.Y})");
mouse.ButtonChanged += (s, a) => Console.WriteLine($"{a.Which} {a.State}");
break;

case DeviceType.Joystick:
var joy = new Joystick(e.DeviceName);
joy.CursorMoved += (s, a) => Console.WriteLine($"{a.Which} at {a.NewPosition.X}, {a.NewPosition.Y}");
joy.ButtonChanged += (s, a) => Console.WriteLine($"Button {a.Which} {a.State}");
joy.HatSwitchPressed += (s, a) => Console.WriteLine($"Hat {a.Direction}");
break;
}
};

Each class delivers its events on its own thread.

USB mass storage​

Files on USB drives are handled through the File System page, not through UsbHostController. The short version: open a StorageController.FromName(EPDomino24.StorageController.UsbHostMassStorage), subscribe to its ConnectionChanged, and call FileSystem.Mount(e.Hdc) when a drive connects to get the /media/usbN/ folder you can read and write with standard System.IO.

See File System for the full example.

Printers, serial adapters, raw HID​

  • Printer (DeviceType.Printer): open with new Printer(e.DeviceName).
  • Serial adapter (DeviceType.Serial): the kernel exposes it as a standard serial port; open with new System.IO.Ports.SerialPort(e.DeviceName).
  • Unknown / specialty devices (DeviceType.Unknown, DeviceType.HID): use new HidDevice(e.DeviceName) for a raw HID report stream, or new RawDevice(e.DeviceName) for raw control transfers to any USB device without a standard driver.