diff --git a/README.md b/README.md
index 1a1dfc5..eb33d1d 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,26 @@
-#Usage
+# Warning : Use this tool at your own risks, nobody can be taken as responsible if it damage your calculator !!!
+
+# 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 optimize your flash
+- you can get your device infos
+
+# 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 :
+
+Simon Lothar for his fx-reverse doc
+Cakeisalie5 for his p7 command line tool
\ No newline at end of file
diff --git a/index.js b/index.js
index 12c6127..e55efe3 100644
--- a/index.js
+++ b/index.js
@@ -1,233 +1,14 @@
-"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;
+'use strict'
+/*function test(){
+ throw 'geswg';
+ console.log('err');
}
-/* 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");
+try {
+ test();
+ console.log('err');
+} catch(err) {
+ console.error(err);
+}*/
- //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'] +
- '
Processor identifier : ' + p7DeviceInformation['Processor identifier'] +
- '
Preprogrammed ROM capaciy : ' + p7DeviceInformation['Preprogrammed ROM capaciy']+
- '
Flash ROM capacity : ' + p7DeviceInformation['Flash ROM capacity'] +
- '
RAM capacity : ' + p7DeviceInformation['RAM capacity'] +
- '
Prepogrammed ROM version : ' + p7DeviceInformation['Prepogrammed ROM version'] +
- '
Boot code version : ' + p7DeviceInformation['Boot code version'] +
- '
Boot code offset : ' + p7DeviceInformation['Boot code offset'] +
- '
Boot code size : ' + p7DeviceInformation['Boot code size'] +
- '
Os code version : ' + p7DeviceInformation['Os code version'] +
- '
Os code offset : ' + p7DeviceInformation['Os code offset'] +
- '
Os code size : ' + p7DeviceInformation['Os code size'] +
- '
Protocol version : ' + p7DeviceInformation['Protocol version'] +
- '
Product ID : ' + p7DeviceInformation['Product ID'] +
- '
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);
-
- }
-}
diff --git a/internal.js b/internal.js
index 93c683c..8a9514d 100644
--- a/internal.js
+++ b/internal.js
@@ -1,153 +1,189 @@
"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.
+var p7 = {
+ device: {},
+ make: {},
+ decode: {},
+ receive: {},
+ send: {}
+};
+
+
+(function() {
+ /* ---------------------Utilitaries--------------------- */
+
+ /* Sum individual bytes
+ * NOT + 1, as defined in fxReverse documentation.
* Be sure it's under 256! */
- return (((~checksum) + 1) & 0xFF);
-}
+ Uint8Array.prototype.p7Checksum = function () {
+ return (((~(this.reduce((accumulator, currentValue) => accumulator + currentValue))) + 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));
-}
+ /* Convert a string into an array of ascii numbers */
+ String.prototype.toAscii = function () {
+ return this.split('').map((char) => char.charCodeAt(0))
+ }
-/* Return an array with the ascii value of each character */
-function p7StringToAscii(string) {
- return string.split('').map(letter => letter.charCodeAt(0));
-}
+ /* Convert an hex number into an array of ascii values
+ * Use the uppercase representation of the number */
+ Number.prototype.hexToAscii = function (padding) {
+ return this.toString(16).toUpperCase().padStart(padding, 0).toAscii();
+ }
-/* 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);
+ /* Convert an ascii array into a string */
+ p7.asciiToString = (array) => String.fromCharCode.apply(null, array);
- //Set Subtype (ST) field
- p7SendBuffer.set(p7HexToAscii(subtype, 2), 1);
+ /* Convert an ascii array representing an hex number into a number */
+ //Uint8Array.prototype.fromAsc
+ p7.asciiToHex = (array) => Number('0x' + p7.asciiToString(array));
+
+
+ p7.sendBuffer = new Uint8Array(1032);
+ p7.receiveBuffer = undefined;//new Uint8Array(1032 + 1);
+
+ /* ---------------------Packet making--------------------- */
+
+ /* Create a basic (Non-Extended) packet and push it to p7.sendBuffer */
+ /* return it's length (6) */
+ p7.make.basicPacket = (type, subtype) => {
+ //Set the Type (T), Subtype (ST) and Extended (EX) fields
+ p7.sendBuffer.set([type]
+ .concat(subtype.hexToAscii(2))
+ .concat([0x30])
+ , 0);
+
+ //Set the Checksum (CS) field
+ p7.sendBuffer.set(p7.sendBuffer.slice(1, 4).p7Checksum().hexToAscii(2), 4);
- //Set Extended (EX) field
- p7SendBuffer.set([0x30], 3);
+ //Return the packet length
+ return 6;
+ }
- //Set Checksum (CS) field
- p7SendBuffer.set(p7HexToAscii(p7Checksum(p7SendBuffer, 6), 2), 4);
-
- //Return basic packet length
- return 6;
-}
+ /* 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) {
+ //Set Overwrite (OW), Data type (DT) and File size (FS) fields
+ p7.sendBuffer.set([0x30, 0x30, /* Overwrite */
+ 0x30, 0x30] /* Data type field ?? */
+ .concat(fileSize.hexToAscii(8)) /* File size field */
+ , 8);
-/* 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);
+
+ 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)));
+
+ //Set Data {1-6} (D{1-6}) fields
+ let data = commandArguments.join('');
+ p7.sendBuffer.set(data.toAscii(), 32);
+
+ return data.length + 24; /* Overwrite (OW), Data type (DT), File size (FS) and Data size (DS) subfields of the Data (D) field of the packet */;
+ }
- //Set Data type (DT) field ????
- p7SendBuffer.set([0x30, 0x30], 10);
+ /* 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 */
+
+ //Set Type (T), Subtype (ST), Extended (EX) and Data size (DT) fields
+ p7.sendBuffer.set([0x01] /* Type field */
+ .concat(subtype.hexToAscii(2)) /* Subtype field */
+ .concat([0x31]) /* Extended field */
+ .concat(dataSize.hexToAscii(4)) /* Data size field */
+ , 0);
+
+ //Set Checksum (CS) field
+ p7.sendBuffer.set(p7.sendBuffer.slice(1, dataSize + 8).p7Checksum().hexToAscii(2), dataSize + 8);
- //Set Filesize (FS) field
- p7SendBuffer.set(p7HexToAscii(fileSize, 8), 12);
+ //Return it's length
+ return dataSize + 10 /* Type (T), Subtype (ST), Extended (EX), Data size (DT) and Checksum (CS) fields */;
+ }
- let packetSize = 20;
+ /* Create a data packet and push it to p7.sendBuffer */
+ /* return it's length */
+ 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([0x31]) /* Extended (EX) field */
+ .concat( /* Data size (DS) field */
+ (data.length + 8 /* Total number (TN) and Current number (CN) subfields */ ).hexToAscii(4))
+ .concat(totalNumber.hexToAscii(4)) /* Total number (TN) subfield */
+ .concat(currentNumber.hexToAscii(4)) /* Current number (CN) subfield */
+ .concat(data) /* Data (DD) subfield */
+ , 0);
+
+ //Set Checksum (CS) field
+ p7.sendBuffer.set(p7.sendBuffer.slice(1, data.length + 16).p7Checksum().hexToAscii(2), data.length + 16);
- //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 it's length
+ return data.length + 18 /* All other fields and subfields */;
+ }
+
+
+ /* ---------------------Packet decoding--------------------- */
+
+ /* Return all the informations of the device, and trim string's overage (255) */
+ p7.decode.extendedAckPacket = () => {
+ return {
+ hardwareIdentifier : p7.asciiToString(p7ReceiveBuffer.slice(8, 16)),
+ processorIdentifier : p7.asciiToString(p7ReceiveBuffer.slice(16, 32)),
+ preprogrammedROMCapacity : p7.asciiToString(p7ReceiveBuffer.slice(32, 40)),
+ flashROMCapacity : p7.asciiToString(p7ReceiveBuffer.slice(40, 48)),
+ ramCapacity : p7.asciiToString(p7ReceiveBuffer.slice(48, 56)),
+ prepogrammedROMVersion : p7.asciiToString(p7ReceiveBuffer.slice(56, 72).filter(number => number !== 255)),
+ bootCodeVersion : p7.asciiToString(p7ReceiveBuffer.slice(72, 88).filter(number => number !== 255)),
+ bootCodeOffset : p7.asciiToString(p7ReceiveBuffer.slice(88, 96).filter(number => number !== 255)),
+ bootCodeSize : p7.asciiToString(p7ReceiveBuffer.slice(96, 104).filter(number => number !== 255)),
+ osCodeVersion : p7.asciiToString(p7ReceiveBuffer.slice(104, 120).filter(number => number !== 255)),
+ osCodeOffset : p7.asciiToString(p7ReceiveBuffer.slice(120, 128)),
+ osCodeSize : p7.asciiToString(p7ReceiveBuffer.slice(128, 136)),
+ protocolVersion : p7.asciiToString(p7ReceiveBuffer.slice(136, 140)),
+ productID : p7.asciiToString(p7ReceiveBuffer.slice(140, 156).filter(number => number !== 255)),
+ username : p7.asciiToString(p7ReceiveBuffer.slice(156, 172).filter(number => number !== 255))
+ }
+ };
+
+ /* 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.asciiToHex(p7.receiveBuffer.slice(12, 20));
+
+ /* ---------------------Packet receiving--------------------- */
+
+ /* Doesn't work for now on */
+ p7.receive.packet = async function () {
+ /*try {
+ let array = undefined;
+ do {
+ array = await p7.device.transferIn(2, 64);
+ console.log(array);
+ } while (array.data.byteLength == 0)
+
+ p7.receiveBuffer = Uint8Array(await p7.device.transferIn(2, 64).data.buffer);
+ } catch (err) {
+ throw new Error("Couldn't receive the first 64 bytes of the packet : " + err.message);
}
- return packetSize - 8; /* Type, Subtype, Extended, Data size fields of the packet */;
-}
+ let packetInfo = {};
+
+ //Set Type (T) field
+ packetInfo.type = p7.receiveBuffer[0];
-/* 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
+ packetInfo.subtype = p7.asciiToHex(p7.receiveBuffer.slice(1, 2));
- //Set Subtype (ST) field
- p7SendBuffer.set(p7HexToAscii(subtype, 2), 1);
+ //Set Extended (EX) field
+ packetInfo.extended = (p7.receiveBuffer[3] === 0x31);
- //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;
+ console.log(packetInfo);
+*/
let transferInResult = 0;
-
+ let err = 0;
//Recieve and parse the packet
do {
- transferInResult = await device.transferIn(2, 64).then(
+ transferInResult = await p7.device.transferIn(2, 64).then(
(result) => {
return result;
}, (error) => {
@@ -155,274 +191,195 @@ async function p7ReceivePacket() {
});
if (err)
return "Couldn't receive the first 64 bytes of the packet : " + err;
+ console.log('retrying');
} while(!transferInResult.data.byteLength);
-
- p7ReceivedPacketInfo.packetSize = 4; /*Type, Subtype and Extended field*/
+
+ //p7ReceivedPacketInfo.packetSize = 4; /*Type, Subtype and Extended field*/
//Copy the received buffer to p7ReceiveBuffer
- p7ReceiveBuffer.set(new Uint8Array(transferInResult.data.buffer), 0);
+ p7.receiveBuffer.set(new Uint8Array(transferInResult.data.buffer), 0);
+ console.log(p7.receiveBuffer.slice(0, 25));
+ }
- //Set Type (T) field
- p7ReceivedPacketInfo.type = p7ReceiveBuffer[0];
+ /* ---------------------Packet sending--------------------- */
- //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*/
+ /* Doesn't work for now on */
+ p7.send.packet = async function (length) {
- //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));
+ /*try {
+ await p7.device.transferOut(1, p7.sendBuffer.slice(0, length));
+ } catch (err) {
+ throw new Error("Couldn't send the packet : " + err.message);
+ }*/
+
+ let err = 0;
+
+ //Send the packet and return the error on failure
+ if (err = await p7.device.transferOut(1, p7.sendBuffer.slice(0, length)).then((success) => 0, (failure) => failure))
+ return "Couldn't send the packet : " + err;
+ };
+
+ /* ---------------------Initialization and exiting--------------------- */
+
+ /* Initiate the connexion with the calculator */
+ p7.init = async function () {
+ try {
+ p7.device = await navigator.usb.requestDevice({filters:[
+ {'vendorId': 0x07cf , 'productId': 0x6101}, /* fx-9750gII */
+ {'vendorId': 0x07cf , 'productId': 0x6102}] /* fx-CP400 */
+ });
+ } catch (err) {
+ throw new Error("Couldn't find the calculator : " + err.message);
}
- else {
- p7ReceivedPacketInfo.packetSize += 4; /*Data size field*/
+ await p7.device.open();
+
+ if (p7.device.configuration === null)
+ await p7.device.selectConfiguration(1); /* Only existing one so it should be selected by default, just checking */
+
+ if (p7.device.configuration.interfaces[0].claimed === false)
+ await p7.device.claimInterface(0); /* Same as for the configuration */
- //Set Data size (DS) field
- p7ReceivedPacketInfo.dataSize = Number('0x' + String.fromCharCode.apply(null, p7ReceiveBuffer.slice(4, 8)), 10);
+ console.log(p7.device);
- //Add the checksum bytes
- p7ReceivedPacketInfo.dataSize+=2;
+ /* Everything went right */
+ return 0;
+ }
+
+ /* End the connexion with the calculator */
+ p7.exit = async function () {
+
+ }
- p7ReceivedPacketInfo.packetSize += (p7ReceivedPacketInfo.dataSize > 56) ? 56 : p7ReceivedPacketInfo.dataSize;
- p7ReceivedPacketInfo.dataSize -= 56;
+ document.getElementById('connect').addEventListener('click', async function () {
+ try {
+ await p7.init();
+ } catch (err) {
+ console.error(err);
+ return err;
+ }
- //Receive the rest of the data
- while(p7ReceivedPacketInfo.dataSize > 0)
- {
- transferInResult = await device.transferIn(2, 64).then(
- (result) => {
- return result;
- }, (error) => {
- err = error;
- });
+ /* Receive and send some usb control message, as defined in fxReverse documentation
+ *
+ * Adapted version (some parameters changed since fxReverse's writing) of usb_control_msg() function's protoype
+ * from linux-manual : https://manpages.debian.org/jessie-backports/linux-manual-4.8/usb_control_msg.9.en.html
+ *
+ * int usb_control_msg(struct usb_device * dev,
+ * uint8_t requesttype,
+ * uint8_t request,
+ * uint16_t value,
+ * uint16_t index,
+ * void * data,
+ * uint16_t size,
+ * int timeout);
+ *
+ * fxReverse2:13:
+ *
+ * int init_connection() {
+ * char *buffer = calloc(0x29, sizeof(char));
+ *
+ * //Receive 0x12 bytes of data
+ * usb_control_message(usb_handle,
+ * 0x80, = 0b10000000
+ * - D7 = 1 -> Data transfer direction: Device-to-host
+ * - D6...D5 = 0 -> Type: Standard
+ * - D4...D0 = 0 -> Recipient: Device
+ * 0x6,
+ * 0x0100,
+ * 0x0,
+ * buffer,
+ * 0x12,
+ * 200);
+ *
+ * //Same arguments (except timeout), but value is 0x200 and it receives 0x29 bytes of data
+ * usb_control_message(usb_handle, 0x80, 0x6, 0x200, 0, buffer, 0x29, 250);
+ *
+ *
+ * usb_control_message(usb_handle,
+ * 0x41, = 0b01000001
+ * - D7 = 0 -> Data transfer direction: Host-to-device
+ * - D6...D5 = 2 -> Type: Vendor
+ * - D4...D0 = 1 -> Interface: Interface
+ * 0x1,
+ * 0x0,
+ * 0,
+ * buffer,
+ * 0x0,
+ * 250);
+ *
+ * free(buffer);
+ * return 0;
+ * }
- 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;
+ ****************************************************************
+
+ let transferInResult = undefined;
+ let controlData = undefined;
+
+ try {
+ transferInResult = await p7.device.controlTransferIn({
+ requestType: 'standard',
+ recipient: 'device',
+ request: 0x06, // GET_DESCRIPTOR
+ value: 0x0100, // Descriptor Type and Descriptor Index
+ index: 0x0000
+ }, 0x12); // Length
+ } catch (err) {
+ console.log(err);
}
- //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;
-}
+ controlData = new Uint8Array(transferInResult.data.buffer);
+
+ console.log('vendor id : 0x' + controlData[9].toString(16).padStart(2, 0) + controlData[8].toString(16).padStart(2,0));
+ console.log('product id : 0x' + controlData[11].toString(16).padStart(2, 0) + controlData[10].toString(16).padStart(2,0));
+ try {
+ transferInResult = await p7.device.controlTransferIn({
+ requestType: 'standard',
+ recipient: 'device',
+ request: 0x06, // GET_DESCRIPTOR
+ value: 0x0200, // Descriptor Type and Descriptor Index
+ index: 0x0000
+ }, 0x29); // Length
+ } catch (err) {
+ console.log(err);
+ }
-/* 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));
+ controlData = new Uint8Array(transferInResult.data.buffer);
- let err = 0;
+ console.log(controlData);
- //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;
+ try {
+ await p7.device.controlTransferOut({
+ requestType: 'vendor',
+ recipient: 'interface',
+ request: 0x01,
+ value: 0x0000,
+ index: 0x0000
+ }, controlData);
+ } catch (err) {
+ console.log(err);
+ } */
- //Receive the packet and return the error on failure
- if (err = await p7ReceivePacket())
- return "Couldn't receive the response packet : " + err;
+ p7.make.basicPacket(0x06, 0x00);
+ console.log(p7.sendBuffer.slice(0, 8));
+/*
+ try {
+ await p7.send.packet(6);
+ } catch (err) {
+ console.log('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++) {
+ let err = 0;
+ if (err = await p7.send.packet(6))
+ console.log('err' + err);
- 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.";
- }
+ /* Error: Stay in an endless loop */
+ await p7.receive.packet();
+ });
- //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};
-}
\ No newline at end of file
+})();
\ No newline at end of file