OpenLogi

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_illumination0()IlluminationState
set_illumination1(state: IlluminationState)()
get_brightness_info2()ControlInfo
get_brightness3()u16
set_brightness4(brightness: u16)()
get_brightness_levels5(start_index: u8)LevelConfig
set_brightness_levels6(levels: &SetLevels)()
get_color_temperature_info7()ControlInfo
get_color_temperature8()u16
set_color_temperature9(color_temperature: u16)()
get_color_temperature_levels10(start_index: u8)LevelConfig
set_color_temperature_levels11(levels: &SetLevels)()
get_brightness_effective_max12()u16
listenevent()Receiver<IlluminationEvent>

除 listen 外,所有方法都是 async,并返回 Result<…, Hidpp20Error>。listen 由 EmittingFeature 提供。

类型

ControlCapabilities

ControlInfo::capabilities 描述一个控制项。未知位会保留。

字段位说明
HAS_EVENTS0此控制项会发送变更通知。
HAS_LINEAR_LEVELS1此控制项支持线性级别表。
HAS_NON_LINEAR_LEVELS2此控制项支持显式级别表。
HAS_DYNAMIC_MAXIMUM3亮度可以有动态有效最大值。

ControlInfo

亮度值的单位为流明。色温值的单位为开尔文。

字段类型说明
capabilitiesControlCapabilities控制项能力位。
minu16最低可接受值。min == max 时只有一个设置值。
maxu16最高可接受值。
resolutionu16有效值满足 (value - min) % resolution == 0。
max_levelsu8非线性级别的最大数量。0 表示不支持。

LevelConfig

读取方法返回一个线性表或一个非线性页。

变体字段说明
Linearmin: u16, max: u16, step: u16含首尾值的等距范围。
NonLinearstart_index: u8, level_count: u8, values: Vec<u16>一页 0~7 个显式值,以及完整表的总大小。

SetLevels

写入方法接受重置、线性表或完整的非线性表。

变体字段说明
Reset—恢复出厂级别配置。
Linearmin: u16, max: u16, step: u16写入线性表。
NonLinearvalues: Vec<u16>写入 1~15 个值。OpenLogi 会将超过 7 个的值分页。

SetLevels::NonLinear 会验证数量。它不验证顺序、范围或间距。

IlluminationState

变体值说明
Off0照明关闭。
On1照明开启。

BrightnessClampedSource

变体值说明
Unknown0来源未知。
HidPlusPlus1HID++ 亮度请求导致截断。
Button2硬件按键导致截断。
Other(u8)其他值未建模的来源字节。

事件

变体载荷说明
IlluminationChangedIlluminationState灯光开关发生变化。
BrightnessChangedu16亮度以流明为单位发生变化。
ColorTemperatureChangedu16色温以开尔文为单位发生变化。
BrightnessEffectiveMaxChangedu16有效最大值以流明为单位发生变化。0 表示无限制。
BrightnessClampedsource、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]

字节字段备注
0capabilitiesControlCapabilities 位字段。
1–2minBE u16。
3–4maxBE u16。
5–6resolutionBE u16。
7max_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–3min 或值 0BE u16。线性表使用 min。
4–5max 或值 1BE u16。线性表使用 max。
6–7step 或值 2BE 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备注
Reset0x020x00全为零位 1 请求重置。其他字节会被忽略。
Linear0x010x00min、max 和 step 均为 BE u16位 0 选择线性表。
NonLinear位 7–5 为当前页的值数量页起始索引和完整表数量最多 7 个 BE u16 值每页发送一个请求。

非线性完整表数量从 values.len() 推导。它不能与页数量冲突。

事件

子 ID事件载荷
0IlluminationChanged字节 0 的位 0 是状态。
1BrightnessChanged字节 0–1:BE 流明亮度。
2ColorTemperatureChanged字节 0–1:BE 开尔文色温。
3BrightnessEffectiveMaxChanged字节 0–1:BE 流明最大值。
4BrightnessClamped字节 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:?}");
    }
}

本页目录