v0.2-development intermediate results. Almost ready.
This commit is contained in:
parent
ad23eb0c82
commit
c4d0959cf3
14 changed files with 405 additions and 293 deletions
|
@ -58,6 +58,10 @@ Set 'Security & Privacy' if needed.
|
||||||
## Known bugs
|
## Known bugs
|
||||||
* Unable to interrupt transmission when libusb awaiting for read event (when user sent NSP list but didn't selected anything on NS).
|
* Unable to interrupt transmission when libusb awaiting for read event (when user sent NSP list but didn't selected anything on NS).
|
||||||
|
|
||||||
|
## NOTES
|
||||||
|
Table 'Status' = 'Uploaded' does not means that file installed. It means that it has been sent to NS without any issues! That's what this app about.
|
||||||
|
Handling successful/failed installation is a purpose of the other side application (TinFoil/GoldLeaf). (And they don't provide any feedback interfaces so I can't detect success/failure.)
|
||||||
|
|
||||||
## TODO:
|
## TODO:
|
||||||
- [x] macOS QA by [Konstanin Kelemen](https://github.com/konstantin-kelemen). Appreciate assistance of [Vitaliy Natarov](https://github.com/SebastianUA).
|
- [x] macOS QA by [Konstanin Kelemen](https://github.com/konstantin-kelemen). Appreciate assistance of [Vitaliy Natarov](https://github.com/SebastianUA).
|
||||||
- [x] Windows support
|
- [x] Windows support
|
||||||
|
|
42
pom.xml
42
pom.xml
|
@ -5,12 +5,50 @@
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
<groupId>loper</groupId>
|
<groupId>loper</groupId>
|
||||||
<artifactId>NS-USBloader</artifactId>
|
|
||||||
<version>0.2-SNAPSHOT</version>
|
|
||||||
<name>NS-USBloader</name>
|
<name>NS-USBloader</name>
|
||||||
|
|
||||||
|
<artifactId>ns-usbloader</artifactId>
|
||||||
|
<version>0.2-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<url>https://github.com/developersu/ns-usbloader/</url>
|
||||||
|
<description>
|
||||||
|
NSP USB loader for TinFoil and GoldLeaf
|
||||||
|
</description>
|
||||||
|
<inceptionYear>2019</inceptionYear>
|
||||||
|
<organization>
|
||||||
|
<name>Dmitry Isaenko</name>
|
||||||
|
<url>https://developersu.blogspot.com/</url>
|
||||||
|
</organization>
|
||||||
|
|
||||||
|
<licenses>
|
||||||
|
<license>
|
||||||
|
<name>GPLv3</name>
|
||||||
|
<url>LICENSE</url>
|
||||||
|
<distribution>manual</distribution>
|
||||||
|
</license>
|
||||||
|
</licenses>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
<developer>
|
||||||
|
<id>developer.su</id>
|
||||||
|
<name>Dmitry Isaenko</name>
|
||||||
|
<roles>
|
||||||
|
<role>Developer</role>
|
||||||
|
</roles>
|
||||||
|
<timezone>+3</timezone>
|
||||||
|
<url>https://developersu.blogspot.com/</url>
|
||||||
|
</developer>
|
||||||
|
</developers>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
<issueManagement>
|
||||||
|
<system>GitHub</system>
|
||||||
|
<url>https://github.com/developer_su/${project.artifactId}/issues</url>
|
||||||
|
</issueManagement>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.openjfx</groupId>
|
<groupId>org.openjfx</groupId>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package nsusbloader.Controllers;
|
package nsusbloader.Controllers;
|
||||||
|
|
||||||
import nsusbloader.NSLDataTypes.FileStatus;
|
import nsusbloader.NSLDataTypes.EFileStatus;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
public class NSLRowModel {
|
public class NSLRowModel {
|
||||||
|
|
||||||
private String status; // 0 = unknown, 1 = uploaded, 2 = bad file
|
private String status;
|
||||||
private File nspFile;
|
private File nspFile;
|
||||||
private String nspFileName;
|
private String nspFileName;
|
||||||
private String nspFileSize;
|
private String nspFileSize;
|
||||||
|
@ -35,24 +35,20 @@ public class NSLRowModel {
|
||||||
public void setMarkForUpload(boolean value){
|
public void setMarkForUpload(boolean value){
|
||||||
markForUpload = value;
|
markForUpload = value;
|
||||||
}
|
}
|
||||||
|
public File getNspFile(){ return nspFile; }
|
||||||
public void setStatus(FileStatus status){ // TODO: Localization
|
public void setStatus(EFileStatus status){ // TODO: Localization
|
||||||
switch (status){
|
switch (status){
|
||||||
case FAILED:
|
|
||||||
this.status = "Upload failed";
|
|
||||||
break;
|
|
||||||
case UPLOADED:
|
case UPLOADED:
|
||||||
this.status = "Uploaded";
|
this.status = "Uploaded";
|
||||||
markForUpload = false;
|
markForUpload = false;
|
||||||
break;
|
break;
|
||||||
case INCORRECT:
|
case FAILED:
|
||||||
|
this.status = "Upload failed";
|
||||||
|
break;
|
||||||
|
case INCORRECT_FILE_FAILED:
|
||||||
this.status = "File incorrect";
|
this.status = "File incorrect";
|
||||||
markForUpload = false;
|
markForUpload = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
public File getNspFile(){
|
|
||||||
return nspFile;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import javafx.scene.control.TableView;
|
||||||
import javafx.scene.control.cell.CheckBoxTableCell;
|
import javafx.scene.control.cell.CheckBoxTableCell;
|
||||||
import javafx.scene.control.cell.PropertyValueFactory;
|
import javafx.scene.control.cell.PropertyValueFactory;
|
||||||
import javafx.util.Callback;
|
import javafx.util.Callback;
|
||||||
import nsusbloader.NSLDataTypes.FileStatus;
|
import nsusbloader.NSLDataTypes.EFileStatus;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
@ -91,7 +91,8 @@ public class NSTableViewController implements Initializable {
|
||||||
for (NSLRowModel model: rowsObsLst){
|
for (NSLRowModel model: rowsObsLst){
|
||||||
if (model != modelChecked)
|
if (model != modelChecked)
|
||||||
model.setMarkForUpload(false);
|
model.setMarkForUpload(false);
|
||||||
}table.refresh();
|
}
|
||||||
|
table.refresh();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
@ -136,9 +137,9 @@ public class NSTableViewController implements Initializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Update files in case something is wrong. Requested from UsbCommunications _OR_ PFS
|
* Update files in case something is wrong. Requested from UsbCommunications
|
||||||
* */
|
* */
|
||||||
public void setFileStatus(String fileName, FileStatus status){
|
public void setFileStatus(String fileName, EFileStatus status){
|
||||||
for (NSLRowModel model: rowsObsLst){
|
for (NSLRowModel model: rowsObsLst){
|
||||||
if (model.getNspFileName().equals(fileName)){
|
if (model.getNspFileName().equals(fileName)){
|
||||||
model.setStatus(status);
|
model.setStatus(status);
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package nsusbloader;
|
package nsusbloader;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
class MediatorControl {
|
class MediatorControl {
|
||||||
private boolean isTransferActive = false;
|
private AtomicBoolean isTransferActive = new AtomicBoolean(false); // Overcoded just for sure
|
||||||
private NSLMainController applicationController;
|
private NSLMainController applicationController;
|
||||||
|
|
||||||
static MediatorControl getInstance(){
|
static MediatorControl getInstance(){
|
||||||
|
@ -11,15 +13,14 @@ class MediatorControl {
|
||||||
private static class MediatorControlHold {
|
private static class MediatorControlHold {
|
||||||
private static final MediatorControl INSTANCE = new MediatorControl();
|
private static final MediatorControl INSTANCE = new MediatorControl();
|
||||||
}
|
}
|
||||||
void registerController(NSLMainController controller){
|
void setController(NSLMainController controller){
|
||||||
this.applicationController = controller;
|
this.applicationController = controller;
|
||||||
}
|
}
|
||||||
|
NSLMainController getContoller(){ return this.applicationController; }
|
||||||
|
|
||||||
synchronized void setTransferActive(boolean state) {
|
synchronized void setTransferActive(boolean state) {
|
||||||
isTransferActive = state;
|
isTransferActive.set(state);
|
||||||
applicationController.notifyTransmissionStarted(state);
|
applicationController.notifyTransmissionStarted(state);
|
||||||
}
|
}
|
||||||
synchronized boolean getTransferActive() {
|
synchronized boolean getTransferActive() { return this.isTransferActive.get(); }
|
||||||
return this.isTransferActive;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,11 @@ package nsusbloader;
|
||||||
import javafx.animation.AnimationTimer;
|
import javafx.animation.AnimationTimer;
|
||||||
import javafx.scene.control.ProgressBar;
|
import javafx.scene.control.ProgressBar;
|
||||||
import javafx.scene.control.TextArea;
|
import javafx.scene.control.TextArea;
|
||||||
|
import nsusbloader.Controllers.NSTableViewController;
|
||||||
|
import nsusbloader.NSLDataTypes.EFileStatus;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
|
||||||
public class MessagesConsumer extends AnimationTimer {
|
public class MessagesConsumer extends AnimationTimer {
|
||||||
|
@ -13,18 +16,24 @@ public class MessagesConsumer extends AnimationTimer {
|
||||||
|
|
||||||
private final BlockingQueue<Double> progressQueue;
|
private final BlockingQueue<Double> progressQueue;
|
||||||
private final ProgressBar progressBar;
|
private final ProgressBar progressBar;
|
||||||
|
private final HashMap<String, EFileStatus> statusMap;
|
||||||
|
private final NSTableViewController tableViewController;
|
||||||
|
|
||||||
private boolean isInterrupted;
|
private boolean isInterrupted;
|
||||||
|
|
||||||
MessagesConsumer(BlockingQueue<String> msgQueue, TextArea logsArea, BlockingQueue<Double> progressQueue, ProgressBar progressBar){
|
MessagesConsumer(BlockingQueue<String> msgQueue, BlockingQueue<Double> progressQueue, HashMap<String, EFileStatus> statusMap){
|
||||||
this.msgQueue = msgQueue;
|
this.isInterrupted = false;
|
||||||
this.logsArea = logsArea;
|
|
||||||
|
this.msgQueue = msgQueue;
|
||||||
|
this.logsArea = MediatorControl.getInstance().getContoller().logArea;
|
||||||
|
|
||||||
this.progressBar = progressBar;
|
|
||||||
this.progressQueue = progressQueue;
|
this.progressQueue = progressQueue;
|
||||||
|
this.progressBar = MediatorControl.getInstance().getContoller().progressBar;
|
||||||
|
|
||||||
|
this.statusMap = statusMap;
|
||||||
|
this.tableViewController = MediatorControl.getInstance().getContoller().tableFilesListController;
|
||||||
|
|
||||||
progressBar.setProgress(0.0);
|
progressBar.setProgress(0.0);
|
||||||
this.isInterrupted = false;
|
|
||||||
MediatorControl.getInstance().setTransferActive(true);
|
MediatorControl.getInstance().setTransferActive(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,6 +52,10 @@ public class MessagesConsumer extends AnimationTimer {
|
||||||
if (isInterrupted) {
|
if (isInterrupted) {
|
||||||
MediatorControl.getInstance().setTransferActive(false);
|
MediatorControl.getInstance().setTransferActive(false);
|
||||||
progressBar.setProgress(0.0);
|
progressBar.setProgress(0.0);
|
||||||
|
|
||||||
|
if (statusMap.size() > 0) // It's safe 'cuz it's could't be interrupted while HashMap populating
|
||||||
|
for (String key : statusMap.keySet())
|
||||||
|
tableViewController.setFileStatus(key, statusMap.get(key));
|
||||||
this.stop();
|
this.stop();
|
||||||
}
|
}
|
||||||
//TODO
|
//TODO
|
||||||
|
|
5
src/main/java/nsusbloader/NSLDataTypes/EFileStatus.java
Normal file
5
src/main/java/nsusbloader/NSLDataTypes/EFileStatus.java
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
package nsusbloader.NSLDataTypes;
|
||||||
|
|
||||||
|
public enum EFileStatus {
|
||||||
|
UPLOADED, INCORRECT_FILE_FAILED, FAILED
|
||||||
|
}
|
5
src/main/java/nsusbloader/NSLDataTypes/EMsgType.java
Normal file
5
src/main/java/nsusbloader/NSLDataTypes/EMsgType.java
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
package nsusbloader.NSLDataTypes;
|
||||||
|
|
||||||
|
public enum EMsgType {
|
||||||
|
PASS, FAIL, INFO, WARNING
|
||||||
|
}
|
|
@ -1,11 +1,3 @@
|
||||||
/**
|
|
||||||
Name: NS-USBloader
|
|
||||||
@author Dmitry Isaenko
|
|
||||||
License: GNU GPL v.3
|
|
||||||
@see https://github.com/developersu/
|
|
||||||
@see https://developersu.blogspot.com/
|
|
||||||
2019, Russia
|
|
||||||
*/
|
|
||||||
package nsusbloader;
|
package nsusbloader;
|
||||||
|
|
||||||
import javafx.application.Application;
|
import javafx.application.Application;
|
||||||
|
|
|
@ -12,7 +12,6 @@ import nsusbloader.Controllers.NSTableViewController;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
@ -21,14 +20,14 @@ public class NSLMainController implements Initializable {
|
||||||
private ResourceBundle resourceBundle;
|
private ResourceBundle resourceBundle;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TextArea logArea;
|
public TextArea logArea; // Accessible from Mediator
|
||||||
@FXML
|
@FXML
|
||||||
private Button selectNspBtn;
|
private Button selectNspBtn;
|
||||||
@FXML
|
@FXML
|
||||||
private Button uploadStopBtn;
|
private Button uploadStopBtn;
|
||||||
private Region btnUpStopImage;
|
private Region btnUpStopImage;
|
||||||
@FXML
|
@FXML
|
||||||
private ProgressBar progressBar;
|
public ProgressBar progressBar; // Accessible from Mediator
|
||||||
@FXML
|
@FXML
|
||||||
private ChoiceBox<String> choiceProtocol;
|
private ChoiceBox<String> choiceProtocol;
|
||||||
@FXML
|
@FXML
|
||||||
|
@ -38,7 +37,7 @@ public class NSLMainController implements Initializable {
|
||||||
private Pane specialPane;
|
private Pane specialPane;
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private NSTableViewController tableFilesListController;
|
public NSTableViewController tableFilesListController; // Accessible from Mediator
|
||||||
|
|
||||||
private Thread usbThread;
|
private Thread usbThread;
|
||||||
|
|
||||||
|
@ -54,7 +53,7 @@ public class NSLMainController implements Initializable {
|
||||||
|
|
||||||
logArea.appendText(rb.getString("logsGreetingsMessage2")+"\n");
|
logArea.appendText(rb.getString("logsGreetingsMessage2")+"\n");
|
||||||
|
|
||||||
MediatorControl.getInstance().registerController(this);
|
MediatorControl.getInstance().setController(this);
|
||||||
|
|
||||||
specialPane.getStyleClass().add("special-pane-as-border"); // UI hacks
|
specialPane.getStyleClass().add("special-pane-as-border"); // UI hacks
|
||||||
|
|
||||||
|
@ -62,6 +61,8 @@ public class NSLMainController implements Initializable {
|
||||||
selectNspBtn.setOnAction(e->{ selectFilesBtnAction(); });
|
selectNspBtn.setOnAction(e->{ selectFilesBtnAction(); });
|
||||||
uploadStopBtn.setOnAction(e->{ uploadBtnAction(); });
|
uploadStopBtn.setOnAction(e->{ uploadBtnAction(); });
|
||||||
|
|
||||||
|
selectNspBtn.getStyleClass().add("buttonSelect");
|
||||||
|
|
||||||
this.btnUpStopImage = new Region();
|
this.btnUpStopImage = new Region();
|
||||||
btnUpStopImage.getStyleClass().add("regionUpload");
|
btnUpStopImage.getStyleClass().add("regionUpload");
|
||||||
//uploadStopBtn.getStyleClass().remove("button");
|
//uploadStopBtn.getStyleClass().remove("button");
|
||||||
|
@ -80,7 +81,6 @@ public class NSLMainController implements Initializable {
|
||||||
btnSwitchImage.getStyleClass().add("regionLamp");
|
btnSwitchImage.getStyleClass().add("regionLamp");
|
||||||
switchThemeBtn.setGraphic(btnSwitchImage);
|
switchThemeBtn.setGraphic(btnSwitchImage);
|
||||||
this.switchThemeBtn.setOnAction(e->switchTheme());
|
this.switchThemeBtn.setOnAction(e->switchTheme());
|
||||||
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Changes UI theme on the go
|
* Changes UI theme on the go
|
||||||
|
@ -139,7 +139,7 @@ public class NSLMainController implements Initializable {
|
||||||
for (File item: nspToUpload)
|
for (File item: nspToUpload)
|
||||||
logArea.appendText(" "+item.getAbsolutePath()+"\n");
|
logArea.appendText(" "+item.getAbsolutePath()+"\n");
|
||||||
}
|
}
|
||||||
UsbCommunications usbCommunications = new UsbCommunications(logArea, progressBar, nspToUpload, choiceProtocol.getSelectionModel().getSelectedItem());
|
UsbCommunications usbCommunications = new UsbCommunications(nspToUpload, choiceProtocol.getSelectionModel().getSelectedItem());
|
||||||
usbThread = new Thread(usbCommunications);
|
usbThread = new Thread(usbCommunications);
|
||||||
usbThread.start();
|
usbThread.start();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package nsusbloader.PFS;
|
package nsusbloader.PFS;
|
||||||
|
|
||||||
import nsusbloader.NSLDataTypes.MsgType;
|
import nsusbloader.NSLDataTypes.EMsgType;
|
||||||
import nsusbloader.ServiceWindow;
|
import nsusbloader.ServiceWindow;
|
||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
|
@ -10,8 +10,6 @@ import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
|
|
||||||
import static nsusbloader.RainbowHexDump.hexDumpUTF8;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used in GoldLeaf USB protocol
|
* Used in GoldLeaf USB protocol
|
||||||
* */
|
* */
|
||||||
|
@ -34,7 +32,7 @@ public class PFSProvider {
|
||||||
nspFileName = nspFile.getName();
|
nspFileName = nspFile.getName();
|
||||||
}
|
}
|
||||||
catch (FileNotFoundException fnfe){
|
catch (FileNotFoundException fnfe){
|
||||||
printLog("File not founnd: \n "+fnfe.getMessage(), MsgType.FAIL);
|
printLog("PFS File not founnd: \n "+fnfe.getMessage(), EMsgType.FAIL);
|
||||||
nspFileName = null;
|
nspFileName = null;
|
||||||
}
|
}
|
||||||
if (Locale.getDefault().getISO3Language().equals("rus"))
|
if (Locale.getDefault().getISO3Language().equals("rus"))
|
||||||
|
@ -50,22 +48,22 @@ public class PFSProvider {
|
||||||
int filesCount;
|
int filesCount;
|
||||||
int header;
|
int header;
|
||||||
|
|
||||||
printLog("Start NSP file analyze for ["+nspFileName+"]", MsgType.INFO);
|
printLog("PFS Start NSP file analyze for ["+nspFileName+"]", EMsgType.INFO);
|
||||||
try {
|
try {
|
||||||
byte[] fileStartingBytes = new byte[12];
|
byte[] fileStartingBytes = new byte[12];
|
||||||
// Read PFS0, files count, header, padding (4 zero bytes)
|
// Read PFS0, files count, header, padding (4 zero bytes)
|
||||||
if (randAccessFile.read(fileStartingBytes) == 12)
|
if (randAccessFile.read(fileStartingBytes) == 12)
|
||||||
printLog("Read file starting bytes", MsgType.PASS);
|
printLog("PFS Read file starting bytes.", EMsgType.PASS);
|
||||||
else {
|
else {
|
||||||
printLog("Read file starting bytes", MsgType.FAIL);
|
printLog("PFS Read file starting bytes.", EMsgType.FAIL);
|
||||||
randAccessFile.close();
|
randAccessFile.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Check PFS0
|
// Check PFS0
|
||||||
if (Arrays.equals(PFS0, Arrays.copyOfRange(fileStartingBytes, 0, 4)))
|
if (Arrays.equals(PFS0, Arrays.copyOfRange(fileStartingBytes, 0, 4)))
|
||||||
printLog("Read PFS0", MsgType.PASS);
|
printLog("PFS Read 'PFS0'.", EMsgType.PASS);
|
||||||
else {
|
else {
|
||||||
printLog("Read PFS0", MsgType.WARNING);
|
printLog("PFS Read 'PFS0'.", EMsgType.WARNING);
|
||||||
if (!ServiceWindow.getConfirmationWindow(nspFileName+"\n"+rb.getString("windowTitleConfirmWrongPFS0"), rb.getString("windowBodyConfirmWrongPFS0"))) {
|
if (!ServiceWindow.getConfirmationWindow(nspFileName+"\n"+rb.getString("windowTitleConfirmWrongPFS0"), rb.getString("windowBodyConfirmWrongPFS0"))) {
|
||||||
randAccessFile.close();
|
randAccessFile.close();
|
||||||
return false;
|
return false;
|
||||||
|
@ -74,19 +72,19 @@ public class PFSProvider {
|
||||||
// Get files count
|
// Get files count
|
||||||
filesCount = ByteBuffer.wrap(Arrays.copyOfRange(fileStartingBytes, 4, 8)).order(ByteOrder.LITTLE_ENDIAN).getInt();
|
filesCount = ByteBuffer.wrap(Arrays.copyOfRange(fileStartingBytes, 4, 8)).order(ByteOrder.LITTLE_ENDIAN).getInt();
|
||||||
if (filesCount > 0 ) {
|
if (filesCount > 0 ) {
|
||||||
printLog("Read files count [" + filesCount + "]", MsgType.PASS);
|
printLog("PFS Read files count [" + filesCount + "]", EMsgType.PASS);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printLog("Read files count", MsgType.FAIL);
|
printLog("PFS Read files count", EMsgType.FAIL);
|
||||||
randAccessFile.close();
|
randAccessFile.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Get header
|
// Get header
|
||||||
header = ByteBuffer.wrap(Arrays.copyOfRange(fileStartingBytes, 8, 12)).order(ByteOrder.LITTLE_ENDIAN).getInt();
|
header = ByteBuffer.wrap(Arrays.copyOfRange(fileStartingBytes, 8, 12)).order(ByteOrder.LITTLE_ENDIAN).getInt();
|
||||||
if (header > 0 )
|
if (header > 0 )
|
||||||
printLog("Read header ["+header+"]", MsgType.PASS);
|
printLog("PFS Read header ["+header+"]", EMsgType.PASS);
|
||||||
else {
|
else {
|
||||||
printLog("Read header ", MsgType.FAIL);
|
printLog("PFS Read header ", EMsgType.FAIL);
|
||||||
randAccessFile.close();
|
randAccessFile.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -105,10 +103,10 @@ public class PFSProvider {
|
||||||
|
|
||||||
for (int i=0; i<filesCount; i++){
|
for (int i=0; i<filesCount; i++){
|
||||||
if (randAccessFile.read(ncaInfoArr) == 24) {
|
if (randAccessFile.read(ncaInfoArr) == 24) {
|
||||||
printLog("Read NCA inside NSP: " + i, MsgType.PASS);
|
printLog("PFS Read NCA inside NSP: " + i, EMsgType.PASS);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printLog("Read NCA inside NSP: "+i, MsgType.FAIL);
|
printLog("PFS Read NCA inside NSP: "+i, EMsgType.FAIL);
|
||||||
randAccessFile.close();
|
randAccessFile.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -117,23 +115,10 @@ public class PFSProvider {
|
||||||
nca_size = ByteBuffer.wrap(Arrays.copyOfRange(ncaInfoArr, 12, 20)).order(ByteOrder.LITTLE_ENDIAN).getLong();
|
nca_size = ByteBuffer.wrap(Arrays.copyOfRange(ncaInfoArr, 12, 20)).order(ByteOrder.LITTLE_ENDIAN).getLong();
|
||||||
nca_name_offset = ByteBuffer.wrap(Arrays.copyOfRange(ncaInfoArr, 20, 24)).order(ByteOrder.LITTLE_ENDIAN).getInt(); // yes, cast from int to long.
|
nca_name_offset = ByteBuffer.wrap(Arrays.copyOfRange(ncaInfoArr, 20, 24)).order(ByteOrder.LITTLE_ENDIAN).getInt(); // yes, cast from int to long.
|
||||||
|
|
||||||
if (offset == 0) // TODO: add consitancy of class checker or reuse with ternary operator
|
printLog(" Padding check", offset == 0?EMsgType.PASS:EMsgType.WARNING);
|
||||||
printLog(" Padding check", MsgType.PASS);
|
printLog(" NCA offset check "+nca_offset, nca_offset >= 0?EMsgType.PASS:EMsgType.WARNING);
|
||||||
else
|
printLog(" NCA size check: "+nca_size, nca_size >= 0?EMsgType.PASS: EMsgType.WARNING);
|
||||||
printLog(" Padding check", MsgType.WARNING);
|
printLog(" NCA name offset check "+nca_name_offset, nca_name_offset >= 0?EMsgType.PASS:EMsgType.WARNING);
|
||||||
if (nca_offset >= 0)
|
|
||||||
printLog(" NCA offset check "+nca_offset, MsgType.PASS);
|
|
||||||
else
|
|
||||||
printLog(" NCA offset check "+nca_offset, MsgType.WARNING);
|
|
||||||
if (nca_size >= 0)
|
|
||||||
printLog(" NCA size check: "+nca_size, MsgType.PASS);
|
|
||||||
else
|
|
||||||
printLog(" NCA size check "+nca_size, MsgType.WARNING);
|
|
||||||
if (nca_name_offset >= 0)
|
|
||||||
printLog(" NCA name offset check "+nca_name_offset, MsgType.PASS);
|
|
||||||
else
|
|
||||||
printLog(" NCA name offset check "+nca_name_offset, MsgType.WARNING);
|
|
||||||
|
|
||||||
|
|
||||||
NCAFile ncaFile = new NCAFile();
|
NCAFile ncaFile = new NCAFile();
|
||||||
ncaFile.setNcaOffset(nca_offset);
|
ncaFile.setNcaOffset(nca_offset);
|
||||||
|
@ -145,15 +130,15 @@ public class PFSProvider {
|
||||||
// Final offset
|
// Final offset
|
||||||
byte[] bufForInt = new byte[4];
|
byte[] bufForInt = new byte[4];
|
||||||
if ((randAccessFile.read(bufForInt) == 4) && (Arrays.equals(bufForInt, new byte[4])))
|
if ((randAccessFile.read(bufForInt) == 4) && (Arrays.equals(bufForInt, new byte[4])))
|
||||||
printLog("Final padding check", MsgType.PASS);
|
printLog("PFS Final padding check", EMsgType.PASS);
|
||||||
else
|
else
|
||||||
printLog("Final padding check", MsgType.WARNING);
|
printLog("PFS Final padding check", EMsgType.WARNING);
|
||||||
|
|
||||||
// Calculate position including header for body size offset
|
// Calculate position including header for body size offset
|
||||||
bodySize = randAccessFile.getFilePointer()+header;
|
bodySize = randAccessFile.getFilePointer()+header;
|
||||||
//*********************************************************************************************
|
//*********************************************************************************************
|
||||||
// Collect file names from NCAs
|
// Collect file names from NCAs
|
||||||
printLog("Collecting file names", MsgType.INFO);
|
printLog("PFS Collecting file names", EMsgType.INFO);
|
||||||
List<Byte> ncaFN; // Temporary
|
List<Byte> ncaFN; // Temporary
|
||||||
byte[] b = new byte[1]; // Temporary
|
byte[] b = new byte[1]; // Temporary
|
||||||
for (int i=0; i<filesCount; i++){
|
for (int i=0; i<filesCount; i++){
|
||||||
|
@ -176,9 +161,10 @@ public class PFSProvider {
|
||||||
randAccessFile.close();
|
randAccessFile.close();
|
||||||
}
|
}
|
||||||
catch (IOException ioe){
|
catch (IOException ioe){
|
||||||
ioe.printStackTrace(); //TODO: INFORM
|
printLog("PFS Failed NSP file analyze for ["+nspFileName+"]\n "+ioe.getMessage(), EMsgType.FAIL);
|
||||||
|
ioe.printStackTrace();
|
||||||
}
|
}
|
||||||
printLog("Finish NSP file analyze for ["+nspFileName+"]", MsgType.PASS);
|
printLog("PFS Finish NSP file analyze for ["+nspFileName+"]", EMsgType.PASS);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -234,7 +220,7 @@ public class PFSProvider {
|
||||||
/**
|
/**
|
||||||
* This is what will print to textArea of the application.
|
* This is what will print to textArea of the application.
|
||||||
**/
|
**/
|
||||||
private void printLog(String message, MsgType type){
|
private void printLog(String message, EMsgType type){
|
||||||
try {
|
try {
|
||||||
switch (type){
|
switch (type){
|
||||||
case PASS:
|
case PASS:
|
||||||
|
@ -249,12 +235,9 @@ public class PFSProvider {
|
||||||
case WARNING:
|
case WARNING:
|
||||||
msgQueue.put("[ WARN ] "+message+"\n");
|
msgQueue.put("[ WARN ] "+message+"\n");
|
||||||
break;
|
break;
|
||||||
default:
|
|
||||||
msgQueue.put(message);
|
|
||||||
}
|
}
|
||||||
}catch (InterruptedException ie){
|
}catch (InterruptedException ie){
|
||||||
ie.printStackTrace(); //TODO: INFORM
|
ie.printStackTrace(); //TODO: ???
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
package nsusbloader;
|
package nsusbloader;
|
||||||
|
|
||||||
import javafx.concurrent.Task;
|
import javafx.concurrent.Task;
|
||||||
import javafx.scene.control.ProgressBar;
|
import nsusbloader.NSLDataTypes.EFileStatus;
|
||||||
import javafx.scene.control.TextArea;
|
import nsusbloader.NSLDataTypes.EMsgType;
|
||||||
import nsusbloader.NSLDataTypes.MsgType;
|
|
||||||
import nsusbloader.PFS.PFSProvider;
|
import nsusbloader.PFS.PFSProvider;
|
||||||
import org.usb4java.*;
|
import org.usb4java.*;
|
||||||
|
|
||||||
|
@ -13,20 +12,19 @@ import java.nio.ByteOrder;
|
||||||
import java.nio.IntBuffer;
|
import java.nio.IntBuffer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.LinkedBlockingQueue;
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
import static nsusbloader.RainbowHexDump.hexDumpUTF8;
|
|
||||||
|
|
||||||
class UsbCommunications extends Task<Void> {
|
class UsbCommunications extends Task<Void> {
|
||||||
private final int DEFAULT_INTERFACE = 0;
|
private final int DEFAULT_INTERFACE = 0;
|
||||||
|
|
||||||
private BlockingQueue<String> msgQueue;
|
private BlockingQueue<String> msgQueue;
|
||||||
private BlockingQueue<Double> progressQueue;
|
private BlockingQueue<Double> progressQueue;
|
||||||
|
private HashMap<String, EFileStatus> statusMap; // BlockingQueue for literally one object. TODO: read more books ; replace to hashMap
|
||||||
|
|
||||||
private MessagesConsumer msgConsumer;
|
private MessagesConsumer msgConsumer;
|
||||||
|
|
||||||
private HashMap<String, File> nspMap;
|
private HashMap<String, File> nspMap;
|
||||||
|
@ -46,14 +44,15 @@ class UsbCommunications extends Task<Void> {
|
||||||
Since this application let user an ability (theoretically) to choose same files in different folders, the latest selected file will be added to the list and handled correctly.
|
Since this application let user an ability (theoretically) to choose same files in different folders, the latest selected file will be added to the list and handled correctly.
|
||||||
I have no idea why he/she will make a decision to do that. Just in case, we're good in this point.
|
I have no idea why he/she will make a decision to do that. Just in case, we're good in this point.
|
||||||
*/
|
*/
|
||||||
UsbCommunications(TextArea logArea, ProgressBar progressBar, List<File> nspList, String protocol){
|
UsbCommunications(List<File> nspList, String protocol){
|
||||||
this.protocol = protocol;
|
this.protocol = protocol;
|
||||||
this.nspMap = new HashMap<>();
|
this.nspMap = new HashMap<>();
|
||||||
for (File f: nspList)
|
for (File f: nspList)
|
||||||
nspMap.put(f.getName(), f);
|
nspMap.put(f.getName(), f);
|
||||||
this.msgQueue = new LinkedBlockingQueue<>();
|
this.msgQueue = new LinkedBlockingQueue<>();
|
||||||
this.progressQueue = new LinkedBlockingQueue<>();
|
this.progressQueue = new LinkedBlockingQueue<>();
|
||||||
this.msgConsumer = new MessagesConsumer(this.msgQueue, logArea, this.progressQueue, progressBar);
|
this.statusMap = new HashMap<>();
|
||||||
|
this.msgConsumer = new MessagesConsumer(this.msgQueue, this.progressQueue, this.statusMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,28 +60,28 @@ class UsbCommunications extends Task<Void> {
|
||||||
this.msgConsumer.start();
|
this.msgConsumer.start();
|
||||||
int result = -9999;
|
int result = -9999;
|
||||||
|
|
||||||
printLog("\tStart chain", MsgType.INFO);
|
printLog("\tStart chain", EMsgType.INFO);
|
||||||
// Creating Context required by libusb. Optional. TODO: Consider removing.
|
// Creating Context required by libusb. Optional. TODO: Consider removing.
|
||||||
contextNS = new Context();
|
contextNS = new Context();
|
||||||
result = LibUsb.init(contextNS);
|
result = LibUsb.init(contextNS);
|
||||||
if (result != LibUsb.SUCCESS) {
|
if (result != LibUsb.SUCCESS) {
|
||||||
printLog("libusb initialization\n Returned: "+result, MsgType.FAIL);
|
printLog("libusb initialization\n Returned: "+result, EMsgType.FAIL);
|
||||||
close();
|
close();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printLog("libusb initialization", MsgType.PASS);
|
printLog("libusb initialization", EMsgType.PASS);
|
||||||
|
|
||||||
// Searching for NS in devices: obtain list of all devices
|
// Searching for NS in devices: obtain list of all devices
|
||||||
DeviceList deviceList = new DeviceList();
|
DeviceList deviceList = new DeviceList();
|
||||||
result = LibUsb.getDeviceList(contextNS, deviceList);
|
result = LibUsb.getDeviceList(contextNS, deviceList);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
printLog("Get device list\n Returned: "+result, MsgType.FAIL);
|
printLog("Get device list\n Returned: "+result, EMsgType.FAIL);
|
||||||
close();
|
close();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printLog("Get device list", MsgType.PASS);
|
printLog("Get device list", EMsgType.PASS);
|
||||||
}
|
}
|
||||||
// Searching for NS in devices: looking for NS
|
// Searching for NS in devices: looking for NS
|
||||||
DeviceDescriptor descriptor;
|
DeviceDescriptor descriptor;
|
||||||
|
@ -91,14 +90,14 @@ class UsbCommunications extends Task<Void> {
|
||||||
descriptor = new DeviceDescriptor(); // mmm.. leave it as is.
|
descriptor = new DeviceDescriptor(); // mmm.. leave it as is.
|
||||||
result = LibUsb.getDeviceDescriptor(device, descriptor);
|
result = LibUsb.getDeviceDescriptor(device, descriptor);
|
||||||
if (result != LibUsb.SUCCESS){
|
if (result != LibUsb.SUCCESS){
|
||||||
printLog("Read file descriptors for USB devices\n Returned: "+result, MsgType.FAIL);
|
printLog("Read file descriptors for USB devices\n Returned: "+result, EMsgType.FAIL);
|
||||||
LibUsb.freeDeviceList(deviceList, true);
|
LibUsb.freeDeviceList(deviceList, true);
|
||||||
close();
|
close();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if ((descriptor.idVendor() == 0x057E) && descriptor.idProduct() == 0x3000){
|
if ((descriptor.idVendor() == 0x057E) && descriptor.idProduct() == 0x3000){
|
||||||
deviceNS = device;
|
deviceNS = device;
|
||||||
printLog("Read file descriptors for USB devices", MsgType.PASS);
|
printLog("Read file descriptors for USB devices", EMsgType.PASS);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,10 +140,10 @@ class UsbCommunications extends Task<Void> {
|
||||||
////////////////////////////////////////// DEBUG INFORMATION END /////////////////////////////////////////////
|
////////////////////////////////////////// DEBUG INFORMATION END /////////////////////////////////////////////
|
||||||
|
|
||||||
if (deviceNS != null){
|
if (deviceNS != null){
|
||||||
printLog("NS in connected USB devices found", MsgType.PASS);
|
printLog("NS in connected USB devices found", EMsgType.PASS);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printLog("NS in connected USB devices not found\n Returned: "+result, MsgType.FAIL);
|
printLog("NS in connected USB devices not found", EMsgType.FAIL);
|
||||||
close();
|
close();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -154,25 +153,25 @@ class UsbCommunications extends Task<Void> {
|
||||||
if (result != LibUsb.SUCCESS) {
|
if (result != LibUsb.SUCCESS) {
|
||||||
switch (result){
|
switch (result){
|
||||||
case LibUsb.ERROR_ACCESS:
|
case LibUsb.ERROR_ACCESS:
|
||||||
printLog("Open NS USB device\n Returned: ERROR_ACCESS", MsgType.FAIL);
|
printLog("Open NS USB device\n Returned: ERROR_ACCESS", EMsgType.FAIL);
|
||||||
printLog("Double check that you have administrator privileges (you're 'root') or check 'udev' rules set for this user (linux only)!",MsgType.INFO);
|
printLog("Double check that you have administrator privileges (you're 'root') or check 'udev' rules set for this user (linux only)!", EMsgType.INFO);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_NO_MEM:
|
case LibUsb.ERROR_NO_MEM:
|
||||||
printLog("Open NS USB device\n Returned: ERROR_NO_MEM", MsgType.FAIL);
|
printLog("Open NS USB device\n Returned: ERROR_NO_MEM", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_NO_DEVICE:
|
case LibUsb.ERROR_NO_DEVICE:
|
||||||
printLog("Open NS USB device\n Returned: ERROR_NO_DEVICE", MsgType.FAIL);
|
printLog("Open NS USB device\n Returned: ERROR_NO_DEVICE", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printLog("Open NS USB device\n Returned:" + result, MsgType.FAIL);
|
printLog("Open NS USB device\n Returned:" + result, EMsgType.FAIL);
|
||||||
}
|
}
|
||||||
close();
|
close();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printLog("Open NS USB device", MsgType.PASS);
|
printLog("Open NS USB device", EMsgType.PASS);
|
||||||
|
|
||||||
printLog("Free device list", MsgType.INFO);
|
printLog("Free device list", EMsgType.INFO);
|
||||||
LibUsb.freeDeviceList(deviceList, true);
|
LibUsb.freeDeviceList(deviceList, true);
|
||||||
|
|
||||||
// DO some stuff to connected NS
|
// DO some stuff to connected NS
|
||||||
|
@ -181,89 +180,89 @@ class UsbCommunications extends Task<Void> {
|
||||||
if (canDetach){
|
if (canDetach){
|
||||||
int usedByKernel = LibUsb.kernelDriverActive(handlerNS, DEFAULT_INTERFACE);
|
int usedByKernel = LibUsb.kernelDriverActive(handlerNS, DEFAULT_INTERFACE);
|
||||||
if (usedByKernel == LibUsb.SUCCESS){
|
if (usedByKernel == LibUsb.SUCCESS){
|
||||||
printLog("Can proceed with libusb driver", MsgType.PASS); // we're good
|
printLog("Can proceed with libusb driver", EMsgType.PASS); // we're good
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
switch (usedByKernel){
|
switch (usedByKernel){
|
||||||
case 1: // used by kernel
|
case 1: // used by kernel
|
||||||
result = LibUsb.detachKernelDriver(handlerNS, DEFAULT_INTERFACE);
|
result = LibUsb.detachKernelDriver(handlerNS, DEFAULT_INTERFACE);
|
||||||
printLog("Detach kernel required", MsgType.INFO);
|
printLog("Detach kernel required", EMsgType.INFO);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
switch (result){
|
switch (result){
|
||||||
case LibUsb.ERROR_NOT_FOUND:
|
case LibUsb.ERROR_NOT_FOUND:
|
||||||
printLog("Detach kernel\n Returned: ERROR_NOT_FOUND", MsgType.FAIL);
|
printLog("Detach kernel\n Returned: ERROR_NOT_FOUND", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_INVALID_PARAM:
|
case LibUsb.ERROR_INVALID_PARAM:
|
||||||
printLog("Detach kernel\n Returned: ERROR_INVALID_PARAM", MsgType.FAIL);
|
printLog("Detach kernel\n Returned: ERROR_INVALID_PARAM", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_NO_DEVICE:
|
case LibUsb.ERROR_NO_DEVICE:
|
||||||
printLog("Detach kernel\n Returned: ERROR_NO_DEVICE", MsgType.FAIL);
|
printLog("Detach kernel\n Returned: ERROR_NO_DEVICE", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_NOT_SUPPORTED: // Should never appear only if libusb buggy
|
case LibUsb.ERROR_NOT_SUPPORTED: // Should never appear only if libusb buggy
|
||||||
printLog("Detach kernel\n Returned: ERROR_NOT_SUPPORTED", MsgType.FAIL);
|
printLog("Detach kernel\n Returned: ERROR_NOT_SUPPORTED", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printLog("Detach kernel\n Returned: " + result, MsgType.FAIL);
|
printLog("Detach kernel\n Returned: " + result, EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
close();
|
close();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printLog("Detach kernel", MsgType.PASS);
|
printLog("Detach kernel", EMsgType.PASS);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case LibUsb.ERROR_NO_DEVICE:
|
case LibUsb.ERROR_NO_DEVICE:
|
||||||
printLog("Can't proceed with libusb driver\n Returned: ERROR_NO_DEVICE", MsgType.FAIL);
|
printLog("Can't proceed with libusb driver\n Returned: ERROR_NO_DEVICE", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_NOT_SUPPORTED:
|
case LibUsb.ERROR_NOT_SUPPORTED:
|
||||||
printLog("Can't proceed with libusb driver\n Returned: ERROR_NOT_SUPPORTED", MsgType.FAIL);
|
printLog("Can't proceed with libusb driver\n Returned: ERROR_NOT_SUPPORTED", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printLog("Can't proceed with libusb driver\n Returned: "+result, MsgType.FAIL);
|
printLog("Can't proceed with libusb driver\n Returned: "+result, EMsgType.FAIL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printLog("libusb doesn't supports function 'CAP_SUPPORTS_DETACH_KERNEL_DRIVER'. Proceeding.", MsgType.WARNING);
|
printLog("libusb doesn't supports function 'CAP_SUPPORTS_DETACH_KERNEL_DRIVER'. Proceeding.", EMsgType.WARNING);
|
||||||
|
|
||||||
// Set configuration (soft reset if needed)
|
// Set configuration (soft reset if needed)
|
||||||
result = LibUsb.setConfiguration(handlerNS, 1); // 1 - configuration all we need
|
result = LibUsb.setConfiguration(handlerNS, 1); // 1 - configuration all we need
|
||||||
if (result != LibUsb.SUCCESS){
|
if (result != LibUsb.SUCCESS){
|
||||||
switch (result){
|
switch (result){
|
||||||
case LibUsb.ERROR_NOT_FOUND:
|
case LibUsb.ERROR_NOT_FOUND:
|
||||||
printLog("Set active configuration to device\n Returned: ERROR_NOT_FOUND", MsgType.FAIL);
|
printLog("Set active configuration to device\n Returned: ERROR_NOT_FOUND", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_BUSY:
|
case LibUsb.ERROR_BUSY:
|
||||||
printLog("Set active configuration to device\n Returned: ERROR_BUSY", MsgType.FAIL);
|
printLog("Set active configuration to device\n Returned: ERROR_BUSY", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_NO_DEVICE:
|
case LibUsb.ERROR_NO_DEVICE:
|
||||||
printLog("Set active configuration to device\n Returned: ERROR_NO_DEVICE", MsgType.FAIL);
|
printLog("Set active configuration to device\n Returned: ERROR_NO_DEVICE", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_INVALID_PARAM:
|
case LibUsb.ERROR_INVALID_PARAM:
|
||||||
printLog("Set active configuration to device\n Returned: ERROR_INVALID_PARAM", MsgType.FAIL);
|
printLog("Set active configuration to device\n Returned: ERROR_INVALID_PARAM", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printLog("Set active configuration to device\n Returned: "+result, MsgType.FAIL);
|
printLog("Set active configuration to device\n Returned: "+result, EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
close();
|
close();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printLog("Set active configuration to device.", MsgType.PASS);
|
printLog("Set active configuration to device.", EMsgType.PASS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Claim interface
|
// Claim interface
|
||||||
result = LibUsb.claimInterface(handlerNS, DEFAULT_INTERFACE);
|
result = LibUsb.claimInterface(handlerNS, DEFAULT_INTERFACE);
|
||||||
if (result != LibUsb.SUCCESS) {
|
if (result != LibUsb.SUCCESS) {
|
||||||
printLog("Claim interface\n Returned: "+result, MsgType.FAIL);
|
printLog("Claim interface\n Returned: "+result, EMsgType.FAIL);
|
||||||
close();
|
close();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printLog("Claim interface", MsgType.PASS);
|
printLog("Claim interface", EMsgType.PASS);
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------------------
|
||||||
if (protocol.equals("TinFoil")) {
|
if (protocol.equals("TinFoil")) {
|
||||||
|
@ -273,17 +272,31 @@ class UsbCommunications extends Task<Void> {
|
||||||
}
|
}
|
||||||
|
|
||||||
close();
|
close();
|
||||||
printLog("\tEnd chain", MsgType.INFO);
|
printLog("\tEnd chain", EMsgType.INFO);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Report transfer status
|
||||||
|
* */
|
||||||
|
private void reportTransferStatus(EFileStatus status){
|
||||||
|
for (String fileName: nspMap.keySet())
|
||||||
|
statusMap.put(fileName, status);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Tinfoil processing
|
* Tinfoil processing
|
||||||
* */
|
* */
|
||||||
private class TinFoil{
|
private class TinFoil{
|
||||||
TinFoil(){
|
TinFoil(){
|
||||||
if (!sendListOfNSP())
|
|
||||||
|
if (!sendListOfNSP()) {
|
||||||
|
reportTransferStatus(EFileStatus.FAILED);
|
||||||
return;
|
return;
|
||||||
proceedCommands();
|
}
|
||||||
|
|
||||||
|
if (proceedCommands()) // REPORT SUCCESS
|
||||||
|
reportTransferStatus(EFileStatus.UPLOADED);
|
||||||
|
else // REPORT FAILURE
|
||||||
|
reportTransferStatus(EFileStatus.FAILED);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Send what NSP will be transferred
|
* Send what NSP will be transferred
|
||||||
|
@ -292,16 +305,17 @@ class UsbCommunications extends Task<Void> {
|
||||||
// Send list of NSP files:
|
// Send list of NSP files:
|
||||||
// Proceed "TUL0"
|
// Proceed "TUL0"
|
||||||
if (!writeToUsb("TUL0".getBytes(StandardCharsets.US_ASCII))) { // new byte[]{(byte) 0x54, (byte) 0x55, (byte) 0x76, (byte) 0x30}
|
if (!writeToUsb("TUL0".getBytes(StandardCharsets.US_ASCII))) { // new byte[]{(byte) 0x54, (byte) 0x55, (byte) 0x76, (byte) 0x30}
|
||||||
printLog("Send list of files: handshake", MsgType.FAIL);
|
printLog("TF Send list of files: handshake", EMsgType.FAIL);
|
||||||
close();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printLog("Send list of files: handshake", MsgType.PASS);
|
printLog("TF Send list of files: handshake", EMsgType.PASS);
|
||||||
//Collect file names
|
//Collect file names
|
||||||
StringBuilder nspListNamesBuilder = new StringBuilder(); // Add every title to one stringBuilder
|
StringBuilder nspListNamesBuilder = new StringBuilder(); // Add every title to one stringBuilder
|
||||||
for(String nspFileName: nspMap.keySet())
|
for(String nspFileName: nspMap.keySet()) {
|
||||||
nspListNamesBuilder.append(nspFileName+'\n'); // And here we come with java string default encoding (UTF-16)
|
nspListNamesBuilder.append(nspFileName); // And here we come with java string default encoding (UTF-16)
|
||||||
|
nspListNamesBuilder.append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
byte[] nspListNames = nspListNamesBuilder.toString().getBytes(StandardCharsets.UTF_8);
|
byte[] nspListNames = nspListNamesBuilder.toString().getBytes(StandardCharsets.UTF_8);
|
||||||
ByteBuffer byteBuffer = ByteBuffer.allocate(Integer.BYTES).order(ByteOrder.LITTLE_ENDIAN); // integer = 4 bytes; BTW Java is stored in big-endian format
|
ByteBuffer byteBuffer = ByteBuffer.allocate(Integer.BYTES).order(ByteOrder.LITTLE_ENDIAN); // integer = 4 bytes; BTW Java is stored in big-endian format
|
||||||
|
@ -310,47 +324,46 @@ class UsbCommunications extends Task<Void> {
|
||||||
//byteBuffer.reset();
|
//byteBuffer.reset();
|
||||||
|
|
||||||
// Sending NSP list
|
// Sending NSP list
|
||||||
|
printLog("TF Send list of files", EMsgType.INFO);
|
||||||
if (!writeToUsb(nspListSize)) { // size of the list we're going to transfer goes...
|
if (!writeToUsb(nspListSize)) { // size of the list we're going to transfer goes...
|
||||||
printLog("Send list of files: send length.", MsgType.FAIL);
|
printLog(" [send list length]", EMsgType.FAIL);
|
||||||
close();
|
|
||||||
return false;
|
return false;
|
||||||
} else
|
}
|
||||||
printLog("Send list of files: send length.", MsgType.PASS);
|
printLog(" [send list length]", EMsgType.PASS);
|
||||||
|
|
||||||
if (!writeToUsb(new byte[8])) { // 8 zero bytes goes...
|
if (!writeToUsb(new byte[8])) { // 8 zero bytes goes...
|
||||||
printLog("Send list of files: send padding.", MsgType.FAIL);
|
printLog(" [send padding]", EMsgType.FAIL);
|
||||||
close();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
printLog(" [send padding]", EMsgType.PASS);
|
||||||
printLog("Send list of files: send padding.", MsgType.PASS);
|
|
||||||
if (!writeToUsb(nspListNames)) { // list of the names goes...
|
if (!writeToUsb(nspListNames)) { // list of the names goes...
|
||||||
printLog("Send list of files: send list itself.", MsgType.FAIL);
|
printLog(" [send list itself]", EMsgType.FAIL);
|
||||||
close();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else
|
printLog(" [send list itself]", EMsgType.PASS);
|
||||||
printLog("Send list of files: send list itself.", MsgType.PASS);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* After we sent commands to NS, this chain starts
|
* After we sent commands to NS, this chain starts
|
||||||
* */
|
* */
|
||||||
private void proceedCommands(){
|
private boolean proceedCommands(){
|
||||||
printLog("Awaiting for NS commands.", MsgType.INFO);
|
printLog("TF Awaiting for NS commands.", EMsgType.INFO);
|
||||||
|
|
||||||
/* byte[] magic = new byte[4];
|
/* byte[] magic = new byte[4];
|
||||||
ByteBuffer bb = StandardCharsets.UTF_8.encode("TUC0").rewind().get(magic);
|
ByteBuffer bb = StandardCharsets.UTF_8.encode("TUC0").rewind().get(magic);
|
||||||
// Let's rephrase this 'string' */
|
// Let's rephrase this 'string' */
|
||||||
final byte[] magic = new byte[]{(byte) 0x54, (byte) 0x55, (byte) 0x43, (byte) 0x30}; // eq. 'TUC0' @ UTF-8 (actually ASCII lol, u know what I mean)
|
final byte[] magic = new byte[]{(byte) 0x54, (byte) 0x55, (byte) 0x43, (byte) 0x30}; // eq. 'TUC0' @ UTF-8 (actually ASCII lol, u know what I mean)
|
||||||
|
|
||||||
byte[] receivedArray;
|
byte[] receivedArray;
|
||||||
|
|
||||||
while (true){
|
while (true){
|
||||||
if (Thread.currentThread().isInterrupted()) // Check if user interrupted process.
|
if (Thread.currentThread().isInterrupted()) // Check if user interrupted process.
|
||||||
return;
|
return false;
|
||||||
receivedArray = readFromUsb();
|
receivedArray = readFromUsb();
|
||||||
if (receivedArray == null)
|
if (receivedArray == null)
|
||||||
return; // catches exception
|
return false; // catches exception
|
||||||
|
|
||||||
if (!Arrays.equals(Arrays.copyOfRange(receivedArray, 0,4), magic)) // Bytes from 0 to 3 should contain 'magic' TUC0, so must be verified like this
|
if (!Arrays.equals(Arrays.copyOfRange(receivedArray, 0,4), magic)) // Bytes from 0 to 3 should contain 'magic' TUC0, so must be verified like this
|
||||||
continue;
|
continue;
|
||||||
|
@ -358,17 +371,17 @@ class UsbCommunications extends Task<Void> {
|
||||||
// 8th to 12th(explicits) bytes in returned data stands for command ID as unsigned integer (Little-endian). Actually, we have to compare arrays here, but in real world it can't be greater then 0/1/2, thus:
|
// 8th to 12th(explicits) bytes in returned data stands for command ID as unsigned integer (Little-endian). Actually, we have to compare arrays here, but in real world it can't be greater then 0/1/2, thus:
|
||||||
// BTW also protocol specifies 4th byte to be 0x00 kinda indicating that that this command is valid. But, as you may see, never happens other situation when it's not = 0.
|
// BTW also protocol specifies 4th byte to be 0x00 kinda indicating that that this command is valid. But, as you may see, never happens other situation when it's not = 0.
|
||||||
if (receivedArray[8] == 0x00){ //0x00 - exit
|
if (receivedArray[8] == 0x00){ //0x00 - exit
|
||||||
printLog("Received EXIT command. Terminating.", MsgType.PASS);
|
printLog("TF Received EXIT command. Terminating.", EMsgType.PASS);
|
||||||
return; // All interaction with USB device should be ended (expected);
|
return true; // All interaction with USB device should be ended (expected);
|
||||||
}
|
}
|
||||||
else if ((receivedArray[8] == 0x01) || (receivedArray[8] == 0x02)){ //0x01 - file range; 0x02 unknown bug on backend side (dirty hack).
|
else if ((receivedArray[8] == 0x01) || (receivedArray[8] == 0x02)){ //0x01 - file range; 0x02 unknown bug on backend side (dirty hack).
|
||||||
printLog("Received FILE_RANGE command. Proceeding: [0x0"+receivedArray[8]+"]", MsgType.PASS);
|
printLog("TF Received FILE_RANGE command. Proceeding: [0x0"+receivedArray[8]+"]", EMsgType.PASS);
|
||||||
/*// We can get in this pocket a length of file name (+32). Why +32? I dunno man.. Do we need this? Definitely not. This app can live without it.
|
/*// We can get in this pocket a length of file name (+32). Why +32? I dunno man.. Do we need this? Definitely not. This app can live without it.
|
||||||
long receivedSize = ByteBuffer.wrap(Arrays.copyOfRange(receivedArray, 12,20)).order(ByteOrder.LITTLE_ENDIAN).getLong();
|
long receivedSize = ByteBuffer.wrap(Arrays.copyOfRange(receivedArray, 12,20)).order(ByteOrder.LITTLE_ENDIAN).getLong();
|
||||||
logsArea.appendText("[V] Received FILE_RANGE command. Size: "+Long.toUnsignedString(receivedSize)+"\n"); // this shit returns string that will be chosen next '+32'. And, BTW, can't be greater then 512
|
logsArea.appendText("[V] Received FILE_RANGE command. Size: "+Long.toUnsignedString(receivedSize)+"\n"); // this shit returns string that will be chosen next '+32'. And, BTW, can't be greater then 512
|
||||||
*/
|
*/
|
||||||
if (!fileRangeCmd()) {
|
if (!fileRangeCmd()) {
|
||||||
return; // catches exception
|
return false; // catches exception
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -392,9 +405,9 @@ class UsbCommunications extends Task<Void> {
|
||||||
long receivedRangeSize = ByteBuffer.wrap(Arrays.copyOfRange(receivedArray, 0,8)).order(ByteOrder.LITTLE_ENDIAN).getLong(); // Note - it could be unsigned long. Unfortunately, this app won't support files greater then 8796093022208 Gb
|
long receivedRangeSize = ByteBuffer.wrap(Arrays.copyOfRange(receivedArray, 0,8)).order(ByteOrder.LITTLE_ENDIAN).getLong(); // Note - it could be unsigned long. Unfortunately, this app won't support files greater then 8796093022208 Gb
|
||||||
byte[] receivedRangeSizeRAW = Arrays.copyOfRange(receivedArray, 0,8); // used (only) when we use sendResponse(). It's just simply.
|
byte[] receivedRangeSizeRAW = Arrays.copyOfRange(receivedArray, 0,8); // used (only) when we use sendResponse(). It's just simply.
|
||||||
long receivedRangeOffset = ByteBuffer.wrap(Arrays.copyOfRange(receivedArray, 8,16)).order(ByteOrder.LITTLE_ENDIAN).getLong(); // Note - it could be unsigned long. Unfortunately, this app won't support files greater then 8796093022208 Gb
|
long receivedRangeOffset = ByteBuffer.wrap(Arrays.copyOfRange(receivedArray, 8,16)).order(ByteOrder.LITTLE_ENDIAN).getLong(); // Note - it could be unsigned long. Unfortunately, this app won't support files greater then 8796093022208 Gb
|
||||||
/* Below, it's REAL NSP file name length that we sent before among others (WITHOUT +32 byes). It can't be greater then... see what is written in the beginning of this code.
|
/* Below, it's REAL NSP file name length that we sent before among others (WITHOUT +32 byes). It can't be greater then... see what is written in the beginning of this code.
|
||||||
We don't need this since in next pocket we'll get name itself UTF-8 encoded. Could be used to double-checks or something like that.
|
We don't need this since in next pocket we'll get name itself UTF-8 encoded. Could be used to double-checks or something like that.
|
||||||
long receivedNspNameLen = ByteBuffer.wrap(Arrays.copyOfRange(receivedArray, 16,24)).order(ByteOrder.LITTLE_ENDIAN).getLong(); */
|
long receivedNspNameLen = ByteBuffer.wrap(Arrays.copyOfRange(receivedArray, 16,24)).order(ByteOrder.LITTLE_ENDIAN).getLong(); */
|
||||||
|
|
||||||
// Requesting UTF-8 file name required:
|
// Requesting UTF-8 file name required:
|
||||||
receivedArray = readFromUsb();
|
receivedArray = readFromUsb();
|
||||||
|
@ -402,25 +415,21 @@ class UsbCommunications extends Task<Void> {
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
String receivedRequestedNSP = new String(receivedArray, StandardCharsets.UTF_8);
|
String receivedRequestedNSP = new String(receivedArray, StandardCharsets.UTF_8);
|
||||||
printLog("Reply to requested file: "+receivedRequestedNSP
|
printLog("TF Reply to requested file: "+receivedRequestedNSP
|
||||||
+"\n Range Size: "+receivedRangeSize
|
+"\n Range Size: "+receivedRangeSize
|
||||||
+"\n Range Offset: "+receivedRangeOffset, MsgType.INFO);
|
+"\n Range Offset: "+receivedRangeOffset, EMsgType.INFO);
|
||||||
|
|
||||||
// Sending response header
|
// Sending response header
|
||||||
if (!sendResponse(receivedRangeSizeRAW)) // Get receivedRangeSize in 'RAW' format exactly as it has been received. It's simply.
|
if (!sendResponse(receivedRangeSizeRAW)) // Get receivedRangeSize in 'RAW' format exactly as it has been received. It's simply.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// Read file starting:
|
|
||||||
// from Range Offset (receivedRangeOffset)
|
|
||||||
// to Range Size (receivedRangeSize) like end: receivedRangeOffset+receivedRangeSize
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
BufferedInputStream bufferedInStream = new BufferedInputStream(new FileInputStream(nspMap.get(receivedRequestedNSP))); // TODO: refactor?
|
BufferedInputStream bufferedInStream = new BufferedInputStream(new FileInputStream(nspMap.get(receivedRequestedNSP))); // TODO: refactor?
|
||||||
byte[] bufferCurrent ;//= new byte[1048576]; // eq. Allocate 1mb
|
byte[] bufferCurrent ;//= new byte[1048576]; // eq. Allocate 1mb
|
||||||
int bufferLength;
|
int bufferLength;
|
||||||
if (bufferedInStream.skip(receivedRangeOffset) != receivedRangeOffset){
|
if (bufferedInStream.skip(receivedRangeOffset) != receivedRangeOffset){
|
||||||
printLog("Requested skip is out of File size. Nothing to transmit.", MsgType.FAIL);
|
printLog("TF Requested skip is out of file size. Nothing to transmit.", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,7 +442,7 @@ class UsbCommunications extends Task<Void> {
|
||||||
return true;
|
return true;
|
||||||
if ((currentOffset + readPice) >= receivedRangeSize )
|
if ((currentOffset + readPice) >= receivedRangeSize )
|
||||||
readPice = Math.toIntExact(receivedRangeSize - currentOffset);
|
readPice = Math.toIntExact(receivedRangeSize - currentOffset);
|
||||||
//System.out.println("CO: "+currentOffset+"\t\tEO: "+receivedRangeSize+"\t\tRP: "+readPice); // TODO: NOTE: -----------------------DEBUG-----------------
|
//System.out.println("CO: "+currentOffset+"\t\tEO: "+receivedRangeSize+"\t\tRP: "+readPice); // TODO: NOTE: DEBUG
|
||||||
// updating progress bar (if a lot of data requested) START BLOCK
|
// updating progress bar (if a lot of data requested) START BLOCK
|
||||||
if (isProgessBarInitiated){
|
if (isProgessBarInitiated){
|
||||||
try {
|
try {
|
||||||
|
@ -460,26 +469,29 @@ class UsbCommunications extends Task<Void> {
|
||||||
if (bufferLength != -1){
|
if (bufferLength != -1){
|
||||||
//write to USB
|
//write to USB
|
||||||
if (!writeToUsb(bufferCurrent)) {
|
if (!writeToUsb(bufferCurrent)) {
|
||||||
printLog("Failure during NSP transmission.", MsgType.FAIL);
|
printLog("TF Failure during NSP transmission.", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
currentOffset += readPice;
|
currentOffset += readPice;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
printLog("Unexpected reading of stream ended.", MsgType.WARNING);
|
printLog("TF Reading of stream suddenly ended.", EMsgType.WARNING);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
bufferedInStream.close();
|
bufferedInStream.close();
|
||||||
} catch (FileNotFoundException fnfe){
|
} catch (FileNotFoundException fnfe){
|
||||||
printLog("FileNotFoundException:\n"+fnfe.getMessage(), MsgType.FAIL);
|
printLog("TF FileNotFoundException:\n "+fnfe.getMessage(), EMsgType.FAIL);
|
||||||
|
fnfe.printStackTrace();
|
||||||
return false;
|
return false;
|
||||||
} catch (IOException ioe){
|
} catch (IOException ioe){
|
||||||
printLog("IOException:\n"+ioe.getMessage(), MsgType.FAIL);
|
printLog("TF IOException:\n "+ioe.getMessage(), EMsgType.FAIL);
|
||||||
|
ioe.printStackTrace();
|
||||||
return false;
|
return false;
|
||||||
} catch (ArithmeticException ae){
|
} catch (ArithmeticException ae){
|
||||||
printLog("ArithmeticException (can't cast end offset minus current to 'integer'):\n"+ae.getMessage(), MsgType.FAIL);
|
printLog("TF ArithmeticException (can't cast end offset minus current to 'integer'):\n "+ae.getMessage(), EMsgType.FAIL);
|
||||||
|
ae.printStackTrace();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -491,32 +503,32 @@ class UsbCommunications extends Task<Void> {
|
||||||
* false if failed
|
* false if failed
|
||||||
* */
|
* */
|
||||||
private boolean sendResponse(byte[] rangeSize){ // This method as separate function itself for application needed as a cookie in the middle of desert.
|
private boolean sendResponse(byte[] rangeSize){ // This method as separate function itself for application needed as a cookie in the middle of desert.
|
||||||
printLog("Sending response", MsgType.INFO);
|
printLog("TF Sending response", EMsgType.INFO);
|
||||||
if (!writeToUsb(new byte[] { (byte) 0x54, (byte) 0x55, (byte) 0x43, (byte) 0x30, // 'TUC0'
|
if (!writeToUsb(new byte[] { (byte) 0x54, (byte) 0x55, (byte) 0x43, (byte) 0x30, // 'TUC0'
|
||||||
(byte) 0x01, // CMD_TYPE_RESPONSE = 1
|
(byte) 0x01, // CMD_TYPE_RESPONSE = 1
|
||||||
(byte) 0x00, (byte) 0x00, (byte) 0x00, // kinda padding. Guys, didn't you want to use integer value for CMD semantic?
|
(byte) 0x00, (byte) 0x00, (byte) 0x00, // kinda padding. Guys, didn't you want to use integer value for CMD semantic?
|
||||||
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00} ) // Send integer value of '1' in Little-endian format.
|
(byte) 0x01, (byte) 0x00, (byte) 0x00, (byte) 0x00} ) // Send integer value of '1' in Little-endian format.
|
||||||
){
|
){
|
||||||
printLog("[1/3]", MsgType.FAIL);
|
printLog(" [1/3]", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
printLog("[1/3]", MsgType.PASS);
|
printLog(" [1/3]", EMsgType.PASS);
|
||||||
if(!writeToUsb(rangeSize)) { // Send EXACTLY what has been received
|
if(!writeToUsb(rangeSize)) { // Send EXACTLY what has been received
|
||||||
printLog("[2/3]", MsgType.FAIL);
|
printLog(" [2/3]", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
printLog("[2/3]", MsgType.PASS);
|
printLog(" [2/3]", EMsgType.PASS);
|
||||||
if(!writeToUsb(new byte[12])) { // kinda another one padding
|
if(!writeToUsb(new byte[12])) { // kinda another one padding
|
||||||
printLog("[3/3]", MsgType.FAIL);
|
printLog(" [3/3]", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
printLog("[3/3]", MsgType.PASS);
|
printLog(" [3/3]", EMsgType.PASS);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Tinfoil processing
|
* GoldLeaf processing
|
||||||
* */
|
* */
|
||||||
private class GoldLeaf{
|
private class GoldLeaf{
|
||||||
// CMD G L U C ID 0 0 0
|
// CMD G L U C ID 0 0 0
|
||||||
|
@ -531,111 +543,132 @@ class UsbCommunications extends Task<Void> {
|
||||||
private final byte[] CMD_Finish = new byte[]{0x47, 0x4c, 0x55, 0x43, 0x07, 0x00, 0x00, 0x00};
|
private final byte[] CMD_Finish = new byte[]{0x47, 0x4c, 0x55, 0x43, 0x07, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
GoldLeaf(){
|
GoldLeaf(){
|
||||||
List<PFSProvider> pfsList = new ArrayList<>();
|
printLog("===========================================================================", EMsgType.INFO);
|
||||||
|
PFSProvider pfsElement = new PFSProvider(nspMap.get(nspMap.keySet().toArray()[0]), msgQueue);
|
||||||
StringBuilder allValidFiles = new StringBuilder();
|
if (!pfsElement.init()) {
|
||||||
StringBuilder nonValidFiles = new StringBuilder();
|
printLog("GL File provided have incorrect structure and won't be uploaded", EMsgType.FAIL);
|
||||||
// Prepare data
|
reportTransferStatus(EFileStatus.INCORRECT_FILE_FAILED);
|
||||||
for (File nspFile : nspMap.values()) {
|
|
||||||
PFSProvider pfsp = new PFSProvider(nspFile, msgQueue);
|
|
||||||
if (pfsp.init()) {
|
|
||||||
pfsList.add(pfsp);
|
|
||||||
allValidFiles.append(nspFile.getName());
|
|
||||||
allValidFiles.append("\n");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nonValidFiles.append(nspFile.getName());
|
|
||||||
nonValidFiles.append("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pfsList.size() == 0){
|
|
||||||
printLog("All files provided have incorrect structure and won't be uploaded", MsgType.FAIL);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printLog("===========================================================================", MsgType.INFO);
|
printLog("GL File structure validated and it will be uploaded", EMsgType.PASS);
|
||||||
printLog("Verified files prepared for upload: \n "+allValidFiles, MsgType.PASS);
|
|
||||||
if (!nonValidFiles.toString().isEmpty())
|
|
||||||
printLog("Files with incorrect structure that won't be uploaded: \n"+nonValidFiles, MsgType.INFO);
|
|
||||||
//--------------------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
if (initGoldLeafProtocol(pfsElement))
|
||||||
|
reportTransferStatus(EFileStatus.UPLOADED);
|
||||||
|
else
|
||||||
|
reportTransferStatus(EFileStatus.FAILED);
|
||||||
|
}
|
||||||
|
private boolean initGoldLeafProtocol(PFSProvider pfsElement){
|
||||||
// Go parse commands
|
// Go parse commands
|
||||||
byte[] readByte;
|
byte[] readByte;
|
||||||
|
|
||||||
for(PFSProvider pfsElement: pfsList) {
|
// Go connect to GoldLeaf
|
||||||
// Go connect to GoldLeaf
|
if (writeToUsb(CMD_ConnectionRequest))
|
||||||
if (writeToUsb(CMD_ConnectionRequest))
|
printLog("GL Initiating GoldLeaf connection", EMsgType.PASS);
|
||||||
printLog("Initiating GoldLeaf connection" + nonValidFiles, MsgType.PASS);
|
else {
|
||||||
else {
|
printLog("GL Initiating GoldLeaf connection", EMsgType.FAIL);
|
||||||
printLog("Initiating GoldLeaf connection" + nonValidFiles, MsgType.FAIL);
|
return false;
|
||||||
return;
|
}
|
||||||
|
while (true) {
|
||||||
|
readByte = readFromUsb();
|
||||||
|
if (readByte == null)
|
||||||
|
return false;
|
||||||
|
if (Arrays.equals(readByte, CMD_ConnectionResponse)) {
|
||||||
|
if (!handleConnectionResponse(pfsElement))
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
int a = 0; // TODO:DEBUG
|
if (Arrays.equals(readByte, CMD_Start)) {
|
||||||
while (true) {
|
if (!handleStart(pfsElement))
|
||||||
System.out.println("In loop. Iter: "+a); // TODO:DEBUG
|
return false;
|
||||||
readByte = readFromUsb();
|
else
|
||||||
if (readByte == null)
|
continue;
|
||||||
return;
|
}
|
||||||
hexDumpUTF8(readByte); // TODO:DEBUG
|
if (Arrays.equals(readByte, CMD_NSPContent)) {
|
||||||
if (Arrays.equals(readByte, CMD_ConnectionResponse)) {
|
if (!handleNSPContent(pfsElement, true))
|
||||||
if (!handleConnectionResponse(pfsElement))
|
return false;
|
||||||
return;
|
else
|
||||||
else
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
if (Arrays.equals(readByte, CMD_NSPTicket)) {
|
||||||
if (Arrays.equals(readByte, CMD_Start)) {
|
if (!handleNSPContent(pfsElement, false))
|
||||||
if (!handleStart(pfsElement))
|
return false;
|
||||||
return;
|
else
|
||||||
else
|
continue;
|
||||||
continue;
|
}
|
||||||
}
|
if (Arrays.equals(readByte, CMD_Finish)) {
|
||||||
if (Arrays.equals(readByte, CMD_NSPContent)) {
|
printLog("GL Closing GoldLeaf connection: Transfer successful.", EMsgType.PASS);
|
||||||
if (!handleNSPContent(pfsElement, true))
|
break;
|
||||||
return;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (Arrays.equals(readByte, CMD_NSPTicket)) {
|
|
||||||
if (!handleNSPContent(pfsElement, false))
|
|
||||||
return;
|
|
||||||
else
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (Arrays.equals(readByte, CMD_Finish)) {
|
|
||||||
printLog("Closing GoldLeaf connection: Transfer successful", MsgType.PASS);
|
|
||||||
break; // TODO: GO TO NEXT NSP
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* ConnectionResponse command handler
|
* ConnectionResponse command handler
|
||||||
* */
|
* */
|
||||||
private boolean handleConnectionResponse(PFSProvider pfsElement){
|
private boolean handleConnectionResponse(PFSProvider pfsElement){
|
||||||
if (!writeToUsb(CMD_NSPName))
|
printLog("GL 'ConnectionResonse' command:", EMsgType.INFO);
|
||||||
|
if (!writeToUsb(CMD_NSPName)) {
|
||||||
|
printLog(" [1/3]", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
if (!writeToUsb(pfsElement.getBytesNspFileNameLength()))
|
}
|
||||||
|
printLog(" [1/3]", EMsgType.PASS);
|
||||||
|
|
||||||
|
if (!writeToUsb(pfsElement.getBytesNspFileNameLength())) {
|
||||||
|
printLog(" [2/3]", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
if (!writeToUsb(pfsElement.getBytesNspFileName()))
|
}
|
||||||
|
printLog(" [2/3]", EMsgType.PASS);
|
||||||
|
|
||||||
|
if (!writeToUsb(pfsElement.getBytesNspFileName())) {
|
||||||
|
printLog(" [3/3]", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
printLog(" [3/3]", EMsgType.PASS);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Start command handler
|
* Start command handler
|
||||||
* */
|
* */
|
||||||
private boolean handleStart(PFSProvider pfsElement){
|
private boolean handleStart(PFSProvider pfsElement){
|
||||||
if (!writeToUsb(CMD_NSPData))
|
printLog("GL Handle 'Start' command:", EMsgType.INFO);
|
||||||
|
if (!writeToUsb(CMD_NSPData)) {
|
||||||
|
printLog(" [Send command]", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
if (!writeToUsb(pfsElement.getBytesCountOfNca()))
|
}
|
||||||
|
printLog(" [Send command]", EMsgType.PASS);
|
||||||
|
|
||||||
|
if (!writeToUsb(pfsElement.getBytesCountOfNca())) {
|
||||||
|
printLog(" [Send length]", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
for (int i = 0; i < pfsElement.getIntCountOfNca(); i++){
|
}
|
||||||
if (!writeToUsb(pfsElement.getNca(i).getNcaFileNameLength()))
|
printLog(" [Send length]", EMsgType.PASS);
|
||||||
|
|
||||||
|
int ncaCount = pfsElement.getIntCountOfNca();
|
||||||
|
printLog(" [Send information for "+ncaCount+" files]", EMsgType.INFO);
|
||||||
|
for (int i = 0; i < ncaCount; i++){
|
||||||
|
if (!writeToUsb(pfsElement.getNca(i).getNcaFileNameLength())) {
|
||||||
|
printLog(" [1/4] File #"+i, EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
if (!writeToUsb(pfsElement.getNca(i).getNcaFileName()))
|
}
|
||||||
|
printLog(" [1/4] File #"+i, EMsgType.PASS);
|
||||||
|
|
||||||
|
if (!writeToUsb(pfsElement.getNca(i).getNcaFileName())) {
|
||||||
|
printLog(" [2/4] File #"+i, EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
if (!writeToUsb(ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putLong(pfsElement.getBodySize()+pfsElement.getNca(i).getNcaOffset()).array())) // offset. real.
|
}
|
||||||
|
printLog(" [2/4] File #"+i, EMsgType.PASS);
|
||||||
|
if (!writeToUsb(ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putLong(pfsElement.getBodySize()+pfsElement.getNca(i).getNcaOffset()).array())) { // offset. real.
|
||||||
|
printLog(" [2/4] File #"+i, EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
if (!writeToUsb(ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putLong(pfsElement.getNca(i).getNcaSize()).array())) // size
|
}
|
||||||
|
printLog(" [3/4] File #"+i, EMsgType.PASS);
|
||||||
|
if (!writeToUsb(ByteBuffer.allocate(8).order(ByteOrder.LITTLE_ENDIAN).putLong(pfsElement.getNca(i).getNcaSize()).array())) { // size
|
||||||
|
printLog(" [4/4] File #"+i, EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
printLog(" [4/4] File #"+i, EMsgType.PASS);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -648,13 +681,18 @@ class UsbCommunications extends Task<Void> {
|
||||||
int requestedNcaID;
|
int requestedNcaID;
|
||||||
boolean isProgessBarInitiated = false;
|
boolean isProgessBarInitiated = false;
|
||||||
if (isItRawRequest) {
|
if (isItRawRequest) {
|
||||||
|
printLog("GL Handle 'Content' command", EMsgType.INFO);
|
||||||
byte[] readByte = readFromUsb();
|
byte[] readByte = readFromUsb();
|
||||||
if (readByte == null || readByte.length != 4)
|
if (readByte == null || readByte.length != 4) {
|
||||||
|
printLog(" [Read requested ID]", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
requestedNcaID = ByteBuffer.wrap(readByte).order(ByteOrder.LITTLE_ENDIAN).getInt();
|
requestedNcaID = ByteBuffer.wrap(readByte).order(ByteOrder.LITTLE_ENDIAN).getInt();
|
||||||
|
printLog(" [Read requested ID = "+requestedNcaID+" ]", EMsgType.PASS);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
requestedNcaID = pfsElement.getNcaTicketID();
|
requestedNcaID = pfsElement.getNcaTicketID();
|
||||||
|
printLog("GL Handle 'Ticket' command (ID = "+requestedNcaID+" )", EMsgType.INFO);
|
||||||
}
|
}
|
||||||
|
|
||||||
long realNcaOffset = pfsElement.getNca(requestedNcaID).getNcaOffset()+pfsElement.getBodySize();
|
long realNcaOffset = pfsElement.getNca(requestedNcaID).getNcaOffset()+pfsElement.getBodySize();
|
||||||
|
@ -683,7 +721,7 @@ class UsbCommunications extends Task<Void> {
|
||||||
|
|
||||||
if (!writeToUsb(readBuf))
|
if (!writeToUsb(readBuf))
|
||||||
return false;
|
return false;
|
||||||
/***********************************/
|
//-----------------------------------------/
|
||||||
if (isProgessBarInitiated){
|
if (isProgessBarInitiated){
|
||||||
try {
|
try {
|
||||||
if (readFrom+readPice == realNcaSize){
|
if (readFrom+readPice == realNcaSize){
|
||||||
|
@ -700,12 +738,13 @@ class UsbCommunications extends Task<Void> {
|
||||||
if ((readPice == 8388608) && (readFrom == 0))
|
if ((readPice == 8388608) && (readFrom == 0))
|
||||||
isProgessBarInitiated = true;
|
isProgessBarInitiated = true;
|
||||||
}
|
}
|
||||||
/***********************************/
|
//-----------------------------------------/
|
||||||
readFrom += readPice;
|
readFrom += readPice;
|
||||||
}
|
}
|
||||||
bufferedInStream.close();
|
bufferedInStream.close();
|
||||||
}
|
}
|
||||||
catch (IOException ioe){
|
catch (IOException ioe){
|
||||||
|
printLog(" Failed to read NCA ID "+requestedNcaID+". IO Exception:\n "+ioe.getMessage(), EMsgType.FAIL);
|
||||||
ioe.printStackTrace();
|
ioe.printStackTrace();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -723,17 +762,17 @@ class UsbCommunications extends Task<Void> {
|
||||||
int result = LibUsb.releaseInterface(handlerNS, DEFAULT_INTERFACE);
|
int result = LibUsb.releaseInterface(handlerNS, DEFAULT_INTERFACE);
|
||||||
|
|
||||||
if (result != LibUsb.SUCCESS)
|
if (result != LibUsb.SUCCESS)
|
||||||
printLog("Release interface\n Returned: "+result+" (sometimes it's not an issue)", MsgType.WARNING);
|
printLog("Release interface\n Returned: "+result+" (sometimes it's not an issue)", EMsgType.WARNING);
|
||||||
else
|
else
|
||||||
printLog("Release interface", MsgType.PASS);
|
printLog("Release interface", EMsgType.PASS);
|
||||||
|
|
||||||
LibUsb.close(handlerNS);
|
LibUsb.close(handlerNS);
|
||||||
printLog("Requested handler close", MsgType.INFO);
|
printLog("Requested handler close", EMsgType.INFO);
|
||||||
}
|
}
|
||||||
// close context in the end
|
// close context in the end
|
||||||
if (contextNS != null) {
|
if (contextNS != null) {
|
||||||
LibUsb.exit(contextNS);
|
LibUsb.exit(contextNS);
|
||||||
printLog("Requested context close", MsgType.INFO);
|
printLog("Requested context close", EMsgType.INFO);
|
||||||
}
|
}
|
||||||
msgConsumer.interrupt();
|
msgConsumer.interrupt();
|
||||||
}
|
}
|
||||||
|
@ -752,25 +791,25 @@ class UsbCommunications extends Task<Void> {
|
||||||
if (result != LibUsb.SUCCESS){
|
if (result != LibUsb.SUCCESS){
|
||||||
switch (result){
|
switch (result){
|
||||||
case LibUsb.ERROR_TIMEOUT:
|
case LibUsb.ERROR_TIMEOUT:
|
||||||
printLog("Data transfer (write) issue\n Returned: ERROR_TIMEOUT", MsgType.FAIL);
|
printLog("Data transfer (write) issue\n Returned: ERROR_TIMEOUT", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_PIPE: //WUT?? I dunno man looks overkill in here..
|
case LibUsb.ERROR_PIPE: //WUT?? I dunno man looks overkill in here..
|
||||||
printLog("Data transfer (write) issue\n Returned: ERROR_PIPE", MsgType.FAIL);
|
printLog("Data transfer (write) issue\n Returned: ERROR_PIPE", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_OVERFLOW:
|
case LibUsb.ERROR_OVERFLOW:
|
||||||
printLog("Data transfer (write) issue\n Returned: ERROR_OVERFLOW", MsgType.FAIL);
|
printLog("Data transfer (write) issue\n Returned: ERROR_OVERFLOW", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_NO_DEVICE:
|
case LibUsb.ERROR_NO_DEVICE:
|
||||||
printLog("Data transfer (write) issue\n Returned: ERROR_NO_DEVICE", MsgType.FAIL);
|
printLog("Data transfer (write) issue\n Returned: ERROR_NO_DEVICE", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printLog("Data transfer (write) issue\n Returned: "+result, MsgType.FAIL);
|
printLog("Data transfer (write) issue\n Returned: "+result, EMsgType.FAIL);
|
||||||
}
|
}
|
||||||
printLog("Execution stopped", MsgType.FAIL);
|
printLog("Execution stopped", EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
}else {
|
}else {
|
||||||
if (writeBufTransferred.get() != message.length){
|
if (writeBufTransferred.get() != message.length){
|
||||||
printLog("Data transfer (write) issue\n Requested: "+message.length+"\n Transferred: "+writeBufTransferred.get(), MsgType.FAIL);
|
printLog("Data transfer (write) issue\n Requested: "+message.length+"\n Transferred: "+writeBufTransferred.get(), EMsgType.FAIL);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -781,7 +820,7 @@ class UsbCommunications extends Task<Void> {
|
||||||
/**
|
/**
|
||||||
* Reading what USB device responded.
|
* Reading what USB device responded.
|
||||||
* @return byte array if data read successful
|
* @return byte array if data read successful
|
||||||
* 'null' if read failed
|
* 'null' if read failed
|
||||||
* */
|
* */
|
||||||
private byte[] readFromUsb(){
|
private byte[] readFromUsb(){
|
||||||
ByteBuffer readBuffer = ByteBuffer.allocateDirect(512);// //readBuffer.order() equals BIG_ENDIAN; DON'T TOUCH. And we will always allocate readBuffer for max-size endpoint supports (512 bytes)
|
ByteBuffer readBuffer = ByteBuffer.allocateDirect(512);// //readBuffer.order() equals BIG_ENDIAN; DON'T TOUCH. And we will always allocate readBuffer for max-size endpoint supports (512 bytes)
|
||||||
|
@ -794,24 +833,24 @@ class UsbCommunications extends Task<Void> {
|
||||||
if (result != LibUsb.SUCCESS){
|
if (result != LibUsb.SUCCESS){
|
||||||
switch (result){
|
switch (result){
|
||||||
case LibUsb.ERROR_TIMEOUT:
|
case LibUsb.ERROR_TIMEOUT:
|
||||||
printLog("Data transfer (read) issue\n Returned: ERROR_TIMEOUT", MsgType.FAIL);
|
printLog("Data transfer (read) issue\n Returned: ERROR_TIMEOUT", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_PIPE: //WUT?? I dunno man looks overkill in here..
|
case LibUsb.ERROR_PIPE: //WUT?? I dunno man looks overkill in here..
|
||||||
printLog("Data transfer (read) issue\n Returned: ERROR_PIPE", MsgType.FAIL);
|
printLog("Data transfer (read) issue\n Returned: ERROR_PIPE", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_OVERFLOW:
|
case LibUsb.ERROR_OVERFLOW:
|
||||||
printLog("Data transfer (read) issue\n Returned: ERROR_OVERFLOW", MsgType.FAIL);
|
printLog("Data transfer (read) issue\n Returned: ERROR_OVERFLOW", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_NO_DEVICE:
|
case LibUsb.ERROR_NO_DEVICE:
|
||||||
printLog("Data transfer (read) issue\n Returned: ERROR_NO_DEVICE", MsgType.FAIL);
|
printLog("Data transfer (read) issue\n Returned: ERROR_NO_DEVICE", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
case LibUsb.ERROR_IO:
|
case LibUsb.ERROR_IO:
|
||||||
printLog("Data transfer (read) issue\n Returned: ERROR_IO", MsgType.FAIL);
|
printLog("Data transfer (read) issue\n Returned: ERROR_IO", EMsgType.FAIL);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printLog("Data transfer (read) issue\n Returned: "+result, MsgType.FAIL);
|
printLog("Data transfer (read) issue\n Returned: "+result, EMsgType.FAIL);
|
||||||
}
|
}
|
||||||
printLog("Execution stopped", MsgType.FAIL);
|
printLog("Execution stopped", EMsgType.FAIL);
|
||||||
return null;
|
return null;
|
||||||
} else {
|
} else {
|
||||||
int trans = readBufTransferred.get();
|
int trans = readBufTransferred.get();
|
||||||
|
@ -827,7 +866,7 @@ class UsbCommunications extends Task<Void> {
|
||||||
/**
|
/**
|
||||||
* This is what will print to textArea of the application.
|
* This is what will print to textArea of the application.
|
||||||
* */
|
* */
|
||||||
private void printLog(String message, MsgType type){
|
private void printLog(String message, EMsgType type){
|
||||||
try {
|
try {
|
||||||
switch (type){
|
switch (type){
|
||||||
case PASS:
|
case PASS:
|
||||||
|
@ -848,6 +887,5 @@ class UsbCommunications extends Task<Void> {
|
||||||
}catch (InterruptedException ie){
|
}catch (InterruptedException ie){
|
||||||
ie.printStackTrace();
|
ie.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
-fx-background: #2d2d2d;
|
-fx-background: #2d2d2d;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button, .buttonUp, .buttonStop{
|
.button, .buttonUp, .buttonStop, .buttonSelect{
|
||||||
-fx-background-color: #4f4f4f;
|
-fx-background-color: #4f4f4f;
|
||||||
-fx-border-color: #4f4f4f;
|
-fx-border-color: #4f4f4f;
|
||||||
-fx-border-radius: 3;
|
-fx-border-radius: 3;
|
||||||
|
@ -13,19 +13,26 @@
|
||||||
-fx-text-fill: #f7fafa;
|
-fx-text-fill: #f7fafa;
|
||||||
-fx-effect: none;
|
-fx-effect: none;
|
||||||
}
|
}
|
||||||
.button:hover, .buttonStop:hover, .buttonUp:hover, .choice-box:hover, .button:focused:hover, .buttonStop:focused:hover, .buttonUp:focused:hover, .choice-box:focused:hover{
|
.button:hover, .buttonStop:hover, .buttonUp:hover, .choice-box:hover, .button:focused:hover, .buttonStop:focused:hover, .buttonUp:focused:hover, .buttonSelect:focused:hover .choice-box:focused:hover{
|
||||||
-fx-background-color: #4f4f4f;
|
-fx-background-color: #4f4f4f;
|
||||||
-fx-border-color: #a4ffff;
|
-fx-border-color: #a4ffff;
|
||||||
-fx-border-radius: 3;
|
-fx-border-radius: 3;
|
||||||
-fx-border-width: 2;
|
-fx-border-width: 2;
|
||||||
-fx-text-fill: #f7fafa;
|
-fx-text-fill: #f7fafa;
|
||||||
}
|
}
|
||||||
.button:focused, .buttonStop:focused, .buttonUp:focused, .choice-box:focused{
|
.button:focused, .buttonStop:focused, .buttonUp:focused, .buttonSelect:focused, .choice-box:focused{
|
||||||
-fx-background-color: #6a6a6a;
|
-fx-background-color: #6a6a6a;
|
||||||
-fx-border-color: #6a6a6a;
|
-fx-border-color: #6a6a6a;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button:pressed, .button:pressed:hover{
|
.button:pressed, .button:pressed:hover{
|
||||||
|
-fx-background-color: #4f4f4f;
|
||||||
|
-fx-border-color: #e82382;
|
||||||
|
-fx-border-radius: 3;
|
||||||
|
-fx-border-width: 2;
|
||||||
|
-fx-text-fill: #f7fafa;
|
||||||
|
}
|
||||||
|
.buttonSelect:pressed, .buttonSelect:pressed:hover{
|
||||||
-fx-background-color: #4f4f4f;
|
-fx-background-color: #4f4f4f;
|
||||||
-fx-border-color: #289de8;
|
-fx-border-color: #289de8;
|
||||||
-fx-border-radius: 3;
|
-fx-border-radius: 3;
|
||||||
|
@ -196,7 +203,18 @@
|
||||||
-fx-padding: 0.0em; /* 0 */
|
-fx-padding: 0.0em; /* 0 */
|
||||||
-fx-table-cell-border-color: #f7fafa;
|
-fx-table-cell-border-color: #f7fafa;
|
||||||
}
|
}
|
||||||
|
// -========================== Context menu =====================-
|
||||||
|
.context-menu {
|
||||||
|
-fx-background-color: #2d2d2d;
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-cursor: hand;
|
||||||
|
}
|
||||||
|
.context-menu .menu-item .label {
|
||||||
|
-fx-text-fill: #f7fafa;
|
||||||
|
}
|
||||||
|
.context-menu .menu-item:focused .label {
|
||||||
|
-fx-text-fill: #f7fafa;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
-fx-background: #ebebeb;
|
-fx-background: #ebebeb;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button, .buttonUp, .buttonStop{
|
.button, .buttonUp, .buttonStop, .buttonSelect{
|
||||||
-fx-background-color: #fefefe;
|
-fx-background-color: #fefefe;
|
||||||
-fx-border-color: #fefefe;
|
-fx-border-color: #fefefe;
|
||||||
-fx-border-radius: 3;
|
-fx-border-radius: 3;
|
||||||
|
@ -14,19 +14,26 @@
|
||||||
-fx-effect: dropshadow(three-pass-box, #b4b4b4, 2, 0, 0, 0);
|
-fx-effect: dropshadow(three-pass-box, #b4b4b4, 2, 0, 0, 0);
|
||||||
|
|
||||||
}
|
}
|
||||||
.button:hover, .buttonStop:hover, .buttonUp:hover, .choice-box:hover, .button:focused:hover, .buttonStop:focused:hover, .buttonUp:focused:hover, .choice-box:focused:hover{
|
.button:hover, .buttonStop:hover, .buttonUp:hover, .choice-box:hover, .button:focused:hover, .buttonStop:focused:hover, .buttonUp:focused:hover, .buttonSelect:focused:hover .choice-box:focused:hover{
|
||||||
-fx-background-color: #fefefe;
|
-fx-background-color: #fefefe;
|
||||||
-fx-border-color: #00caca;
|
-fx-border-color: #00caca;
|
||||||
-fx-border-radius: 3;
|
-fx-border-radius: 3;
|
||||||
-fx-border-width: 2;
|
-fx-border-width: 2;
|
||||||
-fx-text-fill: #2c2c2c;
|
-fx-text-fill: #2c2c2c;
|
||||||
}
|
}
|
||||||
.button:focused, .buttonStop:focused, .buttonUp:focused, .choice-box:focused{
|
.button:focused, .buttonStop:focused, .buttonUp:focused, .buttonSelect:focused, .choice-box:focused{
|
||||||
-fx-background-color: #cccccc;
|
-fx-background-color: #cccccc;
|
||||||
-fx-border-color: #cccccc;
|
-fx-border-color: #cccccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button:pressed, .button:pressed:hover{
|
.button:pressed, .button:pressed:hover{
|
||||||
|
-fx-background-color: #fefefe;
|
||||||
|
-fx-border-color: #e82382;
|
||||||
|
-fx-border-radius: 3;
|
||||||
|
-fx-border-width: 2;
|
||||||
|
-fx-text-fill: #2c2c2c;
|
||||||
|
}
|
||||||
|
.buttonSelect:pressed, .buttonSelect:pressed:hover{
|
||||||
-fx-background-color: #fefefe;
|
-fx-background-color: #fefefe;
|
||||||
-fx-border-color: #289de8;
|
-fx-border-color: #289de8;
|
||||||
-fx-border-radius: 3;
|
-fx-border-radius: 3;
|
||||||
|
@ -197,7 +204,18 @@
|
||||||
-fx-padding: 0.0em; /* 0 */
|
-fx-padding: 0.0em; /* 0 */
|
||||||
-fx-table-cell-border-color: #2c2c2c;
|
-fx-table-cell-border-color: #2c2c2c;
|
||||||
}
|
}
|
||||||
|
// -========================== Context menu =====================-
|
||||||
|
.context-menu {
|
||||||
|
-fx-background-color: #fefefe;
|
||||||
|
-fx-text-fill: white;
|
||||||
|
-fx-cursor: hand;
|
||||||
|
}
|
||||||
|
.context-menu .menu-item .label {
|
||||||
|
-fx-text-fill: #2c2c2c;
|
||||||
|
}
|
||||||
|
.context-menu .menu-item:focused .label {
|
||||||
|
-fx-text-fill: #2c2c2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue