-
Notifications
You must be signed in to change notification settings - Fork 36
Nanokvm usb api driver #1089
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
mparram
wants to merge
4
commits into
jumpstarter-dev:main
Choose a base branch
from
mparram:nanokvm-usb-api-driver
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Nanokvm usb api driver #1089
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
0be977e
add driver nanokvm-usb
mparram e05c775
nanokvm-usb: USB KVM driver with live video stream and HID control
3a0a3fc
fix(nanokvm-usb): address PR review (resources, HID, MJPEG, docs)
bccd9c6
fix(nanokvm-usb): resolve v4l2-ctl before starting reader thread
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
191 changes: 191 additions & 0 deletions
191
docs/source/reference/package-apis/drivers/nanokvm-usb.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,191 @@ | ||
| # NanoKVM-USB Driver | ||
|
|
||
| `jumpstarter-driver-nanokvm-usb` provides KVM (Keyboard, Video, Mouse) control for | ||
| [NanoKVM-USB](https://github.com/sipeed/NanoKVM-USB) devices connected directly | ||
| to the exporter host over USB. | ||
|
|
||
| Unlike the network-based [NanoKVM](nanokvm.md) 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 | ||
| - **Composite driver**: Access video and HID through a unified `NanoKVMUSB` interface | ||
|
|
||
| ## Installation | ||
|
|
||
| ```{code-block} console | ||
| :substitutions: | ||
| $ pip3 install --extra-index-url {{index_url}} jumpstarter-driver-nanokvm-usb | ||
| ``` | ||
|
|
||
| ## Configuration | ||
|
|
||
| ### Basic configuration | ||
|
|
||
| ```yaml | ||
| export: | ||
| nanokvm-usb: | ||
| type: jumpstarter_driver_nanokvm_usb.driver.NanoKVMUSB | ||
| config: | ||
| serial_port: "/dev/ttyACM0" | ||
| baud_rate: 57600 | ||
| # Stable UVC path (survives /dev/videoN renumbering); or use an index: 0 | ||
| 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 | ||
| ``` | ||
|
|
||
| ### 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 | UVC device index or path (e.g. `/dev/v4l/by-path/...`) | int/str | no | 0 | | ||
| | video_width | Requested capture width | int | no | 1920 | | ||
| | video_height | Requested capture height | int | no | 1080 | | ||
| | video_fps | Target capture/stream rate (`0` = no stream sleep throttle) | int | no | 30 | | ||
| | video_format | `mjpeg_passthrough` or `jpeg` (OpenCV re-encode) | str | no | mjpeg_passthrough | | ||
| | video_jpeg_quality | JPEG quality when `video_format=jpeg` (1–100) | int | no | 95 | | ||
| | video_discard_stale | Frames to drop before each capture (freshness) | int | no | 1 | | ||
| | video_stream_buffer_size | Max buffered frames in exported `stream()` | int | no | 32 | | ||
| | v4l2_ctl_executable | Path to `v4l2-ctl` for MJPEG passthrough; default: `PATH` lookup | str | no | (auto) | | ||
| | screen_width | Target screen width for relative mouse moves | int | no | 1920 | | ||
| | screen_height | Target screen height for relative mouse moves | int | no | 1080 | | ||
|
|
||
| MJPEG passthrough requires `v4l-utils` (`v4l2-ctl`) on the exporter host. | ||
|
|
||
| ## Architecture | ||
|
|
||
| The driver is a composite with two child interfaces: | ||
|
|
||
| 1. **video**: UVC snapshot capture and live frame streaming | ||
| 2. **hid**: Keyboard and mouse control over USB serial | ||
|
|
||
| Both 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 | ||
|
|
||
| 1. A client calls `video.stream("stream")` (context manager) or `open_stream()`. | ||
| 2. The exporter starts an async task that captures JPEG frames from UVC and sends | ||
| them through the stream. | ||
| 3. The client reads frames with `stream.receive()` — each message is one JPEG. | ||
| 4. When the client closes the context (or calls `close()`), the exporter stops | ||
| capturing and releases the stream. | ||
|
|
||
| While the stream is active, the exporter dedicates a background task to video | ||
| capture. This does **not** block the whole exporter process (it is async), but it | ||
| does keep the UVC device busy until the client disconnects. HID commands remain | ||
| available on the `hid` child during streaming. | ||
|
|
||
| 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: | ||
|
|
||
| ```python | ||
| image = lease.drivers["nanokvm-usb"].video.snapshot() | ||
| image.save("screen.jpg") | ||
| ``` | ||
|
|
||
| Low-level stream access (raw JPEG bytes): | ||
|
|
||
| ```python | ||
| video = lease.drivers["nanokvm-usb"].video | ||
|
|
||
| with video.stream("stream") as stream: | ||
| while True: | ||
| frame_jpeg = stream.receive() | ||
| ``` | ||
|
|
||
| ## API reference | ||
|
|
||
| ### NanoKVMUSBClient | ||
|
|
||
| Composite client with `video` and `hid` children. | ||
|
|
||
| ### NanoKVMUSBVideoClient | ||
|
|
||
| ```{eval-rst} | ||
| .. autoclass:: jumpstarter_driver_nanokvm_usb.client.NanoKVMUSBVideoClient() | ||
| :members: snapshot | ||
| ``` | ||
|
|
||
| ### NanoKVMUSBHIDClient | ||
|
|
||
| ```{eval-rst} | ||
| .. autoclass:: jumpstarter_driver_nanokvm_usb.client.NanoKVMUSBHIDClient() | ||
| :members: paste_text, press_key, reset_hid, mouse_move_abs, mouse_move_rel, mouse_click, mouse_scroll | ||
| ``` | ||
|
|
||
| ## CLI usage | ||
|
|
||
| ```bash | ||
| # 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 | ||
| ``` | ||
|
|
||
| ## 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: | ||
|
|
||
| ```bash | ||
| 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*` | ||
|
|
||
| ```python | ||
| 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) | | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| __pycache__/ | ||
| .coverage | ||
| coverage.xml |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| # NanoKVM-USB Driver | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please put the contents from the .md you created in the docs file here in this file. Then remove the .md on the docs directory, and link it to this readme, this is how the other drivers do it. |
||
| `jumpstarter-driver-nanokvm-usb` provides KVM (keyboard, video, mouse) for | ||
| [NanoKVM-USB](https://github.com/sipeed/NanoKVM-USB) devices on the exporter host | ||
| (USB serial HID + UVC). | ||
|
|
||
| Full documentation lives in the Jumpstarter docs: | ||
| [NanoKVM-USB driver](https://github.com/jumpstarter-dev/jumpstarter/blob/main/docs/source/reference/package-apis/drivers/nanokvm-usb.md) | ||
| (`docs/source/reference/package-apis/drivers/nanokvm-usb.md`). | ||
|
|
||
| ## Installation | ||
|
|
||
| ```shell | ||
| pip3 install --extra-index-url https://pkg.jumpstarter.dev/simple/ jumpstarter-driver-nanokvm-usb | ||
| ``` | ||
19 changes: 19 additions & 0 deletions
19
python/packages/jumpstarter-driver-nanokvm-usb/examples/exporter.yaml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,19 @@ | ||
| apiVersion: jumpstarter.dev/v1alpha1 | ||
| kind: ExporterConfig | ||
| metadata: | ||
| namespace: default | ||
| name: demo | ||
| endpoint: grpc.jumpstarter.example.com:8082 | ||
| token: "<token>" | ||
| export: | ||
| nanokvm-usb: | ||
| type: jumpstarter_driver_nanokvm_usb.driver.NanoKVMUSB | ||
| config: | ||
| serial_port: "/dev/ttyACM0" | ||
| baud_rate: 57600 | ||
| video_device: 0 | ||
| video_width: 1920 | ||
| video_height: 1080 | ||
| video_fps: 30 | ||
| screen_width: 1920 | ||
| screen_height: 1080 |
13 changes: 13 additions & 0 deletions
13
python/packages/jumpstarter-driver-nanokvm-usb/jumpstarter_driver_nanokvm_usb/__init__.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| from .client import NanoKVMUSBClient, NanoKVMUSBHIDClient, NanoKVMUSBVideoClient | ||
| from .driver import NanoKVMUSB, NanoKVMUSBHID, NanoKVMUSBVideo | ||
| from .mouse import MouseButton | ||
|
|
||
| __all__ = [ | ||
| "NanoKVMUSB", | ||
| "NanoKVMUSBVideo", | ||
| "NanoKVMUSBHID", | ||
| "NanoKVMUSBClient", | ||
| "NanoKVMUSBVideoClient", | ||
| "NanoKVMUSBHIDClient", | ||
| "MouseButton", | ||
| ] |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please copy this file content to python/packages/jumpstarter-driver-nanokvm-usb/README.md and then create a symlink from docs/source/reference/package-apis/drivers/nanokvm-usb.md to python/packages/jumpstarter-driver-nanokvm-usb/README.md
That's what we do with all the drivers.