0x1815 · hostsInfo
检查 Easy-Switch 主机槽位、名称和操作系统,并在设备允许时重命名已配对的主机。
hostsInfo 描述多主机设备保存的主机通道。此功能报告通道配对状态、连接类型、名称元数据和原始描述符页。此功能也提供分页主机名称和操作系统数据。OpenLogi v0.8.15 可读取这些数据,并可重命名已配对通道。
**规格:**没有公开的 Logitech 规格。布局来自对 Logi Options+ 2.8 的静态分析。**交叉核对:**Solaar。用于:Easy-Switch。
函数参考
HostsInfoFeature 要求设备声明功能版本 2。此封装实现函数 0~4 和 7。v0.8.15 没有函数 5、6 和 8 的封装。
方法
| 函数 | HID++ fn | 签名 | 返回值 |
|---|---|---|---|
get_feature_info | 0 | () | HostsInfoFeatureInfo |
get_host_info | 1 | (host: HostIndex) | HostInfo |
get_host_descriptor | 2 | (host: HostIndex, page: u8) | HostDescriptorPage |
get_host_friendly_name | 3 | (host: HostIndex, offset: u8) | HostNameChunk |
set_host_friendly_name | 4 | (host: HostIndex, offset: u8, bytes: [u8; HOST_NAME_CHUNK_LEN]) | () |
get_host_os_version | 7 | (host: HostIndex) | HostOsVersion |
所有方法都是 async,并返回 Result<…, Hidpp20Error>。
类型
HostsInfoFeatureInfo
函数 0 返回此功能的静态信息。
| 字段 | 类型 | 说明 |
|---|---|---|
capabilities | HostsInfoCapabilities | 线格式能力掩码的高字节。 |
descriptor_capabilities | HostDescriptorCapabilities | 线格式能力掩码的低字节。 |
host_count | u8 | 主机通道数量。 |
current_host | HostIndex | 当前主机选择器或 Current。 |
HostInfo
函数 1 返回一个主机通道记录。
| 字段 | 类型 | 说明 |
|---|---|---|
host_index | HostIndex | 设备回显的选择器。 |
status | HostSlotStatus | 空槽或已配对状态。 |
bus_type | HostBusType | 连接类型。 |
page_count | u8 | 描述符页数量。 |
name_len | u8 | 当前主机名称的字节长度。 |
name_max_len | u8 | 主机名称的最大字节长度。 |
HostDescriptorPage
函数 2 返回一个原始描述符页。
| 字段 | 类型 | 说明 |
|---|---|---|
host_index | HostIndex | 设备回显的选择器。 |
bus_type | HostBusType | OpenLogi 对页头高半字节的解码。 |
page_index | u8 | OpenLogi 对页头低半字节的解码。 |
body | [u8; 14] | 原始描述符字节。 |
HostNameChunk
函数 3 返回固定长度的名称块。
| 字段 | 类型 | 说明 |
|---|---|---|
host_index | HostIndex | 设备回显的选择器。 |
offset | u8 | 设备回显的字节偏移量。 |
bytes | [u8; 14] | 名称字节及其后的填充。 |
HOST_NAME_CHUNK_LEN 的值为 14。
HostOsVersion
函数 7 返回保存的操作系统和版本。
| 字段 | 类型 | 说明 |
|---|---|---|
host_index | HostIndex | 设备回显的选择器。 |
os_type | HostOsType | 保存的操作系统类型。 |
major | u8 | 主版本号。 |
minor | u16 | 次版本号,按 BE 解码。 |
patch | u16 | 修订版本号,按 BE 解码。 |
HostIndex
| 变体 | 值 | 说明 |
|---|---|---|
Current | 0xFF | 由设备选择的当前主机通道。 |
Slot(u8) | 0~254 | 显式的零起始主机通道。 |
HostSlotStatus
| 变体 | 值 | 说明 |
|---|---|---|
Empty | 0 | 通道没有已配对的主机。 |
Paired | 1 | 通道有已配对的主机。 |
HostBusType
| 变体 | 值 | 说明 |
|---|---|---|
Undefined | 0 | 未定义或未知的连接。 |
Equad | 1 | eQuad 无线连接。 |
Usb | 2 | USB 连接。 |
Bt | 3 | Bluetooth Classic 连接。 |
Ble | 4 | Bluetooth Low Energy 连接。 |
BlePro | 5 | BLE Pro / Logi Bolt 连接。 |
HostOsType
| 变体 | 值 | 说明 |
|---|---|---|
Unknown | 0 | 没有保存操作系统。 |
Windows | 1 | Windows。 |
WindowsEmbedded | 2 | Windows Embedded。 |
Linux | 3 | Linux。 |
Chrome | 4 | ChromeOS。 |
Android | 5 | Android。 |
MacOs | 6 | macOS。 |
Ios | 7 | iOS 或 iPadOS。 |
WebOs | 8 | webOS。 |
Tizen | 9 | Tizen。 |
HostsInfoCapabilities
这些具名标志位于 BE 能力掩码的高字节。
| 标志 | 位/值 | 说明 |
|---|---|---|
GET_NAME | 1 << 0 / 0x0100 | 可以读取主机名称。Solaar 对此标志作了交叉核对。 |
SET_NAME | 1 << 1 / 0x0200 | 可以写入主机名称。Options+ 2.8 用此标志限制重命名。 |
MOVE_HOST | 1 << 2 / 0x0400 | 可以移动主机槽位。Options+ 2.8 用此标志限制函数 5。 |
DELETE_HOST | 1 << 3 / 0x0800 | 可以删除主机槽位。Options+ 2.8 用此标志限制函数 6。 |
SET_OS_VERSION | 1 << 4 / 0x1000 | 可以写入主机操作系统版本。Options+ 2.8 用此标志限制函数 8。 |
HostDescriptorCapabilities
OpenLogi 将下列标志分配给能力掩码的低字节。
| 标志 | 位/值 | 说明 |
|---|---|---|
EQUAD | 1 << 0 / 0x0001 | OpenLogi 的 eQuad 描述符系列标志。 |
USB | 1 << 1 / 0x0002 | OpenLogi 的 USB 描述符系列标志。 |
BT | 1 << 2 / 0x0004 | OpenLogi 的 Bluetooth Classic 描述符系列标志。 |
BLE | 1 << 3 / 0x0008 | OpenLogi 的 Bluetooth Low Energy 描述符系列标志。 |
公开规格尚未独立确认低字节标志的名称。
事件
OpenLogi v0.8.15 不公开类型化的 HostsInfo 事件。已审阅的证据没有确定未经请求的 0x1815 报告布局。
线格式
此功能除函数 4 外均使用 3 字节短请求。函数 4 使用 16 字节长请求。OpenLogi 使用 extend_payload() 读取响应。
get_feature_info(fn 0)
请求:[0x00, 0x00, 0x00]。
| 字节 | 字段 | 备注 |
|---|---|---|
| 0~1 | capability_mask | 一个 BE u16。OpenLogi 将字节 0 和字节 1 公开为两个独立位标志。 |
| 0 | capabilities | capability_mask 的高字节。未知位会保留。 |
| 1 | descriptor_capabilities | capability_mask 的低字节。未知位会保留。 |
| 2 | host_count | 主机通道数量。 |
| 3 | current_host | 0xFF 会变为 HostIndex::Current。其他值会变为 Slot(n)。 |
OpenLogi 字段保留完整掩码。可用 u16::from_be_bytes([capabilities.bits(), descriptor_capabilities.bits()]) 重建掩码。
get_host_info(fn 1)
请求:[host, 0x00, 0x00]。host 对 HostIndex::Current 为 0xFF,否则为零起始通道号。
| 字节 | 字段 | 备注 |
|---|---|---|
| 0 | host_index | 回显的选择器。 |
| 1 | status | 0 是 Empty。1 是 Paired。其他值会导致解码失败。 |
| 2 | bus_type | 0=Undefined,1=Equad,2=Usb,3=Bt,4=Ble,5=BlePro。其他值会导致解码失败。 |
| 3 | page_count | 描述符页数量。 |
| 4 | name_len | 当前主机名称的字节长度。 |
| 5 | name_max_len | 主机名称的最大字节长度。 |
get_host_descriptor(fn 2)
请求:[host, page, 0x00]。
| 字节 | 字段 | 备注 |
|---|---|---|
| 0 | host_index | 回显的选择器。 |
| 1,位 7~4 | bus_type | OpenLogi 将高半字节解码为 HostBusType。此含义尚未确认。 |
| 1,位 3~0 | page_index | OpenLogi 将低半字节解码为页索引。此含义尚未确认。 |
| 2~15 | body | 14 个原始描述符字节。 |
get_host_friendly_name(fn 3)
请求:[host, offset, 0x00]。offset 是字节偏移量,不是页码。
| 字节 | 字段 | 备注 |
|---|---|---|
| 0 | host_index | 回显的选择器。 |
| 1 | offset | 回显的字节偏移量。 |
| 2~15 | bytes | 最多 14 个名称字节。必要时后接填充。 |
封装返回全部 14 字节。设备层按 name_len 读取名称块。设备层会在拼接名称块前验证返回的选择器和偏移量。
set_host_friendly_name(fn 4)
OpenLogi 发送 16 字节长请求,并等待确认。
| 字节 | 字段 | 备注 |
|---|---|---|
| 0 | host | 显式的零起始主机通道。 |
| 1 | offset | 主机名称缓冲区内的字节偏移量。 |
| 2~15 | bytes | 正好 14 个名称字节或填充字节。 |
原始封装会原样写入所提供的字节。设备层用 14 字节块写入全部 name_max_len 字节。设备层用零字节填充最后一块,从而清除旧名称的尾部。
move_host(fn 5)
OpenLogi v0.8.15 不公开此函数。Options+ 2.8 用两个请求字节移动主机。
| 字节 | 字段 | 备注 |
|---|---|---|
| 0 | 源主机 | 源主机通道。Options+ 2.8。 |
| 1 | 目标主机 | 目标主机通道。Options+ 2.8。 |
| 2 | / | 未恢复其含义。 |
Options+ 2.8 用掩码位 0x0400 限制此操作。未恢复确认布局。
delete_host(fn 6)
OpenLogi v0.8.15 不公开此函数。Options+ 2.8 删除一个主机通道。
| 字节 | 字段 | 备注 |
|---|---|---|
| 0 | host | 要删除的主机通道。Options+ 2.8。 |
| 1~2 | / | 未恢复其含义。 |
Options+ 2.8 用掩码位 0x0800 限制此操作。未恢复确认布局。
get_host_os_version(fn 7)
请求:[host, 0x00, 0x00]。
| 字节 | 字段 | 备注 |
|---|---|---|
| 0 | host_index | 回显的选择器。 |
| 1 | os_type | HostOsType 值。未知值会导致解码失败。 |
| 2 | major | 操作系统主版本号。 |
| 3~4 | minor | BE u16。 |
| 5~6 | patch | BE u16。 |
set_host_os_version(fn 8)
OpenLogi v0.8.15 不公开此函数。Options+ 2.8 写入下列 7 个字节。
| 字节 | 字段 | 备注 |
|---|---|---|
| 0 | host | 主机通道。Options+ 2.8。 |
| 1 | os_type | 操作系统类型。Options+ 2.8。 |
| 2 | major | 操作系统主版本号。Options+ 2.8。 |
| 3~4 | minor | BE u16。Options+ 2.8。 |
| 5~6 | patch | BE u16。Options+ 2.8。 |
| 7… | / | 未恢复其布局。 |
Options+ 2.8 用掩码位 0x1000 限制此操作。
OpenLogi 的用法
OpenLogi 只在 HostsInfo 的功能版本为 2 时创建封装。读取 Easy-Switch 数据时,OpenLogi 先读取函数 0,再为 0..host_count 内的每个索引读取函数 1。OpenLogi 只为已配对通道读取函数 3 和 7。OpenLogi 将总线类型映射为面向用户的连接类型。
设备可以拒绝函数 3 或 7。此时,OpenLogi 会将名称或操作系统保留为空。超时、传输失败,或函数 3 和函数 7 的回显不匹配,都会使完整读取失败。
重命名前,OpenLogi 会读取完整通道表。OpenLogi 要求 SET_NAME、已配对的目标通道、非空的修剪后 UTF-8 名称,以及不超过 name_max_len 的字节长度。OpenLogi 通过函数 4 写入完整的零填充名称缓冲区。随后,OpenLogi 再次读取通道表,并拒绝设备未保留的名称。
OpenLogi 不会自动写入主机名称或操作系统版本。OpenLogi 不调用函数 5、6 或 8。面向用户的 Easy-Switch 页面说明此卡片和 Automation API。
未确认的细节
Options+ 2.8 将函数 0 的字节 0~1 读取为一个 BE u16 掩码。OpenLogi 将相同的两个字节公开为两个 u8 位标志集合,因此不会丢失线格式位。低字节描述符标志的语义名称尚未确认。
OpenLogi 将函数 2 的页头解码为总线类型半字节和页索引半字节。已审阅的静态证据没有独立确认这两个半字节的含义。
Options+ 2.8 确定了函数 5、6 和 8 及其观察到的请求字段。公开规格和硬件抓包都未确认其余字节、确认响应或设备支持。OpenLogi 有意不公开这些持久操作。
Rust 用法
use hidpp::feature::hosts_info::{HostIndex, HostSlotStatus, HostsInfoFeature};
// `device` 是已初始化的可变 HID++ 设备。
device.enumerate_features().await?;
if let Some(feature) = device.get_feature::<HostsInfoFeature>() {
let feature_info = feature.get_feature_info().await?;
for slot in 0..feature_info.host_count {
let host = feature.get_host_info(HostIndex::Slot(slot)).await?;
if host.status == HostSlotStatus::Paired {
let name = feature
.get_host_friendly_name(HostIndex::Slot(slot), 0)
.await?;
let os = feature.get_host_os_version(HostIndex::Slot(slot)).await?;
println!("slot {slot}: {:?}, {:?}", name.bytes, os.os_type);
}
}
}