Added sendFile() function
This commit is contained in:
parent
a64295504d
commit
3012c300f8
|
@ -4,12 +4,8 @@
|
|||
## Usage
|
||||
The buttons are actually diconnected, if you want to test, dive through the code.
|
||||
|
||||
## Things to change
|
||||
- Have a more js-like code approach !
|
||||
|
||||
## Actual possibilities
|
||||
- You can send files to flash memory (at least fls0, but maybe crd0 too), but only below ~1.5 ko (it freezes beyond, will patch this later)
|
||||
- You can list files, make directories, remove directories etc...
|
||||
- You can list files, make directories, remove directories, send files, etc...
|
||||
- you can optimize your flash
|
||||
- you can get your device infos
|
||||
|
||||
|
@ -18,7 +14,7 @@ The buttons are actually diconnected, if you want to test, dive through the code
|
|||
- Make a user friendly interface
|
||||
- Support all p7 protocol's commands
|
||||
- Screen casting ? (not a usb but a graphic difficulty)
|
||||
- other stuffs
|
||||
- other stuffs (os update ?)
|
||||
|
||||
## Thanks to :
|
||||
|
||||
|
|
311
commands.js
311
commands.js
|
@ -1,55 +1,286 @@
|
|||
(function () {
|
||||
/* ---------------------Single commands--------------------- */
|
||||
p7.commands = {
|
||||
/* ---------------------RAM filesystem commands--------------------- */
|
||||
ram: {
|
||||
/* ---------------------Single commands--------------------- */
|
||||
/* Create a directory */
|
||||
createDirectory: (name) =>
|
||||
p7.send.singleCommand(ramCommandSubtype.createDirectory, 0, 0, [name, '', '', '', '', ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't create directory: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Create a directory */
|
||||
p7.commands.createDirectory = (name, filesystem) => p7.send.singleCommand(flashCommandSubtype.createDirectory, 0, 0, [name, '', '', '', filesystem, '']);
|
||||
/* Delete a directory */
|
||||
deleteDirectory: (name) =>
|
||||
p7.send.singleCommand(ramCommandSubtype.deleteDirectory, 0, 0, [name, '', '', '', '', ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't delete directory: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Rename a directory */
|
||||
renameDirectory: (oldName, newName) =>
|
||||
p7.send.singleCommand(ramCommandSubtype.renameDirectory, 0, 0, [oldName, newName, '', '', '', ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't rename directory: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Change working directory */
|
||||
changeDirectory: (name) =>
|
||||
p7.send.singleCommand(ramCommandSubtype.changeDirectory, 0, 0, [name, '', '', '', '', ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't change working directory: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Delete a file */
|
||||
deleteFile: (datatype, fileSize, directory, name, groupName) =>
|
||||
p7.send.singleCommand(ramCommandSubtype.deleteFile, datatype, fileSize, [directory, name, groupName, '', '', ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't delete file: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Rename a file */
|
||||
renameFile: (datatype, directory, oldName, newName) =>
|
||||
p7.send.singleCommand(ramCommandSubtype.renameFile, datatype, 0, [directory, oldName, newName, '', '', ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't rename file: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Copy a file */
|
||||
copyFile: (datatype, oldDirectory, oldName, newDirectory, newName) =>
|
||||
p7.send.singleCommand(ramCommandSubtype.copyFile, datatype, 0, [oldDirectory, oldName, newDirectory, newName, '', ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't copy file: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Reset */
|
||||
reset: () =>
|
||||
p7.send.packet(p7.make.basicPacket(p7PacketType.command, ramCommandSubtype.reset))
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't reset RAM filesystem: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Delete a directory */
|
||||
p7.commands.deleteDirectory = (name, filesystem) => p7.send.singleCommand(flashCommandSubtype.deleteDirectory, 0, 0, [name, '', '', '', filesystem, '']);
|
||||
/* ---------------------Single command requests--------------------- */
|
||||
|
||||
/* Get free space */
|
||||
getCapacity: () =>
|
||||
p7.send.singleCommandRoleswap(ramCommandSubtype.capacityTransmitRequest, 0, 0, ['', '', '', '', '', ''],
|
||||
(buffer) => buffer.commandPacketFileSize()
|
||||
).then((filteredData) => filteredData[0])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't get the size of the free space: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* List files */
|
||||
list: () =>
|
||||
p7.send.singleCommandRoleswap(ramCommandSubtype.fileInfoTransferAllRequest, 0, 0, ['', '', '', '', '', ''],
|
||||
(buffer) => ({
|
||||
datatype: buffer.commandPacketDataType(),
|
||||
size: buffer.commandPacketFileSize(),
|
||||
directoryName: buffer.commandPacketDataField(1),
|
||||
name: buffer.commandPacketDataField(2),
|
||||
groupName: buffer.commandPacketDataField(3)
|
||||
})
|
||||
).catch((err) => {
|
||||
err.message = "Couldn't list files: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Rename a directory */
|
||||
p7.commands.renameDirectory = (oldName, newName, filesystem) => p7.send.singleCommand(flashCommandSubtype.renameDirectory, 0, 0, [oldName, newName, '', '', filesystem, '']);
|
||||
/* Transfer setup entry ? */
|
||||
getSetupEntry: (setupEntry) =>
|
||||
p7.send.singleCommandRoleswap(ramCommandSubtype.setupEntryTransferRequest, 0, 0, [setupEntry, '', '', '', '', ''],
|
||||
(buffer) => ({
|
||||
name: buffer.commandPacketDataField(1),
|
||||
data: buffer.commandPacketDataField(2).asciiToHex()
|
||||
})
|
||||
).catch((err) => {
|
||||
err.message = "Couldn't transfer setup entry: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Change working directory */
|
||||
p7.commands.changeDirectory = (name, filesystem) => p7.send.singleCommand(flashCommandSubtype.changeDirectory, 0, 0, [name, '', '', '', filesystem, '']);
|
||||
/* ---------------------Data commands--------------------- */
|
||||
|
||||
/* Delete a file */
|
||||
p7.commands.deleteFile = (directory, name, filesystem) => p7.send.singleCommand(flashCommandSubtype.deleteFile, 0, 0, [directory, name, '', '', filesystem, '']);
|
||||
/* ---------------------Data command requests--------------------- */
|
||||
|
||||
/* Rename a file */
|
||||
p7.commands.renameFile = (directory, oldName, newName, filesystem) => p7.send.singleCommand(flashCommandSubtype.renameFile, 0, 0, [directory, oldName, newName, '', filesystem, '']);
|
||||
/* Receive a file */
|
||||
getFile: (dataType, directory, name, groupName) =>
|
||||
p7.send.dataCommandRoleswap(ramCommandSubtype.fileTransferRequest, dataType, 0, [directory, name, groupName, '', '', ''],
|
||||
(command, data) => ({
|
||||
dataType: command.commandPacketDataType(),
|
||||
size: command.commandPacketFileSize(),
|
||||
directoryName: command.commandPacketDataField(1),
|
||||
name: command.commandPacketDataField(2),
|
||||
groupName: command.commandPacketDataField(3),
|
||||
data: data
|
||||
})
|
||||
).catch((err) => {
|
||||
err.message = "Couldn't receive file: " + err.message;
|
||||
throw err;
|
||||
})
|
||||
},
|
||||
|
||||
/* Copy a file */
|
||||
p7.commands.copyFile = (oldDirectory, oldName, newDirectory, newName, filesystem) => p7.send.singleCommand(flashCommandSubtype.copyFile, 0, 0, [oldDirectory, oldName, newDirectory, newName, filesystem, '']);
|
||||
/* ---------------------Flash memory filesystem commands--------------------- */
|
||||
|
||||
/* Reset flash? */
|
||||
p7.commands.resetFlash = (filesystem) => p7.send.singleCommand(flashCommandSubtype.resetFlash, 0, 0, ['', '', '', '', filesystem, '']);
|
||||
flash: {
|
||||
/* ---------------------Single commands--------------------- */
|
||||
|
||||
/* Optimize filesystem */
|
||||
p7.commands.optimizeFilesystem = (filesystem) => p7.send.singleCommand(flashCommandSubtype.optimizeFileSystem, 0, 0, ['', '', '', '', filesystem, '']);
|
||||
/* Create a directory */
|
||||
createDirectory: (name, filesystem = 'fls0') =>
|
||||
p7.send.singleCommand(flashCommandSubtype.createDirectory, 0, 0, [name, '', '', '', filesystem, ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't create directory: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Delete a directory */
|
||||
deleteDirectory: (name, filesystem = 'fls0') =>
|
||||
p7.send.singleCommand(flashCommandSubtype.deleteDirectory, 0, 0, [name, '', '', '', filesystem, ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't delete directory: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Rename a directory */
|
||||
renameDirectory: (oldName, newName, filesystem = 'fls0') =>
|
||||
p7.send.singleCommand(flashCommandSubtype.renameDirectory, 0, 0, [oldName, newName, '', '', filesystem, ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't rename directory: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Change working directory */
|
||||
changeDirectory: (name, filesystem = 'fls0') =>
|
||||
p7.send.singleCommand(flashCommandSubtype.changeDirectory, 0, 0, [name, '', '', '', filesystem, ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't change working directory: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Delete a file */
|
||||
deleteFile: (directory, name, filesystem = 'fls0') =>
|
||||
p7.send.singleCommand(flashCommandSubtype.deleteFile, 0, 0, [directory, name, '', '', filesystem, ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't delete file: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Rename a file */
|
||||
renameFile: (directory, oldName, newName, filesystem = 'fls0') =>
|
||||
p7.send.singleCommand(flashCommandSubtype.renameFile, 0, 0, [directory, oldName, newName, '', filesystem, ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't rename file: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Copy a file */
|
||||
copyFile: (oldDirectory, oldName, newDirectory, newName, filesystem = 'fls0') =>
|
||||
p7.send.singleCommand(flashCommandSubtype.copyFile, 0, 0, [oldDirectory, oldName, newDirectory, newName, filesystem, ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't copy file: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Reset */
|
||||
reset: (filesystem = 'fls0') =>
|
||||
p7.send.singleCommand(flashCommandSubtype.resetFlash, 0, 0, ['', '', '', '', filesystem, ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't reset flash: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* Optimize filesystem */
|
||||
optimize: (filesystem = 'fls0') =>
|
||||
p7.send.singleCommand(flashCommandSubtype.optimizeFileSystem, 0, 0, ['', '', '', '', filesystem, ''])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't optimize flash: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
|
||||
/* ---------------------Single command requests--------------------- */
|
||||
|
||||
/* Get free space */
|
||||
getCapacity: (filesystem = 'fls0') =>
|
||||
p7.send.singleCommandRoleswap(flashCommandSubtype.capacityTransmitRequest, 0, 0, ['', '', '', '', filesystem, ''],
|
||||
(buffer) => buffer.commandPacketFileSize()
|
||||
).then((filteredData) => filteredData[0])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't get the size of the free space: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* List files */
|
||||
list: (filesystem = 'fls0') =>
|
||||
p7.send.singleCommandRoleswap(flashCommandSubtype.fileInfoTransferAllRequest, 0, 0, ['', '', '', '', filesystem, ''],
|
||||
(buffer) => ({
|
||||
size: buffer.commandPacketFileSize(),
|
||||
directoryName: buffer.commandPacketDataField(1),
|
||||
name: buffer.commandPacketDataField(2)
|
||||
})
|
||||
).catch((err) => {
|
||||
err.message = "Couldn't list files: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* ---------------------Single command requests--------------------- */
|
||||
/* ---------------------Data commands--------------------- */
|
||||
|
||||
/* Get free space */
|
||||
p7.commands.getCapacity = (filesystem) =>
|
||||
p7.send.singleCommandRoleswap(flashCommandSubtype.capacityTransmitRequest, 0, 0, ['', '', '', '', filesystem, ''],
|
||||
() => p7.decode.commandPacketFileSize()
|
||||
).then((filteredData) => filteredData[0])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't get the size of the free space: " + err.message;
|
||||
throw err;
|
||||
});
|
||||
sendFile: (file, directory, filesystem = 'fls0') =>
|
||||
file.arrayBuffer()
|
||||
.then((fileContent) => p7.send.dataCommand(flashCommandSubtype.fileTransfer, 0, fileContent.length, [directory, file.name.substring(0, 12), "", "", filesystem, ""], fileContent))
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't send file: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
/* List files */
|
||||
p7.commands.list = (filesystem) =>
|
||||
p7.send.singleCommandRoleswap(flashCommandSubtype.fileInfoTransferAllRequest, 0, 0, ['', '', '', '', filesystem, ''],
|
||||
() => ({
|
||||
size: p7.decode.commandPacketFileSize(),
|
||||
DirectoryName: p7.decode.commandPacketDataField(1),
|
||||
name: p7.decode.commandPacketDataField(2)
|
||||
})).catch((err) => {
|
||||
err.message = "Couldn't list files: " + err.message;
|
||||
throw err;
|
||||
});
|
||||
/* ---------------------Data command requests--------------------- */
|
||||
|
||||
getFile: (directory, name, filesystem = 'fls0') =>
|
||||
p7.send.dataCommandRoleswap(flashCommandSubtype.fileTransferRequest, 0, 0, [directory, name, '', '', filesystem, ''],
|
||||
(command, data) => ({
|
||||
size: command.commandPacketFileSize(),
|
||||
directory : command.commandPacketDataField(1),
|
||||
name: command.commandPacketDataField(2),
|
||||
filesystem: command.commandPacketDataField(5),
|
||||
data: data
|
||||
})
|
||||
).then((filteredData) => filteredData[0])
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't receive file: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
getAllFiles: (filesystem = 'fls0') =>
|
||||
p7.send.dataCommandRoleswap(flashCommandSubtype.fileTransferAllRequest, 0, 0, ['', '', '', '', filesystem, ''],
|
||||
(command, data) => ({
|
||||
size: command.commandPacketFileSize(),
|
||||
directory : command.commandPacketDataField(1),
|
||||
name: command.commandPacketDataField(2),
|
||||
filesystem: command.commandPacketDataField(5),
|
||||
data: data
|
||||
})
|
||||
).catch((err) => {
|
||||
err.message = "Couldn't receive all files: " + err.message;
|
||||
throw err;
|
||||
}),
|
||||
|
||||
getFlashImage: (filesystem = 'fls0') =>
|
||||
p7.send.dataCommandRoleswap(flashCommandSubtype.flashImageTransferRequest, 0, 0, ['', '', '', '', filesystem, ''],
|
||||
(command, data)=> ({
|
||||
filesystem: command.commandPacketDataField(5),
|
||||
data: data
|
||||
})
|
||||
).catch((err) => {
|
||||
err.message = "Couldn't dump flash image: " + err.message;
|
||||
throw err;
|
||||
})
|
||||
}
|
||||
};
|
||||
}) ();
|
||||
|
|
8
const.js
8
const.js
|
@ -17,8 +17,8 @@ const sysCommandSubtype = {
|
|||
'setLinkSettings': 0x02, /* Probably unavailable since we are using USB */
|
||||
};
|
||||
|
||||
const mcsCommandSubtype = {
|
||||
/* MCS commands */
|
||||
const ramCommandSubtype = {
|
||||
/* RAM filesystem commands */
|
||||
'createDirectory': 0x20,
|
||||
'deleteDirectory': 0x21,
|
||||
'renameDirectory': 0x22,
|
||||
|
@ -29,7 +29,7 @@ const mcsCommandSubtype = {
|
|||
'renameFile': 0x27,
|
||||
'copyFile': 0x28,
|
||||
'fileTransferAllRequest': 0x29,
|
||||
'unknownResetMCS': 0x2A, /* TODO: TEST */
|
||||
'reset': 0x2A, /* TODO: TEST */
|
||||
'capacityTransmitRequest': 0x2B,
|
||||
'capacityTransmit': 0x2C,
|
||||
'fileInfoTransferAllRequest': 0x2D,
|
||||
|
@ -42,7 +42,7 @@ const mcsCommandSubtype = {
|
|||
};
|
||||
|
||||
const flashCommandSubtype = {
|
||||
/* Flash commands */
|
||||
/* Flash memory filesystem commands */
|
||||
'createDirectory': 0x40,
|
||||
'deleteDirectory': 0x41,
|
||||
'renameDirectory': 0x42,
|
||||
|
|
23
index.js
23
index.js
|
@ -1 +1,22 @@
|
|||
'use strict'
|
||||
'use strict'
|
||||
document.getElementById('connect').addEventListener('click', async function () {
|
||||
p7.device = {};
|
||||
|
||||
var time = performance.now();
|
||||
|
||||
await p7.init()
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
throw err;
|
||||
}).then((deviceInfo) => console.log(deviceInfo));
|
||||
await p7.commands.ram.getFile(254, "@EDIT", "EDIT.CFG", "@EDIT").then((file) => console.log(file));
|
||||
await p7.commands.flash.getAllFiles().then((f) => console.log(f));
|
||||
console.log('Done. (in ' + Math.round(performance.now() - time) + 'ms)');
|
||||
});
|
||||
|
||||
let input = document.getElementById('input');
|
||||
|
||||
input.addEventListener('change', async () => {
|
||||
await p7.commands.flash.sendFile(input.files[0], '');
|
||||
console.log('Done.');
|
||||
});
|
444
internal.js
444
internal.js
|
@ -1,28 +1,11 @@
|
|||
"use strict";
|
||||
|
||||
var p7 = {
|
||||
device: {},
|
||||
make: {},
|
||||
send: {},
|
||||
receive: {},
|
||||
decode: {},
|
||||
commands: {},
|
||||
|
||||
receiveBuffer : new Uint8Array(1032 + 1)
|
||||
};
|
||||
|
||||
var p7 = {};
|
||||
|
||||
|
||||
(function() {
|
||||
/* ---------------------Utilitaries--------------------- */
|
||||
|
||||
/* Sum individual bytes
|
||||
* NOT + 1, as defined in fxReverse documentation.
|
||||
* Be sure it's under 256! */
|
||||
Array.prototype.p7Checksum = Uint8Array.prototype.p7Checksum = function () {
|
||||
return (((~(this.reduce((accumulator, currentValue) => accumulator + currentValue))) + 1) & 0xFF)
|
||||
}
|
||||
|
||||
/* Convert a string into an array of ascii numbers */
|
||||
String.prototype.toAscii = function () {
|
||||
return this.split('').map((char) => char.charCodeAt(0))
|
||||
|
@ -33,214 +16,307 @@ var p7 = {
|
|||
Number.prototype.hexToAscii = function (padding) {
|
||||
return this.toString(16).toUpperCase().padStart(padding, 0).toAscii();
|
||||
}
|
||||
|
||||
/* Sum individual bytes
|
||||
* NOT + 1, as defined in fxReverse documentation.
|
||||
* Be sure it's under 256! */
|
||||
Array.prototype.p7Checksum = function () {
|
||||
return (((~(this.reduce((accumulator, currentValue) => accumulator + currentValue))) + 1) & 0xFF)
|
||||
}
|
||||
|
||||
/* Add the Checksum (CS) field to a packet */
|
||||
Array.prototype.addP7Checksum = function () {
|
||||
return this.concat(this.slice(1, this.length).p7Checksum().hexToAscii(2));
|
||||
}
|
||||
|
||||
/* Convert an ascii array into a string */
|
||||
Array.prototype.asciiToString = Uint8Array.prototype.asciiToString = function () {
|
||||
Array.prototype.asciiToString = function () {
|
||||
let string = [];
|
||||
this.forEach((element) => string.push(String.fromCharCode(element)));
|
||||
return string.join('');
|
||||
}
|
||||
|
||||
/* Convert an ascii array representing an hex number into a number */
|
||||
Array.prototype.asciiToHex = Uint8Array.prototype.asciiToHex = function () {
|
||||
Array.prototype.asciiToHex = function () {
|
||||
return Number('0x' + this.asciiToString());
|
||||
}
|
||||
|
||||
/* ---------------------Packet making--------------------- */
|
||||
|
||||
//Add the checksum to a packet
|
||||
p7.make.checksum = (packet) => packet.concat(packet.slice(1, packet.length).p7Checksum().hexToAscii(2));
|
||||
|
||||
/* Create a basic (Non-Extended) packet */
|
||||
/* Return the packet */
|
||||
p7.make.basicPacket = (type, subtype) => p7.make.checksum([type, //Type (T)
|
||||
...subtype.hexToAscii(2), //Subtype (ST)
|
||||
0x30]); //Extended (EX)
|
||||
|
||||
/* Create an extended command packet */
|
||||
/* Return the packet */
|
||||
p7.make.extendedCommandPacket = (subtype, datatype, fileSize, commandArguments) => {
|
||||
let data = [0x30, 0x30, //Overwrite (OW)
|
||||
...[0x30, 0x30], //Data type (DT) ??
|
||||
...fileSize.hexToAscii(8), //File size (FS)
|
||||
...commandArguments.flatMap((element) => element.length.hexToAscii(2)), //Size of Data {1..6} (SD{1..6})
|
||||
...commandArguments.join('').toAscii()]; //Data {1..6} (D{1..6})
|
||||
|
||||
return p7.make.checksum([0x01, //Type (T)
|
||||
...subtype.hexToAscii(2), //Subtype (ST)
|
||||
0x31, //Extended (EX)
|
||||
...data.length.hexToAscii(4), //Data size (DS)
|
||||
...data]); //Data (D)
|
||||
/* Return the decoded Data (D) field */
|
||||
Array.prototype.decodeDataField = function () {
|
||||
let buffer = [...this]
|
||||
buffer.forEach((element, index) => {
|
||||
if (element === 0x5C)
|
||||
buffer.splice(index, 2, buffer[index + 1] - (buffer[index + 1] !== 0x5C) * 0x20);
|
||||
});
|
||||
return buffer;
|
||||
}
|
||||
|
||||
/* Create a data packet */
|
||||
/* Return the packet */
|
||||
p7.make.dataPacket = (subtype, totalNumber, currentNumber, data) =>
|
||||
p7.make.checksum([0x02, //Type field
|
||||
...subtype.hexToAscii(2), //Subtype (ST) field
|
||||
0x31, //Extended (EX) field
|
||||
...(data.length + 8).hexToAscii(4), //Data size (DS) field
|
||||
...totalNumber.hexToAscii(4), //Total number (TN) subfield
|
||||
...currentNumber.hexToAscii(4), //Current number (CN) subfield
|
||||
...data]); //Data (DD) subfield
|
||||
|
||||
|
||||
/* ---------------------Packet decoding--------------------- */
|
||||
/* Return the encoded Data (D) field */
|
||||
Array.prototype.encodeDataField = function () {
|
||||
return this.flatMap((element) => (element < 0x20) ? [0x5C, (element + 0x20)] : (element === 0x5C) ? [0x5C, 0x5C] : element);
|
||||
}
|
||||
|
||||
/* Return all the informations of the device, and trim string's overage (255) */
|
||||
p7.decode.extendedAckPacket = () => {
|
||||
Array.prototype.extendedAckPacket = function () {
|
||||
return {
|
||||
hardwareIdentifier : p7.receiveBuffer.slice(8, 16).asciiToString(),
|
||||
processorIdentifier : p7.receiveBuffer.slice(16, 32).asciiToString(),
|
||||
preprogrammedROMCapacity : p7.receiveBuffer.slice(32, 40).asciiToString(),
|
||||
flashROMCapacity : p7.receiveBuffer.slice(40, 48).asciiToString(),
|
||||
ramCapacity : p7.receiveBuffer.slice(48, 56).asciiToString(),
|
||||
prepogrammedROMVersion : p7.receiveBuffer.slice(56, 72).filter(number => number !== 255).asciiToString(),
|
||||
bootCodeVersion : p7.receiveBuffer.slice(72, 88).filter(number => number !== 255).asciiToString(),
|
||||
bootCodeOffset : p7.receiveBuffer.slice(88, 96).filter(number => number !== 255).asciiToString(),
|
||||
bootCodeSize : p7.receiveBuffer.slice(96, 104).filter(number => number !== 255).asciiToString(),
|
||||
osCodeVersion : p7.receiveBuffer.slice(104, 120).filter(number => number !== 255).asciiToString(),
|
||||
osCodeOffset : p7.receiveBuffer.slice(120, 128).asciiToString(),
|
||||
osCodeSize : p7.receiveBuffer.slice(128, 136).asciiToString(),
|
||||
protocolVersion : p7.receiveBuffer.slice(136, 140).asciiToString(),
|
||||
productID : p7.receiveBuffer.slice(140, 156).filter(number => number !== 255).asciiToString(),
|
||||
username : p7.receiveBuffer.slice(156, 172).filter(number => number !== 255).asciiToString()
|
||||
hardwareIdentifier : this.slice(8, 16).asciiToString(),
|
||||
processorIdentifier : this.slice(16, 32).asciiToString(),
|
||||
preprogrammedROMCapacity : this.slice(32, 40).asciiToString(),
|
||||
flashROMCapacity : this.slice(40, 48).asciiToString(),
|
||||
ramCapacity : this.slice(48, 56).asciiToString(),
|
||||
prepogrammedROMVersion : this.slice(56, 72).asciiToString(),
|
||||
bootCodeVersion : this.slice(72, 88).asciiToString(),
|
||||
bootCodeOffset : this.slice(88, 96).asciiToString(),
|
||||
bootCodeSize : this.slice(96, 104).asciiToString(),
|
||||
osCodeVersion : this.slice(104, 120).filter(number => number !== 0xFF).asciiToString(),
|
||||
osCodeOffset : this.slice(120, 128).asciiToString(),
|
||||
osCodeSize : this.slice(128, 136).asciiToString(),
|
||||
protocolVersion : this.slice(136, 140).asciiToString(),
|
||||
productID : this.slice(140, 156).filter(number => number !== 0xFF).asciiToString(),
|
||||
username : this.slice(156, 172).filter(number => number !== 0xFF).asciiToString()
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Return the value (as an number) of the Overwrite (OW) subfield of the Data (D) field of an extended command packet */
|
||||
p7.decode.commandPacketOverWrite = () => p7.receiveBuffer.slice(8, 10).asciiToHex();
|
||||
|
||||
Array.prototype.commandPacketOverWrite = function () {
|
||||
return this.slice(8, 10).asciiToHex();
|
||||
}
|
||||
|
||||
/* Return the value (as an number) of the Data type (DT) subfield of the Data (D) field of an extended command packet */
|
||||
p7.decode.commandPacketDataType = () => p7.receiveBuffer.slice(10, 12).asciiToHex();
|
||||
|
||||
Array.prototype.commandPacketDataType = function () {
|
||||
return this.slice(10, 12).asciiToHex();
|
||||
}
|
||||
|
||||
/* Return the value (as an number) of the FileSize (FS) subfield of the Data (D) field of an extended command packet */
|
||||
p7.decode.commandPacketFileSize = () => p7.receiveBuffer.slice(12, 20).asciiToHex();
|
||||
|
||||
|
||||
Array.prototype.commandPacketFileSize = function () {
|
||||
return this.slice(12, 20).asciiToHex();
|
||||
}
|
||||
|
||||
/* Return the value (as a string) of the requested Data (D) subfield of the Data (D) field of an extended command packet */
|
||||
p7.decode.commandPacketDataField = function (field) {
|
||||
Array.prototype.commandPacketDataField = function (field) {
|
||||
let fieldSize = [];
|
||||
|
||||
/* Decode the length of Data {1 - ${length}} (D{1 - ${length}}) subfields */
|
||||
for (let index = 20, i = 0; i < field ; i++)
|
||||
fieldSize.push(p7.receiveBuffer.slice(index, (index += 2)).asciiToHex());
|
||||
|
||||
fieldSize.push(this.slice(index, (index += 2)).asciiToHex());
|
||||
|
||||
/* Get the requested field size */
|
||||
let fieldLength = fieldSize.pop();
|
||||
|
||||
/* Get the index of the requested field */
|
||||
let fieldIndex = (fieldSize.length) ? fieldSize.reduce((accumulator, currentValue) => accumulator + currentValue) + 32 : 32;
|
||||
|
||||
|
||||
/* Return the ascii array as a string */
|
||||
return p7.receiveBuffer.slice(fieldIndex, fieldIndex + fieldLength).asciiToString();
|
||||
}
|
||||
return this.slice(fieldIndex, fieldIndex + fieldLength).asciiToString();
|
||||
};
|
||||
|
||||
p7.decode.commandPacketAllDataFields = function () {
|
||||
/* Return an array containing the value (as a string) of all the Data (D) subfield of the Data (D) field of an extended command packet */
|
||||
Array.prototype.commandPacketAllDataFields = function () {
|
||||
let dataFieldSize = [];
|
||||
let index = 20
|
||||
while(index < 32)
|
||||
dataFieldSize.push(p7.receiveBuffer.subarray(index, (index += 2)).asciiToHex());
|
||||
dataFieldSize.push(this.slice(index, (index += 2)).asciiToHex());
|
||||
|
||||
return dataFieldSize.map((element) => p7.receiveBuffer.slice(index, (index += element)).asciiToString());
|
||||
return dataFieldSize.map((element) => this.slice(index, (index += element)).asciiToString());
|
||||
}
|
||||
|
||||
/* Return the value (as a number) of the Total number (CN) subfield of the Data (D) field of a data packet */
|
||||
Array.prototype.dataPacketDataFieldGetTotalNumber = function () {
|
||||
return this.slice(0, 4).asciiToHex();
|
||||
}
|
||||
|
||||
/* Return the value (as a number) of the Current number (CN) subfield of the Data (D) field of a data packet */
|
||||
Array.prototype.dataPacketDataFieldGetCurrentNumber = function () {
|
||||
return this.slice(4, 8).asciiToHex();
|
||||
}
|
||||
|
||||
/* Return the Data (D) subfield of the Data (D) field of a data packet */
|
||||
Array.prototype.dataPacketDataFieldGetData = function () {
|
||||
return this.slice(8, this.length);
|
||||
}
|
||||
|
||||
/* ---------------------Packet making--------------------- */
|
||||
|
||||
p7.make = {
|
||||
/* Create a basic (Non-Extended) packet
|
||||
* Return the packet */
|
||||
basicPacket: (type, subtype) =>
|
||||
([type, //Type (T)
|
||||
...subtype.hexToAscii(2), //Subtype (ST)
|
||||
0x30].addP7Checksum()), //Extended (EX)
|
||||
|
||||
/* Create an Extended packet
|
||||
* Return the packet */
|
||||
extendedPacket: (type, subtype, dataField) =>
|
||||
([type,
|
||||
...subtype.hexToAscii(2),
|
||||
0x31,
|
||||
...(dataField = dataField.encodeDataField()).length.hexToAscii(4),
|
||||
...dataField].addP7Checksum()),
|
||||
|
||||
/* Create a buffer containing the Data (D) field of a command packet
|
||||
* Return the buffer */
|
||||
commandPacketDataField: (datatype, fileSize, commandArguments) =>
|
||||
([0x30, 0x30, //Overwrite (OW)
|
||||
...datatype.hexToAscii(2), //Data type (DT) ??
|
||||
...fileSize.hexToAscii(8), //File size (FS)
|
||||
...commandArguments.flatMap((element) => element.length.hexToAscii(2)), //Size of Data {1..6} (SD{1..6})
|
||||
...commandArguments.join('').toAscii()]), //Data {1..6} (D{1..6})
|
||||
|
||||
/* Create a buffer containing the Data (D) field of a data packet
|
||||
* Return the buffer */
|
||||
dataPacketDataField: (totalNumber, currentNumber, data) =>
|
||||
([...totalNumber.hexToAscii(4), //Total number (TN) subfield
|
||||
...currentNumber.hexToAscii(4), //Current number (CN) subfield
|
||||
...data]), //Data (DD) subfield
|
||||
|
||||
};
|
||||
|
||||
/* ---------------------Packet receiving--------------------- */
|
||||
|
||||
p7.receive.packet = function () {
|
||||
console.log("%cReceiving...", "color: orange");
|
||||
|
||||
var packetInfo = {};
|
||||
var transfered = 0; //Already transfered bytes
|
||||
|
||||
return p7.device.transferIn(2, 64)
|
||||
.then(function receive(transferInResult) {
|
||||
if (!transferInResult.data.byteLength)
|
||||
return p7.device.transferIn(2, 64).then(receive);
|
||||
|
||||
p7.receiveBuffer.set(new Uint8Array(transferInResult.data.buffer), 0);
|
||||
|
||||
packetInfo.length = 6; //Type (T), Subtype (S), Extended (EX) and Checksum (CS) fields
|
||||
p7.receive = {
|
||||
packet: function () {
|
||||
console.log("%cReceiving...", "color: orange");
|
||||
|
||||
//Set Type (T) field
|
||||
packetInfo.type = p7.receiveBuffer[0];
|
||||
|
||||
//Set Subtype (ST) field
|
||||
packetInfo.subtype = p7.receiveBuffer.slice(1, 2).asciiToHex();
|
||||
var packetInfo = {};
|
||||
|
||||
//Set Extended (EX) field
|
||||
if ((packetInfo.extended = (p7.receiveBuffer[3] === 0x31))) {
|
||||
//Set Data size (DS) field
|
||||
packetInfo.dataSize = p7.receiveBuffer.slice(4, 8).asciiToHex();
|
||||
return p7.device.transferIn(2, 64)
|
||||
.then(function receive(transferInResult) {
|
||||
if (!transferInResult.data.byteLength) {
|
||||
console.log('buffer was empty, retrying');
|
||||
return p7.device.transferIn(2, 64).then(receive);
|
||||
}
|
||||
|
||||
packetInfo.receiveBuffer = Array.from(new Uint8Array(transferInResult.data.buffer));
|
||||
|
||||
packetInfo.length = 6; //Type (T), Subtype (S), Extended (EX) and Checksum (CS) fields
|
||||
|
||||
//Set Type (T) field
|
||||
packetInfo.type = packetInfo.receiveBuffer[0];
|
||||
|
||||
//Set Subtype (ST) field
|
||||
packetInfo.subtype = packetInfo.receiveBuffer.slice(1, 2).asciiToHex();
|
||||
|
||||
packetInfo.length += packetInfo.dataSize + 4; //Data size field
|
||||
|
||||
if ((transfered += 64) < packetInfo.length)
|
||||
return p7.device.transferIn(2, 64)
|
||||
.then(function receiveRemainingPackets(transferInResult) {
|
||||
p7.receiveBuffer.set(new Uint8Array(transferInResult.data.buffer), transfered);
|
||||
//Set Extended (EX) field
|
||||
if ((packetInfo.extended = (packetInfo.receiveBuffer[3] === 0x31))) {
|
||||
console.log('packet is extended');
|
||||
//Set Data size (DS) field
|
||||
packetInfo.dataSize = packetInfo.receiveBuffer.slice(4, 8).asciiToHex();
|
||||
|
||||
packetInfo.length += packetInfo.dataSize + 4; //Data size field
|
||||
|
||||
if (64 < packetInfo.length)
|
||||
return p7.device.transferIn(2, packetInfo.length - 64)
|
||||
.then((transferInResult) => packetInfo.receiveBuffer.push(...(new Uint8Array(transferInResult.data.buffer))));
|
||||
}
|
||||
}).then(() => {
|
||||
if (packetInfo.extended)
|
||||
packetInfo.data = packetInfo.receiveBuffer.slice(8, packetInfo.receiveBuffer.length - 2).decodeDataField();
|
||||
|
||||
if ((transfered += 64) < packetInfo.length)
|
||||
return p7.device.transferIn(2, 64).then(receiveRemainingPackets);
|
||||
});
|
||||
}
|
||||
}).then(() => {
|
||||
//Compute checksum
|
||||
let checksumError = ((packetInfo.checksum = p7.receiveBuffer.slice(packetInfo.length - 2, packetInfo.length).asciiToHex()) !== p7.receiveBuffer.slice(1, packetInfo.length - 2).p7Checksum());
|
||||
//Compute checksum
|
||||
let checksumError = ((packetInfo.checksum = packetInfo.receiveBuffer.slice(packetInfo.length - 2, packetInfo.length).asciiToHex()) !== packetInfo.receiveBuffer.slice(1, packetInfo.length - 2).p7Checksum());
|
||||
|
||||
/* TODO: handle checksum errors */
|
||||
console.log(checksumError);
|
||||
return packetInfo;
|
||||
}).catch((err) => {
|
||||
err.message = "Couldn't receive the packet: " + err.message;
|
||||
throw err;
|
||||
});
|
||||
},
|
||||
|
||||
return packetInfo;
|
||||
}).catch((err) => {
|
||||
err.message = "Couldn't receive the " + transfered + " to " + (transfered + 64) + " bytes of the packet: " + err.message;
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
data: function (responsePacketInfo) {
|
||||
var data = [];
|
||||
|
||||
return p7.send.packet(p7.make.basicPacket(p7PacketType.ack, ackSubtype.default))
|
||||
.then(function receiveData(responsePacketInfo) {
|
||||
if (responsePacketInfo.type !== p7PacketType.data)
|
||||
return [data.flat(), responsePacketInfo];
|
||||
|
||||
data.push(responsePacketInfo.data.dataPacketDataFieldGetData());
|
||||
return p7.send.packet(p7.make.basicPacket(p7PacketType.ack, ackSubtype.default)).then(receiveData);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* ---------------------Packet sending--------------------- */
|
||||
|
||||
p7.send.packet = function (buffer) {
|
||||
console.log("%cSending packet...", "color: green");
|
||||
return p7.device.transferOut(1, Uint8Array.from(buffer))
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't send the packet: " + err.message;
|
||||
throw err;
|
||||
})
|
||||
.then(() => p7.receive.packet())
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't receive the response packet: " + err.message;
|
||||
throw err;
|
||||
});
|
||||
}
|
||||
p7.send = {
|
||||
packet: function (buffer) {
|
||||
console.log("%cSending packet...", "color: green");
|
||||
return p7.device.transferOut(1, Uint8Array.from(buffer))
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't send the packet: " + err.message;
|
||||
throw err;
|
||||
})
|
||||
.then((transferOutResult) => p7.receive.packet())
|
||||
.catch((err) => {
|
||||
err.message = "Couldn't receive the response packet: " + err.message;
|
||||
throw err;
|
||||
});
|
||||
},
|
||||
|
||||
/* Send a single command
|
||||
* Return the informations about the response ack packet */
|
||||
p7.send.singleCommand = (subtype, datatype, fileSize, commandArguments) =>
|
||||
p7.send.packet(p7.make.extendedCommandPacket(subtype, datatype, fileSize, commandArguments))
|
||||
.then((responsePacketInfo) => {
|
||||
//Check if the packet is an ack packet
|
||||
if (!(responsePacketInfo.type === p7PacketType.ack && responsePacketInfo.subtype === ackSubtype.default))
|
||||
throw new Error("The calculator didn't send the expected ack packet!");
|
||||
});
|
||||
/* Send a single command
|
||||
* Return the informations about the response ack packet */
|
||||
singleCommand: (subtype, datatype, fileSize, commandArguments) =>
|
||||
p7.send.packet(p7.make.extendedPacket(p7PacketType.command, subtype, p7.make.commandPacketDataField(datatype, fileSize, commandArguments)))
|
||||
.then((responsePacketInfo) => {
|
||||
if (!(responsePacketInfo.type === p7PacketType.ack && responsePacketInfo.subtype === ackSubtype.default))
|
||||
throw new Error("The calculator didn't send the expected ack packet!:" +
|
||||
"\t{Type: " + responsePacketInfo.type +
|
||||
"\tSubtype: " + responsePacketInfo.subtype + "}");
|
||||
|
||||
/* Send a single command request
|
||||
* Return an array containing the filtered (with `callbackFunction`) Data (D) field of each response command packet */
|
||||
p7.send.singleCommandRoleswap = function (subtype, datatype, fileSize, commandArguments, callbackFunction) {
|
||||
var filteredData = [];
|
||||
return responsePacketInfo;
|
||||
}),
|
||||
|
||||
/* Send a single command request
|
||||
* Return an array containing the filtered (with `callbackFunction`) Data (D) field of each response command packet */
|
||||
singleCommandRoleswap: function (subtype, datatype, fileSize, commandArguments, callbackFunction) {
|
||||
var filteredData = [];
|
||||
|
||||
return p7.send.singleCommand(subtype, datatype, fileSize, commandArguments)
|
||||
.then(() => p7.send.packet(p7.make.basicPacket(p7PacketType.roleswap, roleswapSubtype.default)))
|
||||
.then(function receiveRequestedCommand(responsePacketInfo) {
|
||||
if (responsePacketInfo.type !== p7PacketType.command)
|
||||
return filteredData;
|
||||
|
||||
filteredData.push(callbackFunction(responsePacketInfo.receiveBuffer));
|
||||
return p7.send.packet(p7.make.basicPacket(p7PacketType.ack, ackSubtype.default)).then(receiveRequestedCommand);
|
||||
});
|
||||
},
|
||||
|
||||
dataCommand: function (subtype, datatype, fileSize, commandArguments, data) {
|
||||
var currentPacketNumber = 0;
|
||||
var lastPacketSize = data.length & 0xFF; //Equivalent to data.length % 256, but way faster !
|
||||
var totalPacketNumber = (data.length >> 8) + (lastPacketSize !== 0); //Equivalent to data.length / 256, but way way waaaaaay faster, and return an integer quotient, not a decimal one !!
|
||||
|
||||
return p7.send.singleCommand(subtype, datatype, fileSize, commandArguments)
|
||||
.then((responsePacketInfo) => p7.send.packet(p7.make.basicPacket(p7PacketType.roleswap, roleswapSubtype.default)))
|
||||
.then(function receiveRequestedCommand(responsePacketInfo) {
|
||||
if (responsePacketInfo.type !== p7PacketType.command)
|
||||
return filteredData;
|
||||
|
||||
filteredData.push(callbackFunction());
|
||||
return p7.send.packet(p7.make.basicPacket(p7PacketType.ack, ackSubtype.default)).then(receiveRequestedCommand);
|
||||
});
|
||||
}
|
||||
.then(function sendDataPackets(result) {
|
||||
if ((currentPacketNumber += 1) === totalPacketNumber)
|
||||
return p7.send.packet(p7.make.extendedPacket(p7PacketType.data, subtype, p7.make.dataPacketDataField(totalPacketNumber, currentPacketNumber, data.slice(data.length - lastPacketSize, data.length))))
|
||||
|
||||
return p7.send.packet(p7.make.extendedPacket(p7PacketType.data, subtype, p7.make.dataPacketDataField(totalPacketNumber, currentPacketNumber, data.slice(((currentPacketNumber - 1) << 8), (currentPacketNumber << 8))))).then(sendDataPackets);
|
||||
});
|
||||
},
|
||||
|
||||
dataCommandRoleswap: async function (subtype, datatype, fileSize, commandArguments, callbackFunction) {
|
||||
var filteredData = [];
|
||||
|
||||
return p7.send.singleCommand(subtype, datatype, fileSize, commandArguments)
|
||||
.then(() => p7.send.packet(p7.make.basicPacket(p7PacketType.roleswap, roleswapSubtype.default)))
|
||||
.then(function receiveRequestedData(responsePacketInfo) {
|
||||
if (responsePacketInfo.type === p7PacketType.roleswap)
|
||||
return filteredData;
|
||||
|
||||
let command = responsePacketInfo.receiveBuffer;
|
||||
return p7.receive.data()
|
||||
.then((dataResponse) => {
|
||||
filteredData.push(callbackFunction(command, dataResponse[0]));
|
||||
return receiveRequestedData(dataResponse[1]);
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* ---------------------Initialization and exiting--------------------- */
|
||||
|
||||
/* Connect to the calculator */
|
||||
|
@ -370,32 +446,10 @@ var p7 = {
|
|||
}).then(() => p7.send.packet(p7.make.basicPacket(p7PacketType.command, sysCommandSubtype.getDeviceInfo))
|
||||
.catch(() => {
|
||||
throw new Error("Couldn't ask for the device infos!");
|
||||
}).then(() => p7.decode.extendedAckPacket())));
|
||||
}).then((responsePacketInfo) => responsePacketInfo.receiveBuffer.extendedAckPacket())));
|
||||
|
||||
/* End the connexion with the calculator */
|
||||
p7.exit = async function () {
|
||||
p7.exit = function () {
|
||||
|
||||
}
|
||||
|
||||
|
||||
document.getElementById('connect').addEventListener('click',
|
||||
async function () {
|
||||
var time = performance.now();
|
||||
return p7.init()
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
return err;
|
||||
}).then((deviceInfo) => {
|
||||
console.log(deviceInfo);
|
||||
|
||||
//Main commands
|
||||
p7.commands.list('fls0')
|
||||
.then((fileList) => console.log('The following files are in the flash memory: %o', fileList))
|
||||
.then(() => p7.commands.getCapacity('fls0'))
|
||||
.then((capacity) => console.log('Flash memory free space: ' + capacity + 'o'))
|
||||
.then(() => console.log('Done. (in ' + Math.round(performance.now() - time) + 'ms)'));
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
|
|
Loading…
Reference in New Issue