summaryrefslogtreecommitdiffstats
path: root/webusb.js
diff options
context:
space:
mode:
authorZoRo <dos21h@gmail.com>2019-07-31 21:55:59 +0100
committerZoRo <dos21h@gmail.com>2019-07-31 21:55:59 +0100
commit1a1e39cc91c350e2cd7b0aca5100527059ab23bb (patch)
treef06acc2eda263394246c2d01c5502f6de6586086 /webusb.js
downloadwebusb-1a1e39cc91c350e2cd7b0aca5100527059ab23bb.tar.gz
webusb-1a1e39cc91c350e2cd7b0aca5100527059ab23bb.zip
Dirty commit
Diffstat (limited to 'webusb.js')
-rw-r--r--webusb.js479
1 files changed, 479 insertions, 0 deletions
diff --git a/webusb.js b/webusb.js
new file mode 100644
index 0000000..0f174d4
--- /dev/null
+++ b/webusb.js
@@ -0,0 +1,479 @@
+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(res1 => {
+ var v = new Uint8Array(res1.data.buffer);
+ console.log("0x"+buf2hex(v));
+ }).catch(err=>{
+ console.log(err);
+ });
+
+ console.log("CH341_REQ_SERIAL_INIT")
+ var res2;
+ this.device.controlTransferOut({
+ 'requestType': 'vendor',
+ 'recipient': 'device',
+ 'request':serial.CH341_REQ_SERIAL_INIT,
+ 'value':0,
+ 'index':0,
+ }).then(r => {res2=r;}).catch(err => {console.log(err)});
+ //console.log(buf2hex(res2.));
+ console.log(res2);
+ //return res2;
+ };
+
+ serial.Port.prototype.CH341configure2 = async function() {
+ console.log("CH341configure");
+ //40 a4 ff9f 0000 0000 0
+ let r1 = await this.transferDevVenOut(serial.CH341_REQ_MODEM_CTRL,0xff9f,0x0,0x0);
+ console.log(r1);
+ //40 9a 1312 6483 0000 0
+ let r2 = await this.transferDevVenOut(serial.CH341_REQ_WRITE_REG,0x1312,0x6483,0x0);
+ console.log(r2);
+ //40 9a 2518 00c3 0000 0
+ let r3 = await this.transferDevVenOut(serial.CH341_REQ_WRITE_REG,0x2518,0x00c3,0x0);
+ console.log(r3);
+ //40 a4 ff9f 0000 0000 0
+ let r4 = await this.transferDevVenOut(serial.CH341_REQ_MODEM_CTRL,0xff9f,0x0,0x0);
+ console.log(r4);
+ }
+
+ serial.Port.prototype.CH341setHandshake = function() {
+ };
+
+ serial.Port.prototype.CH341getStatus = function() {
+ console.log("CH341getStatus");
+ var res1;
+ this.device.controlTransferIn({
+ 'requestType': 'vendor',
+ 'recipient': 'device',
+ 'request':serial.CH341_REQ_READ_REG,
+ 'value':0x0706,
+ 'index':0,
+ },2).then(r=>{
+ var v = new new Uint8Array(r.data.buffer);
+ console.log(buf2hex(v));
+ }).catch(err=>{
+ console.log(err);
+ });
+ console.log(res1);
+ return res1;
+ };
+
+ serial.Port.prototype.CH341getStatus2 = async function() {
+ var dev = this.device;
+ try {
+ console.log("CH341getStatus");
+ let res = await dev.controlTransferIn({
+ 'requestType': 'vendor',
+ 'recipient': 'device',
+ 'request':serial.CH341_REQ_READ_REG,
+ 'value':0x0706,
+ 'index':0,
+ },2);
+ console.log(res);
+ return res;
+ } catch (err) {
+ console.log(err);
+ }
+ };
+
+ serial.Port.prototype.CH341getStatus2 = async function() {
+ var dev = this.device;
+ try {
+ console.log("CH341getStatus");
+ let res = await dev.controlTransferIn({
+ 'requestType': 'vendor',
+ 'recipient': 'device',
+ 'request':serial.CH341_REQ_READ_REG,
+ 'value':0x0706,
+ 'index':0,
+ },2);
+ console.log(res);
+ return res;
+ } catch (err) {
+ console.log(err);
+ }
+ };
+
+ serial.Port.prototype.CH341readEP0 = async function() {
+ try {
+ console.log("CH341readEP0");
+ let res = this.device.transferIn(2,32);
+ console.log("Res:"+res);
+ return res;
+ } catch (err) {
+ console.log(err);
+ }
+ };
+
+ serial.Port.prototype.CH341readEP1 = async function(data) {
+ try {
+ console.log("CH341readEP1");
+ let res = await this.device.transferOut(2,data);
+ console.log(res);
+ return res;
+ } catch (err) {
+ console.log(err);
+ }
+ };
+
+ serial.Port.prototype.CH341readEP2 = async function() {
+ try {
+ console.log("CH341readEP2");
+ let res = this.device.transferIn(1,8);
+ console.log("Result from EP2");
+ console.log(res);
+ return res;
+ } catch (err) {
+ console.log(err);
+ }
+ };
+
+ serial.Port.prototype.CH341setBaudrateLCR = async function() {
+ var factor = serial.CH341_BAUDBASE_FACTOR / 38400;
+ console.log(factor);
+ var divider = serial.CH341_BAUDBASE_DIVMAX;
+ factor = 0x10000 - factor;
+ var a = (factor & 0xff00) | divider;
+ console.log(a);
+ a = a | 0x80;
+
+ var lcr = serial.CH341_LCR_ENABLE_TX | serial.CH341_LCR_ENABLE_RX | serial.CH341_LCR_CS8;
+ var lcr = serial.CH341_LCR_ENABLE_TX | serial.CH341_LCR_ENABLE_RX | serial.CH341_LCR_CS8;
+
+ this.CH341controlOut(serial.CH341_REQ_WRITE_REG,0x1312,a);
+ this.CH341controlOut(serial.CH341_REQ_WRITE_REG,0x2518,lcr);
+ };
+
+ serial.Port.prototype.CH341breakReg = async function() {
+ var ch341_break_reg = (serial.CH341_REG_LCR << 8) | serial.CH341_REG_BREAK;
+ console.log(ch341_break_reg);
+ let r = await this.CH341controlIn(serial.CH341_REQ_READ_REG, ch341_break_reg, 0, 2);
+ var u8 = new Uint8Array(r.data.buffer);
+ console.log(u8);
+ u8[0] = u8[0] | serial.CH341_NBREAK_BITS;
+ u8[1] = u8[1] | serial.CH341_LCR_ENABLE_TX;
+ console.log(u8);
+ let r1 = await this.CH341controlOut(serial.CH341_REQ_WRITE_REG,ch341_break_reg, u8);
+ console.log(r1);
+ return r;
+ }
+
+ serial.Port.prototype.CH341setHandshake = async function(ctrl) {
+ var mcr = 0;
+ mcr = mcr | serial.CH341_BIT_CTS;
+ mcr = mcr | serial.CH341_BIT_DSR;
+ mcr = ~mcr;
+ //let r1 = await this.CH341controlOut(serial.CH341_REQ_MODEM_CTRL, ~ctrl, 0);
+ let r1 = await this.CH341controlOut(serial.CH341_REQ_MODEM_CTRL, mcr, 0);
+ console.log(r1);
+ return r1;
+ }
+
+})(); \ No newline at end of file