你是否注意到,在疯狂的技术世界里,总有一个古怪的小项目试图解决一个如此小众的问题,以至于它唯一的竞争对手可能是一把左撇子螺丝刀和一个自隐藏闹钟?

我在日常工作流程中使用两台不同的电脑,并在一台键盘/鼠标之间共享。尝试了在 Amazon 上找到的几个 USB 切换盒后,我发现它们都存在类似的问题——切换需要一段时间,试图找到按钮的过程相当笨拙,而且随着时间的推移,它并没有变得更好。

我想要的只是通过键盘快捷键快速切换输出的方法,同时能够通过神奇地将鼠标指针在显示器之间移动来实现相同的操作。这个项目使你能够做到这两点,即使你的电脑运行不同的操作系统!

DeskHop 机箱和主板

特性

  • 完全免费且开源
  • 切换时无明显延迟
  • 只需将鼠标指针拖动到电脑之间
  • 无需安装软件
  • 价格实惠且易于获取的组件(<15€)
  • 3D 可打印的卡扣式机箱
  • 输出端之间完全的电气隔离
  • 支持 Linux、macOS 和 Windows

用户手册现已提供

开源硬件标志


工作原理

该设备充当你的键盘/鼠标和电脑之间的中介,同时与两台电脑建立并保持连接。然后根据你的选择,选择将你的鼠标和按键转发到哪里。键盘跟随鼠标,反之亦然,因此只需将鼠标拖到另一个桌面即可切换两者。

鼠标

为了让鼠标光标神奇地跳过,鼠标 HID 报告描述符被更改为使用绝对坐标,然后鼠标报告(仍然以相对移动的形式到来)在内部累积,保持对位置的准确计数。

当你试图在另一个显示器的方向离开显示器区域时,它会保持 Y 坐标,并将最大 X 值与最小 X 值交换,然后翻转输出。这确保了光标在另一个显示器上以相同的高度无缝出现,增强了平滑过渡的感知。

DeskHop 鼠标演示

将鼠标从 Mac 拖到 Linux 会自动切换输出。


实际的切换发生在箭头停止移动而另一个箭头开始的瞬间。

键盘

它充当 USB 主机并定期查询你的键盘,在 HID 报告中查找预配置的热键(对我来说通常是 Ctrl + Caps Lock)。找到后,它会将所有后续字符转发到另一个输出。

为了在任何给定时刻直观地指示你正在使用哪个输出,你可以重新利用键盘 LED 灯来提供必要的反馈。

它还会记住每台电脑的 LED 状态,因此你可以准确地恢复到你离开时的状态。

DeskHop 打字演示

如何构建

为了避免构建时的版本不匹配和报告的路径问题,以及避免你下载大型 SDK,该项目现在捆绑了最小的 pico sdk 和 tinyusb。

在 Debian/Ubuntu 系统上,请确保安装以下内容:

apt update
apt install \
    build-essential \
    cmake \
    gcc-arm-none-eabi \
    libnewlib-arm-none-eabi \
    python3

你应该能够通过运行以下命令来构建:

cmake -S . -B build
cmake --build build

此外,要重建 Web UI,请检查 webconfig/ 并执行 ./render.py,你需要安装 jinja2。

另一种选择是使用 docker 通过 'docker compose' 或 'docker-compose':

docker-compose -f misc/docker.yml run --rm build_container

这确保了可重现的构建。

要重建磁盘,请检查 disk/ 文件夹并运行 ./create.sh,如有需要,请根据你的系统进行调整。你需要 dosfstools(以提供 mkdosfs)。

使用预构建镜像

或者,你可以使用预构建镜像。从 0.6 版本开始,只有一个通用镜像。你需要 .uf2 文件,你只需将其复制到设备中,方法如下:

升级固件

选项 1 -(固件 0.6 及更高版本)通过同时按下左 Ctrl + 右 Shift + c + o将设备置于“配置模式”。你的键盘插入的设备将重新启动并变成一个名为“DESKHOP”的 USB 驱动器。你只需将 .uf2 文件复制到其中即可。镜像验证后,设备将刷新并重新启动,然后继续升级另一块板。在此操作期间,LED 将闪烁。完成后,它将写入闪存并重新启动,完成操作。

注意 - 这不是一个真正的通用 USB 驱动器,你不能用它来复制文件。

选项 2 - 使用 ROM 引导加载程序 - 在连接每个 Pico 时按住板载按钮,然后将 uf2 复制到出现的闪存驱动器中。0.6 之后的镜像支持按住按钮而无需摆弄电源,但“插入时按住按钮”应该始终有效,无论设备状态如何。

选项 3 - CDC 闪存命令(仅限调试构建) - 如果固件是使用 DH_DEBUG_CDC_FLASH=ON 构建的,你可以通过 CDC 串行命令触发引导加载程序模式:

echo -n 'flash' > /dev/tty.usbmodem11104

这会立即将设备重置为引导加载程序模式,在那里它显示为“RPI-RP2”驱动器。此功能旨在用于开发工作流程。

其他功能

鼠标减速

有没有试过将 YT 视频滑块移动到特定位置,但你的鼠标移动太跳跃,突然间你的手就像 5 岁时玩“手术”游戏一样小心翼翼?

按右 CTRL + 右 ALT 切换慢速鼠标模式。鼠标指针将大大减慢,使你能够完成更精细的精度工作,并且通过快速再次按下相同的键,鼠标仍可正常移动。

切换锁定

如果你想锁定自己到一个屏幕,请使用 RIGHT CTRL + K。 这将确保你不会意外离开当前屏幕。要关闭,请再次按下相同的键组合。

锁定两个屏幕

你可以使用 RIGHT CTRL + L 同时锁定两台电脑。 要使用此功能,请先在配置中为每个输出设置操作系统(因为快捷键不同)。

游戏模式

如果你在玩游戏,你的游戏可能无法与绝对鼠标模式正常工作。为了解决这个问题,引入了游戏模式,通过 LEFT CTRL + RIGHT SHIFT + G 切换。在游戏模式下,你将被锁定在当前屏幕上,你的鼠标行为像标准的相对鼠标。这也应该可以解决各种虚拟机问题、当前不支持的操作系统等。

屏幕保护程序

据称内置是为了防止电脑进入待机状态,但说实话——它只是看起来很有趣。默认关闭,会让你的鼠标指针像乒乓球一样在屏幕上弹跳。启用后,它会在用户配置标头中定义的不活动期后激活,并在你向该屏幕发送任何输出时自动关闭。

潜在的使用示例——我有一个有问题的 USB 扩展坞,它无法从待机状态恢复视频,因此不允许它睡眠可能是一个方便的解决方法。

硬件

电路基于两块 Raspberry Pi Pico 板,选择它是因为它们便宜(4.10 € / 块),可以手工焊接,并且大多数供应商都有现货。

Pico 通过 UART 连接,并由 Analog Devices ADuM1201 双通道数字隔离器(约 3€)或更便宜、更快且引脚兼容的 TI ISO7721DR(约 1.5€)隔开,后者是首选。

虽然它们通常不支持双 USB,但由于一个令人惊叹的项目,其中 USB 是使用 RP2040 中发现的可编程 IO 魔法实现的,因此支持它既可以充当 USB 主机,也可以充当 USB 设备。

PCB [已更新]

为了尽可能简化 DIY 构建,布线保持在一侧,零件数量保持在最低限度。

PCB 图像

USB D+/D- 差分线应具有相同的长度,但它们故意略微不对称,以抵消相应 GPIO 布线 PICO PCB 本身的长度差异,因此总长度应匹配。

Zd(差分阻抗)目标为 90 欧姆(设法达到 ~107,足够接近 :))。

厚度设计为 1.6 毫米,以确保卡扣式正常工作。

PCB 有 2 个版本(对用户没有重大差异)。原始版本 (v1.0) 更容易焊接和组装,而 v1.1 提供了一些升级,例如:

  • 添加了 ESD 保护 (TPD4E1U06DBVR)

  • 为键盘/鼠标连接器添加了 VBUS 电容

  • 丝印方向标记

  • 为带有预焊接头的克隆板提供孔位,更易于对齐

  • USB 27 欧姆电阻

    由于小型瞬态电压抑制器 IC 和 0805 电阻,此版本的手工焊接难度略高,但完全可以完成。TVS 理论上可以省略(不建议),它仍然可以工作。

即将推出——使用裸 rp2040 的板,不需要 Pico,更小更方便。

机箱

由于我不太擅长 3D,机箱简单而基本,但能完成工作。它应该易于打印,使用约 33g 耗材,需要几个小时。

水平 PCB 移动由穿过孔的销钉抵消,垂直移动由侧面的卡扣式凸耳抵消——不需要螺丝。机箱经过轻微重新设计,带有标志和两个额外的卡扣式凸耳,因此它提供了更好的密封。

两块板上的 Micro USB 连接器从机箱侧面偏移,因此稍大的孔应允许电缆伸入。

盖子是卡扣式设计,带有用于打开的螺丝刀槽。顶部的标记是凹陷的,可以用例如蜡笔完成以获得更好的对比度(或简单地保持原样)。

带 3D 打印机箱的 DeskHop

物料清单

点击此处查看原始 PCB v1.0 BOM
组件 数量 单价 / € 价格 / €
Raspberry Pi Pico 2 4.10 8.20
ADuM1201BRZ 1 2.59 2.59
Cap 1206 SMD 100nF 2 0.09 0.18
USB-A PCB conn. 2 0.20 0.40
Headers 2.54 1x03 2 0.08 0.16
总计 11.53

TI ISO7721DR 可以代替 ADuM 使用——它引脚兼容,更便宜,规格更好。

PCB v1.1

组件 部件 数量 单价 / € 价格 / €
U1, U2 Raspberry Pi Pico 2 4.10 8.20
J1, J4 USB-A PCB conn. 2 0.20 0.40
U4 TI ISO7721DR 1 1.40 1.40
ADuM1201BRZ)
C1, C2 Cap 0805 SMD 100nF 2 0.09 0.18
R1, R2, R3, R4 Res 0805 SMD 27ohm 4 0.03 0.12
U3, U5 TPD4E1U06DBVR 2 0.31 0.62
C3, C4 Cap 4.7uF SMD 0805 2 0.07 0.14
J2, J3 Headers 2.54 1x03 2 0.08 0.16
总计 11.22

USB-A 连接器可以是 Molex MX-67643-0910 或具有相同尺寸的更便宜/经济型产品。

额外步骤:

组装指南

如果你有一些电子产品经验,你不需要这个。但是,你们中的一些人可能没有,在这种情况下,这个视频可能会帮助你完成整个过程。请注意,焊接后你应该清除 PCB 上的助焊剂以防止腐蚀。

这样做的标准过程是使用异丙醇和一把旧牙刷。但你猜怎么着?我不会把我的旧牙刷放到网上,所以你只需要即兴发挥那部分 :)

PCB 组装指南

[注意] 视频组装指南涵盖 pcb v1.0。修订版本非常相似,程序基本相同。

使用指南

键盘快捷键 -(固件版本 0.68+)

配置

  • 左 Shift 左 Ctrl + 右 Shift + C + O - 进入配置模式
  • 右 Shift + F12 + D - 删除闪存配置
  • 右 Shift + F12 + Y - 保存屏幕切换偏移

使用

  • 右 CTRL + 右 ALT - 切换慢速鼠标模式
  • 右 CTRL + K - 锁定/解锁鼠标桌面切换
  • 右 CTRL + L - 一次锁定两个输出(之前设置输出操作系统,见下面的快捷键)
  • 左 Shift 左 CTRL + 右 Shift + G - 切换游戏模式(锁定到屏幕,充当标准鼠标)
  • 左 CTRL + 右 Shift + S - 启用屏幕保护程序
  • 左 CTRL + 右 Shift + X - 禁用屏幕保护程序
  • 左 CTRL + Caps Lock - 在输出之间切换

注意:有些键盘不能同时正确发送两个 shift,这就是为什么快捷键被更改的原因——为了让每个人都能工作。抱歉造成混淆。

切换光标高度校准

这不是必需的,但如果你的屏幕没有完全对齐或尺寸不同,它可能会派上用场。目标是让鼠标指针以完全相同的高度出来。

边框高度差异

只需将你的鼠标停放在较大屏幕上,高度与较小/较低屏幕的高度相同(图示),然后按 右 Shift + F12 + Y。你的 LED(和 Caps Lock)应该闪烁以确认。

对底部边框重复此操作(如果它位于较大屏幕边框的上方)。这将保存到闪存中,从现在起它应该保持这个校准值。

每个输出多个屏幕

Windows 和 Mac 在多个屏幕和绝对定位方面存在问题,因此需要解决方法(仍在实验中)。一个更好的解决方法正在构建中,但目前你必须为每个输出和屏幕数量设置操作系统。

你的主屏幕需要在中间,辅助屏幕在边缘。要配置实际选项,请打开设备的 Web 配置页面。

每个输出多个屏幕

Web 配置模式

从固件 0.6 开始,引入了改进的配置模式。要配置你的设备,请按照以下说明操作:

  1. 按左 Ctrl + 右 Shift + C + O - 你的设备将重新启动并进入配置模式(在你的键盘插入的一侧)。在配置会话期间,LED 将持续闪烁。

  2. 一个名为“DESKHOP”的新 USB 驱动器将出现,其中包含一个文件 config.htm

  3. 使用 Chromium / Chrome 打开该文件。目前不支持 FF,因为它们避免实现 WebHID。

  4. 点击连接并允许 deskhop 设备配对。

    带 URL 的 Web 浏览器

  5. 根据需要配置选项,然后点击保存以写入设备。

  6. 点击菜单中的“退出”以离开配置模式以增加安全性。

    Web 配置

Linux 看不到设备?点击此处。

:Chromium 在 Linux 上无法工作。

:你可能需要调整 /dev 权限或创建相应的 udev 规则文件,并确保你的用户在正确的组中,例如:

/etc/udev/rules.d/99-deskhop.rules

KERNEL=="hidraw*", SUBSYSTEM=="hidraw", ATTRS{idVendor}=="1209", ATTRS{idProduct}=="c000", GROUP="plugdev", MODE="0660"

:为什么不简单地创建一个像 Via 这样的漂亮在线网页,而不是处理这个奇怪的 USB 驱动器问题?

:从随机在线位置加载与你的输入设备交互的 javascript 存在潜在的安全风险。配置网页仅为本地,没有任何内容是从外部加载的。

请注意,配置网页不是因为故意混淆而“奇怪”——它是自解压的,因为存储空间非常有限。整个源代码 100% 开放,是这个仓库的一部分。鼓励你自己重建所有内容。

功能验证

当你连接一个新的 USB 外设时,板子将闪烁 LED 两次,并指示另一块板也这样做。这样你就可以测试每个板的 USB 和传出通信是否正常工作。

通过先在一侧插入键盘,然后在另一侧插入来执行此测试。如果一切正常,LED 在两种情况下都会快速来回闪烁。

安全与防护

有些功能是故意缺失的,尽管它会使设备更易于使用或更易于配置。以下是这些决定的快速分解:

  • 系统之间没有复制粘贴或任何信息共享。这可以防止信息泄露。
  • 没有 WebHID 设备管理,没有明确的用户同意。没有来自输出电脑的入站连接,唯一的例外是标准的键盘 LED 开/关消息,并且严格限制为 1 字节数据。
  • 无法从输出端触发 FW 升级。只有通过特殊键盘快捷键的明确和有意的用户操作才能做到这一点。
  • 插入的键盘/鼠标自定义端点不会被暴露或信息转发到这些设备。它们的潜在漏洞被有效地从电脑中隔离。
  • 不允许保留输入历史记录。
  • 不会出于任何原因启动按键。只有你输入/触发的内容才会输出。
  • 输出端在物理上分离,并通过最小 2kV 的隔离电压进行电气隔离。
  • 设备之间交换的所有数据包都是固定长度的,传输的配置选项仅限于短列表。大多数选项是只读的。可以禁用跨设备固件升级。
  • 没有蓝牙或 WiFi、网络、互联网访问等。
  • 在任何情况下,连接的电脑都不被视为可信。
  • 配置模式在不活动一段时间后会自动禁用。
  • 全部代码都是开源的,没有任何二进制 blob,并经过彻底的注释来解释其目的。我鼓励你永远不要相信任何人,并始终通过进行手动审计来确保你知道你在运行什么。

这仍然不能保证任何事情,但我相信它制定了一套合理的规则来确保你的安全和保护。

常见问题

  1. 我只有两块 Pico,我可以没有 PCB 和隔离器吗?

    当然。推荐使用隔离器,但没有它也应该可以工作。

  2. 如果我的显示器有两种不同的分辨率会怎样?

    鼠标移动是在抽象坐标空间中完成的,你的电脑会计算出它与物理屏幕的对应关系,所以它应该可以工作。

  3. 我在哪里可以买到它?

    我不卖任何东西,这只是一个个人的、非商业性的业余项目。

    更新 1:你似乎可以从 Elecrow(如果你点击此链接) 以 1 件起订(无论是 PCB、组装好的 PCB 还是完全组装好的设备) 据用户报告,你的板子到达时是空白的,你必须自己写入固件。

    更新 2:我从未向 Elecrow 要求任何东西,但几天前他们提出用一小笔预算赞助该项目,该预算将用于未来的板子原型设计。由于我的目标是创建一个更好的板子,具有更多输出等,我相信原型设计服务可能对该项目有益。

  4. 当通过鼠标更改活动屏幕时,键盘是否跟随(反之亦然)?

    是的,想法是让它表现得像一台单一的电脑。

  5. 这是否适用于键盘/鼠标组合接收器,例如 Logitech Unifying 接收器?

    应该可以工作。经过最近的固件更新,对组合接收器的支持应该会好得多。

  6. 这是否适用于具有单独无线接收器(一个用于鼠标,另一个用于键盘)的无线鼠标和键盘?

    应该可以工作——尝试过 Anker 无线鼠标和单独的接收器,工作得很好。

  7. 我在构建或编译时遇到问题

    请查看可能有一些答案的故障排除 Wiki

软件替代方案

如果你在你的特定情况下可以工作,你可以使用几种软件替代方案。

  1. Barrier - 免费,开源
  2. Input Leap - 免费,开源
  3. Synergy - 商业
  4. Mouse Without Borders - 免费,仅限 Windows
  5. Universal Control - 免费,Apple 产品

缺点

  • Windows 10 在 KB5003637 中破坏了 HID 绝对坐标行为,因此你不能在 Windows 上使用多个屏幕(鼠标将停留在主屏幕上)。有一个实验性的解决方法,一个更好的方法正在开发中。
  • 代码需要清理,一些重构等。
  • 没有用各种设备进行测试,我不知道它在你的硬件上会如何工作。有合理的理由相信它可能无法开箱即用。
  • 高级键盘(带有旋钮、额外按钮或滑块)可能会遇到这些额外硬件无法正常工作的问题。
  • 具有 300 个按钮的超现代鼠标可能会看到某些按钮无法按预期工作。
  • 注意:两台电脑都需要连接并为 USB 提供电源才能工作(因为每块板都由它插入的电脑供电)。如今,许多台式机和笔记本电脑即使在关机时也会提供电源。如果你需要在完全断开一块板的情况下运行,你应该能够使用 USB 集线器将键盘和鼠标都插入一个端口。
  • MacOS 在多个屏幕方面存在问题,最新的固件提供了一个实验性的解决方法来修复它。

进展

那么,所有这些热情是怎么回事?我不敢相信——请允许我感谢你们所有人!我从未预料到这样一个简单的个人项目会有这种兴趣,所以最初的功能非常基础(就像我的烹饪技巧一样),主要涵盖我自己的用例。敬请期待固件更新,这些更新将带来更广泛的设备兼容性、更多功能和更少的错误。由于这是一个业余项目,我感谢你对时间限制的理解,并承诺尽我所能。

计划的功能:

  • 针对多屏幕 Windows 和 macOS 的更好解决方法
  • 透明/游戏模式
  • 支持 2 个以上的输出
  • 配置 UI 的改进
  • ... 以及更多!

正在开发一个精简版本,它仅使用一块 Pico W 板提供基本功能,进一步降低成本,即使没有额外的硬件或 PCB,你也可以尝试它。

鼠标轮询现在应该以 1000 Hz 的频率工作(图中的下降是因为我手臂在移动时受伤了 :-)):

鼠标轮询率

赞助/捐赠

我这样做不是为了盈利或任何其他原因,只是为了通过为每个人创造一个更好的工作环境来帮助人们。 如果你想进一步支持该项目,请考虑向像无国界医生这样的慈善机构捐款。

通过 PayPal 向无国界医生捐款

请允许我感谢所有帮助过或正在考虑的人!

免责声明

我恳请任何尝试构建此项目的人理解并承认,我不对任何伤害、损害或其他后果承担责任。你的安全很重要,我鼓励你仔细对待这个项目,在整个过程中采取必要的预防措施,并对你的健康承担个人责任。请不要触电、烧伤、紧张或生气。玩得开心,享受它!

祝你切换愉快!