Anker powerconf c200 linux tools
  • Rust 68.5%
  • QML 28%
  • JavaScript 2.1%
  • Nix 1.4%
Find a file
Chris Toph 6bb7807e54 feat: add preview resolution and mic pickup controls
- expose resolution enumeration command
- add shared UVC payload handling for pickup mode
2026-06-03 21:05:40 -04:00
dms-plugin feat: add preview resolution and mic pickup controls 2026-06-03 21:05:40 -04:00
src feat: add preview resolution and mic pickup controls 2026-06-03 21:05:40 -04:00
.gitignore feat: add Anker C200 DMS plugin 2026-06-03 18:27:00 -04:00
Cargo.lock feat(anker-c200): add Rust camera control CLI 2026-06-03 13:21:36 -04:00
Cargo.toml feat(anker-c200): add Rust camera control CLI 2026-06-03 13:21:36 -04:00
flake.lock feat: add Anker C200 DMS plugin 2026-06-03 18:27:00 -04:00
flake.nix feat: add Anker C200 DMS plugin 2026-06-03 18:27:00 -04:00
README.md feat: add preview resolution and mic pickup controls 2026-06-03 21:05:40 -04:00

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 raw u16
  • hdron/off
  • horizontal_flipon/off
  • vertical_screenon/off
  • anti_flicker — raw byte value
  • pickup_mode — microphone pickup pattern: omni (360°) or focused (90°), or raw byte

Standard V4L2 controls:

  • brightness
  • contrast
  • saturation
  • hue
  • white_balance_automatic
  • gamma
  • power_line_frequency
  • white_balance_temperature
  • sharpness
  • auto_exposure
  • exposure_time_absolute
  • pan_absolute
  • tilt_absolute
  • focus_absolute
  • focus_automatic_continuous
  • zoom_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_QUERYCTRL
  • VIDIOC_G_CTRL
  • VIDIOC_S_CTRL

Anker-specific controls use UVC extension-unit ioctls:

  • UVCIOC_CTRL_QUERY
  • GET_LEN
  • GET_CUR
  • SET_CUR

Resolution enumeration uses standard V4L2 stream ioctls:

  • VIDIOC_ENUM_FMT
  • VIDIOC_ENUM_FRAMESIZES
  • VIDIOC_ENUM_FRAMEINTERVALS
  • VIDIOC_G_FMT

Known Anker UVC extension details:

  • unit id: 0x06
  • vertical_screen: selector 0x0a
  • fov and pickup_mode: selector 0x10 (one shared payload)
  • horizontal_flip: selector 0x11
  • anti_flicker: selector 0x12
  • hdr: selector 0x13

Selector 0x10 payload details:

  • payload staging buffer: 64 bytes
  • Linux reports current payload length as 60 on known hardware
  • set payload starts with bytes 00 01
  • fov value lives at bytes 2..3, little-endian
  • pickup_mode lives at byte 5: 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 status to 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 meta ranges 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