- Rust 68.5%
- QML 28%
- JavaScript 2.1%
- Nix 1.4%
- expose resolution enumeration command - add shared UVC payload handling for pickup mode |
||
|---|---|---|
| dms-plugin | ||
| src | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| flake.lock | ||
| flake.nix | ||
| README.md | ||
anker-c200
Linux CLI for controlling Anker PowerConf C200 cameras.
anker-c200 is a clean Rust reimplementation of the camera-control behavior from this c tool. The C project is used only as protocol reference; this CLI keeps a new command surface designed for terminal use and GUI integration.
Hardware
Target camera:
- Anker PowerConf C200
- USB VID:PID:
291a:3369 - Linux UVC/V4L2 device nodes such as
/dev/video0
The CLI auto-detects the camera by walking /sys/class/video4linux and matching USB VID/PID. A
single camera usually exposes several /dev/videoN nodes (one video-capture node plus a
metadata-only node), and the node numbers are not stable across reconnects. When several nodes match,
the CLI queries VIDIOC_QUERYCAP and selects the one whose per-node device_caps advertise
V4L2_CAP_VIDEO_CAPTURE (the only node that accepts the control ioctls). Only if that still cannot
single one out (for example two physical cameras) does it ask you to choose:
anker-c200 --device /dev/video2 status
Commands
anker-c200 devices
anker-c200 doctor
anker-c200 controls
anker-c200 status
anker-c200 get <control>
anker-c200 set <control> <value>
anker-c200 apply <control=value>...
anker-c200 reset
anker-c200 resolutions
Global flags:
--device /dev/videoN # override auto-detection
--json # stable machine-readable output
Examples:
anker-c200 devices
anker-c200 controls
anker-c200 status
anker-c200 get fov
anker-c200 set fov wide
anker-c200 set hdr on
anker-c200 set pickup_mode focused
anker-c200 set brightness 120
anker-c200 apply fov=wide hdr=on brightness=120
anker-c200 resolutions
anker-c200 --json status
anker-c200 --json apply fov=medium hdr=off
Controls
anker-c200 controls shows one unified catalog.
Anker-specific UVC extension controls:
fov— field of view:narrow(65),medium(78),wide(95), or rawu16hdr—on/offhorizontal_flip—on/offvertical_screen—on/offanti_flicker— raw byte valuepickup_mode— microphone pickup pattern:omni(360°) orfocused(90°), or raw byte
Standard V4L2 controls:
brightnesscontrastsaturationhuewhite_balance_automaticgammapower_line_frequencywhite_balance_temperaturesharpnessauto_exposureexposure_time_absolutepan_absolutetilt_absolutefocus_absolutefocus_automatic_continuouszoom_absolute
zoom_absolute is standard digital zoom. It is not the same as Anker fov; both are exposed because users and GUIs need one camera panel with both concepts visible.
Boolean values accept 1/on/true/yes and 0/off/false/no, case-insensitively. Human output formats booleans as on or off.
anker-c200 reset restores every control to its hardware default. Standard V4L2 controls use the
default reported by VIDIOC_QUERYCTRL. Anker extension controls use the UVC GET_DEF query; a
control whose camera does not report a default is reported as skipped rather than failing the run.
reset is best-effort: each control reports its own result.
The C200 firmware reports a FOV GET_DEF of 0, which is not a valid field of view, so reset
falls back to the medium preset for fov. A camera that reports a real FOV default keeps it.
Resolutions
anker-c200 resolutions lists the capture pixel formats the camera supports, each with its discrete
frame sizes and frame rates, plus the format currently negotiated on the node:
anker-c200 resolutions
anker-c200 --json resolutions
Resolution is standard UVC stream negotiation (VIDIOC_ENUM_FMT / VIDIOC_ENUM_FRAMESIZES /
VIDIOC_ENUM_FRAMEINTERVALS, current format via VIDIOC_G_FMT), not a vendor control. Unlike the
controls above, the capture format is chosen by whichever application opens the camera, so this
command is informational: it does not set a persistent resolution that other apps (Zoom, OBS) inherit.
Protocol notes
The CLI talks directly to Linux device APIs. It does not shell out to v4l2-ctl and does not require v4l-utils at runtime.
Standard controls use V4L2 ioctls:
VIDIOC_QUERYCTRLVIDIOC_G_CTRLVIDIOC_S_CTRL
Anker-specific controls use UVC extension-unit ioctls:
UVCIOC_CTRL_QUERYGET_LENGET_CURSET_CUR
Resolution enumeration uses standard V4L2 stream ioctls:
VIDIOC_ENUM_FMTVIDIOC_ENUM_FRAMESIZESVIDIOC_ENUM_FRAMEINTERVALSVIDIOC_G_FMT
Known Anker UVC extension details:
- unit id:
0x06 vertical_screen: selector0x0afovandpickup_mode: selector0x10(one shared payload)horizontal_flip: selector0x11anti_flicker: selector0x12hdr: selector0x13
Selector 0x10 payload details:
- payload staging buffer:
64bytes - Linux reports current payload length as
60on known hardware - set payload starts with bytes
00 01 fovvalue lives at bytes2..3, little-endianpickup_modelives at byte5:0x00= omni (360°),0x5a= focused (90°)
Because fov and pickup_mode share one payload, writes are read-modify-write: the current
payload is read with GET_CUR, only the target field is changed, then SET_CUR writes it back. A
naive write of a fresh zeroed buffer would reset the sibling field (an earlier bug where set fov
silently reset pickup_mode to omni).
JSON output
--json returns one JSON object per run. Success example:
{
"ok": true,
"device": "/dev/video0",
"data": {
"control": "fov",
"value": {
"raw": 95,
"display": "95 (wide)"
}
}
}
Readings for standard V4L2 controls also include a meta object describing the control's range, so GUIs can render sliders without a second query:
{
"raw": 128,
"display": "128",
"meta": {
"id": 9963776,
"name": "Brightness",
"control_type": "integer",
"minimum": 0,
"maximum": 255,
"step": 1,
"default_value": 128,
"flags": 0
}
}
Anker UVC controls omit meta.
Error example:
{
"ok": false,
"error": {
"kind": "device_not_found",
"message": "no Anker PowerConf C200 video device found; try `anker-c200 devices`"
}
}
Error kinds are stable snake_case strings. User/argument errors exit with code 2; device and IO errors exit with code 1; success exits with code 0.
Permissions
The user running anker-c200 must be allowed to open the camera's /dev/videoN node for read/write. On many Linux systems that means membership in the video group or a matching udev rule.
Use:
anker-c200 devices
anker-c200 doctor
devices lists discovered video nodes and identifies the C200 when VID/PID metadata is visible. doctor checks whether the selected device can be opened.
Persistence and reapply model
From use it seems Anker FOV settings persist after being set by vendor software and then used on Linux. Standard V4L2 controls are more likely to be reset by camera startup or by applications that manage webcam settings themselves.
This project intentionally has no always-running daemon. Use one-shot commands such as:
anker-c200 apply fov=wide hdr=on brightness=120
If a future GUI needs enforced preferences, the GUI/plugin should reapply saved settings on startup, when the control panel opens, or on its own timer.
Dank Material Shell fit
The DMS plugin lives in this repository under dms-plugin/ (see its README). The Control Center pill
icon reapplies the saved control profile; the pill body opens a standalone window with a live camera
preview and Anker / Standard tabs of controls.
Plugin integration:
- The window calls
anker-c200 --json statusto read live values and--json set ...to change them. - Saved preferences are reapplied with
anker-c200 --json apply ...; Reset uses--json reset. - Reapply happens when the window opens; the CLI does not need a daemon.
- Stable JSON, including the
metaranges on V4L2 controls, avoids scraping human tables.
The repository is a tiny monorepo so the plugin and CLI are packaged from the same flake
(packages.<system>.ankerC200 and packages.<system>.anker-c200).
Nix
Run tests and checks:
nix flake check
Enter the dev shell:
nix develop
Build the package:
nix build .#anker-c200
The dev shell includes Rust tooling and v4l-utils for debugging. v4l-utils is not a runtime dependency of anker-c200.
Development
Common commands:
cargo test
cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo run -- --help