e lectron-egg前段业务框架学习记录【4】mac系统node-hid设备打开独占问题

443 阅读3分钟

上接前面三篇,记录自己开发中碰到的问题,以备查看。

mac系统中使用node-hid类库打开usb鼠标设备,无论是异步方式打开还是同步方式打开,都会存在独占方式打开。接管鼠标设备后,能看到鼠标发来的数据,但是操作系统中不能使用鼠标,鼠标指针也不能晃动了。

一 阅读node-hid源码

扒拉node-hid的源码,发现关键说明。 node-hid下面又调用了类库hidapi,而hidapi有真正操作hid设备的方法,

image.png

跟踪源码发现,使用 new HID.HID(vid,pid)最终也会调用new HID.HID(path)。

而在hid_open_path方法中调用了hid_init,在hid_init中初始化为了独占模式。

image.png

image.png

二 解决方案

第一种方式:需要把hid_init中默认的独占模式1改为共享模式0. 第二种方式,需要增加一个函数,在hid_init之后立马调用hid_darwin_set_open_exclusive,设置为共享模式。

三 选中第二种方式

我选择了第二种方案,尽量不改变源码内部的结构,通过增加导出函数的方法达到目的。

3.1 源码下载 + 重新编译

以下是改动步骤: 从git-hub下载node-hid源码,关注Publishing.md中内容。 如果需要,可以在每个MacOS、Windows、Linux上手动测试:

如果需要,可以在每个MacOSWindowsLinux上手动测试:

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 更改导出函数

  1. src/exports.cc ,增加导出函数
exports.Set("hidInitAndNotExclusive", Napi::Function::New(env, &hidInitAndNotExclusive));
  1. src/devices.h 增加函数声明
Napi::Value hidInitAndNotExclusive(const Napi::CallbackInfo &info);
  1. 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();

}
  1. /nodehid.js 增加导出函数
function hidInitAndNotExclusive(...args) {

loadBinding();

return binding.hidInitAndNotExclusive.apply(...args);

}
exports.hidInitAndNotExclusive = hidInitAndNotExclusive;
  1. 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上运行报错了。还有待解决。 报错信息如下:

image.png 我现在还不知道是什么原因。 现在的是在mac编译win64和win32,然后拖动到window系统使用。 编译版本是python3.9.6,官网要求2.7 。不知道是否是这个问题,待验证。

image.png