
本文详解Node.js中使用node-usb库进行USB设备通信时,因误传Buffer对象给endpoint.transfer()导致TypeError [ERR_INVALID_ARG_TYPE]: The "size" argument must be of type number. Received an instance of Buffer错误的根本原因与正确用法。
本文详解node.js中使用`node-usb`库进行usb设备通信时,因误传`buffer`对象给`endpoint.transfer()`导致`typeerror [err_invalid_arg_type]: the "size" argument must be of type number. received an instance of buffer`错误的根本原因与正确用法。
在使用 node-usb(如 usb@1.9.x)进行底层 USB 通信时,Endpoint.transfer() 方法的签名严格区分读写场景,且不接受用户预分配的 Buffer 作为第一个参数——这正是报错的核心原因。
查看官方 TypeScript 定义(源码参考)可知:
- ✅ 读操作(IN endpoint):应调用 endpoint.transfer(size: number, callback),由库内部自动分配并填充 Buffer;
- ❌ 错误写法:endpoint.transfer(buffer, callback) —— 此时 buffer 被误认为是 size 参数,而 size 必须为 number,故抛出 ERR_INVALID_ARG_TYPE。
因此,您原始代码中的这一行:
endpoint.transfer(buffer, (error, actualLength) => { ... });
必须改为指定期望读取的字节数(如 64),而非传入 Buffer:
// ✅ 正确:读操作 —— 仅传 size(number)和回调
endpoint.transfer(64, (error, data) => {
if (error) {
console.error('USB read failed:', error);
targetDevice.close();
return callback('Read failed: ' + error.message);
}
// data 是自动创建的 Buffer,已包含实际接收的数据
const received = data.slice(0, data.length); // 或直接使用 data
targetDevice.close();
callback(null, received.toString('utf8'));
});
⚠️ 注意事项:
- 写操作(OUT endpoint)才使用 endpoint.transfer(buffer, callback) 形式,此时 buffer 是待发送的数据;
- 确保端点方向正确:通过 interface.endpoints.find(ep => ep.direction === 'in') 显式获取 IN 端点;
- node-usb 需要管理员/root 权限访问设备(Windows 下需 WinUSB 驱动,macOS/Linux 需 udev 规则);
- targetDevice.open() 后务必调用 interface.claim()(若接口未被占用),否则 transfer 会失败;
- 实际通信协议(如 CCID、HID、自定义指令)需严格遵循设备手册,缓冲区内容(如 0x04, 0x21, 0x02, blockNum)仅作示意,不可直接复用。
完整修正后的 readDataFromUSBDevice 函数示例:
function readDataFromUSBDevice(vendorId, productId, blockNum, callback) {
const targetDevice = connectToUSBDevice(vendorId, productId);
if (!targetDevice) return callback('USB device not found.');
try {
targetDevice.open();
const interface = targetDevice.interfaces[0];
interface.claim(); // 关键:声明接口所有权
// 显式获取 IN 端点(避免方向错误)
const inEndpoint = interface.endpoints.find(ep => ep.direction === 'in');
if (!inEndpoint) return callback('No IN endpoint found.');
// ✅ 正确调用:只传 size 和回调
inEndpoint.transfer(64, (error, data) => {
interface.release(); // 释放接口
targetDevice.close();
if (error) {
console.error('USB transfer error:', error);
callback('Communication error: ' + error.message);
} else {
callback(null, data.toString('hex')); // 或根据协议解析二进制
}
});
} catch (err) {
targetDevice.close();
callback('Setup error: ' + err.message);
}
}
总结:endpoint.transfer() 的参数语义高度依赖端点方向。牢记「读用 size,写用 buffer」,并配合 interface.claim() 和权限配置,即可稳定实现 USB 设备双向通信。











