forked from hswaw/hscloud
160 lines
3.7 KiB
JavaScript
160 lines
3.7 KiB
JavaScript
/**
|
|
* Low-level interface to programmer's I2C USB class.
|
|
*
|
|
* See //dc/hbj11/flasher/bluepill/src/i2c.rs for more information.
|
|
*/
|
|
|
|
const ControlInRequest = Object.freeze({
|
|
'GetStatus': 1,
|
|
});
|
|
|
|
const ControlOutRequest = Object.freeze({
|
|
'SetLED': 1,
|
|
'ReadI2C': 2,
|
|
'ReadBuffer': 3,
|
|
'WriteI2C': 4,
|
|
'SetWritePointer': 5,
|
|
});
|
|
|
|
export const Status = Object.freeze({
|
|
'Idle': 0,
|
|
'InvalidArgument': 1,
|
|
'Ack': 2,
|
|
'Nack': 3,
|
|
'BusError': 4,
|
|
});
|
|
|
|
export const StatusFromU8 = function(u8) {
|
|
for (const label of Object.keys(Status)) {
|
|
let val = Status[label];
|
|
if (val === u8) {
|
|
return label;
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Low-level interface to programmer's I2C USB class. Thinly wraps available
|
|
* USB transfers.
|
|
*/
|
|
export class USBI2CClassInterface {
|
|
/**
|
|
* @param {USBDevice} usb - The WebUSB device that backs this USB class.
|
|
*/
|
|
constructor(device) {
|
|
this.usb = device;
|
|
this.BUFFER_SIZE = 1024;
|
|
this.PACKET_SIZE = 64;
|
|
}
|
|
|
|
/**
|
|
* Open this programmer via WebUSB and finds all required endpoints.
|
|
*/
|
|
async open() {
|
|
await this.usb.open();
|
|
await this.usb.selectConfiguration(1);
|
|
await this.usb.claimInterface(0);
|
|
|
|
let eps = this.usb.configuration.interfaces[0].alternate.endpoints;
|
|
this.bulk_out = null;
|
|
this.bulk_in = null;
|
|
for (const ep of eps) {
|
|
if (ep.direction == "out" && ep.type == "bulk") {
|
|
this.bulk_out = ep;
|
|
}
|
|
if (ep.direction == "in" && ep.type == "bulk") {
|
|
this.bulk_in = ep;
|
|
}
|
|
}
|
|
if (this.bulk_out === null) {
|
|
throw new Error("Could not find bulk out endpoint");
|
|
}
|
|
if (this.bulk_in === null) {
|
|
throw new Error("Could not find bulk in endpoint");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Performs a USB Control OUT request to the I2C class.
|
|
* @param {number} request - Request number for transfer (0-255).
|
|
* @param {number} value - Value for transfer (0-65535).
|
|
* @returns {Promise<USBOutTransferResult>} The underlying WebUSB transfer result.
|
|
*/
|
|
async controlOut(request, value) {
|
|
return await this.usb.controlTransferOut({
|
|
requestType: "vendor",
|
|
recipient: "interface",
|
|
request: request,
|
|
value: value,
|
|
index: 0,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Read status from programmer.
|
|
* @returns {Status} The status of the programmer.
|
|
*/
|
|
async getStatus() {
|
|
let res = await this.usb.controlTransferIn({
|
|
requestType: "vendor",
|
|
recipient: "interface",
|
|
request: ControlInRequest.GetStatus,
|
|
value: 0,
|
|
index: 0
|
|
}, 1);
|
|
if (res.data.byteLength < 1) {
|
|
throw new Error('returned data too short')
|
|
}
|
|
return res.data.getInt8(0);
|
|
}
|
|
|
|
/**
|
|
* Sends SetLED control OUT request.
|
|
*/
|
|
async setLED(on) {
|
|
return await this.controlOut(ControlOutRequest.SetLED, on ? 1 : 0);
|
|
}
|
|
|
|
/**
|
|
* Sends ReadI2C control OUT request.
|
|
*/
|
|
async readI2C(addr, length) {
|
|
return await this.controlOut(ControlOutRequest.ReadI2C, (length << 8) | addr);
|
|
}
|
|
|
|
/**
|
|
* Sends ReadBuffer control OUT request.
|
|
*/
|
|
async readBuffer(addr, length) {
|
|
return await this.controlOut(ControlOutRequest.ReadBuffer, (length << 8) | addr);
|
|
}
|
|
|
|
/**
|
|
* Sends WriteI2C control OUT request.
|
|
*/
|
|
async writeI2C(addr, length) {
|
|
return await this.controlOut(ControlOutRequest.WriteI2C, (length << 8) | addr);
|
|
}
|
|
|
|
/**
|
|
* Sends SetWritePointer control OUT request.
|
|
*/
|
|
async setWritePointer(addr) {
|
|
return await this.controlOut(ControlOutRequest.SetWritePointer, addr);
|
|
}
|
|
|
|
/**
|
|
* Requets bulk IN data.
|
|
*/
|
|
async bulkIn(length) {
|
|
return await this.usb.transferIn(this.bulk_in.endpointNumber, length);
|
|
}
|
|
|
|
/**
|
|
* Sends bulk OUT data.
|
|
*/
|
|
async bulkOut(data) {
|
|
return await this.usb.transferOut(this.bulk_out.endpointNumber, data);
|
|
}
|
|
}
|