Turn cheap ArtInChip (33c3:0e02) USB-C bar displays into dashboard screens, virtual monitors, or media players on Linux. Built for the popular ZHAOCAILIN 11.3" 1920x440 stretched LCDs sold on AliExpress.
10+ built-in dashboards, EVDI virtual display support, low-CPU website rendering, and video playback. These monitors ship with Windows-only drivers and have zero Linux support — until now.
System Monitor — CPU cores, temps, GPU, memory, disk, swap, network:

Crypto Ticker — live prices from CoinGecko with 24h change:

Clock + Weather — animated weather scenes, 12hr time, system stats:

Docker Monitor — container status, CPU/memory bars, network I/O:

Network Monitor — active connections, state breakdown, process names:

Matrix Rain — digital rain effect with live syslog data:

Pomodoro Timer — 25/5 focus timer with circular progress:

Network Map — live device scanner with color-coded types:

DNS Blocker — AdGuard/Pi-hole stats with query timeline:

Speed Test — internet speed with animated testing and arc gauges:

| Display | Resolution | Chipset | USB ID | Status |
|---|---|---|---|---|
| ZHAOCAILIN 11.3" Bar LCD | 1920x440 | ArtInChip RISC-V | 33c3:0e02 |
Fully working |
| ArtInChip USB Display (0e01) | Various | ArtInChip | 33c3:0e01 |
Should work (untested) |
| ArtInChip USB Display (0e04) | Various | ArtInChip | 33c3:0e04 |
Should work (untested) |
| ArtInChip USB Display (0e05) | Various | ArtInChip | 33c3:0e05 |
Should work (untested) |
If your lsusb shows 33c3:0e0x and you're stuck on Linux, this is for you.
git clone https://github.com/hevnsnt/artinchip-linux.git
cd artinchip-linux
sudo ./install.shThe installer handles dependencies, udev rules, and puts tinyscreen in your PATH. No sudo required after install.
| Mode | Flag | Description |
|---|---|---|
| System Monitor | --sysmon |
CPU per-core bars, temps, GPU, memory, disk, swap, network sparklines |
| Crypto Ticker | --ticker |
Live BTC/ETH/SOL/DOGE/ADA/DOT/LINK/AVAX prices with 24h change |
| Clock + Weather | --clock |
12hr clock, animated weather scenes (fog, rain, sun, snow, storms), system stats |
| Matrix Rain | --matrix |
Digital rain effect with real syslog data overlay |
| Audio Visualizer | --visualizer |
FFT spectrum analyzer from PulseAudio/PipeWire capture |
| Now Playing | --nowplaying |
MPRIS media info (Spotify, etc.) with progress bar |
| Docker Monitor | --docker |
Container status, CPU/memory bars, network I/O |
| Network Monitor | --netmon |
Active connections, state breakdown, process names |
| News Crawl | --news |
Scrolling RSS headlines from Reuters, BBC, Hacker News |
| Pomodoro Timer | --pomodoro |
25/5 focus timer with circular progress and color shifts |
| Network Map | --lanmap |
Live network device scanner via nmap with color-coded device types |
| DNS Blocker | --pihole |
AdGuard Home / Pi-hole stats with timeline and top blocked |
| Speed Test | --speedtest |
Internet speed test with animated particles and arc gauges |
| Mode | Flag | Description |
|---|---|---|
| Website | --url URL |
Low-CPU via EVDI virtual display + Chromium (auto-fallback to CDP) |
| Virtual Monitor | --monitor |
EVDI — tinyscreen becomes a real Linux display |
| YouTube | --video URL |
Fetches up to 4K source, scales to display |
| Local Video | --video FILE |
Any format ffmpeg supports, --loop to repeat |
| Static Image | --image FILE |
Display any image file |
# Single mode
tinyscreen --sysmon
tinyscreen --matrix
tinyscreen --ticker
tinyscreen --docker
tinyscreen --clock
# Display a website (low CPU via EVDI virtual display)
tinyscreen --url https://your-dashboard.example.com/
tinyscreen --url http://192.168.1.178:8420/
# Use as a regular monitor (show anything from your desktop)
tinyscreen --monitor
# Rotate through modes (30 seconds each)
tinyscreen --show all --delay 30
# Rotate specific modes
tinyscreen --show sysmon matrix ticker docker --delay 20
# Play videos
tinyscreen --video "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
tinyscreen --video /path/to/video.mp4 --loop
# Rotate the display output
tinyscreen --sysmon --rotate 180
# Just run — uses config.yml defaults
tinyscreen
# Screenshot current URL render
tinyscreen --screenshot
tinyscreen --screenshot /path/to/output.png
# Control
tinyscreen --status
tinyscreen --offAll commands run in the background by default. Add --fg to run in foreground.
| Flag | Description |
|---|---|
--show MODE [MODE...] |
Rotate through modes (all for all, or list names) |
--delay N |
Seconds per mode when rotating (default: 30) |
--rotate N |
Rotate output 0/90/180/270 degrees |
--fps N |
Target framerate (default: 24) |
-q N |
JPEG quality 1-100 (default: auto) |
--loop |
Loop video playback |
--fg |
Run in foreground (don't daemonize) |
--screenshot [FILE] |
Capture current URL render to PNG |
--monitor |
EVDI virtual monitor — tinyscreen becomes a real display |
--off |
Stop the running instance and blank the display |
--status |
Show current status |
--test |
Show test pattern |
The --url mode displays websites using EVDI (preferred) or CDP screencast (fallback):
EVDI mode (default when available, <5% CPU):
- Creates a virtual monitor via the EVDI kernel module
- Launches a real Chromium browser window on the virtual display
- The EVDI bridge captures pixels and streams them to USB
- CSS animations, JavaScript, and live dashboards all render at up to 30fps
CDP fallback (no EVDI, ~90% CPU):
- Headless Chromium with Chrome DevTools Protocol screencast
- Works without EVDI but uses significantly more CPU
EVDI is auto-detected. If available, --url uses it automatically. If not, it falls back to CDP with a log warning.
--monitor makes the tinyscreen appear as a real Linux display in your desktop environment:
tinyscreen --monitorAfter starting, the tinyscreen shows up in xrandr as DVI-I-1-1 (or similar). You can drag windows onto it, extend your desktop, or use it as a dedicated status display. Pair it with any dashboard webpage, terminal, or application.
# Install EVDI
sudo apt install evdi-dkms libevdi1
# Load at boot
echo "evdi" | sudo tee /etc/modules-load.d/evdi.conf
echo "options evdi initial_device_count=1" | sudo tee /etc/modprobe.d/evdi.conf
# Load now (or reboot)
sudo modprobe evdi initial_device_count=1
# IMPORTANT: Restart your display manager so X11 detects the EVDI card
sudo systemctl restart lightdm # or gdm3 for Ubuntu/GNOMERequirements: X11 desktop session (XFCE, GNOME, KDE), evdi-dkms, libevdi1, xdotool.
The browser viewport is exactly 1920x440 pixels. Key rules:
- Everything must fit in 440px height — no scrolling
- Use horizontal multi-column layouts (3-5 columns)
- Large text: body 16-20px, headers 24-36px, key metrics 48-72px
- Minimal padding (4-8px) — every pixel of height matters
- No navbars, footers, or UI chrome
When you run tinyscreen with no arguments, it reads /opt/tinyscreen/config.yml:
# What to run by default
mode: rotate
# Modes to cycle through
rotate:
modes:
- sysmon
- matrix
- ticker
- docker
- clock
delay: 30 # seconds per mode
# URL mode settings
url: http://your-dashboard.local:8421/
# Global settings
quality: 80 # JPEG quality 1-100
fps: 24 # target framerate
rotate_display: 0 # 0, 90, 180, or 270 degreesCLI flags always override config.yml.
# Edit the systemd service to your preference:
sudo nano /etc/systemd/system/tinyscreen.service
# Enable and start
sudo systemctl enable tinyscreen
sudo systemctl start tinyscreentail -f /tmp/tinyscreen.logThese ArtInChip USB displays require a proprietary RSA authentication handshake before they accept any frame data. The Windows driver does this silently, and ArtInChip's official Linux driver (AiCast) requires a working DRM display pipeline that conflicts with NVIDIA's proprietary drivers.
tinyscreen bypasses the kernel driver entirely and talks directly to the device via USB:
- USB enumeration — Claims the vendor-specific bulk interface (class 0xFF)
- RSA authentication — Two-phase challenge-response required by device firmware:
- Phase 1 (auth_dev): Host encrypts random challenge with RSA public key, device decrypts with private key, returns plaintext
- Phase 2 (auth_host): Device sends RSA-signed blob, host recovers plaintext via public key, returns it
- JPEG frame streaming — 20-byte frame headers + JPEG data over USB bulk transfers
The protocol was reverse-engineered from the aic-render userspace binary and the aic_drm_ud kernel module source.
| Metric | Value |
|---|---|
| USB send rate | 265 fps (JPEG q85, 20KB/frame) |
| Display refresh | 60 Hz (hardware limit) |
| URL mode (CDP screencast) | 60 fps |
| CDP screenshot polling | ~9 fps |
| Sysmon / Docker / Netmon | 2 fps |
| Matrix / News / Ticker | 30 fps |
| Audio Visualizer | 60 fps |
| USB bandwidth used | ~5 MB/s of ~35 MB/s available |
Installed automatically by install.sh:
- Python 3.10+ with:
pyusb,Pillow,cryptography,PyYAML - Chromium or Google Chrome — headless browser for URL mode
- ffmpeg — video decoding
- yt-dlp (optional) — YouTube video support
- numpy (optional) — audio visualizer FFT
- feedparser (optional) — RSS news crawl
- requests — crypto ticker, weather, CDP communication
- websocket-client — CDP WebSocket for URL mode
- Check the display is plugged in:
lsusb | grep 33c3 - Try a different USB cable — many cables that ship with these displays are faulty
- Check dmesg for USB errors:
dmesg | tail -20
Replug the USB cable, or run: sudo udevadm control --reload-rules && sudo udevadm trigger
Make sure the aic_drm_ud kernel module isn't loaded: lsmod | grep aic. If loaded, blacklist it: echo "blacklist aic_drm_ud" | sudo tee /etc/modprobe.d/blacklist-aic.conf
Make sure no old chromium processes are holding port 9222: pkill -f 'chromium.*9222' then retry.
Lower quality (-q 50) or framerate (--fps 15). USB 2.0 Hi-Speed (480 Mbps) is the bottleneck for video.
sudo /opt/tinyscreen/uninstall.shVendor ID: 0x33C3 (ArtInChip)
Product ID: 0x0E02
Interface: 0 (Vendor Specific, Bulk IN EP 0x81, Bulk OUT EP 0x01)
Frame header (20 bytes):
u32 magic = 0xA1C62B01
u32 jpeg_length
u16 frame_id
u16 media_format = 0x10 (JPEG)
u32 reserved = 0
u32 magic = 0xA1C62B01
Auth command (20 bytes, same struct):
magic = 0xA1C62B10 (auth_dev) or 0xA1C62B11 (auth_host)
length = 0x100 (RSA key size)
/opt/tinyscreen/
├── tinyscreen.py # main driver + daemon + all mode dispatch
├── tinyscreen # shell wrapper
├── tinyscreen-evdi.py # EVDI virtual display bridge daemon
├── evdi_wrapper.py # ctypes bindings for libevdi.so
├── edid.py # EDID generator for 1920x440
├── edid_1920x440.bin # pre-generated EDID binary
├── launch-dashboard.sh # standalone dashboard launcher
├── configure-display.sh # xrandr display positioning helper
├── sysmon.py # system monitor renderer
├── config.yml # default configuration
├── modes/
│ ├── ticker.py # crypto price ticker
│ ├── clock.py # clock + animated weather + system info
│ ├── matrix.py # matrix digital rain
│ ├── visualizer.py # audio spectrum analyzer
│ ├── nowplaying.py # MPRIS now playing
│ ├── docker_mon.py # docker container monitor
│ ├── netmon.py # network connections
│ ├── newscrawl.py # RSS news crawl
│ └── pomodoro.py # focus timer
├── tests/
│ └── test_edid.py # EDID generator unit tests
├── tinyscreen-evdi.service # systemd unit for EVDI bridge
├── install.sh
└── uninstall.sh
PRs welcome! Especially for:
- Testing with other ArtInChip display models (0e01, 0e04, 0e05)
- New display modes
- Wayland compositor support
- Custom dashboard templates for the bar form factor
MIT License. See LICENSE.
- Protocol reverse-engineered from ArtInChip's official AiCast Linux driver and
aic-renderbinary - ArtInChip Technology Co., Ltd. for the kernel module source (GPL-2.0)
Keywords: ArtInChip Linux driver, USB bar monitor Linux, ZHAOCAILIN Linux driver, 33c3:0e02 Linux, 1920x440 USB display Linux, stretched bar LCD Linux, AiCast Linux alternative, USB portable monitor Linux driver, ArtInChip RISC-V display, cheap USB monitor Linux, system monitor bar display, hardware dashboard Linux, crypto ticker display, matrix rain display, docker monitor display, CDP screencast display