initial commit

This commit is contained in:
neiviv-ui 2021-07-14 18:31:10 +02:00
commit f493ecd076
4 changed files with 780 additions and 0 deletions

98
const.js Normal file
View File

@ -0,0 +1,98 @@
"use strict";
const p7PacketType = {
'command': 0x01,
'data': 0x02,
'roleswap': 0x03,
'check': 0x05,
'ack': 0x06,
'screenCast': 0x0B, /* Not supported yet */
'error': 0x15,
'terminate': 0x18
};
const sysCommandSubtype = {
/* System commands */
'restartReset': 0x00,
'getDeviceInfo': 0x01,
'setLinkSettings': 0x02, /* Probably unavailable since we are using USB */
};
const mcsCommandSubtype = {
/* MCS commands */
'createDirectory': 0x20,
'deleteDirectory': 0x21,
'renameDirectory': 0x22,
'changeWorkingDirectory': 0x23,
'fileTransferRequest': 0x24,
'fileTransfer': 0x25,
'deleteFile': 0x26,
'renameFile': 0x27,
'copyFile': 0x28,
'fileTransferAllRequest': 0x29,
'unknownResetMCS': 0x2A, /* TODO: TEST */
'capacityTransmitRequest': 0x2B,
'capacityTransmit': 0x2C,
'fileInfoTransferAllRequest': 0x2D,
'fileInfoTransfer': 0x2E,
'ramImageTransferRequest': 0x2F,
'ramImageTransfer': 0x30,
'setupEntryTransferRequest': 0x31,
'setupEntryTransfer': 0x32,
'setupEntryTransferAllRequest': 0x33,
};
const flashCommandSubtype = {
/* Flash commands */
'createDirectory': 0x40,
'deleteDirectory': 0x41,
'renameDirectory': 0x42,
'changeDirectory': 0x43,
'fileTransferRequest': 0x44,
'fileTransfer': 0x45,
'deleteFile': 0x46,
'renameFile': 0x47,
'copyFile': 0x48,
'fileTransferAllRequest': 0x49,
'unknownResetFlash': 0x4A, /* TODO: TEST*/
'capacityTransmitRequest': 0x4B,
'capacityTransmit': 0x4C,
'fileInfoTransferAllRequest': 0x4D,
'fileInfoTransfer': 0x4E,
'flashImageTransferRequest': 0x4F,
'flashImageTransfer': 0x50,
'optimizeFilesystem': 0x51
// 'osUpdateRelated': [0x52 --> 0x57] ?
};
const dataSubtype = {}; /* Theorically always the same as the command packet it succeeds to */
const roleswapSubtype = {
'default': 0x00
};
const checkSubtype = {
'initialization': 0x00,
'default': 0x01
};
const ackSubtype = {
'default': 0x00,
'overwriteYes': 0x01,
'extendedAck': 0x02
};
const errorSubtype = {
'default': 0x00,
'resendRequest': 0x01,
'overwriteRequest': 0x02,
'overwriteNo': 0x03,
'overwriteImpossible': 0x04,
'memoryFull': 0x05
};
const terminateSubtype = {
'default': 0x00,
'userRequest': 0x01,
'timeouts': 0x02,
'overwriteRequest': 0x03
};

21
index.html Normal file
View File

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Hello</h1>
<p id="demo"></p>
<input type="file" id="input">
<br><br><button id="connect">Connect</button>
<script src="const.js"></script>
<script src="internal.js"></script>
<script src="index.js"></script>
</body>
</html>

233
index.js Normal file
View File

@ -0,0 +1,233 @@
"use strict";
let device = undefined;
let fileList = undefined;
let p7SendBuffer = new Uint8Array(1032); //Max send buffer size
let p7ReceiveBuffer = new Uint8Array(1032 + 1); //Max receive buffer size
let p7ReceivedPacketInfo = {
'type' : undefined,
'subtype' : undefined,
'extended' : undefined,
'dataSize' : undefined,
'data' : undefined,
'checksum' : undefined,
'packetSize': undefined
};
let p7DeviceInformation = {
'hardwareIdentifier' : undefined,
'processorIdentifier' : undefined,
'preprogrammedROMCapacity' : undefined,
'flashROMCapacity' : undefined,
'ramCapacity' : undefined,
'prepogrammedROMVersion' : undefined,
'bootCodeVersion' : undefined,
'bootCodeOffset' : undefined,
'bootCodeSize' : undefined,
'osCodeVersion' : undefined,
'osCodeOffset' : undefined,
'osCodeSize' : undefined,
'protocolVersion' : undefined,
'productID' : undefined,
'nameSetByUserInSystem' : undefined
};
var fls0 = [];
var crd0 = [];
/* List the files of a filesystem (fls0, crd0...) */
/* Return 0 on success and the error on failure */
async function list(fileSystem) {
let err = 0;
//Send a command packet requesting the calculator to list it's file (in the flash memory) and receive the response packet
if (err = await p7SendExtendedCommandPacket(flashCommandSubtype.fileInfoTransferAllRequest, 0, 0, 0, ["", "", "", "", fileSystem, ""]))
return "Couldn't send the command packet to the calculator : " + err;
//Send a roleswap packet so that the calculator can become the active side and send the list of it's files (in flash memory)
if (err = await p7SendBasicPacket(p7PacketType.roleswap, roleswapSubtype.default))
return "Couldn't send the roleswap packet : " + err;
//Reset the list since the calculator send each time all it's elements
window[fileSystem] = [];
//Receive and parse the file list
while(p7ReceivedPacketInfo.type !== p7PacketType.roleswap) {
window[fileSystem].push(createFileObject(String.fromCharCode.apply(null, p7CommandPacketGetField(4)), String.fromCharCode.apply(null, p7CommandPacketGetField(0)), String.fromCharCode.apply(null, p7CommandPacketGetField(1)), p7CommandPacketGetFilesize()));
if (err = await p7SendBasicPacket(p7PacketType.ack, ackSubtype.default))
return "Couldn't send the acknowledgement packet : " + err;
}
return 0;
};
async function createDirectory(name, filesystem) {
let err = 0;
//Send a command packet which asks the calculator to create a directory
if (err = await p7SendExtendedCommandPacket(flashCommandSubtype.createDirectory, 0, 0, 0, [name, "", "", "", filesystem, ""]))
return 'Couldn\'t send the command : ' + err;
//Check the response packet type
if (p7ReceivedPacketInfo.type === p7PacketType.ack)
return 0;
return "The response packet wasn't as expected.";
}
async function deleteDirectory(name, filesystem) {
let err = 0;
//Send a command packet which asks the calculator to delete a directory
if (err = await p7SendExtendedCommandPacket(flashCommandSubtype.deleteDirectory, 0, 0, 0, [name, "", "", "", filesystem, ""]))
return 'Couldn\'t send the command : ' + err;
//Check the response packet type
if (p7ReceivedPacketInfo.type === p7PacketType.ack)
return 0;
return "The response packet wasn't as expected.";
}
/* Doesn't work ?? */
async function renameDirectory(oldName, newName, filesystem) {
let err = 0;
//Send a command packet which asks the calculator to delete a directory
if (err = await p7SendExtendedCommandPacket(flashCommandSubtype.renameDirectory, 0, 0, 0, [oldName, newName, "", "", filesystem, ""]))
return 'Couldn\'t send the command : ' + err;
//check the response packet type
if (p7ReceivedPacketInfo.type === p7PacketType.ack)
return 0;
return "The response packet wasn't as expected.";
}
/* Doesn't work ?? */
async function changeDirectory(name, filesystem) {
let err = 0;
//Send a command packet which asks the calculator change working directory
if (err = await p7SendExtendedCommandPacket(flashCommandSubtype.changeDirectory, 0, 0, 0, [name, "", "", "", filesystem, ""]))
return 'Couldn\'t send the command : ' + err;
if (p7ReceivedPacketInfo.type === p7PacketType.ack)
return 0;
return "The response packet wasn't as expected.";
}
/* TODO: finish it */
async function fileTransfer(file, path, fileSystem) {
let err = 0;
console.log('Sending file transfer request');
//Send a command packet which asks the calculator if we can send a file
if (err = await p7SendExtendedCommandPacket(flashCommandSubtype.fileTransfer, 0, 0, file.size, [path, file.name, "", "", fileSystem, ""]))
return 'Couldn\'t send the command : ' + err;
console.log(p7SendBuffer.slice(0, 64));
if (p7ReceivedPacketInfo.type === p7PacketType.error && p7ReceivedPacketInfo.subtype === errorSubtype.overwriteRequest) {
if (err = (confirm('The file already exists, overwrite ?')) ? await p7SendBasicPacket(p7PacketType.ack, ackSubtype.overwriteYes) : await p7SendBasicPacket(p7PacketType.error, errorSubtype.overwriteNo))
return 'Couldn\'t send the overwrite response packet : ' + err;
if (p7ReceivedPacketInfo.type === p7PacketType.error && p7ReceivedPacketInfo.subtype === errorSubtype.overwriteImpossible)
return 'The calculator couldn\'t overwrite the file : ' + err;
}
console.log('Sending data');
if (err = await p7SendData(flashCommandSubtype.fileTransfer, content))
return 'Couldn\'t send the file : ' + err;
if (p7ReceivedPacketInfo.type ==! p7PacketType.ack)
return "unexpected response packet";
return 0;
}
/* TODO: add promise system */
function getCapacity(fileSystem) {
return new Promise((resolve, reject) => {
let err = 0;
//Send a command packet requesting the calculator to send it's capacity (free memory)
if (err = p7SendExtendedCommandPacket(flashCommandSubtype.capacityTransmitRequest, 0, 0, 0, ["", "", "", "", fileSystem, ""]))
reject('Couldn\'t send the command packet to the calculator : ' + err);
//Send a roleswap packet so that the calculator can become the active side and send it's capacity
if (err = p7SendBasicPacket(p7PacketType.roleswap, roleswapSubtype.default))
reject('Couldn\'t send the roleswap packet : ' + err);
let freeMemory = p7CommandPacketGetFilesize();
//Send an acknowledgement packet and receive the response packet
if (err = p7SendBasicPacket(p7PacketType.ack, roleswapSubtype.default))
reject('Couldn\'t send the acknowledgement packet : ' + err);
if (p7ReceivedPacketInfo.type !== p7PacketType.roleswap)
reject('The calculator didn\'t respond with the expected packet : ' + p7ReceivedPacketInfo.type + ' (packet type) ' + p7ReceivedPacketInfo.subtype + ' (packet subtype).');
//Everything went right
resolve(freeMemory);
});
};
async function optimize(fileSystem) {
let err = 0
if (err = await p7SendExtendedCommandPacket(flashCommandSubtype.optimizeFilesystem, 0, 0, 0, ["", "", "", "", fileSystem, ""]))
return "Couldn't optimize the fileSystem : " + err;
return 0;
}
/* Main function */
/* Return 0 on success and the error on failure */
async function talkToCalculator() {
let err = await p7Initialization();
if (err)
return "Failed to initiate the connection : " + err;
console.log("%cExecute user request", "font-size: 14px; color: white");
//if (err = fileTransfer(0, ))
let capacity = 0;
console.log(getCapacity('fls0').then((success) => capacity = success, (failure) => failure));
console.log(capacity);
//var file = document.getElementById('input').files[0];
//var file = await window.showOpenFilePicker();
//await fileTransfer(file, "", 'fls0');
//await list('fls0');
//console.log(file);
/* Terminate packet handling */
// //Check if the packet is a terminate packet
// if (p7ReceivedPacketInfo.type === p7PacketType.terminate)
// return 'The calculator closed the connection' + (err = await p7DecodeTerminatePacket()) ? ';but there was an error exiting the session : ' + err : '.';
document.getElementById('demo').innerHTML =
'Hardware identifier : ' + p7DeviceInformation['Hardware identifier'] +
'<br>Processor identifier : ' + p7DeviceInformation['Processor identifier'] +
'<br>Preprogrammed ROM capaciy : ' + p7DeviceInformation['Preprogrammed ROM capaciy']+
'<br>Flash ROM capacity : ' + p7DeviceInformation['Flash ROM capacity'] +
'<br>RAM capacity : ' + p7DeviceInformation['RAM capacity'] +
'<br>Prepogrammed ROM version : ' + p7DeviceInformation['Prepogrammed ROM version'] +
'<br>Boot code version : ' + p7DeviceInformation['Boot code version'] +
'<br>Boot code offset : ' + p7DeviceInformation['Boot code offset'] +
'<br>Boot code size : ' + p7DeviceInformation['Boot code size'] +
'<br>Os code version : ' + p7DeviceInformation['Os code version'] +
'<br>Os code offset : ' + p7DeviceInformation['Os code offset'] +
'<br>Os code size : ' + p7DeviceInformation['Os code size'] +
'<br>Protocol version : ' + p7DeviceInformation['Protocol version'] +
'<br>Product ID : ' + p7DeviceInformation['Product ID'] +
'<br>Name set by user in system : ' + p7DeviceInformation['Name set by user in system'];
await device.transferOut(1, p7SendBuffer.slice(0, p7MakeBasicPacket(p7PacketType['terminate'],
terminateSubtype['default'])));
}
window.onload = (event) => {
document.querySelector('#connect').onclick = async () => {
let err = 0;
if (err = await talkToCalculator())
console.log('%c%s', "color: red", err);
}
}

428
internal.js Normal file
View File

@ -0,0 +1,428 @@
"use strict";
/* Compute the (p7-like) checksum of a buffer */
function p7Checksum(buffer, length)
{
//Sum individual bytes in Subtype (ST) and following fields
let checksum = 0;
let i = 1;
for(length -= 2 ; i < length ; i++ )
checksum+=buffer[i];
/* NOT + 1, as defined in fxReverse documentation.
* Be sure it's under 256! */
return (((~checksum) + 1) & 0xFF);
}
/* Return an array with the ascii values of each hex digit*/
function p7HexToAscii(hexNumber, digits) {
return p7StringToAscii(hexNumber.toString(16).toUpperCase().padStart(digits, 0));
}
/* Return an array with the ascii value of each character */
function p7StringToAscii(string) {
return string.split('').map(letter => letter.charCodeAt(0));
}
/* Create a basic (Non-Extended) packet and push it to p7SendBuffer */
/* return it's length (6) */
function p7MakeBasicPacket(type, subtype) {
//Set Type (T) field
p7SendBuffer.set([type], 0);
//Set Subtype (ST) field
p7SendBuffer.set(p7HexToAscii(subtype, 2), 1);
//Set Extended (EX) field
p7SendBuffer.set([0x30], 3);
//Set Checksum (CS) field
p7SendBuffer.set(p7HexToAscii(p7Checksum(p7SendBuffer, 6), 2), 4);
//Return basic packet length
return 6;
}
/* Fill Data (D) field of a command packet in p7SendBuffer */
/* return Data (D) field length */
function p7MakeCommandPacketDataField(forceOverwrite, dataType, fileSize, commandArguments) {
//Set Overwrite (OW) field
p7SendBuffer.set([0x30, (forceOverwrite) ? ((forceOverwrite == 1) ? 0x31 : 0x32) : 0x30], 8);
//Set Data type (DT) field ????
p7SendBuffer.set([0x30, 0x30], 10);
//Set Filesize (FS) field
p7SendBuffer.set(p7HexToAscii(fileSize, 8), 12);
let packetSize = 20;
//Set Size of Data {1-6} (SD{1-6}) field
for (let i = 0 ; i < 6 ; packetSize += 2 , i++)
p7SendBuffer.set((commandArguments[i]) ? p7HexToAscii(commandArguments[i].length, 2) : [0x30, 0x30], packetSize);
//Set Data {1-6} (D{1-6}) field
for (let i = 0 ; i < 6 ; i++)
if (commandArguments[i]) {
p7SendBuffer.set(p7StringToAscii(commandArguments[i]), packetSize);
packetSize += commandArguments[i].length;
}
return packetSize - 8; /* Type, Subtype, Extended, Data size fields of the packet */;
}
/* Create an extended command packet and push it to p7SendBuffer */
/* return it's length */
function p7MakeExtendedCommandPacket(subtype, forceOverwrite, dataType, fileSize, commandArguments) {
//Set Type (T) field
p7SendBuffer.set([0x01], 0);
//Set Subtype (ST) field
p7SendBuffer.set(p7HexToAscii(subtype, 2), 1);
//Set Extended (EX) field
p7SendBuffer.set([0x31], 3);
//Set Data (D) field
let dataSize = p7MakeCommandPacketDataField(forceOverwrite, dataType, fileSize, commandArguments);
//Set Data size (DS) field
p7SendBuffer.set(p7HexToAscii(dataSize, 4), 4);
let packetSize = dataSize + 10 /* Type, Subtype, Extended, Data size and Checksum fields */;
//Set Checksum (CS) field
p7SendBuffer.set(p7HexToAscii(p7Checksum(p7SendBuffer, packetSize), 2), packetSize - 2);
//Return it's length
return packetSize;
}
/* Create a data packet and push it to p7SendBuffer */
/* return it's length */
function p7MakeDataPacket(subType, totalNumber, currentNumber, data) {
packetSize = data.length + 18 /* Type, Subtype, Extended, Data size, Data['Total Number'], Data['Current number'] and checksum fields */;
//Set Type (T) field
p7SendBuffer.set([0x02], 0);
//Set Subtype (ST) field
p7SendBuffer.set(p7HexToAscii(subType, 2), 1);
//Set Extended (EX) field
p7SendBuffer.set([0x31], 3);
//Set Data size (DS) field
p7SendBuffer.set(p7HexToAscii(data.length + 8 /* Total number (TN) and Current number (CN) fields */, 4), 4);
//Set Total number (TN) field
p7SendBuffer.set(p7HexToAscii(totalNumber, 4), 8);
//Set Current number (CN) field
p7SendBuffer.set(p7HexToAscii(currentNumber, 4), 12);
//Set Data (DD) field
p7SendBuffer.set(data, 16);
//Set Checksum (CS) field
p7SendBuffer.set(p7HexToAscii(p7Checksum(p7SendBuffer, packetSize), 2), packetSize - 2);
//Return it's length
return packetSize;
}
/* Receive a packet and parse it's properties to p7ReceivedPacketInfo */
/* Make sure their aren't checksums error (ask for a resend if necessary) */
async function p7ReceivePacket() {
console.log("%cReceiving...", "color: orange");
let checksumError = 0;
let err = 0;
do {
//Send an error packet with subtype resend request if there was a checksum error
if (checksumError)
if (err = await p7SendBasicPacket(p7PacketType.error, errorSubtype.resendRequest))
return "Couldn't send an error packet with resend request subtype (there was a checksum error) : " + err;
let transferInResult = 0;
//Recieve and parse the packet
do {
transferInResult = await device.transferIn(2, 64).then(
(result) => {
return result;
}, (error) => {
err = error;
});
if (err)
return "Couldn't receive the first 64 bytes of the packet : " + err;
} while(!transferInResult.data.byteLength);
p7ReceivedPacketInfo.packetSize = 4; /*Type, Subtype and Extended field*/
//Copy the received buffer to p7ReceiveBuffer
p7ReceiveBuffer.set(new Uint8Array(transferInResult.data.buffer), 0);
//Set Type (T) field
p7ReceivedPacketInfo.type = p7ReceiveBuffer[0];
//Set Subtype (ST) field
p7ReceivedPacketInfo.subtype = Number('0x' + String.fromCharCode(p7ReceiveBuffer[1], p7ReceiveBuffer[2]), 16);
//Set Extended (EX) field
p7ReceivedPacketInfo.extended = (p7ReceiveBuffer[3] === 0x31);
if (!p7ReceivedPacketInfo.extended) {
p7ReceivedPacketInfo.packetSize += 2; /*Checksum field*/
//Set Checksum (CS) field
p7ReceivedPacketInfo.checksum = Number('0x' + String.fromCharCode(p7ReceiveBuffer[4], p7ReceiveBuffer[5]), 16);
//Compute the checksum
checksumError = (p7ReceivedPacketInfo.checksum !== p7Checksum(p7ReceiveBuffer, p7ReceivedPacketInfo.packetSize));
}
else {
p7ReceivedPacketInfo.packetSize += 4; /*Data size field*/
//Set Data size (DS) field
p7ReceivedPacketInfo.dataSize = Number('0x' + String.fromCharCode.apply(null, p7ReceiveBuffer.slice(4, 8)), 10);
//Add the checksum bytes
p7ReceivedPacketInfo.dataSize+=2;
p7ReceivedPacketInfo.packetSize += (p7ReceivedPacketInfo.dataSize > 56) ? 56 : p7ReceivedPacketInfo.dataSize;
p7ReceivedPacketInfo.dataSize -= 56;
//Receive the rest of the data
while(p7ReceivedPacketInfo.dataSize > 0)
{
transferInResult = await device.transferIn(2, 64).then(
(result) => {
return result;
}, (error) => {
err = error;
});
if (err)
return "Couldn't receive the " + packetSize + "th and following 64 bytes of the packet : " + err;
p7ReceiveBuffer.set(new Uint8Array(transferInResult.data.buffer), p7ReceivedPacketInfo.packetSize);
p7ReceivedPacketInfo.packetSize += (p7ReceivedPacketInfo.dataSize > 64) ? 64 : p7ReceivedPacketInfo.dataSize;
p7ReceivedPacketInfo.dataSize-=64;
}
//Set Checksum (CS) field
p7ReceivedPacketInfo.checksum = Number('0x' + String.fromCharCode(p7ReceiveBuffer[p7ReceivedPacketInfo.packetSize - 2], p7ReceiveBuffer[p7ReceivedPacketInfo.packetSize - 1]), 16);
//Compute the checksum
checksumError = (p7ReceivedPacketInfo.checksum !== p7Checksum(p7ReceiveBuffer, p7ReceivedPacketInfo.packetSize));
}
} while (checksumError)
console.log(p7ReceivedPacketInfo);
return 0;
}
/* Send a packet */
/* Receive the response and resend the packet if the response was an error with subtype resend request */
/* Return 0 on success and the error on failure */
async function p7SendPacket(packetLength) {
console.log(p7SendBuffer.slice(0, packetLength));
let err = 0;
//Send the packet and return the error on failure
if (err = await device.transferOut(1, p7SendBuffer.slice(0, packetLength)).then((success) => 0, (failure) => failure))
return "Couldn't send the packet : " + err;
//Receive the packet and return the error on failure
if (err = await p7ReceivePacket())
return "Couldn't receive the response packet : " + err;
//Resend the packet if the response was an error packet with subtype resend request and return the error on failure
for (let i = 0 ; (p7ReceivedPacketInfo.type === p7PacketType.error && p7ReceivedPacketInfo.subtype === errorSubtype.resendRequest) ; i++) {
if (err = await device.transferOut(1, p7SendBuffer.slice(0, packetLength)).then((success) => {console.log(success) ; return 0}, (failure) => {return failure}))
return "Couldn't send the packet : " + err;
if (err = await p7ReceivePacket())
return "Couldn't receive the response packet : " + err;
if (i > 2)
return "Too much resend request, the calculator might be broken.";
}
//Everything went right
return 0;
}
/* Send a basic (non-Extended) packet */
/* Return 0 on success and the error on failure */
async function p7SendBasicPacket(type, subtype) {
console.log("%cSending basic packet...", "color: green");
return await p7SendPacket(p7MakeBasicPacket(type, subtype));
}
/* Send an extended command packet */
/* Return 0 on success and the error on failure */
async function p7SendExtendedCommandPacket(subtype, forceOverwrite, dataType, fileSize, commandArguments) {
console.log("%cSending extended command packet...", "color: green");
return await p7SendPacket(p7MakeExtendedCommandPacket(subtype, forceOverwrite, dataType, fileSize, commandArguments));
}
/* Send an extended data packet */
/* Return 0 on success and the error on failure */
async function p7SendDataPacket(subtype, totalNumber, currentNumber, data) {
console.log("%cSending data packet...", "color: green");
return p7SendPacket(p7MakeDataPacket(subtype, totalNumber, currentNumber, data));
}
/* Split the data into 256 bytes-long buffer and send all of them */
/* Return 0 on success and the error on failure */
async function p7SendData(subtype, data) {
let err = 0;
let lastPacketSize = (data.byteLength & 255); //Equivalent to data.byteLength % 256, but way faster !
let totalPacketNumber = (data.byteLength >> 8); //Equivalent to data.byteLength / 256, but way way waaaaaay faster, and return an integer quotient, not a decimal one !!
console.log(lastPacketSize + ' ' + totalPacketNumber);
totalPacketNumber += (lastPacketSize) ? 1 : 0;
let currentPacketNumber = 1;
let currentPacketFirstByteIndex = 0;
//Send all the 256 bytes-long data packets
for (; currentPacketNumber < totalPacketNumber ; currentPacketNumber++)
if (err = await p7SendDataPacket(subtype, totalPacketNumber, currentPacketNumber, data.slice(currentPacketFirstByteIndex, (currentPacketFirstByteIndex += 256))))
return 'Couldn\'t send the ' + currentPacketNumber + ' data packet : ' + err;
//Send the last data packet (if it exists)
if (lastPacketSize)
if (err = await p7SendDataPacket(subtype, totalPacketNumber, currentPacketNumber, data.slice(currentPacketFirstByteIndex, currentPacketFirstByteIndex + lastPacketSize)))
return 'Couldn\'t send the last data packet (' + lastPacketSize + ' bytes) : ' + err;
console.log(p7SendBuffer.slice(0, 64));
console.log(p7ReceivedPacketInfo);
//Everything went allright
return 0;
}
/* Set all device information feilds, and trim string's overage ('ÿ') */
function p7DecodeExtendedAckPacket() {
p7DeviceInformation['Hardware identifier'] = String.fromCharCode.apply(null, p7ReceiveBuffer.slice(8, 16));
p7DeviceInformation['Processor identifier'] = String.fromCharCode.apply(null, p7ReceiveBuffer.slice(16, 32));
p7DeviceInformation['Preprogrammed ROM capacity'] = String.fromCharCode.apply(null, p7ReceiveBuffer.slice(32, 40));
p7DeviceInformation['Flash ROM capacity'] = String.fromCharCode.apply(null, p7ReceiveBuffer.slice(40, 48));
p7DeviceInformation['RAM capacity'] = String.fromCharCode.apply(null, p7ReceiveBuffer.slice(48, 56));
p7DeviceInformation['Prepogrammed ROM version'] = String.fromCharCode.apply(null, p7ReceiveBuffer.slice(56, 72)).replaceAll('ÿ', '');;
p7DeviceInformation['Boot code version'] = String.fromCharCode.apply(null, p7ReceiveBuffer.slice(72, 88)).replaceAll('ÿ', '');
p7DeviceInformation['Boot code offset'] = String.fromCharCode.apply(null, p7ReceiveBuffer.slice(88, 96)).replaceAll('ÿ', '');
p7DeviceInformation['Boot code size'] = String.fromCharCode.apply(null, p7ReceiveBuffer.slice(96, 104)).replaceAll('ÿ', '');
p7DeviceInformation['Os code version'] = String.fromCharCode.apply(null, p7ReceiveBuffer.slice(104, 120)).replaceAll('ÿ', '');
p7DeviceInformation['Os code offset'] = String.fromCharCode.apply(null, p7ReceiveBuffer.slice(120, 128));
p7DeviceInformation['Os code size'] = String.fromCharCode.apply(null, p7ReceiveBuffer.slice(128, 136));
p7DeviceInformation['Protocol version'] = String.fromCharCode.apply(null, p7ReceiveBuffer.slice(136, 140));
p7DeviceInformation['Product ID'] = String.fromCharCode.apply(null, p7ReceiveBuffer.slice(140, 156)).replaceAll('ÿ', '');;
p7DeviceInformation['Name set by user in system'] = String.fromCharCode.apply(null, p7ReceiveBuffer.slice(156, 172)).replaceAll('ÿ', '');
return 0;
}
/* Decode a terminate packet and close the connection */
async function p7DecodeTerminatePacket() {
let err = 0;
switch (p7ReceivedPacketInfo.subtype) {
case terminateSubtype.default:
alert('The calculator asked to close the connection.');
case terminateSubtype.userRequest:
alert('The calculator said you closed the connection!');
case terminateSubtype.timeouts:
alert('The calculator closed the connection because it was inactive for more than 6 minutes.');
case terminateSubtype.overwriteRequest:
alert('The calculator didn\'t accept the overwrite request and closed the connection.');
default:
alert('The calculator asked to terminate communication for an unknown reason : 0x' + p7ReceivedPacketInfo.subtype.toString(16) + ' (the hex code of the reason).');
}
if (err = await p7SendBasicPacket(p7PacketType.ack, ackSubtype.default))
return 'Couldn\'t send acknowledgement packet : ' + err;
return (err = await p7Exit()) ? 'Couldn\'t exit properly : ' + err : 0;
}
/* Return the value (as an number) of Filesize (FS) subfield of Data (D) field of an extended command packet */
function p7CommandPacketGetFilesize() {
return Number('0x' + String.fromCharCode.apply(null, p7ReceiveBuffer.slice(12, 20)), 16);
}
/* Return the trimed receive buffer only containing Data (DD) subfield of Data (D) field of an extended command packet */
function p7CommandPacketGetField(field) {
let fieldStart = 32; /* D1 field first byte's position */
for (let i = 0 ; i < 2 * field ; i += 2)
fieldStart += Number('0x' + String.fromCharCode(p7ReceiveBuffer[20 + i], p7ReceiveBuffer[21 + i]), 16);
let fieldEnd = fieldStart + Number('0x' + String.fromCharCode(p7ReceiveBuffer[20 + 2 * field], p7ReceiveBuffer[21 + 2 * field]), 16);
return p7ReceiveBuffer.slice(fieldStart, fieldEnd);
}
/* Connect to the calculator */
/* Return 0 on success and the error on failure */
async function p7Initialization() {
let err = 0;
err = await navigator.usb.requestDevice({filters:[{'vendorId': 0x07cf , 'productId': 0x6101}, {'vendorId': 0x07cf , 'productId': 0x6102}]}).then(
(selectedDevice) => {
device = selectedDevice;
return 0;
}, (error) => error
);
if (err)
return "Couldn't get the selected device (maybe the user didn't select one) : " + err;
if (err = await device.open().then(() => 0, (error) => error))
return "Couldn't connect to the calculator : " + err;
//It's the only existing configuration (should be selected by default), just checkin'
if (err = await device.selectConfiguration(1).then(() => 0, (error) => error))
return "Couldn't select the configuration (configurationValue : 1) : " + err;
if (err = await device.claimInterface(0 /* It's the only existing one */).then(() => 0, (error) => error))
return "Couldn't claim the interface (interfaceNumber : 0) : " + err;
console.log(device);
console.log('%cInitialisation packet', "font-size: 14px; color: white");
if (err = await p7SendBasicPacket(p7PacketType['check'], checkSubtype['initialization']))
return "Failed to send init packet : " + err;
if (!(p7ReceivedPacketInfo.type === p7PacketType.ack && p7ReceivedPacketInfo.subtype === ackSubtype.default))
return "Not the expected response packet."; /* TODO: handle this error */
console.log('%cRequesting device\'s informations', "font-size: 14px; color: white");
if (err = await p7SendBasicPacket(p7PacketType['command'], sysCommandSubtype['getDeviceInfo']))
return "Failed to request device info : " + err;
if (!(p7ReceivedPacketInfo.type === p7PacketType.ack && p7ReceivedPacketInfo.subtype === ackSubtype.extendedAck))
return "Not the expected response packet."; /* TODO: add a handle to this error */
p7DecodeExtendedAckPacket();
return 0;
}
/* Disconnect from the calculator */
/* Return 0 on success and the error on failure */
async function p7Exit() {
let err = 0;
return (err = await device.close().then((success) => {return 0}, (failure) => {return failure})) ? "There was an error disconnecting from the calculator : " + err : 0;
}
/* Return an object describing a file (or a directory) */
function createFileObject(device, path, name, size) {
//Directories never have size, only their own path
return (size) ? {type: 'file', path: path, name: name, size: size} : {type: 'directory', path: path};
}