Skip to content

Commit

Permalink
update usb@2, and rewrite to typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
song940 committed Aug 4, 2022
1 parent a030591 commit 0311321
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 177 deletions.
1 change: 1 addition & 0 deletions packages/usb/package.json
Expand Up @@ -9,6 +9,7 @@
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"escpos-adapter": "^3.0.0-alpha.4",
"usb": "*"
},
"keywords": [],
Expand Down
286 changes: 109 additions & 177 deletions packages/usb/src/index.ts
@@ -1,211 +1,143 @@
'use strict';
const os = require('os');
const util = require('util');
const EventEmitter = require('events');
let mUsb = null;
const os = require('os');
import { Adapter } from "escpos-adapter";
import { usb, getDeviceList, findByIds } from 'usb';

/**
* [USB Class Codes ]
* @type {Object}
* @docs http://www.usb.org/developers/defined_class
*/
const IFACE_CLASS = {
AUDIO : 0x01,
HID : 0x03,
AUDIO: 0x01,
HID: 0x03,
PRINTER: 0x07,
HUB : 0x09
HUB: 0x09
};

/**
* [function USB]
* @param {[type]} vid [description]
* @param {[type]} pid [description]
* @return {[type]} [description]
*/
function USB(vid, pid){

if (!mUsb) {
/** Changing Code From USB Library NPM
* @see https://github.com/node-usb/node-usb#migrating-to-v200
* **/
let { usb } = require('usb');
mUsb = usb;
}

EventEmitter.call(this);
let self = this;
this.device = null;
if(vid && pid){
this.device = mUsb.findByIds(vid, pid);
}else if(vid){
export default class USBAdapter extends Adapter<[timeout?: number]> {
constructor(vid?: number, pid?: number) {
super();
let self = this;
this.device = null;
if (vid && pid) {
this.device = findByIds(vid, pid);
} else if (vid) {
// Set spesific USB device from devices array as coming from USB.findPrinter() function.
// for example
// let devices = escpos.USB.findPrinter();
// => devices [ Device1, Device2 ];
// And Then
// const device = new escpos.USB(Device1); OR device = new escpos.USB(Device2);
this.device = vid;
}else{
let devices = USB.findPrinter();
if(devices && devices.length)
this.device = devices[0];
}
if (!this.device)
throw new Error('Can not find printer');

mUsb.on('detach', function(device){
if(device == self.device) {
self.emit('detach' , device);
self.emit('disconnect', device);
self.device = null;
} else {
let devices = USBAdapter.findPrinter();
if (devices && devices.length)
this.device = devices[0];
}
});

return this;

};
if (!this.device)
throw new Error('Can not find printer');

usb.on('detach', function (device) {
if (device == self.device) {
self.emit('detach', device);
self.emit('disconnect', device);
self.device = null;
}
});

/**
* [findPrinter description]
* @return {[type]} [description]
*/
USB.findPrinter = function(){
if (!mUsb) {
let { usb } = require('usb');
mUsb = usb;
return this;
}
return usb.getDeviceList().filter(function(device){
try{
return device.configDescriptor.interfaces.filter(function(iface){
return iface.filter(function(conf){
return conf.bInterfaceClass === IFACE_CLASS.PRINTER;
static findPrinter() {
return getDeviceList().filter(function (device) {
try {
return device.configDescriptor?.interfaces.filter(function (iface) {
return iface.filter(function (conf) {
return conf.bInterfaceClass === IFACE_CLASS.PRINTER;
}).length;
}).length;
}).length;
}catch(e){
// console.warn(e)
return false;
}
});
};
/**
* getDevice
*/
USB.getDevice = function(vid, pid){
return new Promise((resolve, reject) => {
const device = new USB(vid, pid);
device.open(err => {
if(err) return reject(err);
resolve(device);
} catch (e) {
// console.warn(e)
return false;
}
});
});
};

/**
* make USB extends EventEmitter
*/
util.inherits(USB, EventEmitter);

/**
* [open usb device]
* @param {Function} callback [description]
* @return {[type]} [description]
*/
USB.prototype.open = function (callback){
let self = this, counter = 0, index = 0;
this.device.open();
this.device.interfaces.forEach(function(iface){
(function(iface){
iface.setAltSetting(iface.altSetting, function(){
try {
// http://libusb.sourceforge.net/api-1.0/group__dev.html#gab14d11ed6eac7519bb94795659d2c971
// libusb_kernel_driver_active / libusb_attach_kernel_driver / libusb_detach_kernel_driver : "This functionality is not available on Windows."
if ("win32" !== os.platform()) {
if(iface.isKernelDriverActive()) {
try {
iface.detachKernelDriver();
} catch(e) {
console.error("[ERROR] Could not detatch kernel driver: %s", e)
}
static getDevice(vid: number, pid: number) {
return new Promise((resolve, reject) => {
try {
const device = findByIds(vid, pid);
device?.open();
resolve(device);
} catch (err) {
reject(err);
}
});
};
open(callback?: ((error: Error | null) => void) | undefined): this {
let self = this, counter = 0, index = 0;
this.device.open();
this.device.interfaces.forEach(function (iface: any) {
(function (iface) {
iface.setAltSetting(iface.altSetting, function () {
try {
// http://libusb.sourceforge.net/api-1.0/group__dev.html#gab14d11ed6eac7519bb94795659d2c971
// libusb_kernel_driver_active / libusb_attach_kernel_driver / libusb_detach_kernel_driver : "This functionality is not available on Windows."
if ("win32" !== os.platform()) {
if (iface.isKernelDriverActive()) {
try {
iface.detachKernelDriver();
} catch (e) {
console.error("[ERROR] Could not detatch kernel driver: %s", e)
}
}
}
}
iface.claim(); // must be called before using any endpoints of this interface.
iface.endpoints.filter(function(endpoint){
if(endpoint.direction == 'out' && !self.endpoint) {
self.endpoint = endpoint;
}
if(endpoint.direction == 'in' && !self.deviceToPcEndpoint) {
self.deviceToPcEndpoint = endpoint;
iface.claim(); // must be called before using any endpoints of this interface.
iface.endpoints.filter(function (endpoint: any) {
if (endpoint.direction == 'out' && !self.endpoint) {
self.endpoint = endpoint;
}
if (endpoint.direction == 'in' && !self.deviceToPcEndpoint) {
self.deviceToPcEndpoint = endpoint;
}
});
if (self.endpoint) {
self.emit('connect', self.device);
callback && callback(null);
} else if (++counter === self.device.interfaces.length && !self.endpoint) {
callback && callback(new Error('Can not find endpoint from printer'));
}
});
if(self.endpoint) {
self.emit('connect', self.device);
callback && callback(null, self);
} else if(++counter === this.device.interfaces.length && !self.endpoint){
callback && callback(new Error('Can not find endpoint from printer'));
} catch (err: any) {
// Try/Catch block to prevent process from exit due to uncaught exception.
// i.e LIBUSB_ERROR_ACCESS might be thrown by claim() if USB device is taken by another process
// example: MacOS Parallels
callback && callback(err);
}
} catch (e) {
// Try/Catch block to prevent process from exit due to uncaught exception.
// i.e LIBUSB_ERROR_ACCESS might be thrown by claim() if USB device is taken by another process
// example: MacOS Parallels
callback && callback(e);
}
});
})(iface);
});
return this;

};

/**
* [function write]
* @param {[type]} data [description]
* @return {[type]} [description]
*/
USB.prototype.write = function(data, callback){
this.emit('data', data);
this.endpoint.transfer(data, callback);
return this;
};

/**
* read buffer from the printer
* @param {Function} callback
* @return {USB}
*/
USB.prototype.read = function(callback) {
this.deviceToPcEndpoint.transfer(64, (error,data) => callback(data));

return this;
};

USB.prototype.close = function(callback){

if(this.device) {

});
})(iface);
});
return this;
}
read(callback?: ((data: Buffer) => void) | undefined): void {
this.deviceToPcEndpoint.transfer(64, (error: any, data: Buffer) => {
callback && callback(data);
});
}
write(data: string | Buffer, callback?: ((error: Error | null) => void) | undefined): this {
this.emit('data', data);
this.endpoint.transfer(data, callback);
return this;
}
close(callback?: ((error: Error | null) => void) | undefined, timeout?: number | undefined): this {
if (!this.device) callback && callback(null);
try {

this.device.close();
mUsb.removeAllListeners('detach');

usb.removeAllListeners('detach');
callback && callback(null);
this.emit('close', this.device);

}
catch (e) {
callback && callback(e);
catch (err: any) {
callback && callback(err);
}

return this;
}
else {
callback && callback(null);
}

return this;

};

/**
* [exports description]
* @type {[type]}
*/
module.exports = USB;
}

0 comments on commit 0311321

Please sign in to comment.