From 3a06091c37ce9dcb467a6d4e74e8dee04417e878 Mon Sep 17 00:00:00 2001 From: neiviv-ui Date: Thu, 22 Jul 2021 18:25:57 +0200 Subject: [PATCH] Added list() and flash mem single packet commands --- README.md | 10 ++-- commands.js | 50 ++++++++++++++++++ const.js | 2 +- index.html | 1 + internal.js | 142 +++++++++++++++++++++++++++++++++++++++++----------- 5 files changed, 170 insertions(+), 35 deletions(-) create mode 100644 commands.js diff --git a/README.md b/README.md index da2c343..7ff4d0f 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,26 @@ # Warning : Use this tool at your own risks, nobody can be taken as responsible if it damage your calculator !!! -# Usage +## Usage The buttons are actually diconnected, if you want to test, dive through the code. -# Things to change +## Things to change - Have a more js-like code approach ! -# Actual possibilities +## 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 optimize your flash - you can get your device infos -# Future possibilities +## Future possibilities - Make a user friendly interface - Support all p7 protocol's commands - Screen casting ? (not a usb but a graphic difficulty) - other stuffs -# Thanks to : +## Thanks to : - Simon Lothar for his fx-reverse doc - Cakeisalie5 for his p7 command line tool \ No newline at end of file diff --git a/commands.js b/commands.js new file mode 100644 index 0000000..f331d39 --- /dev/null +++ b/commands.js @@ -0,0 +1,50 @@ +(function () { + /* ---------------------Single commands--------------------- */ + + /* Create a directory */ + p7.commands.createDirectory = async (name, fileSystem) => await p7.send.singleCommand(flashCommandSubtype.createDirectory, 0, 0, [name, '', '', '', fileSystem, '']); + + /* Delete a directory */ + p7.commands.deleteDirectory = async (name, fileSystem) => await p7.send.singleCommand(flashCommandSubtype.deleteDirectory, 0, 0, [name, '', '', '', fileSystem, '']); + + /* Rename a directory */ + p7.commands.renameDirectory = async (oldName, newName, fileSystem) => await p7.send.singleCommand(flashCommandSubtype.renameDirectory, 0, 0, [oldName, newName, '', '', fileSystem, '']); + + /* Change working directory */ + p7.commands.changeDirectory = async (name, fileSystem) => await p7.send.singleCommand(flashCommandSubtype.changeDirectory, 0, 0, [name, '', '', '', fileSystem, '']); + + /* Delete a file */ + p7.commands.deleteFile = async (directory, name, fileSystem) => await p7.send.singleCommand(flashCommandSubtype.deleteFile, 0, 0, [directory, name, '', '', fileSystem, '']); + + /* Rename a file */ + p7.commands.renameFile = async (directory, oldName, newName, fileSystem) => await p7.send.singleCommand(flashCommandSubtype.renameFile, 0, 0, [directory, oldName, newName, '', fileSystem, '']); + + /* Copy a file */ + p7.commands.copyFile = async (oldDirectory, oldName, newDirectory, newName, fileSystem) => await p7.send.singleCommand(flashCommandSubtype.copyFile, 0, 0, [oldDirectory, oldName, newDirectory, newName, fileSystem, '']); + + /* Optimize fileSystem */ + p7.commands.optimizeFileSystem = async (fileSystem) => await p7.send.singleCommand(flashCommandSubtype.optimizeFileSystem, 0, 0, ['', '', '', '', fileSystem, '']); + + /* ---------------------Single command requests--------------------- */ + + /* List files */ + p7.commands.list = async function (fileSystem) { + let fileList = []; + + try { + (await p7.send.singleCommandRoleswap(flashCommandSubtype.fileInfoTransferAllRequest, 0, 0, ['', '', '', '', fileSystem, ''])) + .forEach(element => + fileList.push({ + size: element.fileSize, + DirectoryName: element.data[0], + name: element.data[1] + }) + ); + } catch (err) { + throw new Error("Couldn't list files: " + err.message); + } + + return fileList; + } + +}) (); \ No newline at end of file diff --git a/const.js b/const.js index 341e118..7396536 100644 --- a/const.js +++ b/const.js @@ -60,7 +60,7 @@ const flashCommandSubtype = { 'fileInfoTransfer': 0x4E, 'flashImageTransferRequest': 0x4F, 'flashImageTransfer': 0x50, - 'optimizeFilesystem': 0x51 + 'optimizeFileSystem': 0x51 // 'osUpdateRelated': [0x52 --> 0x57] ? }; diff --git a/index.html b/index.html index 16cf759..77a49fe 100644 --- a/index.html +++ b/index.html @@ -16,6 +16,7 @@ + \ No newline at end of file diff --git a/internal.js b/internal.js index 194e5e9..7edc07d 100644 --- a/internal.js +++ b/internal.js @@ -3,9 +3,13 @@ var p7 = { device: {}, make: {}, - decode: {}, + send: {}, receive: {}, - send: {} + decode: {}, + commands: {}, + + sendBuffer : new Uint8Array(1032), + receiveBuffer : new Uint8Array(1032 + 1) }; @@ -46,9 +50,6 @@ var p7 = { return Number('0x' + this.asciiToString()); } - p7.sendBuffer = new Uint8Array(1032); - p7.receiveBuffer = new Uint8Array(1032 + 1); - /* ---------------------Packet making--------------------- */ /* Create a basic (Non-Extended) packet and push it to p7.sendBuffer */ @@ -69,7 +70,7 @@ var p7 = { /* Fill the Data (D) field of a command packet in p7.sendBuffer */ /* return the Data (D) field length */ - p7.make.commandPacketDataField = function (dataType, fileSize, commandArguments) { + p7.make.commandPacketDataField = function (datatype, fileSize, commandArguments) { //Set Overwrite (OW), Data type (DT) and File size (FS) fields p7.sendBuffer.set([0x30, 0x30, /* Overwrite */ 0x30, 0x30] /* Data type field ?? */ @@ -78,6 +79,7 @@ var p7 = { let index = 18; + //Set Size of Data {1-6} (SD{1-6}) fields commandArguments.forEach(element => p7.sendBuffer.set(element.length.hexToAscii(2), (index += 2))); @@ -90,8 +92,8 @@ var p7 = { /* Create an extended command packet and push it to p7.sendBuffer */ /* return it's length */ - p7.make.extendedCommandPacket = function (subtype, dataType, fileSize, commandArguments) { - let dataSize = p7.make.commandPacketDataField(dataType, fileSize, commandArguments); /* Data field */ + p7.make.extendedCommandPacket = function (subtype, datatype, fileSize, commandArguments) { + let dataSize = p7.make.commandPacketDataField(datatype, fileSize, commandArguments); /* Data field */ //Set Type (T), Subtype (ST), Extended (EX) and Data size (DT) fields p7.sendBuffer.set([0x01] /* Type field */ @@ -109,12 +111,12 @@ var p7 = { /* Create a data packet and push it to p7.sendBuffer */ /* return it's length */ - p7.make.dataPacket = function (subType, totalNumber, currentNumber, data) { + p7.make.dataPacket = function (subtype, totalNumber, currentNumber, data) { /* Set Type (T), Subtype (ST), Extended (EX), Data size (DS), * Data (D) fields and Data (D) subfields : * Total Number (TN), Current Number (CN), and Data (DD) */ p7.sendBuffer.set([0x02] /* Type field */ - .concat(subType.hexToAscii(2)) /* Subtype (ST) field */ + .concat(subtype.hexToAscii(2)) /* Subtype (ST) field */ .concat([0x31]) /* Extended (EX) field */ .concat( /* Data size (DS) field */ (data.length + 8 /* Total number (TN) and Current number (CN) subfields */ ).hexToAscii(4)) @@ -154,8 +156,44 @@ var p7 = { } }; - /* Rturn 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(); + /* 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(); + + /* 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(); + + /* 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(); + + + /* 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) { + 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()); + + /* 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(); + } + + p7.decode.commandPacketAllDataFields = function () { + let dataFieldSize = []; + let index = 20 + while(index < 32) + dataFieldSize.push(p7.receiveBuffer.slice(index, (index += 2)).asciiToHex()); + + let dataField = []; + dataFieldSize.forEach((element) => dataField.push(p7.receiveBuffer.slice(index, (index += element)).asciiToString())); + return dataField; + } /* ---------------------Packet receiving--------------------- */ @@ -207,13 +245,15 @@ var p7 = { if (checksumError && (checksumTries++) < 3) { console.log('there was a checksum error'); try { - packetInfo = await p7.send.packet(p7.make.basicPacket(p7PacketType.error, errorSubtype.resendRequest)); + packetInfo = await p7.send.basicPacket(p7PacketType.error, errorSubtype.resendRequest); } catch (err) { throw new Error("Couldn't send the resend request: " + err.message); } } - if (checksumTries === 4) + if (checksumTries === 4) { + checksumTries = 0; throw new Error("There were three checksum in a row, the calculator or the cable may be broken!"); + } return packetInfo; } @@ -242,6 +282,55 @@ var p7 = { return responsePacketInfo; }; + p7.send.basicPacket = async (type, subtype) => await p7.send.packet(p7.make.basicPacket(type, subtype)); + + p7.send.extendedCommandPacket = async (subtype, datatype, fileSize, commandArguments) => await p7.send.packet(p7.make.extendedCommandPacket(subtype, datatype, fileSize, commandArguments)); + + p7.send.dataPacket = async (subtype, totalNumber, currentNumber, data) => await p7.send.packet(p7.make.dataPacket(subtype, totalNumber, currentNumber, data)); + + /* Send a single command + * Return the informations about the response ack packet */ + p7.send.singleCommand = async function (subtype, datatype, fileSize, commandArguments) { + /* Send the command */ + let responsePacketInfo = await p7.send.extendedCommandPacket(subtype, datatype, fileSize, commandArguments); + + /* 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 !"); + + return responsePacketInfo; + } + + /* Send a single command request + * Return the Data (D) field of the response command packet(s) */ + p7.send.singleCommandRoleswap = async function (subtype, datatype, fileSize, commandArguments) { + /* Array to store the Data (D) field of the response command packet(s) */ + let requestedCommandResult = []; + + /* Send the command */ + let responsePacketInfo = await p7.send.extendedCommandPacket(subtype, datatype, fileSize, commandArguments); + if (!(responsePacketInfo.type === p7PacketType.ack && responsePacketInfo.subtype === ackSubtype.default)) + throw new Error("The calculator didn't send the expected ack packet !"); + + /* Exchange roles */ + responsePacketInfo = await p7.send.basicPacket(p7PacketType.roleswap, roleswapSubtype.default); + + /* Receive all the requested command packets and store their Data (D) field */ + while (responsePacketInfo.type === p7PacketType.command) { + requestedCommandResult.push({ + overwrite: p7.decode.commandPacketOverWrite(), + datatype: p7.decode.commandPacketDataType(), + fileSize: p7.decode.commandPacketFileSize(), + data: p7.decode.commandPacketAllDataFields() + }) + responsePacketInfo = await p7.send.basicPacket(p7PacketType.ack, ackSubtype.default); + } + + /* Everything went right */ + return requestedCommandResult; + } + + /* ---------------------Initialization and exiting--------------------- */ /* Initiate the connexion with the calculator */ @@ -380,21 +469,11 @@ var p7 = { async function () { try { await p7.init(); - } catch (err) { - console.error(err); - return err; - } - - try { - await p7.send.packet(p7.make.basicPacket(p7PacketType.check, checkSubtype.initialization)); - } catch (err) { - console.error(err); - return err; - } - + + await p7.send.basicPacket(p7PacketType.check, checkSubtype.initialization); - try { - await p7.send.packet(p7.make.basicPacket(p7PacketType.command, sysCommandSubtype.getDeviceInfo)); + await p7.send.basicPacket(p7PacketType.command, sysCommandSubtype.getDeviceInfo); + } catch (err) { console.error(err); return err; @@ -402,6 +481,11 @@ var p7 = { console.log(p7.decode.extendedAckPacket()); - }); + console.log(await p7.commands.list('fls0')); + + console.log(await p7.commands.createDirectory('test', 'fls0')); + + console.log(await p7.commands.list('fls0')); + }); })(); \ No newline at end of file