mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-29 08:44:15 +01:00
Debug/server cleanup
This commit is contained in:
parent
d9456bcd14
commit
5d5d743f05
@ -1,6 +1,7 @@
|
|||||||
use crate::sc64;
|
use crate::sc64;
|
||||||
use chrono::Local;
|
use chrono::Local;
|
||||||
use colored::Colorize;
|
use colored::Colorize;
|
||||||
|
use encoding_rs::EUC_JP;
|
||||||
use panic_message::panic_message;
|
use panic_message::panic_message;
|
||||||
use std::{
|
use std::{
|
||||||
fs::File,
|
fs::File,
|
||||||
@ -116,74 +117,99 @@ impl TryFrom<Vec<u8>> for ScreenshotMetadata {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_FILE_LENGTH: u64 = 8 * 1024 * 1024;
|
macro_rules! success {
|
||||||
|
($($a: tt)*) => {
|
||||||
|
println!("{}", format!($($a)*).bright_blue());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! error {
|
||||||
|
($($a: tt)*) => {{
|
||||||
|
println!("{}", format!("Error: {}", format!($($a)*)).bright_red());
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! stop {
|
||||||
|
($r: expr, $($a: tt)*) => {{
|
||||||
|
error!($($a)*);
|
||||||
|
$r
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
const MAX_PACKET_LENGTH: usize = 8 * 1024 * 1024;
|
||||||
|
|
||||||
impl Handler {
|
impl Handler {
|
||||||
pub fn process_user_input(&self) -> Option<sc64::DebugPacket> {
|
pub fn process_user_input(&self) -> Option<sc64::DebugPacket> {
|
||||||
if let Ok(line) = self.line_rx.try_recv() {
|
let line = match self.line_rx.try_recv() {
|
||||||
if line.len() == 0 {
|
Ok(line) => {
|
||||||
return None;
|
if line.len() == 0 {
|
||||||
}
|
|
||||||
let mut data: Vec<u8> = Vec::new();
|
|
||||||
if line.matches("@").count() != 2 {
|
|
||||||
data.append(&mut line.as_bytes().to_vec());
|
|
||||||
data.append(&mut [b'\0'].to_vec());
|
|
||||||
return Some(sc64::DebugPacket {
|
|
||||||
datatype: DataType::Text.into(),
|
|
||||||
data,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
let start = line.find("@").unwrap();
|
|
||||||
let end = line.rfind("@").unwrap();
|
|
||||||
let path = &line[start + 1..end];
|
|
||||||
if path.len() == 0 {
|
|
||||||
println!("Invalid path provided");
|
|
||||||
return None;
|
return None;
|
||||||
}
|
|
||||||
let mut file = match File::open(path) {
|
|
||||||
Ok(file) => file,
|
|
||||||
Err(error) => {
|
|
||||||
println!("Couldn't open file: {error}");
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let length = match file.metadata() {
|
|
||||||
Ok(metadata) => metadata.len(),
|
|
||||||
Err(error) => {
|
|
||||||
println!("Couldn't get file length: {error}");
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if length > MAX_FILE_LENGTH {
|
|
||||||
println!("File too big ({length} bytes), exceeding max size of {MAX_FILE_LENGTH} bytes");
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
let mut data = vec![0u8; length as usize];
|
|
||||||
if let Err(error) = file.read_exact(&mut data) {
|
|
||||||
println!("Couldn't read file contents: {error}");
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
if line.starts_with("@") && line.ends_with("@") {
|
|
||||||
return Some(sc64::DebugPacket {
|
|
||||||
datatype: DataType::RawBinary.into(),
|
|
||||||
data,
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
let mut combined_data: Vec<u8> = Vec::new();
|
line
|
||||||
combined_data.append(&mut line[0..start].as_bytes().to_vec());
|
|
||||||
combined_data.append(&mut [b'@'].to_vec());
|
|
||||||
combined_data.append(&mut format!("{length}").into_bytes());
|
|
||||||
combined_data.append(&mut [b'@'].to_vec());
|
|
||||||
combined_data.append(&mut data);
|
|
||||||
combined_data.append(&mut [b'\0'].to_vec());
|
|
||||||
return Some(sc64::DebugPacket {
|
|
||||||
datatype: DataType::Text.into(),
|
|
||||||
data: combined_data,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(_) => return None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let token_count = line.matches("@").count();
|
||||||
|
|
||||||
|
if (token_count % 2) != 0 {
|
||||||
|
return stop!(None, "Missing closing '@' token");
|
||||||
}
|
}
|
||||||
None
|
|
||||||
|
let packet = if token_count == 2 && line.starts_with("@") && line.ends_with("@") {
|
||||||
|
sc64::DebugPacket {
|
||||||
|
datatype: DataType::RawBinary.into(),
|
||||||
|
data: match load_file(line.trim_matches('@')) {
|
||||||
|
Ok(data) => data,
|
||||||
|
Err(error) => return stop!(None, "{error}"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let mut is_text = true;
|
||||||
|
let mut path = String::new();
|
||||||
|
let mut character_buffer = vec![0u8; 4];
|
||||||
|
let mut data = vec![0u8; 0];
|
||||||
|
for character in line.chars() {
|
||||||
|
if character == '@' {
|
||||||
|
if is_text {
|
||||||
|
is_text = false;
|
||||||
|
} else {
|
||||||
|
let mut file = match load_file(&path) {
|
||||||
|
Ok(data) => data,
|
||||||
|
Err(error) => return stop!(None, "{error}"),
|
||||||
|
};
|
||||||
|
let length = file.len();
|
||||||
|
data.append(&mut format!("@{length}@").into_bytes());
|
||||||
|
data.append(&mut file);
|
||||||
|
is_text = true;
|
||||||
|
path = String::new();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if is_text {
|
||||||
|
let encoded = character.encode_utf8(&mut character_buffer);
|
||||||
|
data.append(&mut encoded.as_bytes().to_vec());
|
||||||
|
} else {
|
||||||
|
path.push(character);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sc64::DebugPacket {
|
||||||
|
datatype: DataType::Text.into(),
|
||||||
|
data,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if packet.data.len() > MAX_PACKET_LENGTH {
|
||||||
|
return stop!(
|
||||||
|
None,
|
||||||
|
"Debug packet size too big ({}), exceeding maximum size of {}",
|
||||||
|
packet.data.len(),
|
||||||
|
MAX_PACKET_LENGTH
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_debug_packet(&mut self, debug_packet: sc64::DebugPacket) {
|
pub fn handle_debug_packet(&mut self, debug_packet: sc64::DebugPacket) {
|
||||||
@ -194,9 +220,53 @@ impl Handler {
|
|||||||
DataType::Header => self.handle_datatype_header(&data),
|
DataType::Header => self.handle_datatype_header(&data),
|
||||||
DataType::Screenshot => self.handle_datatype_screenshot(&data),
|
DataType::Screenshot => self.handle_datatype_screenshot(&data),
|
||||||
DataType::GDB => self.handle_datatype_gdb(&data),
|
DataType::GDB => self.handle_datatype_gdb(&data),
|
||||||
_ => {
|
_ => error!("Received unknown debug packet datatype: 0x{datatype:02X}"),
|
||||||
println!("Unknown debug packet datatype: 0x{datatype:02X}");
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_is_viewer_64(&self, message: Vec<u8>) {
|
||||||
|
print!("{}", EUC_JP.decode(&message).0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn handle_save_writeback(
|
||||||
|
&self,
|
||||||
|
save_writeback: sc64::SaveWriteback,
|
||||||
|
path: &Option<PathBuf>,
|
||||||
|
) {
|
||||||
|
let filename = &if let Some(path) = path {
|
||||||
|
path.to_string_lossy().to_string()
|
||||||
|
} else {
|
||||||
|
generate_filename(
|
||||||
|
"save",
|
||||||
|
match save_writeback.save {
|
||||||
|
sc64::SaveType::Eeprom4k | sc64::SaveType::Eeprom16k => "eep",
|
||||||
|
sc64::SaveType::Sram | sc64::SaveType::SramBanked | sc64::SaveType::Sram1m => {
|
||||||
|
"srm"
|
||||||
|
}
|
||||||
|
sc64::SaveType::Flashram => "fla",
|
||||||
|
_ => "sav",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
};
|
||||||
|
match File::create(filename) {
|
||||||
|
Ok(mut file) => {
|
||||||
|
if let Err(error) = file.write_all(&save_writeback.data) {
|
||||||
|
error!("Couldn't write save [{filename}]: {error}");
|
||||||
|
}
|
||||||
|
success!("Wrote [{}] save to [{filename}]", save_writeback.save);
|
||||||
}
|
}
|
||||||
|
Err(error) => error!("Couldn't create save writeback file [{filename}]: {error}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn receive_gdb_packet(&self) -> Option<sc64::DebugPacket> {
|
||||||
|
if let Some(data) = self.gdb_rx.try_recv().ok() {
|
||||||
|
Some(sc64::DebugPacket {
|
||||||
|
datatype: DataType::GDB.into(),
|
||||||
|
data,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,17 +275,15 @@ impl Handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn handle_datatype_raw_binary(&self, data: &[u8]) {
|
fn handle_datatype_raw_binary(&self, data: &[u8]) {
|
||||||
let filename = &self.generate_filename("binaryout", "bin");
|
let filename = &generate_filename("binaryout", "bin");
|
||||||
match File::create(filename) {
|
match File::create(filename) {
|
||||||
Ok(mut file) => {
|
Ok(mut file) => {
|
||||||
if let Err(error) = file.write_all(data) {
|
if let Err(error) = file.write_all(data) {
|
||||||
println!("Error during raw binary write: {error}");
|
error!("Couldn't write raw binary [{filename}]: {error}");
|
||||||
}
|
}
|
||||||
println!("Wrote [{}] bytes to [{}]", data.len(), filename);
|
success!("Wrote [{}] bytes to [{filename}]", data.len());
|
||||||
}
|
|
||||||
Err(error) => {
|
|
||||||
println!("Error during raw binary file creation: {error}");
|
|
||||||
}
|
}
|
||||||
|
Err(error) => error!("Couldn't create raw binary file [{filename}]: {error}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -226,10 +294,7 @@ impl Handler {
|
|||||||
fn handle_datatype_screenshot(&mut self, data: &[u8]) {
|
fn handle_datatype_screenshot(&mut self, data: &[u8]) {
|
||||||
let header = match self.header.take() {
|
let header = match self.header.take() {
|
||||||
Some(header) => header,
|
Some(header) => header,
|
||||||
None => {
|
None => return error!("Got screenshot packet without header data"),
|
||||||
println!("Got screenshot packet without header data");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let ScreenshotMetadata {
|
let ScreenshotMetadata {
|
||||||
format,
|
format,
|
||||||
@ -237,15 +302,11 @@ impl Handler {
|
|||||||
width,
|
width,
|
||||||
} = match header.try_into() {
|
} = match header.try_into() {
|
||||||
Ok(data) => data,
|
Ok(data) => data,
|
||||||
Err(error) => {
|
Err(error) => return error!("{error}"),
|
||||||
println!("{error}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let format_size: u32 = format.into();
|
let format_size: u32 = format.into();
|
||||||
if data.len() as u32 != format_size * width * height {
|
if data.len() as u32 != format_size * width * height {
|
||||||
println!("Data length did not match header data for screenshot datatype");
|
return error!("Data length did not match header data for screenshot datatype");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
let mut image = image::RgbaImage::new(width, height);
|
let mut image = image::RgbaImage::new(width, height);
|
||||||
for (x, y, pixel) in image.enumerate_pixels_mut() {
|
for (x, y, pixel) in image.enumerate_pixels_mut() {
|
||||||
@ -262,68 +323,45 @@ impl Handler {
|
|||||||
ScreenshotPixelFormat::Rgba32 => [p[0], p[1], p[2], p[3]],
|
ScreenshotPixelFormat::Rgba32 => [p[0], p[1], p[2], p[3]],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let filename = &self.generate_filename("screenshot", "png");
|
let filename = &generate_filename("screenshot", "png");
|
||||||
if let Some(error) = image.save(filename).err() {
|
if let Some(error) = image.save(filename).err() {
|
||||||
println!("Error during image save: {error}");
|
return error!("Couldn't save screenshot [{filename}]: {error}");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
println!("Wrote {width}x{height} pixels to [{filename}]");
|
success!("Wrote {width}x{height} pixels to [{filename}]");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_datatype_gdb(&self, data: &[u8]) {
|
fn handle_datatype_gdb(&self, data: &[u8]) {
|
||||||
self.gdb_tx.send(data.to_vec()).ok();
|
self.gdb_tx.send(data.to_vec()).ok();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn handle_save_writeback(
|
fn load_file(path: &str) -> Result<Vec<u8>, String> {
|
||||||
&self,
|
if path.len() == 0 {
|
||||||
save_writeback: sc64::SaveWriteback,
|
return Err(format!("Couldn't open file: Specified path is empty"));
|
||||||
path: &Option<PathBuf>,
|
|
||||||
) {
|
|
||||||
let filename = &if let Some(path) = path {
|
|
||||||
path.to_string_lossy().to_string()
|
|
||||||
} else {
|
|
||||||
self.generate_filename(
|
|
||||||
"save",
|
|
||||||
match save_writeback.save {
|
|
||||||
sc64::SaveType::Eeprom4k | sc64::SaveType::Eeprom16k => "eep",
|
|
||||||
sc64::SaveType::Sram | sc64::SaveType::SramBanked | sc64::SaveType::Sram1m => {
|
|
||||||
"srm"
|
|
||||||
}
|
|
||||||
sc64::SaveType::Flashram => "fla",
|
|
||||||
_ => "sav",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
};
|
|
||||||
match File::create(filename) {
|
|
||||||
Ok(mut file) => {
|
|
||||||
if let Err(error) = file.write_all(&save_writeback.data) {
|
|
||||||
println!("Error during save write: {error}");
|
|
||||||
}
|
|
||||||
println!("Wrote [{}] save to [{}]", save_writeback.save, filename);
|
|
||||||
}
|
|
||||||
Err(error) => {
|
|
||||||
println!("Error during save writeback file creation: {error}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
let mut file = match File::open(path) {
|
||||||
|
Ok(file) => file,
|
||||||
|
Err(error) => return Err(format!("Couldn't open file [{path}]: {error}")),
|
||||||
|
};
|
||||||
|
let length = match file.metadata() {
|
||||||
|
Ok(metadata) => metadata.len(),
|
||||||
|
Err(error) => return Err(format!("Couldn't get file [{path}] length: {error}")),
|
||||||
|
};
|
||||||
|
if length > MAX_PACKET_LENGTH as u64 {
|
||||||
|
return Err(format!("File [{path}] size too big"));
|
||||||
|
}
|
||||||
|
let mut data = vec![0u8; length as usize];
|
||||||
|
match file.read_exact(&mut data) {
|
||||||
|
Ok(()) => Ok(data),
|
||||||
|
Err(error) => Err(format!("Couldn't read file [{path}] contents: {error}")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn generate_filename(&self, prefix: &str, extension: &str) -> String {
|
fn generate_filename(prefix: &str, extension: &str) -> String {
|
||||||
format!(
|
format!(
|
||||||
"{prefix}-{}.{extension}",
|
"{prefix}-{}.{extension}",
|
||||||
Local::now().format("%y%m%d%H%M%S.%f")
|
Local::now().format("%y%m%d%H%M%S.%f")
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
pub fn receive_gdb_packet(&self) -> Option<sc64::DebugPacket> {
|
|
||||||
if let Some(data) = self.gdb_rx.try_recv().ok() {
|
|
||||||
Some(sc64::DebugPacket {
|
|
||||||
datatype: DataType::GDB.into(),
|
|
||||||
data,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new(gdb_port: Option<u16>) -> Result<Handler, sc64::Error> {
|
pub fn new(gdb_port: Option<u16>) -> Result<Handler, sc64::Error> {
|
||||||
|
@ -504,22 +504,22 @@ fn handle_64dd_command(connection: Connection, args: &_64DDArgs) -> Result<(), s
|
|||||||
while !exit.load(Ordering::Relaxed) {
|
while !exit.load(Ordering::Relaxed) {
|
||||||
if let Some(data_packet) = sc64.receive_data_packet()? {
|
if let Some(data_packet) = sc64.receive_data_packet()? {
|
||||||
match data_packet {
|
match data_packet {
|
||||||
sc64::DataPacket::Disk(mut packet) => {
|
sc64::DataPacket::DiskRequest(mut disk_packet) => {
|
||||||
let track = packet.info.track;
|
let track = disk_packet.info.track;
|
||||||
let head = packet.info.head;
|
let head = disk_packet.info.head;
|
||||||
let block = packet.info.block;
|
let block = disk_packet.info.block;
|
||||||
if let Some(ref mut disk) = selected_disk {
|
if let Some(ref mut disk) = selected_disk {
|
||||||
let (reply_packet, rw) = match packet.kind {
|
let (reply_packet, rw) = match disk_packet.kind {
|
||||||
sc64::DiskPacketKind::Read => (
|
sc64::DiskPacketKind::Read => (
|
||||||
disk.read_block(track, head, block)?.map(|data| {
|
disk.read_block(track, head, block)?.map(|data| {
|
||||||
packet.info.set_data(&data);
|
disk_packet.info.set_data(&data);
|
||||||
packet
|
disk_packet
|
||||||
}),
|
}),
|
||||||
"[R]".bright_blue(),
|
"[R]".bright_blue(),
|
||||||
),
|
),
|
||||||
sc64::DiskPacketKind::Write => (
|
sc64::DiskPacketKind::Write => (
|
||||||
disk.write_block(track, head, block, &packet.info.data)?
|
disk.write_block(track, head, block, &disk_packet.info.data)?
|
||||||
.map(|_| packet),
|
.map(|_| disk_packet),
|
||||||
"[W]".bright_yellow(),
|
"[W]".bright_yellow(),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
@ -595,11 +595,11 @@ fn handle_debug_command(connection: Connection, args: &DebugArgs) -> Result<(),
|
|||||||
while !exit.load(Ordering::Relaxed) {
|
while !exit.load(Ordering::Relaxed) {
|
||||||
if let Some(data_packet) = sc64.receive_data_packet()? {
|
if let Some(data_packet) = sc64.receive_data_packet()? {
|
||||||
match data_packet {
|
match data_packet {
|
||||||
sc64::DataPacket::IsViewer64(message) => {
|
sc64::DataPacket::DebugData(debug_packet) => {
|
||||||
print!("{message}")
|
debug_handler.handle_debug_packet(debug_packet);
|
||||||
}
|
}
|
||||||
sc64::DataPacket::Debug(debug_packet) => {
|
sc64::DataPacket::IsViewer64(message) => {
|
||||||
debug_handler.handle_debug_packet(debug_packet)
|
debug_handler.handle_is_viewer_64(message);
|
||||||
}
|
}
|
||||||
sc64::DataPacket::SaveWriteback(save_writeback) => {
|
sc64::DataPacket::SaveWriteback(save_writeback) => {
|
||||||
debug_handler.handle_save_writeback(save_writeback, &args.save);
|
debug_handler.handle_save_writeback(save_writeback, &args.save);
|
||||||
|
@ -39,10 +39,10 @@ impl TryFrom<u32> for DataType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Command<'a> {
|
pub struct Command {
|
||||||
pub id: u8,
|
pub id: u8,
|
||||||
pub args: [u32; 2],
|
pub args: [u32; 2],
|
||||||
pub data: &'a [u8],
|
pub data: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Response {
|
pub struct Response {
|
||||||
|
@ -103,7 +103,7 @@ impl SC64 {
|
|||||||
let data = self.link.execute_command(&Command {
|
let data = self.link.execute_command(&Command {
|
||||||
id: b'v',
|
id: b'v',
|
||||||
args: [0, 0],
|
args: [0, 0],
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
if data.len() != 4 {
|
if data.len() != 4 {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
@ -117,7 +117,7 @@ impl SC64 {
|
|||||||
let data = self.link.execute_command(&Command {
|
let data = self.link.execute_command(&Command {
|
||||||
id: b'V',
|
id: b'V',
|
||||||
args: [0, 0],
|
args: [0, 0],
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
if data.len() != 8 {
|
if data.len() != 8 {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
@ -134,7 +134,7 @@ impl SC64 {
|
|||||||
self.link.execute_command(&Command {
|
self.link.execute_command(&Command {
|
||||||
id: b'R',
|
id: b'R',
|
||||||
args: [0, 0],
|
args: [0, 0],
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -152,7 +152,7 @@ impl SC64 {
|
|||||||
self.link.execute_command(&Command {
|
self.link.execute_command(&Command {
|
||||||
id: b'B',
|
id: b'B',
|
||||||
args,
|
args,
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -161,7 +161,7 @@ impl SC64 {
|
|||||||
let data = self.link.execute_command(&Command {
|
let data = self.link.execute_command(&Command {
|
||||||
id: b'c',
|
id: b'c',
|
||||||
args: [config_id.into(), 0],
|
args: [config_id.into(), 0],
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
if data.len() != 4 {
|
if data.len() != 4 {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
@ -176,7 +176,7 @@ impl SC64 {
|
|||||||
self.link.execute_command(&Command {
|
self.link.execute_command(&Command {
|
||||||
id: b'C',
|
id: b'C',
|
||||||
args: config.into(),
|
args: config.into(),
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -185,7 +185,7 @@ impl SC64 {
|
|||||||
let data = self.link.execute_command(&Command {
|
let data = self.link.execute_command(&Command {
|
||||||
id: b'a',
|
id: b'a',
|
||||||
args: [setting_id.into(), 0],
|
args: [setting_id.into(), 0],
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
if data.len() != 4 {
|
if data.len() != 4 {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
@ -200,7 +200,7 @@ impl SC64 {
|
|||||||
self.link.execute_command(&Command {
|
self.link.execute_command(&Command {
|
||||||
id: b'A',
|
id: b'A',
|
||||||
args: setting.into(),
|
args: setting.into(),
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -209,7 +209,7 @@ impl SC64 {
|
|||||||
let data = self.link.execute_command(&Command {
|
let data = self.link.execute_command(&Command {
|
||||||
id: b't',
|
id: b't',
|
||||||
args: [0, 0],
|
args: [0, 0],
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
if data.len() != 8 {
|
if data.len() != 8 {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
@ -223,7 +223,7 @@ impl SC64 {
|
|||||||
self.link.execute_command(&Command {
|
self.link.execute_command(&Command {
|
||||||
id: b'T',
|
id: b'T',
|
||||||
args: convert_from_datetime(datetime),
|
args: convert_from_datetime(datetime),
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -232,7 +232,7 @@ impl SC64 {
|
|||||||
let data = self.link.execute_command(&Command {
|
let data = self.link.execute_command(&Command {
|
||||||
id: b'm',
|
id: b'm',
|
||||||
args: [address, length as u32],
|
args: [address, length as u32],
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
if data.len() != length {
|
if data.len() != length {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
@ -246,7 +246,7 @@ impl SC64 {
|
|||||||
self.link.execute_command(&Command {
|
self.link.execute_command(&Command {
|
||||||
id: b'M',
|
id: b'M',
|
||||||
args: [address, data.len() as u32],
|
args: [address, data.len() as u32],
|
||||||
data,
|
data: data.to_vec(),
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -256,7 +256,7 @@ impl SC64 {
|
|||||||
&Command {
|
&Command {
|
||||||
id: b'U',
|
id: b'U',
|
||||||
args: [datatype as u32, data.len() as u32],
|
args: [datatype as u32, data.len() as u32],
|
||||||
data,
|
data: data.to_vec(),
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
false,
|
false,
|
||||||
@ -268,7 +268,7 @@ impl SC64 {
|
|||||||
self.link.execute_command(&Command {
|
self.link.execute_command(&Command {
|
||||||
id: b'D',
|
id: b'D',
|
||||||
args: [error as u32, 0],
|
args: [error as u32, 0],
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -277,7 +277,7 @@ impl SC64 {
|
|||||||
self.link.execute_command(&Command {
|
self.link.execute_command(&Command {
|
||||||
id: b'W',
|
id: b'W',
|
||||||
args: [0, 0],
|
args: [0, 0],
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -286,7 +286,7 @@ impl SC64 {
|
|||||||
let data = self.link.execute_command(&Command {
|
let data = self.link.execute_command(&Command {
|
||||||
id: b'p',
|
id: b'p',
|
||||||
args: [wait as u32, 0],
|
args: [wait as u32, 0],
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
if data.len() != 4 {
|
if data.len() != 4 {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
@ -301,7 +301,7 @@ impl SC64 {
|
|||||||
self.link.execute_command(&Command {
|
self.link.execute_command(&Command {
|
||||||
id: b'P',
|
id: b'P',
|
||||||
args: [address, 0],
|
args: [address, 0],
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -311,7 +311,7 @@ impl SC64 {
|
|||||||
&Command {
|
&Command {
|
||||||
id: b'f',
|
id: b'f',
|
||||||
args: [address, 0],
|
args: [address, 0],
|
||||||
data: &[],
|
data: vec![],
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
@ -335,7 +335,7 @@ impl SC64 {
|
|||||||
&Command {
|
&Command {
|
||||||
id: b'F',
|
id: b'F',
|
||||||
args: [address, length as u32],
|
args: [address, length as u32],
|
||||||
data: &[],
|
data: vec![],
|
||||||
},
|
},
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
@ -352,7 +352,7 @@ impl SC64 {
|
|||||||
let data = self.link.execute_command(&Command {
|
let data = self.link.execute_command(&Command {
|
||||||
id: b'?',
|
id: b'?',
|
||||||
args: [0, 0],
|
args: [0, 0],
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
Ok(data.try_into()?)
|
Ok(data.try_into()?)
|
||||||
}
|
}
|
||||||
@ -361,7 +361,7 @@ impl SC64 {
|
|||||||
let data = self.link.execute_command(&Command {
|
let data = self.link.execute_command(&Command {
|
||||||
id: b'%',
|
id: b'%',
|
||||||
args: [0, 0],
|
args: [0, 0],
|
||||||
data: &[],
|
data: vec![],
|
||||||
})?;
|
})?;
|
||||||
Ok(data.try_into()?)
|
Ok(data.try_into()?)
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ pub fn run_server(
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum Event {
|
enum Event {
|
||||||
Command((u8, [u32; 2], Vec<u8>)),
|
Command(Command),
|
||||||
Response(Response),
|
Response(Response),
|
||||||
Packet(Packet),
|
Packet(Packet),
|
||||||
KeepAlive,
|
KeepAlive,
|
||||||
@ -114,12 +114,8 @@ fn server_process_events(
|
|||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
for event in event_receiver.into_iter() {
|
for event in event_receiver.into_iter() {
|
||||||
match event {
|
match event {
|
||||||
Event::Command((id, args, data)) => {
|
Event::Command(command) => {
|
||||||
serial_writer.send_command(&Command {
|
serial_writer.send_command(&command)?;
|
||||||
id,
|
|
||||||
args,
|
|
||||||
data: &data,
|
|
||||||
})?;
|
|
||||||
}
|
}
|
||||||
Event::Response(response) => {
|
Event::Response(response) => {
|
||||||
stream_writer.write_all(&u32::to_be_bytes(DataType::Response.into()))?;
|
stream_writer.write_all(&u32::to_be_bytes(DataType::Response.into()))?;
|
||||||
@ -188,10 +184,12 @@ fn server_stream_thread(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut buffer = [0u8; 4];
|
let mut buffer = [0u8; 4];
|
||||||
let mut id = [0u8; 1];
|
let mut id_buffer = [0u8; 1];
|
||||||
let mut args = [0u32; 2];
|
let mut args = [0u32; 2];
|
||||||
|
|
||||||
stream_reader.read_exact(&mut id)?;
|
stream_reader.read_exact(&mut id_buffer)?;
|
||||||
|
let id = id_buffer[0];
|
||||||
|
|
||||||
stream_reader.read_exact(&mut buffer)?;
|
stream_reader.read_exact(&mut buffer)?;
|
||||||
args[0] = u32::from_be_bytes(buffer);
|
args[0] = u32::from_be_bytes(buffer);
|
||||||
stream_reader.read_exact(&mut buffer)?;
|
stream_reader.read_exact(&mut buffer)?;
|
||||||
@ -202,8 +200,10 @@ fn server_stream_thread(
|
|||||||
let mut data = vec![0u8; command_data_length];
|
let mut data = vec![0u8; command_data_length];
|
||||||
stream_reader.read_exact(&mut data)?;
|
stream_reader.read_exact(&mut data)?;
|
||||||
|
|
||||||
let event = Event::Command((id[0], args, data));
|
if event_sender
|
||||||
if event_sender.send(event).is_err() {
|
.send(Event::Command(Command { id, args, data }))
|
||||||
|
.is_err()
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -222,15 +222,13 @@ fn server_serial_thread(
|
|||||||
let response = serial_reader.process_incoming_data(DataType::Packet, &mut packets)?;
|
let response = serial_reader.process_incoming_data(DataType::Packet, &mut packets)?;
|
||||||
|
|
||||||
if let Some(response) = response {
|
if let Some(response) = response {
|
||||||
let event = Event::Response(response);
|
if event_sender.send(Event::Response(response)).is_err() {
|
||||||
if event_sender.send(event).is_err() {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(packet) = packets.pop_front() {
|
if let Some(packet) = packets.pop_front() {
|
||||||
let event = Event::Packet(packet);
|
if event_sender.send(Event::Packet(packet)).is_err() {
|
||||||
if event_sender.send(event).is_err() {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -245,8 +243,7 @@ fn server_keepalive_thread(event_sender: Sender<Event>, exit_flag: Arc<AtomicBoo
|
|||||||
while !exit_flag.load(Ordering::Relaxed) {
|
while !exit_flag.load(Ordering::Relaxed) {
|
||||||
if keepalive.elapsed() >= Duration::from_secs(5) {
|
if keepalive.elapsed() >= Duration::from_secs(5) {
|
||||||
keepalive = Instant::now();
|
keepalive = Instant::now();
|
||||||
let event = Event::KeepAlive;
|
if event_sender.send(Event::KeepAlive).is_err() {
|
||||||
if event_sender.send(event).is_err() {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use super::{link::Packet, Error};
|
use super::{link::Packet, Error};
|
||||||
use encoding_rs::EUC_JP;
|
|
||||||
use std::fmt::Display;
|
use std::fmt::Display;
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
@ -581,9 +580,9 @@ impl From<Setting> for [u32; 2] {
|
|||||||
|
|
||||||
pub enum DataPacket {
|
pub enum DataPacket {
|
||||||
Button,
|
Button,
|
||||||
Debug(DebugPacket),
|
DebugData(DebugPacket),
|
||||||
Disk(DiskPacket),
|
DiskRequest(DiskPacket),
|
||||||
IsViewer64(String),
|
IsViewer64(Vec<u8>),
|
||||||
SaveWriteback(SaveWriteback),
|
SaveWriteback(SaveWriteback),
|
||||||
UpdateStatus(UpdateStatus),
|
UpdateStatus(UpdateStatus),
|
||||||
}
|
}
|
||||||
@ -593,9 +592,9 @@ impl TryFrom<Packet> for DataPacket {
|
|||||||
fn try_from(value: Packet) -> Result<Self, Self::Error> {
|
fn try_from(value: Packet) -> Result<Self, Self::Error> {
|
||||||
Ok(match value.id {
|
Ok(match value.id {
|
||||||
b'B' => Self::Button,
|
b'B' => Self::Button,
|
||||||
b'U' => Self::Debug(value.data.try_into()?),
|
b'U' => Self::DebugData(value.data.try_into()?),
|
||||||
b'D' => Self::Disk(value.data.try_into()?),
|
b'D' => Self::DiskRequest(value.data.try_into()?),
|
||||||
b'I' => Self::IsViewer64(EUC_JP.decode(&value.data).0.into()),
|
b'I' => Self::IsViewer64(value.data),
|
||||||
b'S' => Self::SaveWriteback(value.data.try_into()?),
|
b'S' => Self::SaveWriteback(value.data.try_into()?),
|
||||||
b'F' => {
|
b'F' => {
|
||||||
if value.data.len() != 4 {
|
if value.data.len() != 4 {
|
||||||
|
Loading…
Reference in New Issue
Block a user