Skip to content

Instantly share code, notes, and snippets.

View sjmf's full-sized avatar
🐝

Samantha Finnigan sjmf

🐝
View GitHub Profile
@sjmf
sjmf / ch9329_descriptor.py
Created May 5, 2026 23:21
CH9329 USB HID Descriptor
# Combined composite descriptor read from CH9329 (359 bytes, verified
# from 0x81 capture). As CH9329 is a composite device, it presents a
# convenient HID descriptor to emulate.
#
# Contains Report IDs: 1=keyboard, 2=system-ctrl, 3=consumer-ctrl,
# 4=relative-mouse (RID 0x04, range -127..127), 5=absolute-mouse (RID 0x05,
# range 0..4095 for both X and Y), 6=vendor-HID.
# Wire capture confirms the real LC announces the CH9329 composite descriptor
# on PORT=0x01 (HP/HM, P2 in the UC 0x12 keepalive).
# Use as: CH9350Comm(port, state=STATE_0, kbd_desc=CH9329_DESC,
@sjmf
sjmf / s3_lc.txt
Created May 3, 2026 21:30
CH9350L state-3/4 mode bidirectional captures (issue #13) — abs-mouse via dipswitch S1=LOW
[sniff LC] Opening /dev/cu.usbserial-0001 @ 115200 8N1 log=tmp/s3_lc.txt
22:19:54.408787 [LC] [sync: skipped 1B: 00]
22:19:54.411561 [LC] 57 ab 86 | DEVICE_NOTIFY []
22:19:54.675123 [LC] 57 ab 80 ff | LED_STATUS [0xFF unknown]
22:19:54.675596 [LC] 57 ab 89 | STATUS_ANNOUNCE []
22:19:54.889148 [LC] 57 ab 80 ff | LED_STATUS [0xFF unknown]
22:19:59.509114 [LC] 57 ab 04 01 00 02 00 03 00 00 | MOUSE_ABS btn=0x00 x=2 y=3 wheel=0
22:19:59.510436 [LC] 57 ab 04 01 00 04 00 05 00 00 | MOUSE_ABS btn=0x00 x=4 y=5 wheel=0
22:19:59.562138 [LC] 57 ab 04 01 00 05 00 06 00 00 | MOUSE_ABS btn=0x00 x=5 y=6 wheel=0
@sjmf
sjmf / absmouse_uc.txt
Last active May 3, 2026 21:03
CH9350L state-2 mode bidirectional capture (issue #13)
[sniff UC] Opening /dev/cu.usbserial-2130 @ 115200 8N1 log=tmp/absmouse_uc.txt
22:01:55.610957 [UC] 57 ab 12 00 00 00 00 00 07 ac 20 | UC_KEEPALIVE p1=0000 p2=0000 led=0x00[-] status=0x07[p0enum,p1enum,uart] ver=ac20
22:01:55.663372 [UC] 57 ab 12 00 00 00 00 00 07 ac 20 | UC_KEEPALIVE p1=0000 p2=0000 led=0x00[-] status=0x07[p0enum,p1enum,uart] ver=ac20
22:01:59.528460 [UC] 57 ab 12 00 00 00 00 00 07 ac 20 | UC_KEEPALIVE p1=0000 p2=0000 led=0x00[-] status=0x07[p0enum,p1enum,uart] ver=ac20
22:01:59.629656 [UC] 57 ab 12 00 00 00 00 00 07 ac 20 | UC_KEEPALIVE p1=0000 p2=0000 led=0x00[-] status=0x07[p0enum,p1enum,uart] ver=ac20
22:01:59.681114 [UC] 57 ab 12 00 00 00 00 00 07 ac 20 | UC_KEEPALIVE p1=0000 p2=0000 led=0x00[-] status=0x07[p0enum,p1enum,uart] ver=ac20
22:01:59.736437 [UC] 57 ab 12 00 00 00 00 00 07 ac 20 | UC_KEEPALIVE p1=0000 p2=0000 led=0x00[-] status=0x07[p0enum,p1enum,uart] ver=ac20
22:01:59.790835 [UC] 57 ab 12 00 00 00 00 00 07 ac 20 | UC_KEEPALIVE p1=0000 p2=0000 le
@sjmf
sjmf / sniff_emu.txt
Last active May 3, 2026 10:25
CH9350L UART bus sniff — bidirectional capture (LC + UC), real keyboard + mouse source, with 0x81 Device Connection Frames decoded
[sniff UC] Opening /dev/cu.usbserial-110 @ 115200 8N1 log=sniff_emu.txt
11:20:15.089867 [UC] [sync: skipped 1B: 00]
11:20:15.090985 [UC] 57 ab 12 00 00 00 00 00 07 ac 20 | UC_KEEPALIVE p1=0000 p2=0000 led=0x00[-] tail=07ac20
11:20:16.229085 [UC] 57 ab 12 40 00 03 15 00 04 ac 0b | UC_KEEPALIVE p1=4000 p2=0315 led=0x00[-] tail=04ac0b
11:20:21.431744 [UC] 57 ab 12 40 00 03 15 00 07 ac 20 | UC_KEEPALIVE p1=4000 p2=0315 led=0x00[-] tail=07ac20
11:20:42.524922 [UC] 57 ab 12 40 00 03 15 00 07 ac 20 | UC_KEEPALIVE p1=4000 p2=0315 led=0x00[-] tail=07ac20
11:21:15.102974 [UC] 57 ab 12 40 00 03 15 00 07 ac 20 | UC_KEEPALIVE p1=4000 p2=0315 led=0x00[-] tail=07ac20
11:21:18.694012 [UC] 57 ab 12 40 00 03 15 00 07 ac 20 | UC_KEEPALIVE p1=4000 p2=0315 led=0x00[-] tail=07ac20
11:21:22.332487 [UC] 57 ab 12 40 00 03 15 00 07 ac 20 | UC_KEEPALIVE p1=4000 p2=0315 led=0x00[-] tail=07ac20
@sjmf
sjmf / sniff_com4_3.txt
Created May 2, 2026 22:11
CH9350L UART bus sniff — real keyboard + mouse source (HID boot protocol, verified decoder output)
[sniff] Opening COM4 @ 115200 8N1 log=sniff_com4_3.txt
22:44:04.451 57 ab 86 | STARTUP_0x86 []
22:44:04.704 57 ab 80 ff | STARTUP_0x80 [0xFF]
22:44:04.934 57 ab 80 ff | STARTUP_0x80 [0xFF]
22:44:04.935 57 ab 82 a3 | HEARTBEAT io=3
22:44:04.935 57 ab 82 a3 | HEARTBEAT io=3
22:44:04.991 57 ab 82 a3 | HEARTBEAT io=3
22:44:04.992 57 ab 82 a3 | HEARTBEAT io=3
22:44:05.044 57 ab 82 a3 | HEARTBEAT io=3
@sjmf
sjmf / sniff_com4.txt
Created May 2, 2026 22:10
CH9350L UART bus sniff — CH9329 bridge as USB source (absolute mouse, state 0/1 frames verified)
[sniff] Opening COM4 @ 115200 8N1 log=sniff_com4.txt
03:38:11.226 57 ab 82 a3 | HEARTBEAT io=3
03:38:12.257 57 ab 82 a3 | HEARTBEAT io=3
03:38:13.227 57 ab 82 a3 | HEARTBEAT io=3
03:38:14.305 57 ab 82 a3 | HEARTBEAT io=3
03:38:15.288 57 ab 82 a3 | HEARTBEAT io=3
03:38:16.280 57 ab 82 a3 | HEARTBEAT io=3
03:38:17.310 57 ab 82 a3 | HEARTBEAT io=3
03:38:17.547 57 ab 83 0a 23 05 00 d5 03 66 0e 00 c9 1a | KEY_PAIRED ser=0x23 MOUSE_ABS btn=0x00 x=981 y=3686 wheel=0 ctr=C9 sum=1AOK
@sjmf
sjmf / ch9350_poc.py
Last active May 3, 2026 18:48
CH9350L lower-computer protocol PoC — kvm-serial issue #13
#!/usr/bin/env python3
"""
CH9350L UART protocol PoC — issue #13.
Two subcommands:
sniff PORT passively decode frames on a serial line. Tag with --tag
LC/UC for two-port bidirectional captures (merge logs by
timestamp afterwards).
emulate PORT drive a real CH9350L upper computer from this host: send
@sjmf
sjmf / probe_qt_camera_enumeration.py
Created April 23, 2026 14:50
Probe Qt5 QCamera enumeration. Standalone hardware-verification script.
#!/usr/bin/env python
"""
Probe Qt5 QCamera enumeration. Standalone hardware-verification script: prints
every attached camera and its supported viewfinder settings, so changes to Qt
or the operating-system camera stack can be smoke-tested against real devices.
Mirrors what kvm_serial/backend/video.py:enumerate_cameras() does at runtime,
but with verbose per-device output and timing so behaviour can be inspected
without launching the GUI.
@sjmf
sjmf / verify_avfoundation_alignment.py
Last active April 21, 2026 17:48
Verify AVFoundation and OpenCV device alignment
#!/usr/bin/env python
"""
Verify that AVFoundation and OpenCV enumerate cameras in the same order.
Identity check (not just count): opens each OpenCV index in turn, then scans
AVFoundation devices for the one whose dimensions match to the default dims of
the device. That uniqueID is the ground-truth identity of the OpenCV-opened device.
The script compares against our enumerator's ordering and reports the real mapping.
Run with multiple cameras attached:
@sjmf
sjmf / README.md
Created October 11, 2025 15:22
Monorepo extractor

Monorepo Extractor

extract.sh

Let's say I have a private, monolithic git repo where I store my docker compose server configurations.

The folders are in a structure like this:

/ root
 |- project1/