Skip to main content

USB Client

USB Client turns a SITCore device into a USB peripheral — something that plugs into a PC, like a mouse, keyboard, joystick, mass-storage drive, or a custom device class. (The opposite role, where SITCore acts as the USB host driving connected peripherals, lives on the USB Host page.)

By default, the USB Client port is used by Visual Studio for application deployment and debugging. To free it for other purposes, switch the debug interface to serial using the MOD pin — see Special Pins. The debug interface can also be fully disabled as part of IP Protection.

NuGet package: GHIElectronics.TinyCLR.Devices.UsbClient — contains both the API and the built-in device drivers (mouse, keyboard, joystick, mass storage).

USB Mouse

Acts as a USB mouse, with both absolute and relative cursor modes.

  • Relative modeMoveCursor(dx, dy) moves the cursor by an offset from its current position. MoveCursor(10, 0) followed by MoveCursor(-10, 0) returns to the starting position.
  • Absolute modeMoveCursor(x, y) sets the cursor to that coordinate from the top-left corner of the screen.
using System;
using System.Threading;
using GHIElectronics.TinyCLR.Devices.UsbClient;

var usbclientController = UsbClientController.GetDefault();
var absolutePosition = true;
var mouse = new Mouse(usbclientController, absolutePosition);

mouse.DeviceStateChanged += UsbClientDeviceStateChanged;
mouse.Enable();

void UsbClientDeviceStateChanged(RawDevice sender, DeviceState state) {
var i = 0.0;
if (state == DeviceState.Configured) {
new Thread(() => {
while (true) {
((Mouse)sender).MoveCursor(
Mouse.MaxRange / 4 + (int)(Math.Cos(i) * Mouse.MaxRange / 10),
Mouse.MaxRange / 4 + (int)(Math.Sin(i) * Mouse.MaxRange / 10));
i += 0.03;
Thread.Sleep(50);
}
}).Start();
}
}

USB Keyboard

Acts as a USB keyboard. Each key supports Press, Release, and Stroke (a Press followed by a Release).

using System.Threading;
using GHIElectronics.TinyCLR.Devices.UsbClient;

var usbClientSetting = new UsbClientSetting() {
ManufactureName = "Manufacture_Name",
ProductName = "Product_Name",
SerialNumber = "serialnumber",
};

var usbclientController = UsbClientController.GetDefault();
var kb = new Keyboard(usbclientController, usbClientSetting);

var keys = new Key[] {
Key.G, Key.H, Key.I, Key.Space,
Key.E, Key.L, Key.E, Key.C, Key.T, Key.R, Key.O, Key.N, Key.I, Key.C, Key.S,
};

kb.Enable();

while (kb.DeviceState != DeviceState.Configured)
Thread.Sleep(100);

kb.Press(Key.LeftShift); // Hold shift to type uppercase.
for (var i = 0; i < keys.Length; i++) {
kb.Stroke(keys[i]);
Thread.Sleep(500); // Type twice a second.
}
kb.Release(Key.LeftShift);

USB Joystick

Acts as a USB joystick — axes plus buttons.

using GHIElectronics.TinyCLR.Devices.UsbClient;
using System.Threading;

var usbclientController = UsbClientController.GetDefault();

var usbClientSetting = new UsbClientSetting() {
ManufactureName = "Manufacture_Name",
ProductName = "Product_Name",
SerialNumber = "serialnumber",
};

var joystick = new Joystick(usbclientController, usbClientSetting);
joystick.DeviceStateChanged += UsbClientDeviceStateChanged;
joystick.Enable();

Thread.Sleep(Timeout.Infinite);

void UsbClientDeviceStateChanged(RawDevice sender, DeviceState state) {
if (state == DeviceState.Configured) {
new Thread(() => {
var joystick = (Joystick)sender;
while (true) {
joystick.PressButton(0);
Thread.Sleep(500);
joystick.ReleaseButton(0);
Thread.Sleep(1000);
}
}).Start();
}
}

USB Mass Storage

Acts as a USB mass-storage device, exposing on-board storage to a connected PC as a removable drive. Common use case: a data logger writes parameters to an SD card during operation, then when the USB cable is connected it stops logging and hands the SD card over to the PC for download.

The storage backing the mass-storage volume can be an SD card, the on-chip QSPI flash, or a USB thumb drive connected to the SITCore's USB Host port.

SD card

using GHIElectronics.TinyCLR.Devices.Storage;
using GHIElectronics.TinyCLR.Devices.UsbClient;
using GHIElectronics.TinyCLR.Pins;
using System.Diagnostics;

var sd = StorageController.FromName(FEZBit.StorageController.SdCard);

var usbclientController = UsbClientController.GetDefault();
var usbclient_masstorage = new MassStorage(usbclientController);

var ready = false;
usbclient_masstorage.DeviceStateChanged += (a, b) => {
Debug.WriteLine("state : " + b.ToString());

if (b == DeviceState.Configured)
ready = true;
};

usbclient_masstorage.AttachLogicalUnit(sd.Hdc);
usbclient_masstorage.Enable();

while (!ready) ;

// Wait a few seconds for the PC to mount the new drive.

QSPI

warning

USB Mass Storage on QSPI uses the entire 16 MB of QSPI flash. Once formatted by the PC, any data previously stored there is lost — including any external deployment binaries or Tiny File System data. Don't enable USB Mass Storage on QSPI if you're using QSPI for anything else.

using GHIElectronics.TinyCLR.Devices.Storage;
using GHIElectronics.TinyCLR.Devices.UsbClient;
using GHIElectronics.TinyCLR.Pins;
using System.Diagnostics;

var qspi = StorageController.FromName(SC20100.StorageController.QuadSpi);

var usbclientController = UsbClientController.GetDefault();
var usbclient_masstorage = new MassStorage(usbclientController);

var ready = false;
usbclient_masstorage.DeviceStateChanged += (a, b) => {
Debug.WriteLine("state : " + b.ToString());

if (b == DeviceState.Configured)
ready = true;
};

usbclient_masstorage.AttachLogicalUnit(qspi.Hdc);
usbclient_masstorage.Enable();

while (!ready) ;

// Wait a few seconds for the PC to mount the new drive.

USB thumb drive

A thumb drive connected to the SITCore's USB Host port can be exposed back through USB Client — effectively passing the thumb drive's storage through to the PC.

using GHIElectronics.TinyCLR.Devices.Storage;
using GHIElectronics.TinyCLR.Devices.UsbClient;
using GHIElectronics.TinyCLR.Devices.UsbHost;
using GHIElectronics.TinyCLR.Pins;
using System.Diagnostics;

var usbHostController = UsbHostController.GetDefault();
StorageController storageController = null;
var usbHostReady = false;

usbHostController.OnConnectionChangedEvent += (a, b) => {
switch (b.DeviceStatus) {
case DeviceConnectionStatus.Connected:
switch (b.Type) {
case BaseDevice.DeviceType.MassStorage:
storageController = StorageController.FromName(SC20260.StorageController.UsbHostMassStorage);
usbHostReady = true;
break;
}
break;
}
};

usbHostController.Enable();
while (!usbHostReady) ;

var usbclientController = UsbClientController.GetDefault();
var usbclient_masstorage = new MassStorage(usbclientController);

var ready = false;
usbclient_masstorage.DeviceStateChanged += (a, b) => {
Debug.WriteLine("state : " + b.ToString());

if (b == DeviceState.Configured)
ready = true;
};

usbclient_masstorage.AttachLogicalUnit(storageController.Hdc);
usbclient_masstorage.Enable();

while (!ready) ;

// Wait a few seconds for the PC to mount the new drive.

PC data transfer

For serial-style two-way communication with a connected PC (the device shows up as a virtual COM port or a WinUSB endpoint), see USB PC Comm.

USB Raw

For advanced cases — any USB device class not provided as a built-in driver — you can build a fully custom USB device with USB Raw. The built-in mouse driver inside GHIElectronics.TinyCLR.Devices.UsbClient is a good reference implementation.

API reference

NamespaceDescription
GHIElectronics.TinyCLR.Devices.UsbClientUSB device (client) profile classes