NanoKVM-USB Driver¶
jumpstarter-driver-nanokvm-usb provides KVM (Keyboard, Video, Mouse) control for
NanoKVM-USB devices connected directly
to the exporter host over USB.
Unlike a network-based NanoKVM driver, this package talks to the hardware through:
USB Serial (default 57600 baud) for keyboard and mouse HID reports
UVC (USB video class) for HDMI capture as a standard camera device
Features¶
Video capture: Snapshots and live JPEG frame streams from the UVC device
Keyboard control: Paste text and press keys via serial HID
Mouse control: Absolute and relative movement, clicks, and scrolling
VNC: Embedded RFB server (view the captured HDMI and control HID from noVNC/TigerVNC)
Composite driver: Access video, HID, and VNC through a unified
NanoKVMUSBinterface
Installation¶
$ pip3 install --extra-index-url https://pkg.jumpstarter.dev/simple jumpstarter-driver-nanokvm-usb
Configuration¶
Basic configuration¶
export:
nanokvm-usb:
type: jumpstarter_driver_nanokvm_usb.driver.NanoKVMUSB
config:
serial_port: "/dev/ttyACM0"
baud_rate: 57600
video_device: "/dev/v4l/by-path/pci-0000:00:14.0-usbv2-0:3.4.3:1.0-video-index0"
video_width: 1920
video_height: 1080
video_fps: 30
screen_width: 1920
screen_height: 1080
vnc_enabled: true
# vnc_layout: es # DUT keyboard layout (default us)
# vnc_password: "secret"
# vnc_tcp_port: 5900
# vnc_tcp_bind: "0.0.0.0" # LAN; VncAuth is not TLS
# vnc_max_clients: 2
Config parameters¶
Parameter |
Description |
Type |
Required |
Default |
|---|---|---|---|---|
serial_port |
Serial device path for HID |
str |
yes |
|
baud_rate |
Serial baud rate |
int |
no |
57600 |
video_device |
OpenCV camera index or device path |
int/str |
no |
0 |
video_width |
Requested capture width |
int |
no |
1920 |
video_height |
Requested capture height |
int |
no |
1080 |
video_fps |
Capture rate for |
int |
no |
30 |
screen_width |
Target screen width for relative mouse moves |
int |
no |
1920 |
screen_height |
Target screen height for relative mouse moves |
int |
no |
1080 |
vnc_enabled |
Start an embedded RFB server (Unix socket child |
bool |
no |
false |
vnc_password |
VNC password (VncAuth). Empty/None = no authentication |
str |
no |
|
vnc_tcp_port |
Also bind RFB TCP on the exporter ( |
int |
no |
|
vnc_tcp_bind |
Address for |
str |
no |
127.0.0.1 |
vnc_encrypt |
Default noVNC |
bool |
no |
false |
vnc_layout |
DUT keyboard layout for VNC character injection ( |
str |
no |
us |
vnc_max_clients |
Maximum simultaneous RFB clients |
int |
no |
2 |
Architecture¶
The driver is a composite with video and HID children, plus an optional VNC
child when vnc_enabled is true:
video: UVC snapshot capture and live frame streaming
hid: Keyboard and mouse control over USB serial
vnc: Unix-socket RFB endpoint (noVNC / any VNC client), opt-in
Video stream and VNC share a single capture pump so /dev/video* is opened once.
Keyboard and mouse events from the VNC client are translated to the same HID path as hid.
The children share a single NanoKVMUSBDevice instance on the exporter so the
serial port and camera are opened once.
Video streaming¶
The stream() driver method is exposed as a Jumpstarter stream (not a regular
RPC call). Video does not go to a fixed URL on the exporter; it is tunneled over
the Jumpstarter connection to whichever client opens the stream.
Lifecycle¶
A client calls
video.stream("stream")(context manager) oropen_stream().The exporter’s shared FramePump already captures JPEG frames from UVC; the stream task forwards those frames to the client.
The client reads frames with
stream.receive()— each message is one JPEG.When the client closes the context (or calls
close()), the exporter stops the stream task. Capture continues if VNC or another stream is still using the pump.
HID commands remain available on the hid child during streaming and VNC.
For recording, OCR, frame deduplication, and preprocessing without blocking
jmp shell, use edge-clearance-delivery/video-receiver/ (stream-bridge.py +
video-receiver.py).
Client examples¶
Single frame via snapshot:
image = lease.drivers["nanokvm-usb"].video.snapshot()
image.save("screen.jpg")
Low-level stream access (raw JPEG bytes):
video = lease.drivers["nanokvm-usb"].video
with video.stream("stream") as stream:
while True:
frame_jpeg = stream.receive()
VNC¶
Set vnc_enabled: true to start the embedded RFB server (disabled by default).
The exporter runs an RFB 3.8 server on a Unix socket. Jumpstarter tunnels that
socket to the client (same pattern as QEMU): you do not need to be on the
exporter host. Keyboard and mouse in the VNC client go to the NanoKVM-USB HID.
From the Jumpstarter client (any machine with a lease):
j nanokvm-usb vnc session
That opens noVNC against a TCP/WebSocket port on your machine. For a native viewer (TigerVNC, Remmina) on the client:
j nanokvm-usb vnc forward-tcp 5900
# then connect to localhost:5900
Or from Python:
with lease.drivers["nanokvm-usb"].session() as url:
print(url) # noVNC URL
TCP on the exporter (optional): set vnc_tcp_port to bind RFB on the exporter
host. Default vnc_tcp_bind is 127.0.0.1 (local viewers on that machine only).
Use vnc_tcp_bind: "0.0.0.0" to accept LAN clients without a Jumpstarter tunnel.
A non-loopback bind is reachable on the network even with vnc_password: VncAuth
is not TLS. vnc_max_clients defaults to 2.
Printable keys are injected as HID combos for vnc_layout (the DUT OS
keyboard), not the VNC client’s layout. Default is us. Set vnc_layout: es
if the DUT uses a Spanish keyboard so @, ñ, and AltGr characters land
correctly even when Remmina is using another layout. Only us and es are
built in; extra layout tables in vnc_keymap.py are welcome as pull requests.
API reference¶
NanoKVMUSBClient¶
Composite client with video, hid, and vnc children.
NanoKVMUSBVideoClient¶
- class jumpstarter_driver_nanokvm_usb.client.NanoKVMUSBVideoClient¶
Client interface for NanoKVM-USB video capture.
NanoKVMUSBHIDClient¶
- class jumpstarter_driver_nanokvm_usb.client.NanoKVMUSBHIDClient¶
Client interface for NanoKVM-USB HID control.
NanoKVMUSBVNCClient¶
- class jumpstarter_driver_nanokvm_usb.client.NanoKVMUSBVNCClient¶
Client for the embedded RFB endpoint (noVNC session).
CLI usage¶
# Snapshot
j nanokvm-usb video snapshot
# Keyboard
j nanokvm-usb hid paste "Hello, World!"
j nanokvm-usb hid press enter
# Mouse
j nanokvm-usb hid mouse move 0.5 0.5
j nanokvm-usb hid mouse click --button left --x 0.5 --y 0.5
# VNC (view + HID) via Jumpstarter tunnel
j nanokvm-usb vnc session
j nanokvm-usb vnc forward-tcp 5900
Host requirements¶
The exporter must run on the machine where the NanoKVM-USB is plugged in.
Linux permissions¶
Add your user to the dialout group for serial port access:
sudo usermod -a -G dialout $USER
On Arch Linux, use the uucp group instead. Log out and back in after changing
group membership.
Finding devices¶
Serial port (Linux): typically /dev/ttyACM0 or /dev/ttyUSB0
Video device: OpenCV camera index or /dev/video*
from jumpstarter_driver_nanokvm_usb.video import VideoCapture
for device in VideoCapture.list_devices():
print(device)
Differences from the network NanoKVM driver¶
Feature |
NanoKVM (network) |
NanoKVM-USB |
|---|---|---|
Connection |
HTTP/WebSocket |
USB serial + UVC |
Video stream |
MJPEG from device API |
UVC capture on exporter host |
Virtual disk/CD-ROM |
Yes |
No |
Device reboot |
Yes |
No |
Auth |
Username/password |
None (local USB) |