From a64295504d1d6fccd2f17632717d8b107371d395 Mon Sep 17 00:00:00 2001 From: neiviv-ui Date: Tue, 27 Jul 2021 17:03:32 +0200 Subject: [PATCH] Fully asynchronous internal commands --- commands.js | 53 ++++---- internal.js | 343 +++++++++++++++++++++++++--------------------------- 2 files changed, 190 insertions(+), 206 deletions(-) diff --git a/commands.js b/commands.js index 5361054..9713cce 100644 --- a/commands.js +++ b/commands.js @@ -2,61 +2,54 @@ /* ---------------------Single commands--------------------- */ /* Create a directory */ - p7.commands.createDirectory = async (name, filesystem) => await p7.send.singleCommand(flashCommandSubtype.createDirectory, 0, 0, [name, '', '', '', filesystem, '']); + p7.commands.createDirectory = (name, filesystem) => 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, '']); + p7.commands.deleteDirectory = (name, filesystem) => 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, '']); + p7.commands.renameDirectory = (oldName, newName, filesystem) => 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, '']); + p7.commands.changeDirectory = (name, filesystem) => 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, '']); + p7.commands.deleteFile = (directory, name, filesystem) => 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, '']); + p7.commands.renameFile = (directory, oldName, newName, filesystem) => 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, '']); + p7.commands.copyFile = (oldDirectory, oldName, newDirectory, newName, filesystem) => p7.send.singleCommand(flashCommandSubtype.copyFile, 0, 0, [oldDirectory, oldName, newDirectory, newName, filesystem, '']); /* Reset flash? */ - p7.commands.resetFlash = async (filesystem) => await p7.send.singleCommand(flashCommandSubtype.resetFlash, 0, 0, ['', '', '', '', filesystem, '']); + p7.commands.resetFlash = (filesystem) => p7.send.singleCommand(flashCommandSubtype.resetFlash, 0, 0, ['', '', '', '', filesystem, '']); /* Optimize filesystem */ - p7.commands.optimizeFilesystem = async (filesystem) => await p7.send.singleCommand(flashCommandSubtype.optimizeFileSystem, 0, 0, ['', '', '', '', filesystem, '']); + p7.commands.optimizeFilesystem = (filesystem) => p7.send.singleCommand(flashCommandSubtype.optimizeFileSystem, 0, 0, ['', '', '', '', filesystem, '']); /* ---------------------Single command requests--------------------- */ /* Get free space */ - p7.commands.getCapacity = async function (filesystem) { - try { - return (await p7.send.singleCommandRoleswap(flashCommandSubtype.capacityTransmitRequest, 0, 0, ['', '', '', '', filesystem, ''], - () => p7.decode.commandPacketFileSize() - ))[0]; - } catch (err) { + 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; - } - } + }); /* List files */ - p7.commands.list = async function (filesystem) { - try { - return await p7.send.singleCommandRoleswap(flashCommandSubtype.fileInfoTransferAllRequest, 0, 0, ['', '', '', '', filesystem, ''], - () => ({ - size: p7.decode.commandPacketFileSize(), - DirectoryName: p7.decode.commandPacketDataField(1), - name: p7.decode.commandPacketDataField(2) - }) - ); - } catch (err) { + 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; - } - } - + }); }) (); diff --git a/internal.js b/internal.js index 54d5f59..e1a16bf 100644 --- a/internal.js +++ b/internal.js @@ -200,211 +200,202 @@ var p7 = { /* ---------------------Packet sending--------------------- */ - p7.send.packet = async function (buffer) { + p7.send.packet = function (buffer) { console.log("%cSending packet...", "color: green"); return p7.device.transferOut(1, Uint8Array.from(buffer)) - .then(() => p7.receive.packet()); + .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.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; - } + 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 request - * Return the Data (D) field of the response command packet(s) */ - p7.send.singleCommandRoleswap = async function (subtype, datatype, fileSize, commandArguments, callbackFunction) { - /* Array to store the Data (D) field of the response command packet(s) */ - let result = []; + * 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 = []; - /* 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) { - result.push(callbackFunction()); - responsePacketInfo = await p7.send.basicPacket(p7PacketType.ack, ackSubtype.default); - } - - /* Everything went right */ - return result; + 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); + }); } - /* ---------------------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"); - } + /* Connect to the calculator */ + p7.connect = () => + navigator.usb.requestDevice({filters:[ + {'vendorId': 0x07cf , 'productId': 0x6101}, //fx-9750gII + {'vendorId': 0x07cf , 'productId': 0x6102}] //fx-CP400 + }).then((device) => { + p7.device = device + return p7.device.open(); + }).then(() => { + if (p7.device.configuration === null) + return p7.device.selectConfiguration(1); //Only existing one so it should be selected by default, just checking + }).then(() => { + if (p7.device.configuration.interfaces[0].claimed === false) + return p7.device.claimInterface(0); //Same as for the configuration + }); + + /* 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; + * } + **************************************************************** - 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 */ + let transferInResult = undefined; + let controlData = undefined; - console.log(p7.device); - - /* Everything went right */ - return 0; - - /* 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; - * } - **************************************************************** - - 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); - } - - 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 { + 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); - } - - controlData = new Uint8Array(transferInResult.data.buffer); - console.log(controlData); - - try { - await p7.device.controlTransferOut({ - requestType: 'vendor', - recipient: 'interface', - request: 0x01, - value: 0x0000, - index: 0x0000 - }, controlData); - } catch (err) { - console.log(err); - } */ + requestType: 'standard', + recipient: 'device', + request: 0x06, // GET_DESCRIPTOR + value: 0x0100, // Descriptor Type and Descriptor Index + index: 0x0000 + }, 0x12); // Length + } catch (err) { + console.log(err); } + 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); + } + + controlData = new Uint8Array(transferInResult.data.buffer); + console.log(controlData); + + try { + await p7.device.controlTransferOut({ + requestType: 'vendor', + recipient: 'interface', + request: 0x01, + value: 0x0000, + index: 0x0000 + }, controlData); + } catch (err) { + console.log(err); + } */ + + /* Initialize the connection with the calculator */ + p7.init = () => + p7.connect() + .catch(() => { + throw new Error("Couldn't connect to the calculator!"); + }).then(() => p7.send.packet(p7.make.basicPacket(p7PacketType.check, checkSubtype.initialization)) + .catch(() => { + throw new Error("Couldn't send the initialisation packet!"); + }).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()))); + /* End the connexion with the calculator */ - p7.exit = async function () { + p7.exit = async function () { } - document.getElementById('connect').addEventListener('click', async function () { var time = performance.now(); - try { - await p7.init(); - - await p7.send.basicPacket(p7PacketType.check, checkSubtype.initialization); - - await p7.send.basicPacket(p7PacketType.command, sysCommandSubtype.getDeviceInfo); - - } catch (err) { + return p7.init() + .catch((err) => { console.error(err); return err; - } + }).then((deviceInfo) => { + console.log(deviceInfo); - console.log(p7.decode.extendedAckPacket()); + //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)')); + }) - - console.log(await p7.commands.list('fls0')); - - console.log(performance.now() - time); }); -})(); \ No newline at end of file + +})();