首页/新闻资讯/正文详情

Solaar 内部实现剖析:Linux 下 Logitech HID++ 设备管理的三层架构

发布时间:2026/9/25 7:50:33 来源:云帆数科 栏目:资讯中心
Solaar 内部实现剖析:Linux 下 Logitech HID++ 设备管理的三层架构
开发工具【免费下载链接】SolaarLinux device manager for Logitech devices项目地址https://gitcode.com/gh_mirrors/so/Solaar点击查看免费下载本文依据仓库内 docs/implementation.md 的系统架构文档结合 lib/logitech_receiver、lib/hidapi 与 lib/solaar 的源码实现深入剖析 Solaar 的组件划分、HID 1.0/2.0 协议封装、通知与状态机制、设置系统以及 Solaar 规则的底层原理。读者读完后将能够理解 Solaar 从硬件发现、协议交互到 GUI/CLI 呈现的完整调用链掌握其可扩展的设置模板与规则引擎的设计思路从而为二次开发、调试设备问题或编写自定义规则提供直接的代码级依据。Solaar 的整体组件架构Solaar 是一个运行在 Linux 上的 Logitech 外设管理程序用于管理通过 Unifying、Bolt、Lightspeed、Nano 接收器连接或通过 USB 线缆、蓝牙直接连接的键盘、鼠标和触控板。它不是设备驱动程序不处理设备的普通输入事件而是使用 Logitech 私有的 HID以及新引入的 Centurion命令直接与设备通信因此只能修改设备自身支持的那部分能力。依据 docs/implementation.md 的说明Solaar 由三大组件构成接收器与设备相关代码位于 lib/logitech_receiver负责创建和维护计算机上每个使用 HID 协议的接收器Receiver与设备Device对象。命令行接口CLI代码位于 lib/solaar/cli提供show、config、pair、unpair、probe、profiles等子命令。图形用户界面GUI代码位于 lib/solaar/ui提供基于 GTK 的主窗口、托盘图标、配对窗口与规则编辑器。三者的交互关系可以用 implementation.md 中给出的架构图概括原文为 Mermaid 图此处以文字还原用户界面层UIGUI与 CLI 都汇聚到核心的 Solaar 逻辑核心层Solaar 维护接收器对象Receiver与设备对象Device并通过 dbus 提供进程间通信硬件接口层Receiver与Device都经由hidapi与hid parser同底层硬件通信外设层最终与 Logitech 鼠标、键盘等物理设备交互。Solaar 在启动时执行接收器与设备的发现DiscoveryGUI 运行期间还会借助 GLib 监听新硬件的接入见下文发现与 I/O一节。这一分层设计使协议逻辑logitech_receiver、系统接口hidapi与用户界面solaar/ui相互解耦是理解后续所有模块的骨架。接收器与设备对象Receiver / Device对象创建与职责lib/logitech_receiver/receiver.py 中的Receiver类和 lib/logitech_receiver/device.py 中的Device类是核心层两个最重要的对象。它们在 Linux 上通过 lib/hidapi/udev_impl.py 与udev系统交互而被发现详见后文发现与 I/O。Receiver对象代表一个物理接收器Unifying/Bolt/Lightspeed/Nano 等负责枚举已配对设备、处理配对/取消配对、维护剩余配对数等信息。从源码看receiver.py中还按接收器种类派生了多个子类例如支持 Bolt、Lightspeed 等不同接收器模型并通过create_receiver()工厂函数按产品信息创建对应的实例。Device对象代表一个具体的键盘、鼠标或触控板。其构造与初始化过程较复杂Device.__init__需要接收底层接口、所属接收器、设备编号、在线状态与配对信息等参数并注册设置回调setting_callback。源码中device.py的create_device()负责从底层设备信息构建Device实例。设备属性的存取模型Device对象缓存了大量设备属性并提供读取与写入这些属性的方法这是理解整个设置系统的关键写入方法setter一般先存储新值再调用hidpp10或hidpp20中的函数实际修改设备。读取方法getter先检查值是否已在对象上缓存若已缓存则直接返回缓存值否则调用hidpp10或hidpp20中的函数向设备查询得到结果后缓存并返回。以电池信息为例lib/logitech_receiver/device.py 中battery()方法会根据设备协议分流HID 1.0 设备走hidpp10.get_batteryHID 2.0 设备则通过hidpp20.get_battery查询并且会把识别出的电池特性feature缓存到持久化存储的_battery键中避免每次重复探测。值得注意的是并非所有与设备的通信都经由Device类完成部分设置settings会直接与设备交互见设置系统一节源码中 lib/logitech_receiver/settings.py 的Setting类同时支持基于寄存器HID 1.0和基于特性HID 2.0的读写通道RegisterRW与FeatureRW。HID 协议封装HID 2.0 与特性Feature机制lib/logitech_receiver/hidpp20.py 使用 HID 2.0及更新版本协议与设备交互。该模块中的多数函数通过向设备发送消息来修改内部状态例如设置存储在设备中的主机名另有大量函数查询内部状态并解释响应例如返回鼠标发送移动报告的频率后者的结果一般会缓存到设备对象中。还有少量函数会创建并返回较大的结构或类对象。HID 2.0 协议围绕一系列**特性feature**构建每个特性拥有独立的功能。其中有一个所有支持该协议的设备都必须实现的特性用于提供设备所支持特性的清单。hidpp20模块因此提供了FeaturesArray类lib/logitech_receiver/hidpp20.py存储设备提供的特性及其访问方式每个实现 HID 2.0 的设备都有一个该类的实例。其_check()方法通过向设备发送request(0x0000, FEATURE_SET)获取特性集索引再读取特性数量并逐一登记它还支持 Centurion 设备通过 CentPPBridge 桥接枚举子设备特性的特殊流程_check_centurion与_discover_sub_device_features。feature_request函数是使用最频繁的函数它依据FeaturesArray中记录的特性索引等信息构造 HID 2.0 消息并发送给设备Device.feature_request()是其在设备对象上的封装。按键重编程与转移Divert机制许多设备允许重新编程部分按键或按钮。重编程按键或按钮的一个主要目的是让它产生 HID 消息而不是正常的 HID 消息这被称为将按键转移divert到 HID。hidpp20.py中与此相关的类包括ReprogrammableKeylib/logitech_receiver/hidpp20.py存储一个按键在某一版本能力下的重编程信息提供访问与更新这些信息的方法其只读属性包括key控件名、default_task控件原生功能、flags能力与软件处理期望。ReprogrammableKeyV4lib/logitech_receiver/hidpp20.py在 V4 版本能力上的扩展额外支持按键重映射remap与转移提供set_diverted()、set_persistently_diverted()、set_rawXY_reporting()等方法还维护mapped_to、remappable_to、mapping_flags等属性。PersistentRemappableAction为另一版本的能力提供同样的按键信息存储。KeysArray存储一批按键的重编程信息并提供访问方法。Device类在适当时会请求设备的KeysArray信息并缓存在设备对象上对应device.keys/device.remap_keys属性见 lib/logitech_receiver/device.py 的keys()、remap_keys()方法。手势Gesture支持许多指针设备提供手势识别能力识别到手势后发送对应的 HID 消息。hidpp20.py中的Gesture类lib/logitech_receiver/hidpp20.py存储单个手势的信息是否可启用、是否可转移、默认状态、索引等Gestures类lib/logitech_receiver/hidpp20.py存储设备上所有手势的信息。Gesture通过GESTURE_2特性的 0x10/0x20 函数查询/设置启用状态通过 0x30/0x40 函数查询/设置转移状态且被设计为可直接充当设置的读取器/写入器read enabled; write set。Device类在适当时请求Gestures信息并存储在设备上对应device.gestures。游戏设备的 LED 分区与板载配置Onboard Profileshidpp20.py还处理两类游戏设备专用能力LED 分区控制LEDEffectSetting类存储一个 LED 分区当前的效果状态。该信息既可以直接来自 LED 特性也属于 Onboard Profiles 的组成部分因此该类提供了字节串接口又因为 Solaar 将这类信息以 YAML 存储该类同时提供 YAML 接口from_yaml/to_yaml。LEDEffectsInfo类存储设备上有哪些 LED 分区、各分区可执行哪些效果并提供通过查询设备来构建对象的方法。Onboard Profiles许多游戏设备通过选择板载配置文件来受控。一个板载 Profile 设定设备报告移动的速率、一组移动传感器灵敏度、鼠标按键或 G/M 键的动作集合以及最多两个 LED 分区的效果。相关类包括Buttonlib/logitech_receiver/hidpp20.py存储一个按键或键动作的信息OnboardProfilelib/logitech_receiver/hidpp20.py存储单个 Profile内部使用LEDEffectSetting与Button。由于读写 Profile 很复杂该类提供字节串接口from_bytes/to_bytes其中包括 CRC16 校验、DPI 分辨率列表、16 个按键与 16 个 G 键、4 组灯光效果等字段的编码又因为 Solaar 会把设备中的 Profiles 导出为 YAML 文档、从 YAML 文档导入到设备该类同样提供 YAML 接口OnboardProfileslib/logitech_receiver/hidpp20.py存储设备的全部 Profiles 信息提供通过查询设备来构造OnboardProfiles对象的接口。HID 1.0lib/logitech_receiver/hidpp10.py 使用 HID 1.0 协议与设备交互。与 2.0 的特性模型不同1.0 协议以**寄存器register**为操作对象模块提供read_register()与write_register()通用读写函数并封装了get_battery()电池状态解析、get_firmware()固件信息、get_notification_flags()/set_notification_flags()通知标志位、get_device_features()、set_3leds()等常用操作。hidpp10_constants.py则定义了 1.0 协议的寄存器地址、通知标志与错误码等常量。低级信息与访问descriptors / base_usb / base三个模块构成了设备模型信息与底层 I/O 的基础descriptorslib/logitech_receiver/descriptors.py建立 Solaar 需要支持的设备模型信息。对大多数现代设备 Solaar 可以自行探测全部信息因此这里主要针对较老的或特殊的设备模型。信息可包括设备模型名称、短名称、使用的 HID 协议、支持的 HID 寄存器、若干设备标识符以及设备模型用于 HID 消息的 USB 接口。历史上还包含基于 HID 的设置信息现已迁移至setting_templates。信息可通过多种途径检索如get_wpid、get_codename、get_usbid、get_btid。base_usblib/logitech_receiver/base_usb.py建立 Solaar 支持的大部分接收器模型信息包括 USB ID、用于 HID 消息的 USB 接口、接收器模型种类及部分能力。它同时按 USB ID 和蓝牙 ID 建立设备模型清单并提供判断某 USB ID 或蓝牙 ID 是否为 HID 设备模型的函数。源码中_unifying_receiver、_bolt_receiver、_nano_receiver、_lightspeed_receiver、_ex100_receiver等工厂函数分别描述了各类接收器的信息。只要接收器不是太特殊Solaar 现在也能支持其他接收器。baselib/logitech_receiver/base.py提供发现与 I/O 的核心函数发现函数用于枚举当前所有接收器和设备并注册新接收器/设备被发现时的回调打开/关闭与接收器、设备的 I/O 通道向接收器、设备写入 HID 消息以及读取 HID 消息把 HID 消息转换为通知make_notification发送 HID 消息的函数request见 lib/logitech_receiver/base.py从参数构造消息可选地等待并返回响应。它会先清空输入缓冲区写入请求数据然后循环读取直到超时或看到看似响应的消息为止其间出现的其他消息如果合适会转成通知否则被忽略。实现上还注意在请求的 SoftwareId 中置最高位以便更容易把通知与请求响应区分开单独的 ping 函数发送 ping 消息并等待回复ping。通知Notifications与状态Status机制HID 设备不仅响应命令还会自发地发出 HID 消息——例如移动灵敏度改变时、或某个被转移diverted的按键被按下时。这些自发消息被称为通知notification。行为规范的软件可以把通知与命令响应区分开文档特别提示Linux 的 HIDPP 驱动曾有一段时间行为不规范至今可能仍不规范会导致设备发出无法与通知区分的响应。通知处理链路由三个模块协同完成listenerlib/logitech_receiver/listener.py提供EventsListener线程类lib/logitech_receiver/listener.py为给定设备或接收器建立一个监听线程读取所有来自该设备/接收器的 HID 消息把属于通知的消息转换为 Solaar 的通知结构并调用注册的回调。线程内部使用容量 16 的有界队列暂存待处理通知并处理处理某通知时又产生新通知的情况_notifications_hook将未被处理的响应重新入队。notificationslib/logitech_receiver/notifications.py提供process()函数lib/logitech_receiver/notifications.py根据通知来源分流处理接收器通知用于指示配对尝试的进度。源码中通过event_handler_mapping把PAIRING_LOCK、DEVICE_DISCOVERY_NOTIFICATION、DISCOVERY_STATUS_NOTIFICATION、PAIRING_STATUS_NOTIFICATION、PASSKEY_PRESSED_NOTIFICATION、PASSKEY_REQUEST_NOTIFICATION等子 ID 分发给对应的handle_*函数例如handle_pairing_lock负责打开/关闭配对锁并记录配对错误见 lib/logitech_receiver/notifications.py设备通知一部分用于配对一部分用于信号设备与接收器的连接/断开一部分属于 HID 1.0 协议的其他部分还有一部分属于 HID 2.0 协议。_process_feature_notification()会根据通知字段、设备状态及其 HID 2.0 特性来确定通知含义并相应更新设备及其状态。设备状态更新可能触发 Solaar 用户界面的更新某些通知的处理还会直接运行更新界面的函数。设备还可以提供回调以特殊处理通知这一设施被两类特殊的 Solaar 设置所使用。HID 2.0 通知处理完毕后会被送到diversion模块在那里启动 Solaar 规则处理见 lib/logitech_receiver/notifications.py 与 lib/logitech_receiver/diversion.py 的process_notification它会维护按键按下/抬起状态并调用evaluate_rules。status相关逻辑文档描述的status模块负责记录设备状态其中DeviceStatus类记录设备的电池状态并提供接口在设备连接状态变化时发出信号以调用回调。在当前源码结构中这一职责主要由Device.changed()lib/logitech_receiver/device.py承担设备状态变化时它会更新online标志、按需把已保存的设置重新推送给设备settings.apply_all_settings、为 1.0 设备设置通知标志、重新读取电池信息read_battery最后调用status_callback在 GUI 场景下该回调用于更新 Solaar 用户界面见 lib/solaar/listener.py 中dev.status_callback self._status_changed的接线。GUI 进程侧的通知分发入口位于 lib/solaar/listener.py 与 lib/solaar/listener.py。设置Settings系统GUI 的核心设置的基本构成Solaar GUI 是围绕**设置settings**构建的。一个设置包含存储设备某方面值的全部所需信息从设备读取它、写入设备、把它的状态记录到字典中。同时设置还包含显示与操作所需的信息使用何种用户界面元素、允许哪些值、显示的标签、以及提供额外信息的提示文本tooltip。设置可以基于 HID 1.0使用设备提供的 HID 1.0 寄存器也可以基于 HID 2.0使用设备提供的 HID 2.0 特性。两个模块负责此系统lib/logitech_receiver/settings.py提供创建与支撑设置的类和函数。核心的Setting类定义name、label、description、feature/register、rw_options、validator_class、validator_options等类属性build()类方法根据设备协议1.0 用寄存器、2.0 用特性构造对应的读写通道FeatureRW/RegisterRW与验证器validator并实例化设置。lib/logitech_receiver/settings_templates.py包含 Solaar 支持的全部设置以及判断某设备能支持哪些基于特性的设置的函数。例如文档中提到的HiresSmoothInvert、Backlight等设置类的真实定义都在此文件中。布尔设置的实现示例implementation.md 给出的布尔设置示例在 lib/logitech_receiver/settings_templates.py 中与源码完全一致class HiresSmoothInvert(settings.Setting): name hires-smooth-invert label _(Scroll Wheel Direction) description _(Invert direction for vertical scroll with wheel.) feature _F.HIRES_WHEEL rw_options {read_fnid: 0x10, write_fnid: 0x20} validator_options {true_value: 0x04, mask: 0x04}各字段含义文档原意 源码佐证这是布尔设置布尔是设置的默认类型因为未指定validator_classsettings.py中build()会使用默认的布尔验证器。name记录设置状态时使用的字典键。在 lib/logitech_receiver/settings.py 的_pre_read()中可以看到设置首次读取时会先尝试从设备的持久化存储persister按name键取出已保存的值。label用户界面中显示的标签description提示文本tooltip。feature用于从设备读取/写回设置状态的 HID 2.0 特性此处为_F.HIRES_WHEEL高分辨率滚轮特性。rw_options读写设置状态时使用的选项此处用特性命令 0x10 读取、0x20 写入。validator_options把设置值转成字节、把字节转成设置值的选项。此处取单字节默认用0x04掩码结果0x04为真、其余为假写真值时写0x04写假值写0x00默认。因为这是布尔设置且掩码只覆盖字节的一部分写入设备前会把要写的值与从设备读回的字节按位或OR后再写以免破坏同一字节中的其他位。同文件中的HiresSmoothResolution与HiresMode展示了同一特性的其他位掩码用法true_value: 0x02, mask: 0x02与true_value: 0x01, mask: 0x01。选择Choice设置的实现示例implementation.md 给出的选择设置示例在 lib/logitech_receiver/settings_templates.py 中与源码完全一致class Backlight(settings.Setting): name backlight-qualitative label _(Backlight Timed) description _(Set illumination time for keyboard.) feature _F.BACKLIGHT choices_universe common.NamedInts(Off0, Varying2, VeryShort5, Short10, Medium20, Long60, VeryLong180) validator_class settings_validator.ChoicesValidator validator_options {choices: choices_universe}各字段含义因为指定了validator_class _ChoicesV即ChoicesValidator这是选择设置。choices_universe设置所有可能存储的值及其在用户界面中的显示名称。common.NamedInts定义于 lib/logitech_receiver/common.py构造带名字的整数集合这里把 0关闭、2变化、5很短、10短、20中、60长、180很长秒映射为可读名称。validator_options提供当前允许的选择此处总是与全部选择相同。同样基于 BACKLIGHT 特性的还有Backlight2Level、Backlight2Duration系列Backlight2DurationHandsOut/HandsIn/Powered见 lib/logitech_receiver/settings_templates.py它们用RangeValidator定义取值范围时长设置范围为 1–600 秒写入时按 5 秒单位向上取整展示了同一特性上布尔/选择/范围多种设置形态的共存。设置的扩展与局限Solaar GUI 会取这些设置并构造显示与修改设置的界面。这种模式允许非常快速地实现简单设置但它绕过了设备对象中存储的数据。因此settings.py在build()中通过断言强制协议与读写通道匹配HID 1.0 设备必须用寄存器通道、2.0 设备必须用特性通道见 lib/logitech_receiver/settings.py保证模板定义不会与设备协议错配。此外 lib/logitech_receiver/settings_validator.py 提供了一整套验证器布尔BooleanValidator含true_value/mask等选项、选择ChoicesValidator、范围RangeValidator、按键映射KeysValidator等覆盖设置从字节到值、从值到字节的全部转换逻辑。对于需要绕过Device对象缓存、直接与设备交互的设置模板中的自定义rw_class如Backlight2通过device.backlight读写就是直接从设置与设备通信的典型实现。Solaar 规则Rules与 diversion 模块diversion模块lib/logitech_receiver/diversion.py之所以如此命名是因为它最初主要处理被转移diverted的按键通知。如今它实现了完整的Solaar 规则引擎规则求值入口notifications.py在处理完 HID 2.0 通知后调用diversion.process_notification(device, notification, feature)lib/logitech_receiver/notifications.py。process_notification先维护按键按下/抬起状态对REPROG_CONTROLS_V4通知解析 4 个按下键、对GKEY解析 G 键位图等随后调用evaluate_ruleslib/logitech_receiver/diversion.py最终进入规则集合的evaluate()求值。规则结构规则由条件conditions 动作actions组成diversion.py中实现了大量条件类如按键条件、范围/位测试条件、主机名条件与动作类如按键模拟、滚动模拟、键击序列、执行进程等并支持把规则序列化为 YAML_save_config_rule_file/load_config_rule_file。GUI 侧的规则编辑器位于 lib/solaar/ui/diversion_rules.py规则文件默认存放于~/.config/solaar/rules.yaml。规则引擎的完整用户文档见 docs/rules.md。发现 HID 接收器与设备及 I/Oudev 发现机制lib/hidapi 中的代码负责发现使用 HID 协议的接收器与设备。Linux 下使用的是 lib/hidapi/udev_impl.py它是某段旧 Python 代码的修改版提供了对 Linuxudev系统的接口。识别逻辑依据 implementation.md 与源码推断USB 接收器最初代码只支持 USB 接收器及与其配对的设备。它依据一份Logitech HID 接收器及其 USB ID的列表用 USB ID 识别 HID 接收器随后加入所有与该接收器配对、且在带 WPID 的 HID 设备列表中的设备。WPIDWireless Product ID用于标识与 HID 接收器配对的设备类型。现在代码还会加入所有与 HID 接收器配对的设备无论它们是否在列表中。直连设备现在代码也能识别通过 USB 或蓝牙直连的 HID 设备识别途径有几种内部 HID 设备列表中带 USB ID 或蓝牙 ID 的条目USB ID 或蓝牙 ID 落在若干已知支持 HID 的 ID 区间内的任何设备或任何拥有声称支持 HID 的 HID 协议描述符的设备——最后一种方法需要一个外部 Python 模块来解析 HID 协议描述符该模块并非总是存在。监听新硬件设备与接收器的发现发生在 Solaar 启动时GUI 运行期间udev代码还会利用 GLib 提供的设施监听新硬件的连接。这一能力对应 lib/logitech_receiver/base.py 的monitor_glib()方法它接收 GLib 主循环、回调与过滤函数用于在 GUI 事件循环内持续监控设备接入。实际数据读写hidapi代码同样负责向设备/接收器实际写入与读取数据。base.py中的write()/read()封装了底层句柄的字节级读写并针对 Centurion 设备实现了帧头构造_centurion_frame_header与解包_unwrap_centurion_frame等特殊处理_read()会过滤掉与当前请求无关的消息_is_relevant_message把应保留的消息交给通知钩子。Device与Receiver各自的request()方法在此基础上提供了更高层的请求语义。Solaar 应用层启动、CLI 与 GUI启动与公共组件solaar包lib/solaar中的__init__.py、configuration.py、gtk.py、i18n.py、listener.py、tasks.py等文件构成应用层的公共部分version与commit文件包含 Solaar 当前版本与 git 提交信息。命令行接口CLICLI 位于 lib/solaar/cli使用argparse构建子命令解析器见 lib/solaar/cli/init.py。主要子命令及其参数依据源码确认show显示某个设备或全部设备的信息device参数可以是设备编号1..6、序列号、设备名称子串或默认的all。probe探测接收器仅调试用途。profiles打印或加载设备的 YAML 配置文件转储仅对活跃设备生效profiles参数为要加载的 YAML 文件路径。config打印或加载设备特定设置加载复杂设置时使用与~/.config/solaar/config.yaml相同的语法仅对活跃设备生效参数依次为setting、value_key、extra_subkey、extra2。pair将新设备与接收器配对设备须与接收器兼容Unifying 接收器最多支持 6 个已配对设备。unpair从接收器取消配对某设备并非所有接收器都允许支持--receiver、--slot强制清除指定槽位仅 Lightspeed 接收器与--dry-run选项。图形用户界面GUIGUI 位于 lib/solaar/ui包括主窗口window.py、托盘tray.py、配对窗口pair_window.py、规则编辑器diversion_rules.py、关于对话框ui/about等。GUI 的启动方式可参考 docs/index.md--windowshow默认主窗口可见、--windowhide隐藏启动、--windowonly不使用系统托盘且主窗口可见。GUI 被设计为在后台持续运行监控设备、修改设备、响应设备发出的部分消息因此文档建议在用户登录时自动启动 Solaar使设备设置能在登录时及整个会话期间被应用。常用工具函数、结构与类lib/logitech_receiver/common.py 提供通用工具crc16计算配置文件profiles中使用的校验和。NamedInt、NamedInts、UnsortedNamedInts提供带名字的整数与整数集合是设置选择项、特性枚举、按键码等的基础类型。FirmwareInfo提供设备固件信息。BATTERY_APPROX设备电池近似电量的具名整数集合。其他辅助模块lib/logitech_receiver/i18n.py提供少数需要翻译、但翻译软件可能看不到的字符串。lib/logitech_receiver/special_keys.py为各种按键码和颜色集合提供具名整数。关键模块速查职责模块路径接收器对象lib/logitech_receiver/receiver.py设备对象lib/logitech_receiver/device.pyHID 1.0 协议lib/logitech_receiver/hidpp10.pyHID 2.0 协议与特性类lib/logitech_receiver/hidpp20.py设备模型描述符lib/logitech_receiver/descriptors.py接收器型号信息lib/logitech_receiver/base_usb.py底层请求与 I/Olib/logitech_receiver/base.py通知监听线程lib/logitech_receiver/listener.py通知处理与分发lib/logitech_receiver/notifications.py设置基类与读写通道lib/logitech_receiver/settings.py设置模板全部设置lib/logitech_receiver/settings_templates.py设置值验证器lib/logitech_receiver/settings_validator.pySolaar 规则引擎lib/logitech_receiver/diversion.pyudev 发现与 I/O 实现lib/hidapi/udev_impl.pyCLI 入口与子命令lib/solaar/cli/init.pyGUI 监听与状态回调lib/solaar/listener.pyGUI 主窗口lib/solaar/ui/window.py相关文档延伸阅读docs/index.mdSolaar 总览、支持设备、预编译包与手动安装说明docs/capabilities.md能力清单包括 Gnome 下系统托盘的配置方法docs/usage.mdGUI 与 CLI 使用指南docs/rules.mdSolaar 规则的编写与配置docs/devices.md支持设备列表与特性docs/features.mdHID 特性说明docs/installation.md手动安装步骤docs/hidpp-documentation.txtHID 协议文档设备型号说明示例见 docs/devices 目录下的各 txt 文件。赞分享开发工具【免费下载链接】SolaarLinux device manager for Logitech devices项目地址https://gitcode.com/gh_mirrors/so/Solaar点击查看免费下载相关推荐Logitech设备管理终极指南如何在Linux下用Solaar实现完美控制Logitech设备管理终极指南如何在Linux下用Solaar实现完美控制 想要在Linux系统中完美管理你的Logitech无线设备吗Solaar作为一开发工具SWR-Firestore错误处理最佳实践构建健壮的Firestore应用SWR Firestore错误处理最佳实践构建健壮的Firestore应用 在现代React应用开发中处理数据获取和错误管理是构建可靠用户体验的关键环节。S如何训练自定义AiZynthFinder模型从数据准备到模型部署的完整指南如何训练自定义AiZynthFinder模型从数据准备到模型部署的完整指南 AiZynthFinder是一个强大的逆合成规划工具它使用蒙特卡洛树搜索算法来递科研人工智能上一篇OpenInference数据隐私保护如何安全地监控敏感AI应用数据下一篇Eino框架终极指南掌握AI智能体的函数调用与执行机制创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关推荐

金融支付系统开发实战:幂等、对账与资金安全核心设计
金融支付系统开发实战:幂等、对账与资金安全核心设计

1. 从"financial-services"这个标题里能读出什么"financial-services"这个词看起来简单,甚至有点泛,但它其实是一个典型的领域级标签,而不是某个具体产品名或技术框架名。拿到这个标题的时候,我第一反应是&am… · 2026/9/25 7:50:33

手机云原生开发实战:终端兼容性与云原生IDE选型指南
手机云原生开发实战:终端兼容性与云原生IDE选型指南

1. 这不是“手机上写个Hello World”——而是真正在移动设备上跑通完整开发闭环2026年,我用折叠屏手机在高铁上完成了从需求评审、代码编写、单元测试到容器镜像构建、Kubernetes集群部署的全流程。没有远程桌面,不依赖PC中转,整个过程在终端… · 2026/9/25 7:50:33

Twig html_attr_type 过滤器:将数组转换为符合 HTML 属性语法的专用值对象
Twig html_attr_type 过滤器:将数组转换为符合 HTML 属性语法的专用值对象

后端 【免费下载链接】Twig Twig, the flexible, fast, and secure template language for PHP 项目地址: https://gitcode.com/gh_mirrors/tw/Twig 点击查看 免费下载 本文介绍 Twig html-extra 包中的 html_attr_type 过滤器:它把普通的 PHP 数组转换… · 2026/9/25 7:50:33

人工智能数学基础:习题答案+源代码如何帮你彻底弄懂公式
人工智能数学基础:习题答案+源代码如何帮你彻底弄懂公式

简介:一份聚焦人工智能数学基础的资源包,由唐宇迪编著,面向AI学生与从业者,帮助逐项补齐线性代数、概率统计、微积分、最优化、图论、离散数学与动态规划等核心数学短板,通过习题与代码将理论落到实践。压缩包整体约6.… · 2026/9/25 8:20:28

HDMI信号传输原理:从TMDS编码到音频PCM打包的FPGA实现
HDMI信号传输原理:从TMDS编码到音频PCM打包的FPGA实现

HDMI 这玩意儿现在满大街都是,电视、显示器、机顶盒、笔记本、游戏机,甚至树莓派和 FPGA 开发板上都标配。但真要问一句“HDMI 到底是怎么把画面和声音从一根线送过去的”,能说清楚的人并不多。我当初调 FPGA 的 HDMI 输出时,对着… · 2026/9/25 8:20:22

8G显存本地部署minimaxh3:ComfyUI剪枝版+加速LoRA实战
8G显存本地部署minimaxh3:ComfyUI剪枝版+加速LoRA实战

1. 为什么要在8G显存上折腾minimaxh3本地部署先把结论摆在前面:8G显存跑minimaxh3,能跑,但绝对不是“点一下按钮就出片”的体验。我前后折腾了差不多两周,从最初的直接爆显存,到后来能把一段5秒的480P视频稳定生成出来… · 2026/9/25 8:20:16

物联网健康监测系统设计:从树莓派网关到多传感器报警闭环
物联网健康监测系统设计:从树莓派网关到多传感器报警闭环

简介:一套面向物联网开发者和嵌入式学习者的健康监测系统设计资料,围绕树莓派网关、加速度计、音频与视频监测、Web端应用等核心模块展开,覆盖从硬件数据采集、传感器信号处理到云端传输与远程管理的完整链路,可支撑课程设计、项目… · 2026/9/25 8:20:16

Atlas 300V 24G部署YOLO实战:从硬件认知到推理调优全流程
Atlas 300V 24G部署YOLO实战:从硬件认知到推理调优全流程

最近后台私信里问得最多的一个东西,就是Atlas 300V 24G。问来问去其实就两句话:这卡到底是不是运算加速卡?能不能用来部署YOLO?我的回答一直很直接:能,而且就是干这个的。Atlas 300V 24G是华为昇腾阵营里一… · 2026/9/25 8:20:16

让Codex像安全工程师一样审代码:Cloudflare Security Audit Skill解析
让Codex像安全工程师一样审代码:Cloudflare Security Audit Skill解析

现在让任何一个主流编程代理去“审一遍代码安全”,它多半会给你交出一份看似全面的报告:SQL 注入、XSS、SSRF 列得整整齐齐,但仔细一看,全是模型对漏洞定义的通识复述,既没确认数据流是否真的从用户输入走到了危险函数… · 2026/9/25 8:20:16

数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)
数值优化(Numerical Optimization)学习系列-03-共轭梯度方法(Conjugate Gradient)

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31

MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码