无线环境下,也许键盘接收器与键盘所处位置并不一定在同一个房间,或者离得很远。
可以将无线键盘接收器插在linux
设备上,使用 usbip
共享到远程主机上,
usbip Linux安装和使用有现成的教程,但也许接收器插在 Linux 主机上,但需要操作 Windows
系统。(一般Moonlight 远程串流需要用到)
linux 安装 server端 ( Ubuntu 22 ):
# 树莓派使用下面的命令
sudo apt install usbip
## 以下两行为 Ubuntu22
sudo apt install linux-tools-virtual
# 根据系统内核的不同,安装的版本不同,安装前输入 usbip 会有提示
apt install linux-tools-6.5.0-21-generic
安装完成后,使用脚本 开机自动加载 usbip
开机命令加入 loadusbip.sh init
#!/usr/bin/env bash
function init(){
modprobe usbip-core
modprobe usbip-host
# 作为服务端不需要加载此模块
# modprobe usbip-vudc
modprobe vhci-hcd
usbipd -D # 让usbipd在后台运行
# usbip list --local # 查看当前可用usb设备
# usbip bind --busid=ID # ID为看到的可用usb的id 比如: 1-1.1
echo -E 'init usbip success'
}
function loadusb(){
id=`usbip list -l |grep $1 |grep - |awk '{print $3}'`
if [ "$id"x != ""x ]; then
usbip bind --busid="$id"
fi
}
if [ "$1"x == "init"x ]; then
init
elif [ "$1"x == "restart"x ]; then
if [ "$2"x != ""x ]; then
usbip unbind --busid="$2"
fi
fi
# 键盘接收器
loadusb "1f81:2102"
windows 安装 usbip 客户端并加载
github项目 release 页面下载最新 usbip 并解压到一个目录中
在目录的上方输入 cmd
即可打开命令行窗口。
windows 初次运行需要执行安装命令:
usbip.exe install
然后执行挂载命令即可:
usbip list --remote=服务机ip # 查看服务机的bind绑定列表
usbip attach --remote=服务机ip --busid=ID # id为查看到的id
windows 自动挂载
windows 现在已经可以挂载usb设备了。但每次重启后,都要重新启动命令行,执行挂载,可以使用windows 的计划任务
选择创建基本任务
设定程序路径,并打开属性对话框
必须设置使用管理员权限运行
设定触发器。使其连接网络、开机重启、系统休眠都能自动挂载,防止无线键盘失连:
设定联网自动运行的事件id为 8001
:
联网及系统启动触发器建议设置 30s 延迟,启动及联网时,立即执行任务未必能加载成功。
windows 开机启动有黑窗口问题
开机执行 usbip attach
即可, 但是如果使用的是 cmd
脚本,开机会有黑窗口,使用 vbs 即可隐藏掉黑窗口问题
start.vbs
:
set ws=WScript.CreateObject("WScript.Shell")
ws.Run "cmd /c D:\software\usbip-win-0.3.6-dev\loadusb.bat",0
loadusb.bat
脚本:
@echo off
%1(start /min cmd.exe /c %0 :&exit)
%1 mshta vbscript:CreateObject("Shell.Application").ShellExecute("cmd.exe","/c %~s0 ::","","runas",1)(window.close)&&exit
cd /d "%~dp0"
curl http://nuc:8295/restart?id=3-7.3
usbip.exe attach -r nuc -b 3-7.3
异常断开优化
正常情况下,网络断开的
usbip
设备能够自动恢复,例如关闭wifi、关机等操作。然而如果直接拔掉 windows 电源。设备会一直处于一个挂载状态,无法再被开机自动挂载。
此时必须执行
usbip unbind --busid=xxx
取消绑定,然后再次执行usbip bind --busid=xxx
才行然而一切都要自动化,无感连接。不能因为连接无线键盘做额外的任何操作
于是可以每次电脑开机都自动取消挂载并重新挂载。
Linux上使用 root
用户启动一个 node 程序,监听 8295
端口,每次收到 restart
命令重启usb设备
源码如下:
#!/usr/local/bin/node
const { createServer } = require("http");
const urlparse = require('url');
var exec = require('child_process').exec;
const HOST = "0.0.0.0";
const PORT = 8295;
async function execmd(cmd){
console.log(cmd);
let over = false; let waitcall = null;
let _err, _stdout, _stderr = null;
exec(cmd, async function(err,stdout,stderr){
_err = err; _stdout = stdout; _stderr = stderr;
if (! over){
over = true;
if(waitcall){
waitcall(); waitcall = null;
}
}
});
if (! over){
await new Promise(r => {waitcall = r});
}
return [_err, _stdout, _stderr];
}
const server = createServer(async (req, resp) => {
if (req.url.indexOf("/restart")==0){
// res = await execmd('echo test');
// console.log(req.url);
let id = urlparse.parse(req.url, true).query['id'];
console.log(id);
if (id && id != ''){
// 传入正确的 loadusbip.sh 路径
await execmd('/xxxxx/loadusbip.sh restart ' + id);
}
resp.writeHead(200, { "Content-Type": "plain/text" });
resp.end("执行成功");
} else {
resp.writeHead(500, { "Content-Type": "plain/text" });
resp.write("必须传入正确的链接");
resp.end();
}
});
server.listen(PORT, HOST, (error) => {
if (error) {
console.log("Something wrong: ", error);
return;
}
console.log(`server is listening on http://${HOST}:${PORT} ...`);
});
在执行 usbip.exe attach
前执行重启命令即可:
curl http://nuc:8295/restart?id=3-7.3
如上面 loadusb.bat
所示。 现在 windows 可以自动无感加载一个远程的键盘接收器了。只要网络能够通畅,这个接收器就可以通过无线键盘操作主机设备。
U盘、鼠标、连接的手机等均可以实现此操作
外网环境自动挂载远程设备有一定的安全风险