var serial = {};
function buf2hex(buffer) { // buffer is an ArrayBuffer
return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('');
}
(function() {
'use strict';
serial.status = 0; //disconnected
serial.CP210_VENDOR_WRITE_REQUEST_TYPE = 0x40;
serial.CP210_VENDOR_WRITE_REQUEST = 0x01;
serial.CP210_VENDOR_READ_REQUEST_TYPE = 0xc0;
serial.CP210_VENDOR_READ_REQUEST = 0x01;
serial.CP210_GET_LINE_REQUEST_TYPE = 0xa1;
serial.CP210_GET_LINE_REQUEST = 0x21;
serial.CP210_SET_LINE_REQUEST_TYPE = 0x21;
serial.CP210_SET_LINE_REQUEST = 0x20;
serial.CP210_SET_CONTROL_REQUEST_TYPE = 0x21;
serial.CP210_SET_CONTROL_REQUEST = 0x22;
serial.CP210_BREAK_REQUEST_TYPE = 0x21;
serial.CP210_BREAK_REQUEST = 0x23;
serial.CH341_REQ_READ_VERSION = 0x5F;
serial.CH341_REQ_WRITE_REG = 0x9A;
serial.CH341_REQ_READ_REG = 0x95;
serial.CH341_REQ_SERIAL_INIT = 0xA1;
serial.CH341_REQ_MODEM_CTRL = 0xA4;
serial.CH341_REG_BREAK = 0x05;
serial.CH341_REG_LCR = 0x18;
serial.CH341_LCR_ENABLE_RX = 0x80;
serial.CH341_LCR_ENABLE_TX = 0x40;
serial.CH341_LCR_MARK_SPACE = 0x20;
serial.CH341_LCR_PAR_EVEN = 0x10;
serial.CH341_LCR_ENABLE_PAR = 0x08;
serial.CH341_LCR_STOP_BITS_2 = 0x04;
serial.CH341_LCR_CS8 = 0x03;
serial.CH341_LCR_CS7 = 0x02;
serial.CH341_LCR_CS6 = 0x01;
serial.CH341_LCR_CS5 = 0x00;
serial.CH341_BIT_CTS = 0x01;
serial.CH341_BIT_DSR = 0x02;
serial.CH341_BIT_RI = 0x04;
serial.CH341_BIT_DCD = 0x08;
serial.CH341_BAUDBASE_FACTOR = 1532620800;
serial.CH341_BAUDBASE_DIVMAX = 3;
serial.CH341 = 0x1;
serial.CP201 = 0x2;
//CH341
//https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/usb/serial/ch341.c?h=v5.3-rc1
//cp210
//https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/usb/serial/cp210x.c?h=v5.3-rc1
//requestType standard/class/vendor 0=standard, 1=class, 2=vendor, 3=reserved)
//recipient device/inteface/endpoint/other 0=device, 1=interface, 2=endpoint,3=other)
serial.getPorts = function() {
return navigator.usb.getDevices().then(devices => {
return devices.map(device => new serial.Port(device));
});
};
serial.requestPort = function() {
const filters = [
{ vendorId:0x067b, productId:0x2303 }, //cp210
{ vendorId:0x1a86, productId:0x7523 }, //ch341
];
return navigator.usb.requestDevice({ 'filters': filters }).then(
device => new serial.Port(device)
);
}
serial.Port = function(device) {
this.device = device;
if ((device.vendorId == 0x067b) && (device.productId == 0x2303))
{
this.device.t = serial.CP201;
}
if ((device.vendorId == 0x1a86) && (device.productId == 0x7523))
{
this.device.t = serial.CH341;
}
};
serial.Port.prototype.connect = function(){
this.device.open().then(() => {
if (this.device.configuration === null) {
return this.device.selectConfiguration(1);
}
}).then(() => this.device.claimInterface(0))
.then(() => this.device.selectAlternateInterface(0,0))
.catch(error => {
console.log("ERROR "+error);
})
};
serial.Port.prototype.claim = function(i) {
this.device.claimInterface(i)
.catch(error => {
console.log("ERROR "+error);
})
}
serial.Port.prototype.close = function() {
return this.device.close();
}
serial.Port.prototype.reset = function() {
return this.device.reset();
}
serial.Port.prototype.disconnect = function() {
return this.device_.controlTransferOut({
'requestType': 'class',
'recipient': 'interface',
'request': 0x22,
'value': 0x00,
'index': 0x02})
.then(() => this.device.close());
};
serial.Port.prototype.send = function(data) {
return this.device.transferOut(4, data);
};
serial.Port.prototype.vendorWrite = function(value,index) {
console.log("Write idx "+index+" val = "+value)
return this.device.controlTransferOut({
'requestType': 'vendor',
'recipient': 'device',
'request': serial.VENDOR_WRITE_REQUEST,
'value': value,
'index': index,
});
};
serial.Port.prototype.vendorRead = function(value) {
console.log("Read val="+value);
return this.device.controlTransferIn({
'requestType': 'vendor',
'recipient': 'device',
'request':serial.VENDOR_READ_REQUEST,
'value':value,
'index':0,
},1);
};
serial.Port.prototype.checkDevice = function() {
};
serial.Port.prototype.patchDevice = function() {
};
serial.Port.prototype.getLineRequest = function() {
console.log("Get line request");
return this.device.controlTransferIn({
'requestType': 'class',
'recipient': 'interface',
'request':serial.GET_LINE_REQUEST,
'value':0,
'index':0,
},7);
};
serial.Port.prototype.setLineRequest = function() {
console.log("Set line request");
return this.device.controlTransferOut({
'requestType': 'class',
'recipient': 'interface',
'request':serial.SET_LINE_REQUEST,
'value':0,
'index':0,
},7);
};
serial.Port.prototype.setControlRequest = function() {
console.log("Set control request");
return this.device.controlTransferOut({
'requestType': 'class',
'recipient': 'interface',
'request':serial.SET_CONTROL_REQUEST,
'value':0,
'index':0,
},7);
};
serial.Port.prototype.breakRequest = function() {
console.log("Break request");
return this.device.controlTransferOut({
'requestType': 'class',
'recipient': 'interface',
'request':serial.BREAK_REQUEST,
'value':0,
'index':0,
},7);
};
serial.Port.prototype.transferIn = function(reqtype,recp,req,val,idx,dataread) {
console.log("transferIn");
return this.device.controlTransferIn({
'requestType': reqtype,
'recipient': recp,
'request':req,
'value':val,
'index':idx,
},dataread);
};
serial.Port.prototype.transferInfClaIn = function(req,val,idx,dataread) {
console.log("transferInfClaIn");
this.transferIn("interface","class",req,val,idx,dataread);
};
serial.Port.prototype.transferOut = function(reqtype,recp,req,val,idx) {
console.log("transferOut");
return this.device.controlTransferOut({
'requestType': reqtype,
'recipient': recp,
'request':req,
'value':val,
'index':idx,
});
};
serial.Port.prototype.transferDevVenOut = function(req,val,idx) {
console.log("transferDevVenOut");
this.transferOut("vendor","device",req,val,idx);
}
serial.Port.prototype.transferIntClaOut = function(req,val,idx) {
console.log("transferIntClaOut");
this.transferOut("class","interface",req,val,idx);
}
serial.Port.prototype.bulkOut = async function(ep) {
var buf = new ArrayBuffer(1);
let r = await this.device.transferOut(ep,buf);
console.log(buf);
console.log(r);
return r;
}
serial.Port.prototype.bulkIn = async function(ep,l) {
let r = await this.device.transferIn(ep,l);
console.log(r);
return r;
}
serial.Port.prototype.EncodeBaudRate = function() {
};
//https://gist.github.com/fe1320e2539ce9afc529f51cce656bae
serial.Port.prototype.init = function() {
this.vendorRead( 0x8484)
.then(() => this.vendorWrite(0x0404 , 0))
.then(() => this.vendorRead( 0x8484))
.then(() => this.vendorRead( 0x8383))
.then(() => this.vendorRead( 0x8484))
.then(() => this.vendorWrite(0x0404 , 1))
.then(() => this.vendorRead( 0x8484))
.then(() => this.vendorRead( 0x8383))
.then(() => this.vendorWrite(0 , 1))
.then(() => this.vendorWrite(1 , 0))
.then(() => this.vendorWrite(2 , 0x24))
.then(r =>{ console.log("Done "+r);})
.catch(err => {console.log("Error "+err);}); // 2,0x44
};
serial.Port.prototype.CH341controlIn = function(req,val,idx,dataread) {
console.log("CH341controlIn");
return this.device.controlTransferIn({
'requestType': 'vendor',
'recipient': 'device',
'request':req,
'value':val,
'index':idx,
},dataread);
};
serial.Port.prototype.CH341controlOut = function(req,val,idx) {
console.log("CH341controlOut");
return this.device.controlTransferOut({
'requestType': 'vendor',
'recipient': 'device',
'request':req,
'value':val,
'index':idx,
});
};
serial.Port.prototype.CH341configure = function() {
//serial.Port.prototype.CH341configure = async() => {
console.log("CH341configure");
this.device.controlTransferIn({
'requestType': 'vendor',
'recipient': 'device',
'request':serial.CH341_REQ_READ_VERSION,
'value':0,
'index':0,
},2).then