Skip to content

Instantly share code, notes, and snippets.

@ryanmjacobs
Last active April 28, 2018 02:06
Show Gist options
  • Save ryanmjacobs/326cd56e8c21c929ec831484cfe5aadb to your computer and use it in GitHub Desktop.
Save ryanmjacobs/326cd56e8c21c929ec831484cfe5aadb to your computer and use it in GitHub Desktop.
// make sure to unbind your device first
// https://stackoverflow.com/questions/47695160/failed-to-claim-interface-0-device-or-resource-busy
// echo -n "1-1.3:1.0" | sudo tee /sys/bus/usb/drivers/ch341/unbind
let device;
async function connectDevice(dev) {
await dev.open();
if (dev.configuration === null)
await dev.selectConfiguration(1).catch(error => { log(error); });
let ifaces = dev.configuration.interfaces.map(e => e.interfaceNumber);
await dev.claimInterface(ifaces[0]).catch(error => { log(error); });
device = dev;
}
async function send(buf) {
console.log (device.opened);
var sendData = prompt("Enter something to send","Cascadia");
var buffer = new ArrayBuffer(sendData.length+2);
var bufferView = new Uint8Array(buffer);
for (var i=0, strLen=sendData.length; i < strLen; i++) {
bufferView[i+1] = sendData.charCodeAt(i);
}
bufferView[0] = strLen+2;
bufferView[strLen+1] = 13;
if (device.opened) {
await device.controlTransferOut({
requestType: "vendor",
recipient: "device",
request: 250,
value: 24, // AMW more data follows
index: 0,
}, buffer);
}
}
document.getElementById("webusb-connect").onclick = function() {
navigator.usb.requestDevice({ filters: [{ vendorId: 0x1209 }] })
.then(dev => {
connectDevice(dev);
}).catch(error => { log(error); });
};
navigator.usb.getDevices().then(devs => {
console.log(devs);
});
// not sure what this function does...
document.getElementById("webusb-send").onclick = function() {
let buf = new ArrayBuffer(5);
send(buf);
}
// or this one...
document.getElementById("webusb-rec").onclick = function() {
let budf = new ArrayBuffer(5)
console.log(device.opened);
if (!device.opened)
return;
device.controlTransferIn({
requestType: "vendor",
recipient: "device",
request: 249,
value: 0x70,
index: 0x81
}, 64).then(result => {
let decoder = new TextDecoder();
console.log('Received: ' + decoder.decode(result.data)+ '\n');
log('Received: ' + decoder.decode(result.data)+ '\n');
}).catch(error => console.log(error));
};
// We define our function as an 'async function' so that we can
// write blocking code within our function body using the 'await'
// keyword.
document.getElementById("webusb-sendCmd").onclick = async function() {
const cmd = 1;
try {
// The await keyword will 'block' until the promise resolves.
// sendCmd() is a function that returns a Promise, because
// it optimally returns device.controlTransferOut, (which is a
// Promise).
await sendCmd();
const results = await requestCmdResult();
console.log("The results are: ....");
console.log(results);
} catch (error) {
// One of our promises failed to resolve.
console.log(error);
if (error == "some error string") {
// handle it
} else if (error == "other error string") {
// handle it
}
}
}
function sendCmd(cmd) {
// Good code returns early for failures.
// This is better than wrapping your entire function body with
// a single if statement.
if (!device.opened)
return Promise.reject("error: device not opened");
console.log(device.opened);
console.log(cmd);
// If you look at the WebUSB spec:
// https://wicg.github.io/webusb/#dom-usbdevice-controltransferout
// it says that controlTransferOut returns a Promise,
// so we simply return this Promise so that it bubbles up through
// our higher level code that can handles the errors.
//
// Promises can either resolve (which means success!)
// or reject (which means failure).
//
// Typically, you can take a Promise and describe what you want to do
// when it resolves with a .then(), like so:
//
// const p = new Promise();
// p.then(someData => console.log(someData));
//
// You could also add a catch block to catch rejected errors.
//
// p.then(someData => console.log(someData))
// .catch(someError => console.log(error));
//
// OR in more modern JavaScript, you can use async/await to block the
// Promise (which is incredibly useful for dealing with multiple
// Promises).
//
// function oldMethod() {
// const a = new Promise();
// a.then(resultA => {
// const b = new Promise();
// b.then(resultB => {
// const c = new Promise();
// b.then(resultC => {
// console.log(resultA, resultB, resultC);
// });
// });
// });
// }
//
// async function newMethod() {
// const resultA = await ( new Promise() );
// const resultB = await ( new Promise() );
// const resultC = await ( new Promise() );
//
// console.log(resultA, resultB, resultC);
// }
return device.controlTransferOut({
requestType: "vendor",
recipient: "device",
request: 250,
value: cmd,
index: 0
});
}
function requestResults() {
if (!device.opened)
return Promise.reject("error: device not opened");
return device.controlTransferIn({
requestType: "vendor",
recipient: "device",
request: 249,
value: 0x70,
index: 0x81
}, 64).then(result => {
let decoder = new TextDecoder();
console.log('Received: ' + decoder.decode(result.data)+ '\n');
log('Received: ' + decoder.decode(result.data)+ '\n');
return result.data;
});
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment