0x1990 · illumination
设备照明控制,包含电源、亮度、色温、可选级别和版本 1 的有效亮度上限。
此功能通过独立的亮度和色温控制设备灯光。OpenLogi 将此功能用于响应 HID++ 0x1990 的 Litra Glow 和 Litra Beam 补光灯。请参阅 Litra 补光灯。
**规格:**Logitech HID++ 2.0 —— illumination。**交叉核对:**Logi Options+ 2.8(静态分析)。用于:Litra 补光灯。
函数参考
IlluminationFeature(0x1990)提供以下方法。
方法
| 函数 | HID++ fn | 签名 | 返回值 |
|---|---|---|---|
get_illumination | 0 | () | IlluminationState |
set_illumination | 1 | (state: IlluminationState) | () |
get_brightness_info | 2 | () | ControlInfo |
get_brightness | 3 | () | u16 |
set_brightness | 4 | (brightness: u16) | () |
get_brightness_levels | 5 | (start_index: u8) | LevelConfig |
set_brightness_levels | 6 | (levels: &SetLevels) | () |
get_color_temperature_info | 7 | () | ControlInfo |
get_color_temperature | 8 | () | u16 |
set_color_temperature | 9 | (color_temperature: u16) | () |
get_color_temperature_levels | 10 | (start_index: u8) | LevelConfig |
set_color_temperature_levels | 11 | (levels: &SetLevels) | () |
get_brightness_effective_max | 12 | () | u16 |
listen | event | () | Receiver<IlluminationEvent> |
除 listen 外,所有方法都是 async,并返回 Result<…, Hidpp20Error>。listen 由 EmittingFeature 提供。
类型
ControlCapabilities
ControlInfo::capabilities 描述一个控制项。未知位会保留。
| 字段 | 位 | 说明 |
|---|---|---|
HAS_EVENTS | 0 | 此控制项会发送变更通知。 |
HAS_LINEAR_LEVELS | 1 | 此控制项支持线性级别表。 |
HAS_NON_LINEAR_LEVELS | 2 | 此控制项支持显式级别表。 |
HAS_DYNAMIC_MAXIMUM | 3 | 亮度可以有动态有效最大值。 |
ControlInfo
亮度值的单位为流明。色温值的单位为开尔文。
| 字段 | 类型 | 说明 |
|---|---|---|
capabilities | ControlCapabilities | 控制项能力位。 |
min | u16 | 最低可接受值。min == max 时只有一个设置值。 |
max | u16 | 最高可接受值。 |
resolution | u16 | 有效值满足 (value - min) % resolution == 0。 |
max_levels | u8 | 非线性级别的最大数量。0 表示不支持。 |
LevelConfig
读取方法返回一个线性表或一个非线性页。
| 变体 | 字段 | 说明 |
|---|---|---|
Linear | min: u16, max: u16, step: u16 | 含首尾值的等距范围。 |
NonLinear | start_index: u8, level_count: u8, values: Vec<u16> | 一页 0~7 个显式值,以及完整表的总大小。 |
SetLevels
写入方法接受重置、线性表或完整的非线性表。
| 变体 | 字段 | 说明 |
|---|---|---|
Reset | — | 恢复出厂级别配置。 |
Linear | min: u16, max: u16, step: u16 | 写入线性表。 |
NonLinear | values: Vec<u16> | 写入 1~15 个值。OpenLogi 会将超过 7 个的值分页。 |
SetLevels::NonLinear 会验证数量。它不验证顺序、范围或间距。
IlluminationState
| 变体 | 值 | 说明 |
|---|---|---|
Off | 0 | 照明关闭。 |
On | 1 | 照明开启。 |
BrightnessClampedSource
| 变体 | 值 | 说明 |
|---|---|---|
Unknown | 0 | 来源未知。 |
HidPlusPlus | 1 | HID++ 亮度请求导致截断。 |
Button | 2 | 硬件按键导致截断。 |
Other(u8) | 其他值 | 未建模的来源字节。 |
事件
| 变体 | 载荷 | 说明 |
|---|---|---|
IlluminationChanged | IlluminationState | 灯光开关发生变化。 |
BrightnessChanged | u16 | 亮度以流明为单位发生变化。 |
ColorTemperatureChanged | u16 | 色温以开尔文为单位发生变化。 |
BrightnessEffectiveMaxChanged | u16 | 有效最大值以流明为单位发生变化。0 表示无限制。 |
BrightnessClamped | source、brightness | 亮度被限制到有效最大值。 |
最后两个事件是版本 1 的协议新增内容。
线格式
短请求使用 3 字节载荷。所有多字节字段均为 BE。get_*_info 需要至少 8 个载荷字节的长回复。每个 get_*_levels 调用需要完整的 16 字节长载荷。OpenLogi 会拒绝这些函数的短回复。
get_illumination(fn 0)
请求:[0x00, 0x00, 0x00]
| 字节 | 字段 | 备注 |
|---|---|---|
| 0 | 状态 | 位 0:0 = Off;1 = On。 |
set_illumination(fn 1)
请求:[state, 0x00, 0x00],其中 state 为 0 或 1。
回复是确认。OpenLogi 不检查回复载荷。
get_brightness_info(fn 2)和 get_color_temperature_info(fn 7)
请求:[0x00, 0x00, 0x00]
| 字节 | 字段 | 备注 |
|---|---|---|
| 0 | capabilities | ControlCapabilities 位字段。 |
| 1–2 | min | BE u16。 |
| 3–4 | max | BE u16。 |
| 5–6 | resolution | BE u16。 |
| 7 | max_levels | 仅低半字节。 |
get_brightness(fn 3)、get_color_temperature(fn 8)和 get_brightness_effective_max(fn 12)
请求:[0x00, 0x00, 0x00]
| 字节 | 字段 | 备注 |
|---|---|---|
| 0–1 | 值 | BE u16;对于 fn 12,0 表示没有有效上限。 |
函数 12 是版本 1 的函数。它仅在亮度通告 HAS_DYNAMIC_MAXIMUM 时适用。
set_brightness(fn 4)和 set_color_temperature(fn 9)
请求:[value_hi, value_lo, 0x00],其中值为 BE u16。
回复是确认。OpenLogi 不检查回复载荷。
get_brightness_levels(fn 5)和 get_color_temperature_levels(fn 10)
请求:[start_index << 4, 0x00, 0x00]。start_index 必须不大于 0x0f。
| 字节 | 字段 | 备注 |
|---|---|---|
| 0 | 标志 | 位 0 选择线性表。位 7–5 给出非线性页的值数量。 |
| 1 | 页信息 | 位 7–4 是 start_index。位 3–0 是总 level_count。 |
| 2–3 | min 或值 0 | BE u16。线性表使用 min。 |
| 4–5 | max 或值 1 | BE u16。线性表使用 max。 |
| 6–7 | step 或值 2 | BE u16。线性表使用 step。 |
| 8–15 | 值 3–6 | 仅非线性值,每对为 BE u16。 |
set_brightness_levels(fn 6)和 set_color_temperature_levels(fn 11)
OpenLogi 将每个载荷作为 16 字节长请求发送。
| 变体 | 字节 0 | 字节 1 | 字节 2–7 | 备注 |
|---|---|---|---|---|
Reset | 0x02 | 0x00 | 全为零 | 位 1 请求重置。其他字节会被忽略。 |
Linear | 0x01 | 0x00 | min、max 和 step 均为 BE u16 | 位 0 选择线性表。 |
NonLinear | 位 7–5 为当前页的值数量 | 页起始索引和完整表数量 | 最多 7 个 BE u16 值 | 每页发送一个请求。 |
非线性完整表数量从 values.len() 推导。它不能与页数量冲突。
事件
| 子 ID | 事件 | 载荷 |
|---|---|---|
| 0 | IlluminationChanged | 字节 0 的位 0 是状态。 |
| 1 | BrightnessChanged | 字节 0–1:BE 流明亮度。 |
| 2 | ColorTemperatureChanged | 字节 0–1:BE 开尔文色温。 |
| 3 | BrightnessEffectiveMaxChanged | 字节 0–1:BE 流明最大值。 |
| 4 | BrightnessClamped | 字节 0 是来源;字节 1–2 是 BE 截断亮度。 |
OpenLogi 的用法
Litra 驱动程序从灯光节点的根 feature 解析 0x1990。解析和首次状态读取的时限均为 1 秒。驱动程序读取亮度和色温信息、电源状态和支持的值。
仅当已解析的 feature 版本至少为 1,且亮度具有 HAS_DYNAMIC_MAXIMUM 时,驱动程序才调用 fn 12。非零且低于静态最大值的限制会成为报告的亮度上限。限制为 0 或不低于静态最大值时,没有作用。
写入 Litra 前,OpenLogi 会读取当前状态。它仅在控制值不同时发送电源、亮度或色温。随后它会读回已写入的控制项。代理会保留 HID++ 连接,在通知后重新读取,并发布在灯上作出的改动。
代理会在重新连接、保存设置和摄像头使用状态改变后重新应用已保存的灯光设置。Litra 补光灯页面说明面向用户的行为。本参考仅说明 HID++ 路径。
通用 IlluminationFeature 不保存已协商的 feature 版本。其 fn 12 方法没有内部版本或能力检查,仍可调用。Litra 设备路径会应用这两项检查。
未确认的细节
Logi Options+ 静态分析确认了 5 种照明事件载荷形状。该分析没有恢复事件子 ID 跳转表的顺序。OpenLogi 按上表顺序映射子 ID 0~4。硬件抓包应确认这个映射。
Rust 用法
use hidpp::{
device::Device,
feature::{
illumination::{ControlCapabilities, IlluminationFeature, IlluminationState},
EmittingFeature,
},
};
// `device` 已为 HID++ 通道和设备索引创建。
device.enumerate_features().await?;
if let Some(feature) = device.get_feature::<IlluminationFeature>() {
let info = feature.get_brightness_info().await?;
if info.capabilities.contains(ControlCapabilities::HAS_DYNAMIC_MAXIMUM) {
// 调用方还必须确认已协商的 feature 版本至少为 1。
let limit = feature.get_brightness_effective_max().await?;
println!("effective limit: {limit}");
}
feature.set_illumination(IlluminationState::On).await?;
let events = feature.listen();
while let Ok(event) = events.recv().await {
println!("{event:?}");
}
}