remote connection preparations

This commit is contained in:
Mateusz Faderewski 2023-03-05 16:44:45 +01:00
parent 90a79eccb8
commit 33c6e2bbdc
3 changed files with 105 additions and 58 deletions

View File

@ -25,9 +25,13 @@ struct Cli {
#[command(subcommand)] #[command(subcommand)]
command: Commands, command: Commands,
/// Use SC64 device matching provided serial number /// Connect to SC64 device on provided serial port
#[arg(long)] #[arg(short, long, conflicts_with = "remote")]
sn: Option<String>, port: Option<String>,
/// Connect to SC64 device on provided remote address
#[arg(short, long, conflicts_with = "port")]
remote: Option<String>,
} }
#[derive(Subcommand)] #[derive(Subcommand)]
@ -64,6 +68,9 @@ enum Commands {
#[command(subcommand)] #[command(subcommand)]
command: FirmwareCommands, command: FirmwareCommands,
}, },
/// Expose SC64 device over network
Server(ServerArgs),
} }
#[derive(Args)] #[derive(Args)]
@ -170,6 +177,13 @@ struct FirmwareArgs {
firmware: PathBuf, firmware: PathBuf,
} }
#[derive(Args)]
struct ServerArgs {
/// Listen on provided address:port
#[arg(default_value = "127.0.0.1:9064")]
address: String,
}
#[derive(Clone, ValueEnum)] #[derive(Clone, ValueEnum)]
enum SaveType { enum SaveType {
None, None,
@ -224,6 +238,11 @@ impl From<TvType> for sc64::TvType {
} }
} }
enum Connection {
Local(Option<String>),
Remote(String),
}
fn main() { fn main() {
let cli = Cli::parse(); let cli = Cli::parse();
@ -232,7 +251,7 @@ fn main() {
panic::set_hook(Box::new(|_| {})); panic::set_hook(Box::new(|_| {}));
} }
match panic::catch_unwind(|| handle_command(&cli.command, cli.sn)) { match panic::catch_unwind(|| handle_command(&cli.command, cli.port, cli.remote)) {
Ok(_) => {} Ok(_) => {}
Err(payload) => { Err(payload) => {
eprintln!("{}", panic_message(&payload).red()); eprintln!("{}", panic_message(&payload).red());
@ -241,17 +260,23 @@ fn main() {
} }
} }
fn handle_command(command: &Commands, sn: Option<String>) { fn handle_command(command: &Commands, port: Option<String>, remote: Option<String>) {
let connection = if let Some(remote) = remote {
Connection::Remote(remote)
} else {
Connection::Local(port)
};
let result = match command { let result = match command {
Commands::List => handle_list_command(), Commands::List => handle_list_command(),
Commands::Upload(args) => handle_upload_command(sn, args), Commands::Upload(args) => handle_upload_command(connection, args),
Commands::DownloadSave(args) => handle_download_save_command(sn, args), Commands::DownloadSave(args) => handle_download_save_command(connection, args),
Commands::_64DD(args) => handle_64dd_command(sn, args), Commands::_64DD(args) => handle_64dd_command(connection, args),
Commands::Debug(args) => handle_debug_command(sn, args), Commands::Debug(args) => handle_debug_command(connection, args),
Commands::Dump(args) => handle_dump_command(sn, args), Commands::Dump(args) => handle_dump_command(connection, args),
Commands::Info => handle_info_command(sn), Commands::Info => handle_info_command(connection),
Commands::Set { command } => handle_set_command(sn, command), Commands::Set { command } => handle_set_command(connection, command),
Commands::Firmware { command } => handle_firmware_command(sn, command), Commands::Firmware { command } => handle_firmware_command(connection, command),
Commands::Server(args) => handle_server_command(connection, args),
}; };
match result { match result {
Ok(()) => {} Ok(()) => {}
@ -260,18 +285,18 @@ fn handle_command(command: &Commands, sn: Option<String>) {
} }
fn handle_list_command() -> Result<(), sc64::Error> { fn handle_list_command() -> Result<(), sc64::Error> {
let devices = sc64::list_serial_devices()?; let devices = sc64::list_local_devices()?;
println!("{}", "Found devices:".bold()); println!("{}", "Found devices:".bold());
for (i, d) in devices.iter().enumerate() { for (i, d) in devices.iter().enumerate() {
println!(" {i}: {}", d.sn); println!(" {i}: [{}] at port [{}]", d.serial_number, d.port);
} }
Ok(()) Ok(())
} }
fn handle_upload_command(sn: Option<String>, args: &UploadArgs) -> Result<(), sc64::Error> { fn handle_upload_command(connection: Connection, args: &UploadArgs) -> Result<(), sc64::Error> {
let mut sc64 = init_sc64(sn, true)?; let mut sc64 = init_sc64(connection, true)?;
let (rom_file_unbuffered, rom_name, rom_length) = open_file(&args.rom)?; let (rom_file_unbuffered, rom_name, rom_length) = open_file(&args.rom)?;
let mut rom_file = BufReader::new(rom_file_unbuffered); let mut rom_file = BufReader::new(rom_file_unbuffered);
@ -328,10 +353,10 @@ fn handle_upload_command(sn: Option<String>, args: &UploadArgs) -> Result<(), sc
} }
fn handle_download_save_command( fn handle_download_save_command(
sn: Option<String>, connection: Connection,
args: &DownloadSaveArgs, args: &DownloadSaveArgs,
) -> Result<(), sc64::Error> { ) -> Result<(), sc64::Error> {
let mut sc64 = init_sc64(sn, true)?; let mut sc64 = init_sc64(connection, true)?;
let (mut file, name) = create_file(&args.path)?; let (mut file, name) = create_file(&args.path)?;
@ -342,8 +367,8 @@ fn handle_download_save_command(
Ok(()) Ok(())
} }
fn handle_64dd_command(sn: Option<String>, args: &_64DDArgs) -> Result<(), sc64::Error> { fn handle_64dd_command(connection: Connection, args: &_64DDArgs) -> Result<(), sc64::Error> {
let _ = (sn, args); let _ = (connection, args);
// TODO: handle 64DD stuff // TODO: handle 64DD stuff
@ -355,13 +380,13 @@ fn handle_64dd_command(sn: Option<String>, args: &_64DDArgs) -> Result<(), sc64:
Ok(()) Ok(())
} }
fn handle_debug_command(sn: Option<String>, args: &DebugArgs) -> Result<(), sc64::Error> { fn handle_debug_command(connection: Connection, args: &DebugArgs) -> Result<(), sc64::Error> {
let mut debug_handler = debug::new(args.gdb)?; let mut debug_handler = debug::new(args.gdb)?;
if let Some(port) = args.gdb { if let Some(port) = args.gdb {
println!("GDB TCP socket listening at [0.0.0.0:{port}]"); println!("GDB TCP socket listening at [0.0.0.0:{port}]");
} }
let mut sc64 = init_sc64(sn, true)?; let mut sc64 = init_sc64(connection, true)?;
if args.isv.is_some() { if args.isv.is_some() {
sc64.configure_is_viewer_64(args.isv)?; sc64.configure_is_viewer_64(args.isv)?;
@ -403,8 +428,8 @@ fn handle_debug_command(sn: Option<String>, args: &DebugArgs) -> Result<(), sc64
Ok(()) Ok(())
} }
fn handle_dump_command(sn: Option<String>, args: &DumpArgs) -> Result<(), sc64::Error> { fn handle_dump_command(connection: Connection, args: &DumpArgs) -> Result<(), sc64::Error> {
let mut sc64 = init_sc64(sn, true)?; let mut sc64 = init_sc64(connection, true)?;
let (mut dump_file, dump_name) = create_file(&args.path)?; let (mut dump_file, dump_name) = create_file(&args.path)?;
@ -421,8 +446,8 @@ fn handle_dump_command(sn: Option<String>, args: &DumpArgs) -> Result<(), sc64::
Ok(()) Ok(())
} }
fn handle_info_command(sn: Option<String>) -> Result<(), sc64::Error> { fn handle_info_command(connection: Connection) -> Result<(), sc64::Error> {
let mut sc64 = init_sc64(sn, false)?; let mut sc64 = init_sc64(connection, true)?;
let (major, minor) = sc64.check_firmware_version()?; let (major, minor) = sc64.check_firmware_version()?;
let state = sc64.get_device_state()?; let state = sc64.get_device_state()?;
@ -453,8 +478,8 @@ fn handle_info_command(sn: Option<String>) -> Result<(), sc64::Error> {
Ok(()) Ok(())
} }
fn handle_set_command(sn: Option<String>, command: &SetCommands) -> Result<(), sc64::Error> { fn handle_set_command(connection: Connection, command: &SetCommands) -> Result<(), sc64::Error> {
let mut sc64 = init_sc64(sn, true)?; let mut sc64 = init_sc64(connection, true)?;
match command { match command {
SetCommands::Rtc => { SetCommands::Rtc => {
@ -484,7 +509,7 @@ fn handle_set_command(sn: Option<String>, command: &SetCommands) -> Result<(), s
} }
fn handle_firmware_command( fn handle_firmware_command(
sn: Option<String>, connection: Connection,
command: &FirmwareCommands, command: &FirmwareCommands,
) -> Result<(), sc64::Error> { ) -> Result<(), sc64::Error> {
match command { match command {
@ -502,7 +527,7 @@ fn handle_firmware_command(
} }
FirmwareCommands::Backup(args) => { FirmwareCommands::Backup(args) => {
let mut sc64 = init_sc64(sn, false)?; let mut sc64 = init_sc64(connection, false)?;
let (mut backup_file, backup_name) = create_file(&args.firmware)?; let (mut backup_file, backup_name) = create_file(&args.firmware)?;
@ -523,7 +548,7 @@ fn handle_firmware_command(
} }
FirmwareCommands::Update(args) => { FirmwareCommands::Update(args) => {
let mut sc64 = init_sc64(sn, false)?; let mut sc64 = init_sc64(connection, false)?;
let (mut update_file, update_name, update_length) = open_file(&args.firmware)?; let (mut update_file, update_name, update_length) = open_file(&args.firmware)?;
@ -546,8 +571,26 @@ fn handle_firmware_command(
} }
} }
fn init_sc64(sn: Option<String>, check_firmware: bool) -> Result<sc64::SC64, sc64::Error> { fn handle_server_command(connection: Connection, args: &ServerArgs) -> Result<(), sc64::Error> {
let mut sc64 = sc64::new(sn)?; let port = if let Connection::Local(port) = connection {
port
} else {
None
};
let _server = sc64::new_server(port, args.address.clone())?;
let exit = setup_exit_flag();
while !exit.load(Ordering::Relaxed) {}
Ok(())
}
fn init_sc64(connection: Connection, check_firmware: bool) -> Result<sc64::SC64, sc64::Error> {
let mut sc64 = match connection {
Connection::Local(port) => sc64::new_local(port),
Connection::Remote(remote) => sc64::new_remote(remote),
}?;
if check_firmware { if check_firmware {
sc64.check_firmware_version()?; sc64.check_firmware_version()?;

View File

@ -1,9 +1,9 @@
use super::{error::Error, utils}; use super::{error::Error, utils};
use std::{collections::VecDeque, time::Duration}; use std::{collections::VecDeque, time::Duration};
pub struct Device { pub struct LocalDevice {
pub sn: String,
pub port: String, pub port: String,
pub serial_number: String,
} }
pub struct Command { pub struct Command {
@ -184,33 +184,33 @@ impl Link for SerialLink {
} }
} }
pub fn list_serial_devices() -> Result<Vec<Device>, Error> { pub fn list_local_devices() -> Result<Vec<LocalDevice>, Error> {
const SC64_VID: u16 = 0x0403; const SC64_VID: u16 = 0x0403;
const SC64_PID: u16 = 0x6014; const SC64_PID: u16 = 0x6014;
const SC64_SID: &str = "SC64"; const SC64_SID: &str = "SC64";
let mut devices: Vec<Device> = Vec::new(); let mut serial_devices: Vec<LocalDevice> = Vec::new();
for device in serialport::available_ports()?.into_iter() { for device in serialport::available_ports()?.into_iter() {
if let serialport::SerialPortType::UsbPort(info) = device.port_type { if let serialport::SerialPortType::UsbPort(info) = device.port_type {
let sn = info.serial_number.unwrap_or("".to_string()); let serial_number = info.serial_number.unwrap_or("".to_string());
if info.vid == SC64_VID && info.pid == SC64_PID && sn.starts_with(SC64_SID) { if info.vid == SC64_VID && info.pid == SC64_PID && serial_number.starts_with(SC64_SID) {
devices.push(Device { serial_devices.push(LocalDevice {
sn,
port: device.port_name, port: device.port_name,
serial_number,
}); });
} }
} }
} }
if devices.len() == 0 { if serial_devices.len() == 0 {
return Err(Error::new("No SC64 devices found")); return Err(Error::new("No SC64 devices found"));
} }
return Ok(devices); return Ok(serial_devices);
} }
pub fn new_serial(port: &str) -> Result<Box<dyn Link>, Error> { pub fn new_local(port: &str) -> Result<Box<dyn Link>, Error> {
let mut link = SerialLink { let mut link = SerialLink {
serial: serialport::new(port, 115_200).open()?, serial: serialport::new(port, 115_200).open()?,
packets: VecDeque::new(), packets: VecDeque::new(),

View File

@ -7,7 +7,7 @@ mod utils;
pub use self::{ pub use self::{
error::Error, error::Error,
link::list_serial_devices, link::list_local_devices,
types::{ types::{
BootMode, ButtonMode, ButtonState, CicSeed, DataPacket, DdDiskState, DdDriveType, DdMode, BootMode, ButtonMode, ButtonState, CicSeed, DataPacket, DdDiskState, DdDriveType, DdMode,
DebugPacket, DiskPacket, FpgaDebugData, McuStackUsage, SaveType, Switch, TvType, DebugPacket, DiskPacket, FpgaDebugData, McuStackUsage, SaveType, Switch, TvType,
@ -684,21 +684,15 @@ impl SC64 {
} }
} }
pub fn new(sn: Option<String>) -> Result<SC64, Error> { pub fn new_local(port: Option<String>) -> Result<SC64, Error> {
let port = match sn { let port = if let Some(port) = port {
Some(sn) => match list_serial_devices()?.iter().find(|d| d.sn == sn) { port
Some(device) => device.port.clone(), } else {
None => { list_local_devices()?[0].port.clone()
return Err(Error::new(
"No SC64 device found matching provided serial number",
))
}
},
None => list_serial_devices()?[0].port.clone(),
}; };
let mut sc64 = SC64 { let mut sc64 = SC64 {
link: link::new_serial(&port)?, link: link::new_local(&port)?,
}; };
let identifier = sc64 let identifier = sc64
@ -711,3 +705,13 @@ pub fn new(sn: Option<String>) -> Result<SC64, Error> {
Ok(sc64) Ok(sc64)
} }
pub fn new_remote(remote: String) -> Result<SC64, Error> {
let _ = remote;
Err(Error::new("Remote connection not implemented yet"))
}
pub fn new_server(port: Option<String>, bind: String) -> Result<(), Error> {
let _ = (port, bind);
Err(Error::new("SC64 server not implemented yet"))
}