Skip to main content

Serial KVM Controller (CH9329 and CH9350L)

PyPI License: MIT Black Run Tests codecov

A Software KVM for UART-to-USB-HID bridge chips (CH9329 and CH9350L).

Control your computers using an emulated keyboard and mouse!

This app and python module allows you to control a second device using a UART-to-USB-HID bridge chip (CH9329 or CH9350L) and a video capture device. You can find these from vendors on eBay and AliExpress for a low price. However, there is very little software support available for these modules, and protocol documentation is sparse.

This software captures keyboard and mouse inputs from the local computer, sending these over a serial UART connection to the bridge chip, which will output USB HID mouse and keyboard movements and scan codes to the remote computer.

The kvm_serial package provides options for running the GUI, or as a script providing flexible options.

App icon


Download the latest release for Windows, Mac or Linux.

See INSTALLATION.md for information on installing serial drivers, if required.

GUI Usage

Run the GUI using the executable for your platform, or with Python using python -m kvm_serial.

KVM Window The Serial KVM window running on OSX, controlling a Windows remote machine

The module can be installed from PyPI (pip install kvm-serial), or locally from a cloned git repo (pip install -e .).

The GUI app will do a lot of the work for you: it will enumerate video devices and serial ports, and give you a window to interact with the guest in. Application settings can be changed from the menus (File, Options, View), for example if the app doesn't select the correct devices by default.

kvm-serial supports both CH9329 and CH9350L bridge hardware. See the user guides for hardware-specific setup:

Kit List

This module requires a little bit of hardware to get going. You will need:

  • A UART-to-USB-HID bridge chip (CH9329 or CH9350L) — optionally with an assembled cable or module
  • Video capture card (e.g. HDMI)

You can likely get everything you need for under £30, which is incredible when compared to the price of a KVM crash cart adapter.

Bridge Module/Cable

PLEASE NOTE: I am a hobbyist. I have no affiliation with any manufacturer developing or selling bridge hardware.

Home-made serial KVM module A home-made serial KVM module: CH9329 module soldered to SILabs CP2102. CH340 works, too.

Pre-assembled cables and modules are available from eBay and AliExpress:

  • CH9329 cables: Search for "CH9329 cable usb". Just make sure it has "CH9329" in the name; a USB-A to USB-A cable won't do and can damage your machine. See the CH9329 User Guide for full hardware and wiring details.
  • CH9350L modules: Less common than CH9329 but available; typically come as breakout boards with serial connector and dipswitches. See the CH9350L User Guide for dipswitch configuration and working state selection.

You can build your own by soldering a bridge chip to a UART transceiver chip (e.g. SILabs CP2102 or CH340).

Video Capture Card

You also need a capture card that takes the display output from your remote machine and presents it as a USB device to your local system. The "UGREEN Video Capture Card HDMI to USB C Capture Device" was a good balance of price versus value. The more you spend on a capture device, the more responsive your video feed will likely be (to a point). HDMI and VGA hardware is available.

Installing Python Dependencies

Note: These instructions are not required if using the executables, but you may need to do some other setup. See INSTALLATION.md for information on installing serial drivers.

Standard installation (running the application from pip):

# OPTIONAL: Create and activate a Virtual environment
python -m venv ./.venv
./.venv/scripts/activate

# Install the module from PyPI and run the GUI
pip install kvm-serial
python -m kvm-serial

OR using uv package manager (a faster alternative to pip, if available):
Note: uv run may not work on Windows. See #15.

uv run kvm-gui

Install from source (for development- includes PyInstaller for building executables, pytest for testing, etc.):

pip install -e ".[dev]"

Script Usage

A script called control.py is also provided for use directly from the terminal, so you can also control remotes from a headless environment! (e.g. Pi to Pi!)

Packages must be installed first. Use your preferred python package manager, e.g. pip, uv

Usage examples for the control.py script:

# Run using module
python -m kvm_serial.control

# Run using `uv`
uv run kvm-control

# Run with mouse and video support; use a Mac OSX serial port:
python -m kvm_serial.control -e /dev/cu.usbserial-A6023LNH

# Run the script using keyboard 'tty' mode (no mouse, no video)
python control.py --mode tty /dev/tty.usbserial0

# Run using `pyusb` keyboard mode (which requires root):
sudo python control.py --mode usb /dev/tty.usbserial0

# Increase logging using --verbose (or -v), and use COM1 serial port (Windows)
python control.py --verbose COM1

# Use CH9350L in state 3 (absolute mouse — recommended for desktop use)
python control.py --ch9350 --ch9350-state 3 /dev/cu.usbserial-XXXX

# Use CH9350L in state 2 (BIOS keyboard + relative mouse — for BIOS/UEFI use)
python control.py --ch9350 --ch9350-state 2 /dev/cu.usbserial-XXXX

# Use CH9350L in state 0 (full descriptor handshake)
python control.py --ch9350 --ch9350-state 0 /dev/cu.usbserial-XXXX

Use python control.py --help to view all available options. By default, the CH9329 protocol is used; pass --ch9350 to switch to CH9350L protocol. See the CH9329 User Guide and CH9350L User Guide for hardware-specific setup and usage.

Mouse capture is provided using the parameter --mouse (-e). Appropriate system permissions (Privacy and Security) may be required on macOS.

For live video, use the GUI (kvm-gui). See MODES.md for keyboard capture mode options.

Troubleshooting

Permissions errors on Linux: if your system user does not have serial write permissions (resulting in a permission error), you can add your user to the dialout group: e.g. sudo usermod -a -G dialout $USER. You must fully log out of the system to apply the change.

Difficulty installing requirements: If you get command not found: pip or similar when installing requirements, try: python -m pip [...] to run pip instead.

Acknowledgements

With thanks to @beijixiaohu, the author of the ch9329Comm PyPi package and GitHub repo (in Chinese), some code of which is re-used under the MIT License.

Thank you, once again, to everyone who has contributed to this project.

License

(c) 2023-26 Samantha Finnigan and contributors (except where acknowledged) and released under MIT License.

Metadata

Release files for kvm-serial 1.5.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kvm-serial 1.5.6
File Size Uploaded
kvm_serial-1.5.6.tar.gz 64.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for kvm-serial 1.5.6
File Interpreter ABI Platform
kvm_serial-1.5.6-py3-none-any.whl Python 3 none any Details

Total release size: 132.9 kB

Release files / kvm_serial-1.5.6.tar.gz

Download URL kvm_serial-1.5.6.tar.gz
Size 64.1 kB
Tags Source
SHA-256 checksum
How to use checksums
59aa5f1319c64e7008487c8cd3e8e18c822910d20618bf45b960e477cd7a2246
BLAKE2b-256 checksum
How to use checksums
d7c16f37fce2743984dcf3276759240c5f66baddec245ee19e6f92e7fbd6a88e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 10, 2026.

Transparency log

Release files / kvm_serial-1.5.6-py3-none-any.whl

Download URL kvm_serial-1.5.6-py3-none-any.whl
Size 68.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
08ce8bf401c280932c78435a8da62f2b35fd9dfc99457bc166926d0deaad51af
BLAKE2b-256 checksum
How to use checksums
05df16e8cbad32aa0e533836d391f5e74e91e50d0a6dd699adae5c28cd3922ef
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 10, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

1.5.6 This release

2 release files

1.5.5

2 release files

1.5.4

2 release files

1.5.3

2 release files

1.5.2

2 release files

1.5.1

2 release files

1.5.0

2 release files

1.4.2

2 release files

1.4.1

2 release files

1.4.0

2 release files

1.3.0

1 release file

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page