上接前面三篇,记录自己开发中碰到的问题,以备查看。
mac系统中使用node-hid类库打开usb鼠标设备,无论是异步方式打开还是同步方式打开,都会存在独占方式打开。接管鼠标设备后,能看到鼠标发来的数据,但是操作系统中不能使用鼠标,鼠标指针也不能晃动了。
一 阅读node-hid源码
扒拉node-hid的源码,发现关键说明。 node-hid下面又调用了类库hidapi,而hidapi有真正操作hid设备的方法,
跟踪源码发现,使用 new HID.HID(vid,pid)最终也会调用new HID.HID(path)。
而在hid_open_path方法中调用了hid_init,在hid_init中初始化为了独占模式。
二 解决方案
第一种方式:需要把hid_init中默认的独占模式1改为共享模式0. 第二种方式,需要增加一个函数,在hid_init之后立马调用hid_darwin_set_open_exclusive,设置为共享模式。
三 选中第二种方式
我选择了第二种方案,尽量不改变源码内部的结构,通过增加导出函数的方法达到目的。
3.1 源码下载 + 重新编译
以下是改动步骤: 从git-hub下载node-hid源码,关注Publishing.md中内容。 如果需要,可以在每个MacOS、Windows、Linux上手动测试:
如果需要,可以在每个MacOS、Windows、Linux上手动测试:
git clone https://github.com/node-hid/node-hid.git
cd node-hid
npm run distclean # if not a fresh checkout
npm run prepublishOnly # get the hidapi submodule
npm install --build-from-source # rebuilds the C code
npm run showdevices # simple test
node ./src/test-ps3.js # simple test
首先更改test-ps3.js中源码,按照path方式打开设备。之后启动源码,测试原代码是否正常运行。
var HID = require('../');
var REPL = require('repl');
var repl = REPL.start('node-hid> ');
//后期增加的函数, hid初始化并设置以非独占模式(共享模式)打开
HID.hidInitAndNotExclusive();
var hid = new HID.HID(1133, 49271);
hid.on('data', (data) => {
console.log('got ps3 data', data);
})
repl.context.hid = hid;
setTimeout(function () {
console.log("\n closing");
hid.close();
}, 3000);
3.2 更改导出函数
- src/exports.cc ,增加导出函数
exports.Set("hidInitAndNotExclusive", Napi::Function::New(env, &hidInitAndNotExclusive));
- src/devices.h 增加函数声明
Napi::Value hidInitAndNotExclusive(const Napi::CallbackInfo &info);
- src/devices.cc 增加函数实现
// add by sun, hid初始化并设置以非独占模式(共享模式)打开
Napi::Value hidInitAndNotExclusive(const Napi::CallbackInfo &info)
{
Napi::Env env = info.Env();
auto appCtx = ApplicationContext::get();
if (!appCtx)
{
Napi::TypeError::New(env, "hidapi not initialized").ThrowAsJavaScriptException();
return env.Null();
}
hid_init();
hid_darwin_set_open_exclusive(0); // 0共享,1独占模式
return env.Null();
}
- /nodehid.js 增加导出函数
function hidInitAndNotExclusive(...args) {
loadBinding();
return binding.hidInitAndNotExclusive.apply(...args);
}
exports.hidInitAndNotExclusive = hidInitAndNotExclusive;
- hidapi/hidapi/hidapi.h 增加函数声明
/** @brief Changes the behavior of all further calls to @ref hid_open or @ref hid_open_path.
By default on Darwin platform all devices opened by HIDAPI with @ref hid_open or @ref hid_open_path
are opened in exclusive mode (see kIOHIDOptionsTypeSeizeDevice).
Since version 0.12.0, @ref HID_API_VERSION >= HID_API_MAKE_VERSION(0, 12, 0)
@ingroup API
@param open_exclusive When set to 0 - all further devices will be opened
in non-exclusive mode. Otherwise - all further devices will be opened
in exclusive mode.
@note During the initialisation by @ref hid_init - this property is set to 1 (TRUE).
This is done to preserve full backward compatibility with previous behavior.
@note Calling this function before @ref hid_init or after @ref hid_exit has no effect.
*/
void HID_API_EXPORT_CALL hid_darwin_set_open_exclusive(int open_exclusive);
3.3 代码更改完毕后,重新编译源码,
npm run distclean # if not a fresh checkout
npm run prepublishOnly # get the hidapi submodule
npm install --build-from-source # rebuilds the C code
npm run showdevices # simple test
node ./src/test-ps3.js # simple test
3.4 拷贝编译后的源码
最后把整个项目(根目录下所有文件)复制到 应用项目aaa根目录下的/node_moudles/node_hid下。
3.5 在应用项目aaa中使用我们新增的函数
getUsbhidDeviceList() {
// mac系统需要单独处理
if (process.platform !== 'darwin') {
// hid初始化并设置以非独占模式(共享模式)打开
HID.hidInitAndNotExclusive();
}
//主线程获取usb列表
const list = HID.devices();
return list;
}
后记
现在mac系统上运行没问题,但是在window上运行报错了。还有待解决。 报错信息如下:
我现在还不知道是什么原因。
现在的是在mac编译win64和win32,然后拖动到window系统使用。
编译版本是python3.9.6,官网要求2.7 。不知道是否是这个问题,待验证。