Skip to content

Commit 573d930

Browse files
authored
Add MkDocs documentation site with GitHub Pages deployment
Merge pull request #28 from sjmf/6-github-pages
2 parents ae90d00 + 6233a5e commit 573d930

File tree

8 files changed

+596
-1
lines changed

8 files changed

+596
-1
lines changed

.github/workflows/docs.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Documentation
2+
3+
on:
4+
push:
5+
branches: [main]
6+
paths:
7+
- 'docs/**'
8+
- 'mkdocs.yml'
9+
- 'README.md'
10+
- 'CONTRIBUTING.md'
11+
workflow_dispatch:
12+
13+
permissions:
14+
contents: write
15+
16+
jobs:
17+
deploy:
18+
name: Build and deploy documentation
19+
runs-on: ubuntu-latest
20+
steps:
21+
- uses: actions/checkout@v4
22+
23+
- uses: actions/setup-python@v4
24+
with:
25+
python-version: '3.10'
26+
cache: 'pip'
27+
28+
- name: Install MkDocs and Material theme
29+
run: pip install mkdocs-material
30+
31+
- name: Deploy to GitHub Pages
32+
run: mkdocs gh-deploy --force

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ kvm.dist
1818
uv.lock
1919
.venv/
2020

21+
# MkDocs build output
22+
site/
23+
2124
# Icon generation intermediate files
2225
assets/icon.iconset/
2326
assets/icon_*.png

docs/CONTRIBUTING.md

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
# Contributing to KVM Serial
2+
3+
Firstly, thank you for taking the time to contribute! I really appreciate it. ❤️
4+
5+
This guide outlines how to contribute to the KVM Serial project, and helps ensure a smooth experience for everyone involved.
6+
7+
If this project has been useful to you, please consider giving it a star. ⭐️
8+
9+
## Table of Contents
10+
11+
- [Code of Conduct](#code-of-conduct)
12+
- [I Have a Question](#i-have-a-question)
13+
- [Getting Started](#getting-started)
14+
- [Development Setup](#development-setup)
15+
- [How to Contribute](#how-to-contribute)
16+
- [Reporting Bugs](#reporting-bugs)
17+
- [Pull Requests](#pull-requests)
18+
- [Testing](#testing)
19+
- [Documentation](#documentation)
20+
21+
## Code of Conduct
22+
23+
This project is committed to providing a welcoming and inclusive environment for all contributors. In summary: be decent to others in this space, act in good faith and assume good faith on others' parts, and conduct onself in a way which would be acceptable in the workplace.
24+
25+
All participants should:
26+
27+
- Be respectful and considerate in communications
28+
- Show empathy towards other community members
29+
- Accept constructive criticism gracefully
30+
- Focus on what is best for the project
31+
32+
Unacceptable behavior includes:
33+
34+
- Any conduct that would be inappropriate in a professional setting
35+
- Harassment of any kind
36+
- Discriminatory jokes and language
37+
- Personal or political attacks
38+
- Publishing others' private information
39+
- Trolling or insulting comments
40+
41+
Violations should be reported to the project maintainer(s), who will take appropriate action.
42+
43+
## I Have a Question
44+
45+
Before asking a question:
46+
47+
1. Read the [Home](index.md) page and any available documentation
48+
2. Search existing [Issues](https://github.com/sjmf/kvm-serial/issues) to see if your question has already been answered
49+
3. Search the internet for answers first: putting errors from the console into a search engine is a great place to start.
50+
51+
If you still need clarification, please:
52+
53+
- Open a [new issue](https://github.com/sjmf/kvm-serial/issues/new)
54+
- Provide as much context as possible: issues saying "it doesn't work", without further detail, will be closed saying "yes, it does".
55+
- Include relevant system information (OS, Python version, hardware details)
56+
57+
## Getting Started
58+
59+
### Forking the Repository
60+
61+
You will need to fork the repository if you want to contribute via [Pull Request](#pull-requests).
62+
If that's you, read on!
63+
64+
1. Fork the repository on GitHub
65+
2. Clone your fork locally:
66+
```bash
67+
git clone https://github.com/your-username/kvm-serial.git
68+
cd kvm-serial
69+
```
70+
3. Add the canonical repository to pull upstream changes:
71+
```bash
72+
git remote add upstream https://github.com/sjmf/kvm-serial.git
73+
```
74+
75+
## Development Setup
76+
77+
To develop the code, there's a few steps to get set up:
78+
79+
1. **Python Environment**: Ensure you have Python 3.8+ installed
80+
2. **Install Dependencies and Dev Dependencies**:
81+
```bash
82+
pip install -e .
83+
pip install '.[dev]'
84+
```
85+
3. **Install Pre-commit Hooks**:
86+
```bash
87+
pre-commit install
88+
pre-commit run --all-files # Run pre-commit on all files (optional)
89+
```
90+
91+
Pre-commit hooks help to ensure that any code contributed follows the code style (`black`).
92+
93+
## How to Contribute
94+
95+
Contributions are fab! I really appreciate your being interested in this project. A contribution might be a bug report, a suggestion for a feature enhancement, addressing an oversight in the documentation or test suite, or just a well-structured question about how to use this project e.g. in a way we've not seen before.
96+
97+
If you're considering giving back in the form of a contribution, here's the best way to do that:
98+
99+
### Reporting Bugs
100+
101+
#### Before Submitting a Bug Report
102+
103+
Please ensure you're using the latest version of the software and verify that the issue is actually a bug rather than a configuration problem or user error. Search through existing [bug reports](https://github.com/sjmf/kvm-serial/issues?q=is%3Aissue+label%3Abug) to see if someone else has already encountered the same problem.
104+
105+
When preparing your bug report, collect comprehensive information about your system environment. This should include your Python version and operating system, details about your hardware setup (particularly the CH9329 device and any connected cameras), your serial port configuration, complete error messages with stack traces, and clear steps that reliably reproduce the issue.
106+
107+
#### How to Submit a Bug Report
108+
109+
Open a [new issue](https://github.com/sjmf/kvm-serial/issues/new) with a clear, descriptive title that summarizes the problem. Describe both what behavior you expected to see and what actually happened. The most valuable bug reports include step-by-step reproduction instructions that allow maintainers to recreate the issue on their own systems. Include all the system and configuration information you collected, as this context is often crucial for diagnosing the root cause.
110+
111+
### Pull Requests
112+
113+
#### Before Creating a Pull Request
114+
115+
1. **Create an Issue First**: For significant changes, create an issue to discuss the approach
116+
2. **Fork and Branch**: Create a feature branch from `main`
117+
3. **Stay Updated**: Regularly sync with upstream:
118+
```bash
119+
git fetch upstream
120+
git rebase upstream/main
121+
```
122+
123+
#### Pull Request Guidelines
124+
125+
1. **One Change Per PR**: Submit separate PRs for different features/fixes
126+
2. **Clear Description**: Explain what your PR does and why
127+
3. **Reference Issues**: Link to related issues with "Fixes #123"
128+
4. **Test Your Changes**: Ensure all tests pass
129+
5. **Follow Code Standards**: Use pre-commit hooks and linting
130+
131+
### Commit Message Guidelines
132+
133+
Examples:
134+
135+
- `feat(video): add support for USB 3.0 cameras`
136+
- `fix(serial): handle port disconnection gracefully`
137+
- `docs(readme): update installation instructions`
138+
139+
## Testing
140+
141+
### Running Tests
142+
143+
```bash
144+
# Run all tests
145+
python -m pytest
146+
147+
# Run with coverage
148+
python -m pytest --cov=kvm_serial
149+
150+
# Run specific test categories, e.g.:
151+
python -m pytest tests/kvm
152+
python -m pytest tests/backend
153+
```
154+
155+
### Writing Tests
156+
157+
Tests should be placed in the `tests/` directory. When writing new tests, focus on covering both successful operations and error conditions, ensuring that external dependencies like hardware devices are properly mocked to prevent actual device access during testing.
158+
159+
Follow established patterns in the existing test suite, particularly around the use of context managers for patching and the helper methods provided by the base test class. The test structure emphasizes isolation and repeatability, so each test should be able to run independently without relying on state from other tests.
160+
161+
Always check that tests pass in concert with other tests: tests can modify the global import state of the test environment, which can result in interference for example where a test accidentally makes an import which can then no longer be patched. I've gone to some lengths to check that tests don't interfere with each other (or skip them where they do), but it's far too easy to write a test where this can occur!
162+
163+
## Documentation
164+
165+
Documentation improvements are always welcome. Good documentation contributions focus on the user experience, and often come from people who have recently worked through setup or usage scenarios themselves.
166+
167+
When updating documentation, prioritise clarity and accuracy over comprehensiveness. Include practical examples where they help illustrate concepts, and always test any instructions or code examples you add to ensure they work as described. If you're documenting new features, consider including both basic usage examples and more advanced scenarios.
168+
169+
Documentation should be updated whenever functionality changes. This includes not just user-facing features, but also development processes, testing procedures, and troubleshooting information. The goal is to reduce friction for both users and future contributors.
170+
171+
## Legal Notice
172+
173+
By contributing to this project, you agree that:
174+
175+
- You have authored 100% of the contributed content
176+
- You have the necessary rights to the content
177+
- Your contribution may be provided under the project license
178+
179+
## Questions?
180+
181+
If you have questions about contributing, feel free to:
182+
183+
- Open an [issue](https://github.com/sjmf/kvm-serial/issues/new)
184+
- Contact the maintainers
185+
186+
Thank you for contributing to KVM Serial! 🎉
File renamed without changes.

docs/index.md

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
# Serial KVM Controller (CH9329)
2+
3+
[![PyPI](https://img.shields.io/pypi/v/kvm-serial)](https://pypi.org/project/kvm-serial/)
4+
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/sjmf/kvm-serial/blob/main/LICENSE.md)
5+
[![Black](https://img.shields.io/badge/code%20style-black-black)](https://github.com/sjmf/kvm-serial/actions/workflows/lint.yml)
6+
[![Run Tests](https://img.shields.io/github/actions/workflow/status/sjmf/kvm-serial/test.yml?label=Unit%20Tests)](https://github.com/sjmf/kvm-serial/actions/workflows/test.yml)
7+
[![codecov](https://img.shields.io/codecov/c/gh/sjmf/kvm-serial)](https://codecov.io/gh/sjmf/kvm-serial)
8+
9+
A Software KVM, using the CH9329 UART Serial to USB HID controller.
10+
11+
Control your computers using an emulated keyboard and mouse!
12+
13+
This app and python module allows you to control to a second device using a CH9329 module (or cable)
14+
and a video capture device. You can find these from vendors on eBay and AliExpress for a low price.
15+
However, there is very little software support available for these modules, and CH9329
16+
protocol documentation is sparse.
17+
18+
This software captures keyboard and mouse inputs from the local computer, sending these over a
19+
serial UART connection to the CH9329 USB HID module, which will output USB HID mouse and keyboard
20+
movements and scan codes to the remote computer.
21+
22+
The `kvm_serial` package provides options for running the GUI, or as a script providing flexible options.
23+
24+
<a href="https://github.com/sjmf/kvm-serial/releases/latest/"> <img align="left" src="https://raw.githubusercontent.com/sjmf/kvm-serial/main/assets/icon.png" alt="App icon" height="100" /></a>
25+
26+
<hr />
27+
28+
__[Download the latest release](https://github.com/sjmf/kvm-serial/releases/latest/)__ for Windows, Mac or Linux.
29+
30+
*See [Installation](INSTALLATION.md) for information on installing serial drivers, if required.*
31+
32+
33+
## GUI Usage
34+
35+
Run the GUI using the [executable for your platform](https://github.com/sjmf/kvm-serial/releases/latest/), or with Python using `python -m kvm_serial`.
36+
37+
![KVM Window](https://wp.finnigan.dev/wp-content/uploads/2025/09/output-4.gif)
38+
*The Serial KVM window running on OSX, controlling a Windows remote machine*
39+
40+
The module can be [installed from PyPI](https://pypi.org/project/kvm-serial/) (`pip install kvm-serial`),
41+
or locally from a cloned git repo (`pip install -e .`).
42+
43+
The GUI app will do a lot of the work for you: it will enumerate video devices and serial ports,
44+
and give you a window to interact with the guest in. Application settings can be changed from the
45+
menus (File, Options, View), for example if the app doesn't select the correct devices by default.
46+
47+
## Kit List
48+
49+
This module requires a little bit of hardware to get going. You will need:
50+
51+
* CH9329 module or cable
52+
* Video capture card (e.g. HDMI)
53+
54+
You can likely get everything you need for under £30, which is incredible when compared to the
55+
price of a KVM crash cart adapter.
56+
57+
### CH9329 module/cable assembled as cables
58+
59+
_PLEASE NOTE: I am a hobbyist. I have no affiliation with any manufacturer developing or selling CH9329 hardware._
60+
61+
[![Home-made serial KVM module](https://wp.finnigan.dev/wp-content/uploads/2023/11/mini-uart.jpg)](https://wp.finnigan.dev/?p=682)
62+
*A home-made serial KVM module: CH9329 module soldered to SILabs CP2102. CH340 works, too.*
63+
64+
So, I don't have a specific vendor to recommend, but if you put "*CH9329 cable usb*" into a search
65+
engine, you will find the right thing. Just make sure what you buy has "CH9329" in the name: a USB-A
66+
to USB-A cable won't do, and can damage your machine.
67+
68+
The modules have a USB-A male connector on one end, and serial connector on the other. The cables
69+
have USB-A both ends, as they are already put together and should pretty much be plug-and-play: just
70+
make sure it's the right way around. I just soldered a CH9329 module to a UART transceiver chip
71+
myself, as above.
72+
73+
### Video capture card
74+
75+
You also need a capture card that takes the display output from your remote machine, and presents it
76+
as a USB device to your local system. I found the "*UGREEN Video Capture Card HDMI to USB C Capture
77+
Device*" was a good balance of price versus value. The more you spend on a capture device, the more
78+
responsive your video feed will likely be (to a point). HDMI and VGA hardware is available.
79+
80+
## Installing Python Dependencies
81+
82+
_Note:_ These instructions are not required if using the executables, but you may need to do some other setup. See [Installation](INSTALLATION.md) for information on installing serial drivers.
83+
84+
**Standard installation** (running the application from `pip`):
85+
86+
```bash
87+
# OPTIONAL: Create and activate a Virtual environment
88+
python -m venv ./.venv
89+
./.venv/scripts/activate
90+
91+
# Install the module from PyPI and run the GUI
92+
pip install kvm-serial
93+
python -m kvm-serial
94+
```
95+
96+
OR using [`uv` package manager](https://docs.astral.sh/uv) (a faster alternative to pip, if available):
97+
*Note: `uv run` may not work on Windows. See [#15](https://github.com/sjmf/kvm-serial/issues/15).*
98+
99+
```bash
100+
uv run kvm-gui
101+
```
102+
103+
**Install from source** (for development- includes PyInstaller for building executables, pytest for testing, etc.):
104+
105+
```bash
106+
pip install -e ".[dev]"
107+
```
108+
109+
## Script Usage
110+
111+
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!)
112+
113+
Packages must be installed first. Use your preferred python package manager. E.g.:
114+
115+
116+
117+
Usage examples for the `control.py` script:
118+
119+
```bash
120+
# Run using module
121+
python -m kvm_serial.control
122+
123+
# Run using `uv`
124+
uv run kvm-control
125+
126+
# Run with mouse and video support; use a Mac OSX serial port:
127+
python -m kvm_serial.control -ex /dev/cu.usbserial-A6023LNH
128+
129+
# Run the script using keyboard 'tty' mode (no mouse, no video)
130+
python control.py --mode tty /dev/tty.usbserial0
131+
132+
# Run using `pyusb` keyboard mode (which requires root):
133+
sudo python control.py --mode usb /dev/tty.usbserial0
134+
135+
# Increase logging using --verbose (or -v), and use COM1 serial port (Windows)
136+
python control.py --verbose COM1
137+
```
138+
139+
Use `python control.py --help` to view all available options. Keyboard capture and transmission is the default functionality of control.py: a couple of extra parameters are used to enable mouse and video. For most purposes, the default capture mode will suffice.
140+
141+
Mouse capture is provided using the parameter `--mouse` (`-e`). It uses pynput for capturing mouse input and transmits this over the serial link simultaneously to keyboard input. Appropriate system permissions (Privacy and Security) may be required to use mouse capture.
142+
143+
Video capture is provided using the parameter `--video` (`-x`). It uses OpenCV for capturing frames from the camera device. Again, system permissions for webcam access may need to be granted.
144+
145+
See [Keyboard Modes](MODES.md) for more information on the various other options to the script.
146+
Implementations are provided for all the main python input capture methods.
147+
148+
## Troubleshooting
149+
150+
**Permissions errors on Linux**:
151+
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.
152+
153+
**Difficulty installing requirements**: If you get `command not found: pip` or similar when installing requirements, try: `python -m pip [...]` to run pip instead.
154+
155+
## Acknowledgements
156+
With thanks to [@beijixiaohu](https://github.com/beijixiaohu), the author of the [ch9329Comm PyPi package](https://pypi.org/project/ch9329Comm/) and [GitHub repo](https://github.com/beijixiaohu/CH9329_COMM/) (in Chinese), some code of which is re-used under the MIT License.
157+
158+
Thank you, once again, to everyone who has [contributed](CONTRIBUTING.md) to this project.
159+
160+
## License
161+
(c) 2023-25 Samantha Finnigan and contributors (except where acknowledged) and released under [MIT License](https://github.com/sjmf/kvm-serial/blob/main/LICENSE.md).

0 commit comments

Comments
 (0)