mirror of
https://github.com/Polprzewodnikowy/SummerCart64.git
synced 2024-11-22 14:09:16 +01:00
server performance increased
This commit is contained in:
parent
2e011bcad6
commit
b942d33ec6
119
sw/deployer/Cargo.lock
generated
119
sw/deployer/Cargo.lock
generated
@ -9,7 +9,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "d0e9889e6db118d49d88d84728d0e964d973a5680befb5f85f55141beea5c20b"
|
checksum = "d0e9889e6db118d49d88d84728d0e964d973a5680befb5f85f55141beea5c20b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"mach",
|
"mach 0.1.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -20,7 +20,7 @@ checksum = "99696c398cbaf669d2368076bdb3d627fb0ce51a26899d7c61228c5c0af3bf4a"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"CoreFoundation-sys",
|
"CoreFoundation-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"mach",
|
"mach 0.1.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -125,9 +125,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "chrono"
|
name = "chrono"
|
||||||
version = "0.4.23"
|
version = "0.4.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
|
checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"iana-time-zone",
|
"iana-time-zone",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@ -281,7 +281,7 @@ version = "3.2.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bbcf33c2a618cbe41ee43ae6e9f2e48368cd9f9db2896f10167d8d762679f639"
|
checksum = "bbcf33c2a618cbe41ee43ae6e9f2e48368cd9f9db2896f10167d8d762679f639"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"nix",
|
"nix 0.26.2",
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -373,17 +373,17 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "exr"
|
name = "exr"
|
||||||
version = "1.5.3"
|
version = "1.6.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e8af5ef47e2ed89d23d0ecbc1b681b30390069de70260937877514377fc24feb"
|
checksum = "bdd2162b720141a91a054640662d3edce3d50a944a50ffca5313cd951abb35b4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit_field",
|
"bit_field",
|
||||||
"flume",
|
"flume",
|
||||||
"half",
|
"half",
|
||||||
"lebe",
|
"lebe",
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
|
"rayon-core",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"threadpool",
|
|
||||||
"zune-inflate",
|
"zune-inflate",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -412,15 +412,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608"
|
checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.26"
|
version = "0.3.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364"
|
checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getrandom"
|
name = "getrandom"
|
||||||
@ -718,10 +718,10 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mach2"
|
name = "mach"
|
||||||
version = "0.4.1"
|
version = "0.3.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8"
|
checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
@ -765,6 +765,17 @@ dependencies = [
|
|||||||
"getrandom",
|
"getrandom",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nix"
|
||||||
|
version = "0.24.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nix"
|
name = "nix"
|
||||||
version = "0.26.2"
|
version = "0.26.2"
|
||||||
@ -915,18 +926,18 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.51"
|
version = "1.0.52"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
|
checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.23"
|
version = "1.0.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
|
checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@ -1017,6 +1028,7 @@ dependencies = [
|
|||||||
"md5",
|
"md5",
|
||||||
"panic-message",
|
"panic-message",
|
||||||
"rust-ini",
|
"rust-ini",
|
||||||
|
"serial2",
|
||||||
"serialport",
|
"serialport",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -1038,27 +1050,39 @@ version = "1.0.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
|
checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serial2"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fa2370e12745a20d3dcd07438fc72f399c74f59537a35863a1a7a9ff2482040"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serialport"
|
name = "serialport"
|
||||||
version = "4.2.1-alpha.0"
|
version = "4.2.0"
|
||||||
source = "git+https://github.com/serialport/serialport-rs?branch=main#e1f46eef5af7df2430f0a595681243e46f721b2a"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "aab92efb5cf60ad310548bc3f16fa6b0d950019cb7ed8ff41968c3d03721cf12"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"CoreFoundation-sys",
|
"CoreFoundation-sys",
|
||||||
"IOKit-sys",
|
"IOKit-sys",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libudev",
|
"libudev",
|
||||||
"mach2",
|
"mach 0.3.2",
|
||||||
"nix",
|
"nix 0.24.3",
|
||||||
"regex",
|
"regex",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "simd-adler32"
|
name = "simd-adler32"
|
||||||
version = "0.3.4"
|
version = "0.3.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "14a5df39617d7c8558154693a1bb8157a4aab8179209540cc0b10e5dc24e0b18"
|
checksum = "238abfbb77c1915110ad968465608b68e869e0772622c9656714e73e5a1a522f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
@ -1068,9 +1092,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
version = "0.9.5"
|
version = "0.9.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7dccf47db1b41fa1573ed27ccf5e08e3ca771cb994f776668c5ebda893b248fc"
|
checksum = "b5d6e0250b93c8427a177b849d144a96d5acc57006149479403d7861ab721e34"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"lock_api",
|
"lock_api",
|
||||||
]
|
]
|
||||||
@ -1107,15 +1131,6 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "threadpool"
|
|
||||||
version = "1.8.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
|
|
||||||
dependencies = [
|
|
||||||
"num_cpus",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tiff"
|
name = "tiff"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
@ -1270,9 +1285,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
|
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm",
|
"windows_aarch64_gnullvm",
|
||||||
"windows_aarch64_msvc",
|
"windows_aarch64_msvc",
|
||||||
@ -1285,45 +1300,45 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
|
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
|
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
|
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
|
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
|
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
|
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.42.1"
|
version = "0.42.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
|
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zune-inflate"
|
name = "zune-inflate"
|
||||||
|
@ -20,7 +20,8 @@ include-flate = { version = "0.2.0", features = ["stable"] }
|
|||||||
md5 = "0.7.0"
|
md5 = "0.7.0"
|
||||||
panic-message = "0.3.0"
|
panic-message = "0.3.0"
|
||||||
rust-ini = "0.18.0"
|
rust-ini = "0.18.0"
|
||||||
serialport = { git = "https://github.com/serialport/serialport-rs", branch = "main" }
|
serial2 = "0.1.7"
|
||||||
|
serialport = "4.2.0"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
@ -16,8 +16,7 @@ use std::{
|
|||||||
atomic::{AtomicBool, Ordering},
|
atomic::{AtomicBool, Ordering},
|
||||||
Arc,
|
Arc,
|
||||||
},
|
},
|
||||||
time::Duration,
|
{panic, process},
|
||||||
{panic, process, thread},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
@ -483,11 +482,14 @@ fn handle_64dd_command(connection: Connection, args: &_64DDArgs) -> Result<(), s
|
|||||||
disk::Format::Development => sc64::DdDriveType::Development,
|
disk::Format::Development => sc64::DdDriveType::Development,
|
||||||
};
|
};
|
||||||
|
|
||||||
sc64.configure_64dd(sc64::DdMode::Full, drive_type)?;
|
let dd_mode = sc64::DdMode::Full;
|
||||||
|
println!("64DD mode set to [{dd_mode} / {drive_type}]");
|
||||||
|
sc64.configure_64dd(dd_mode, drive_type)?;
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"{}",
|
"{}: {}",
|
||||||
"Press button on the SC64 device to cycle through provided disks".bold()
|
"[64DD]".bold(),
|
||||||
|
"Press button on the SC64 device to cycle through provided disks".bright_purple()
|
||||||
);
|
);
|
||||||
|
|
||||||
let exit = setup_exit_flag();
|
let exit = setup_exit_flag();
|
||||||
@ -499,30 +501,30 @@ fn handle_64dd_command(connection: Connection, args: &_64DDArgs) -> Result<(), s
|
|||||||
let head = packet.info.head;
|
let head = packet.info.head;
|
||||||
let block = packet.info.block;
|
let block = packet.info.block;
|
||||||
if let Some(ref mut disk) = selected_disk {
|
if let Some(ref mut disk) = selected_disk {
|
||||||
let reply_packet = match packet.kind {
|
let (reply_packet, rw) = match packet.kind {
|
||||||
sc64::DiskPacketKind::Read => {
|
sc64::DiskPacketKind::Read => (
|
||||||
print!("{}", "[R]".cyan());
|
|
||||||
disk.read_block(track, head, block)?.map(|data| {
|
disk.read_block(track, head, block)?.map(|data| {
|
||||||
packet.info.set_data(&data);
|
packet.info.set_data(&data);
|
||||||
packet
|
packet
|
||||||
})
|
}),
|
||||||
}
|
"[R]".cyan(),
|
||||||
sc64::DiskPacketKind::Write => {
|
),
|
||||||
print!("{}", "[W]".yellow());
|
sc64::DiskPacketKind::Write => (
|
||||||
let data = &packet.info.data;
|
disk.write_block(track, head, block, &packet.info.data)?
|
||||||
disk.write_block(track, head, block, data)?.map(|_| packet)
|
.map(|_| packet),
|
||||||
}
|
"[W]".yellow(),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
let lba = if let Some(lba) = disk.get_lba(track, head, block) {
|
let lba = if let Some(lba) = disk.get_lba(track, head, block) {
|
||||||
format!("{lba}")
|
format!("{lba}")
|
||||||
} else {
|
} else {
|
||||||
"Invalid".to_string()
|
"Invalid".to_string()
|
||||||
};
|
};
|
||||||
let message = format!(" {track:4}:{head}:{block} / LBA: {lba}");
|
let message = format!("{track:4}:{head}:{block} / LBA: {lba}");
|
||||||
if reply_packet.is_some() {
|
if reply_packet.is_some() {
|
||||||
println!("{}", message.green());
|
println!("{}: {} {}", "[64DD]".bold(), rw, message.green());
|
||||||
} else {
|
} else {
|
||||||
println!("{}", message.red());
|
println!("{}: {} {}", "[64DD]".bold(), rw, message.red());
|
||||||
}
|
}
|
||||||
sc64.reply_disk_packet(reply_packet)?;
|
sc64.reply_disk_packet(reply_packet)?;
|
||||||
} else {
|
} else {
|
||||||
@ -533,7 +535,11 @@ fn handle_64dd_command(connection: Connection, args: &_64DDArgs) -> Result<(), s
|
|||||||
if selected_disk.is_some() {
|
if selected_disk.is_some() {
|
||||||
sc64.set_64dd_disk_state(sc64::DdDiskState::Ejected)?;
|
sc64.set_64dd_disk_state(sc64::DdDiskState::Ejected)?;
|
||||||
selected_disk = None;
|
selected_disk = None;
|
||||||
println!("64DD disk ejected [{}]", disk_names[selected_disk_index]);
|
println!(
|
||||||
|
"{}: Disk ejected [{}]",
|
||||||
|
"[64DD]".bold(),
|
||||||
|
disk_names[selected_disk_index].green()
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
selected_disk_index += 1;
|
selected_disk_index += 1;
|
||||||
if selected_disk_index >= disks.len() {
|
if selected_disk_index >= disks.len() {
|
||||||
@ -541,16 +547,20 @@ fn handle_64dd_command(connection: Connection, args: &_64DDArgs) -> Result<(), s
|
|||||||
}
|
}
|
||||||
selected_disk = Some(&mut disks[selected_disk_index]);
|
selected_disk = Some(&mut disks[selected_disk_index]);
|
||||||
sc64.set_64dd_disk_state(sc64::DdDiskState::Inserted)?;
|
sc64.set_64dd_disk_state(sc64::DdDiskState::Inserted)?;
|
||||||
println!("64DD disk inserted [{}]", disk_names[selected_disk_index]);
|
println!(
|
||||||
|
"{}: Disk inserted [{}]",
|
||||||
|
"[64DD]".bold(),
|
||||||
|
disk_names[selected_disk_index].bright_green()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
thread::sleep(Duration::from_millis(1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sc64.reset_state()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -558,25 +568,25 @@ fn handle_debug_command(connection: Connection, args: &DebugArgs) -> Result<(),
|
|||||||
let mut sc64 = init_sc64(connection, true)?;
|
let mut sc64 = init_sc64(connection, true)?;
|
||||||
|
|
||||||
let mut debug_handler = debug::new(args.gdb)?;
|
let mut debug_handler = debug::new(args.gdb)?;
|
||||||
if let Some(port) = args.gdb {
|
|
||||||
println!("GDB TCP socket listening at [0.0.0.0:{port}]");
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.isv.is_some() {
|
if args.isv.is_some() {
|
||||||
sc64.configure_is_viewer_64(args.isv)?;
|
sc64.configure_is_viewer_64(args.isv)?;
|
||||||
println!(
|
println!(
|
||||||
"IS-Viewer 64 configured and listening at ROM offset [0x{:08X}]",
|
"{}: Listening on ROM offset [{}]",
|
||||||
args.isv.unwrap()
|
"[IS-Viewer 64]".bold(),
|
||||||
|
format!("0x{:08X}", args.isv.unwrap())
|
||||||
|
.to_string()
|
||||||
|
.bright_blue()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{}", "Debug mode started".bold());
|
println!("{}: Started", "[Debug]".bold());
|
||||||
|
|
||||||
let exit = setup_exit_flag();
|
let exit = setup_exit_flag();
|
||||||
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::IsViewer(message) => {
|
sc64::DataPacket::IsViewer64(message) => {
|
||||||
print!("{message}")
|
print!("{message}")
|
||||||
}
|
}
|
||||||
sc64::DataPacket::Debug(debug_packet) => {
|
sc64::DataPacket::Debug(debug_packet) => {
|
||||||
@ -588,17 +598,16 @@ fn handle_debug_command(connection: Connection, args: &DebugArgs) -> Result<(),
|
|||||||
sc64.send_debug_packet(gdb_packet)?;
|
sc64.send_debug_packet(gdb_packet)?;
|
||||||
} else if let Some(debug_packet) = debug_handler.process_user_input() {
|
} else if let Some(debug_packet) = debug_handler.process_user_input() {
|
||||||
sc64.send_debug_packet(debug_packet)?;
|
sc64.send_debug_packet(debug_packet)?;
|
||||||
} else {
|
|
||||||
thread::sleep(Duration::from_millis(1));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
println!("{}", "Debug mode ended".bold());
|
|
||||||
|
|
||||||
if args.isv.is_some() {
|
if args.isv.is_some() {
|
||||||
sc64.configure_is_viewer_64(None)?;
|
sc64.configure_is_viewer_64(None)?;
|
||||||
|
println!("{}: Stopped listening", "[IS-Viewer 64]".bold());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("{}: Stopped", "[Debug]".bold());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ impl std::error::Error for Error {}
|
|||||||
|
|
||||||
impl Display for Error {
|
impl Display for Error {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||||
write!(f, "SC64 error: {}", self.description.as_str())
|
write!(f, "{}", self.description.as_str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
use super::error::Error;
|
use super::error::Error;
|
||||||
|
use serial2::SerialPort;
|
||||||
use std::{
|
use std::{
|
||||||
collections::VecDeque,
|
collections::VecDeque,
|
||||||
io::{BufReader, BufWriter, ErrorKind, Read, Write},
|
io::{BufReader, BufWriter, ErrorKind, Read, Write},
|
||||||
net::{TcpListener, TcpStream},
|
net::{TcpListener, TcpStream},
|
||||||
|
sync::{
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
mpsc::{channel, Receiver, Sender},
|
||||||
|
Arc,
|
||||||
|
},
|
||||||
|
thread,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -63,20 +70,20 @@ trait Backend {
|
|||||||
) -> Result<Option<Response>, Error>;
|
) -> Result<Option<Response>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SerialBackend {
|
struct Serial {
|
||||||
serial: Box<dyn serialport::SerialPort>,
|
serial: SerialPort,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SerialBackend {
|
impl Serial {
|
||||||
fn reset(&mut self) -> Result<(), Error> {
|
fn reset(&self) -> Result<(), Error> {
|
||||||
const WAIT_DURATION: Duration = Duration::from_millis(10);
|
const WAIT_DURATION: Duration = Duration::from_millis(10);
|
||||||
const RETRY_COUNT: i32 = 100;
|
const RETRY_COUNT: i32 = 100;
|
||||||
|
|
||||||
self.serial.write_data_terminal_ready(true)?;
|
self.serial.set_dtr(true)?;
|
||||||
for n in 0..=RETRY_COUNT {
|
for n in 0..=RETRY_COUNT {
|
||||||
self.serial.clear(serialport::ClearBuffer::All)?;
|
self.serial.discard_buffers()?;
|
||||||
std::thread::sleep(WAIT_DURATION);
|
thread::sleep(WAIT_DURATION);
|
||||||
if self.serial.read_data_set_ready()? {
|
if self.serial.read_dsr()? {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if n == RETRY_COUNT {
|
if n == RETRY_COUNT {
|
||||||
@ -84,10 +91,10 @@ impl SerialBackend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.serial.write_data_terminal_ready(false)?;
|
self.serial.set_dtr(false)?;
|
||||||
for n in 0..=RETRY_COUNT {
|
for n in 0..=RETRY_COUNT {
|
||||||
std::thread::sleep(WAIT_DURATION);
|
thread::sleep(WAIT_DURATION);
|
||||||
if !self.serial.read_data_set_ready()? {
|
if !self.serial.read_dsr()? {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if n == RETRY_COUNT {
|
if n == RETRY_COUNT {
|
||||||
@ -97,10 +104,44 @@ impl SerialBackend {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Backend for SerialBackend {
|
fn read_data(&self, buffer: &mut [u8], block: bool) -> Result<Option<()>, Error> {
|
||||||
fn send_command(&mut self, command: &Command) -> Result<(), Error> {
|
let timeout = Instant::now();
|
||||||
|
let mut position = 0;
|
||||||
|
let length = buffer.len();
|
||||||
|
while position < length {
|
||||||
|
if timeout.elapsed() > Duration::from_secs(5) {
|
||||||
|
return Err(Error::new("Serial read timeout"));
|
||||||
|
}
|
||||||
|
match self.serial.read(&mut buffer[position..length]) {
|
||||||
|
Ok(0) => return Err(Error::new("Unexpected end of serial data")),
|
||||||
|
Ok(bytes) => position += bytes,
|
||||||
|
Err(error) => match error.kind() {
|
||||||
|
ErrorKind::Interrupted | ErrorKind::TimedOut => {
|
||||||
|
if !block && position == 0 {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => return Err(error.into()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(Some(()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_exact(&self, buffer: &mut [u8]) -> Result<(), Error> {
|
||||||
|
match self.read_data(buffer, true)? {
|
||||||
|
Some(()) => Ok(()),
|
||||||
|
None => Err(Error::new("Unexpected end of serial data")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_header(&self, block: bool) -> Result<Option<[u8; 4]>, Error> {
|
||||||
|
let mut header = [0u8; 4];
|
||||||
|
Ok(self.read_data(&mut header, block)?.map(|_| header))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_command(&self, command: &Command) -> Result<(), Error> {
|
||||||
self.serial.write_all(b"CMD")?;
|
self.serial.write_all(b"CMD")?;
|
||||||
self.serial.write_all(&command.id.to_be_bytes())?;
|
self.serial.write_all(&command.id.to_be_bytes())?;
|
||||||
self.serial.write_all(&command.args[0].to_be_bytes())?;
|
self.serial.write_all(&command.args[0].to_be_bytes())?;
|
||||||
@ -114,29 +155,27 @@ impl Backend for SerialBackend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn process_incoming_data(
|
fn process_incoming_data(
|
||||||
&mut self,
|
&self,
|
||||||
data_type: DataType,
|
data_type: DataType,
|
||||||
packets: &mut VecDeque<Packet>,
|
packets: &mut VecDeque<Packet>,
|
||||||
) -> Result<Option<Response>, Error> {
|
) -> Result<Option<Response>, Error> {
|
||||||
let mut buffer = [0u8; 4];
|
let block = matches!(data_type, DataType::Response);
|
||||||
|
while let Some(header) = self.read_header(block)? {
|
||||||
while matches!(data_type, DataType::Response)
|
let (packet_token, error) = (match &header[0..3] {
|
||||||
|| self.serial.bytes_to_read()? as usize >= buffer.len()
|
|
||||||
{
|
|
||||||
self.serial.read_exact(&mut buffer)?;
|
|
||||||
let (packet_token, error) = (match &buffer[0..3] {
|
|
||||||
b"CMP" => Ok((false, false)),
|
b"CMP" => Ok((false, false)),
|
||||||
b"PKT" => Ok((true, false)),
|
b"PKT" => Ok((true, false)),
|
||||||
b"ERR" => Ok((false, true)),
|
b"ERR" => Ok((false, true)),
|
||||||
_ => Err(Error::new("Unknown response token")),
|
_ => Err(Error::new("Unknown response token")),
|
||||||
})?;
|
})?;
|
||||||
let id = buffer[3];
|
let id = header[3];
|
||||||
|
|
||||||
self.serial.read_exact(&mut buffer)?;
|
let mut buffer = [0u8; 4];
|
||||||
|
|
||||||
|
self.read_exact(&mut buffer)?;
|
||||||
let length = u32::from_be_bytes(buffer) as usize;
|
let length = u32::from_be_bytes(buffer) as usize;
|
||||||
|
|
||||||
let mut data = vec![0u8; length];
|
let mut data = vec![0u8; length];
|
||||||
self.serial.read_exact(&mut data)?;
|
self.read_exact(&mut data)?;
|
||||||
|
|
||||||
if packet_token {
|
if packet_token {
|
||||||
packets.push_back(Packet { id, data });
|
packets.push_back(Packet { id, data });
|
||||||
@ -152,48 +191,80 @@ impl Backend for SerialBackend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new_serial_backend(port: &str) -> Result<SerialBackend, Error> {
|
fn new_serial(port: &str) -> Result<Serial, Error> {
|
||||||
let serial = serialport::new(port, 115_200)
|
let mut serial = SerialPort::open(port, 115_200)?;
|
||||||
.timeout(Duration::from_secs(10))
|
serial.set_read_timeout(Duration::from_millis(10))?;
|
||||||
.open()?;
|
serial.set_write_timeout(Duration::from_secs(5))?;
|
||||||
let mut backend = SerialBackend { serial };
|
let backend = Serial { serial };
|
||||||
backend.reset()?;
|
backend.reset()?;
|
||||||
Ok(backend)
|
Ok(backend)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SerialBackend {
|
||||||
|
inner: Serial,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Backend for SerialBackend {
|
||||||
|
fn send_command(&mut self, command: &Command) -> Result<(), Error> {
|
||||||
|
self.inner.send_command(command)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_incoming_data(
|
||||||
|
&mut self,
|
||||||
|
data_type: DataType,
|
||||||
|
packets: &mut VecDeque<Packet>,
|
||||||
|
) -> Result<Option<Response>, Error> {
|
||||||
|
self.inner.process_incoming_data(data_type, packets)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_serial_backend(port: &str) -> Result<SerialBackend, Error> {
|
||||||
|
let backend = SerialBackend {
|
||||||
|
inner: new_serial(port)?,
|
||||||
|
};
|
||||||
|
Ok(backend)
|
||||||
|
}
|
||||||
|
|
||||||
struct TcpBackend {
|
struct TcpBackend {
|
||||||
stream: TcpStream,
|
|
||||||
reader: BufReader<TcpStream>,
|
reader: BufReader<TcpStream>,
|
||||||
writer: BufWriter<TcpStream>,
|
writer: BufWriter<TcpStream>,
|
||||||
header_position: usize,
|
|
||||||
header: [u8; 4],
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcpBackend {
|
impl TcpBackend {
|
||||||
fn read_header(&mut self, block: bool) -> Result<bool, Error> {
|
fn read_data(&mut self, buffer: &mut [u8], block: bool) -> Result<Option<()>, Error> {
|
||||||
self.stream.set_nonblocking(!block)?;
|
let timeout = Instant::now();
|
||||||
while self.header_position != 4 {
|
let mut position = 0;
|
||||||
self.header_position +=
|
let length = buffer.len();
|
||||||
match self.reader.read(&mut self.header[self.header_position..4]) {
|
while position < length {
|
||||||
Ok(0) => return Err(Error::new("Unexpected end of stream")),
|
if timeout.elapsed() > Duration::from_secs(10) {
|
||||||
Ok(length) => length,
|
return Err(Error::new("Stream read timeout"));
|
||||||
|
}
|
||||||
|
match self.reader.read(&mut buffer[position..length]) {
|
||||||
|
Ok(0) => return Err(Error::new("Unexpected end of stream data")),
|
||||||
|
Ok(bytes) => position += bytes,
|
||||||
Err(error) => match error.kind() {
|
Err(error) => match error.kind() {
|
||||||
ErrorKind::Interrupted => 0,
|
ErrorKind::Interrupted | ErrorKind::TimedOut => {
|
||||||
ErrorKind::WouldBlock => 0,
|
if !block && position == 0 {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => return Err(error.into()),
|
_ => return Err(error.into()),
|
||||||
},
|
},
|
||||||
};
|
|
||||||
if !block {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.stream.set_nonblocking(false)?;
|
Ok(Some(()))
|
||||||
if self.header_position == 4 {
|
|
||||||
self.header_position = 0;
|
|
||||||
return Ok(true);
|
|
||||||
} else {
|
|
||||||
return Ok(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_exact(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
|
||||||
|
match self.read_data(buffer, true)? {
|
||||||
|
Some(()) => Ok(()),
|
||||||
|
None => Err(Error::new("Unexpected end of stream data")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_header(&mut self, block: bool) -> Result<Option<[u8; 4]>, Error> {
|
||||||
|
let mut header = [0u8; 4];
|
||||||
|
Ok(self.read_data(&mut header, block)?.map(|_| header))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -220,20 +291,20 @@ impl Backend for TcpBackend {
|
|||||||
data_type: DataType,
|
data_type: DataType,
|
||||||
packets: &mut VecDeque<Packet>,
|
packets: &mut VecDeque<Packet>,
|
||||||
) -> Result<Option<Response>, Error> {
|
) -> Result<Option<Response>, Error> {
|
||||||
|
let block = matches!(data_type, DataType::Response);
|
||||||
|
while let Some(header) = self.read_header(block)? {
|
||||||
|
let payload_data_type: DataType = u32::from_be_bytes(header).try_into()?;
|
||||||
let mut buffer = [0u8; 4];
|
let mut buffer = [0u8; 4];
|
||||||
|
|
||||||
while self.read_header(matches!(data_type, DataType::Response))? {
|
|
||||||
let payload_data_type: DataType = u32::from_be_bytes(self.header).try_into()?;
|
|
||||||
match payload_data_type {
|
match payload_data_type {
|
||||||
DataType::Response => {
|
DataType::Response => {
|
||||||
let mut response_info = vec![0u8; 2];
|
let mut response_info = vec![0u8; 2];
|
||||||
self.reader.read_exact(&mut response_info)?;
|
self.read_exact(&mut response_info)?;
|
||||||
|
|
||||||
self.reader.read_exact(&mut buffer)?;
|
self.read_exact(&mut buffer)?;
|
||||||
let response_data_length = u32::from_be_bytes(buffer) as usize;
|
let response_data_length = u32::from_be_bytes(buffer) as usize;
|
||||||
|
|
||||||
let mut data = vec![0u8; response_data_length];
|
let mut data = vec![0u8; response_data_length];
|
||||||
self.reader.read_exact(&mut data)?;
|
self.read_exact(&mut data)?;
|
||||||
|
|
||||||
return Ok(Some(Response {
|
return Ok(Some(Response {
|
||||||
id: response_info[0],
|
id: response_info[0],
|
||||||
@ -243,13 +314,13 @@ impl Backend for TcpBackend {
|
|||||||
}
|
}
|
||||||
DataType::Packet => {
|
DataType::Packet => {
|
||||||
let mut packet_info = vec![0u8; 1];
|
let mut packet_info = vec![0u8; 1];
|
||||||
self.reader.read_exact(&mut packet_info)?;
|
self.read_exact(&mut packet_info)?;
|
||||||
|
|
||||||
self.reader.read_exact(&mut buffer)?;
|
self.read_exact(&mut buffer)?;
|
||||||
let packet_data_length = u32::from_be_bytes(buffer) as usize;
|
let packet_data_length = u32::from_be_bytes(buffer) as usize;
|
||||||
|
|
||||||
let mut data = vec![0u8; packet_data_length];
|
let mut data = vec![0u8; packet_data_length];
|
||||||
self.reader.read_exact(&mut data)?;
|
self.read_exact(&mut data)?;
|
||||||
|
|
||||||
packets.push_back(Packet {
|
packets.push_back(Packet {
|
||||||
id: packet_info[0],
|
id: packet_info[0],
|
||||||
@ -272,7 +343,7 @@ fn new_tcp_backend(address: &str) -> Result<TcpBackend, Error> {
|
|||||||
let stream = match TcpStream::connect(address) {
|
let stream = match TcpStream::connect(address) {
|
||||||
Ok(stream) => {
|
Ok(stream) => {
|
||||||
stream.set_write_timeout(Some(Duration::from_secs(10)))?;
|
stream.set_write_timeout(Some(Duration::from_secs(10)))?;
|
||||||
stream.set_read_timeout(Some(Duration::from_secs(10)))?;
|
stream.set_read_timeout(Some(Duration::from_millis(10)))?;
|
||||||
stream
|
stream
|
||||||
}
|
}
|
||||||
Err(error) => {
|
Err(error) => {
|
||||||
@ -283,13 +354,7 @@ fn new_tcp_backend(address: &str) -> Result<TcpBackend, Error> {
|
|||||||
};
|
};
|
||||||
let reader = BufReader::new(stream.try_clone()?);
|
let reader = BufReader::new(stream.try_clone()?);
|
||||||
let writer = BufWriter::new(stream.try_clone()?);
|
let writer = BufWriter::new(stream.try_clone()?);
|
||||||
Ok(TcpBackend {
|
Ok(TcpBackend { reader, writer })
|
||||||
stream,
|
|
||||||
reader,
|
|
||||||
writer,
|
|
||||||
header_position: 0,
|
|
||||||
header: [0, 0, 0, 0],
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Link {
|
pub struct Link {
|
||||||
@ -408,109 +473,225 @@ pub fn run_server(
|
|||||||
event_callback: fn(ServerEvent),
|
event_callback: fn(ServerEvent),
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let listener = TcpListener::bind(address)?;
|
let listener = TcpListener::bind(address)?;
|
||||||
|
let listening_address = listener.local_addr()?;
|
||||||
event_callback(ServerEvent::Listening(listener.local_addr()?.to_string()));
|
event_callback(ServerEvent::Listening(listening_address.to_string()));
|
||||||
|
|
||||||
for stream in listener.incoming() {
|
for stream in listener.incoming() {
|
||||||
match stream {
|
match stream {
|
||||||
Ok(mut stream) => match server_accept_connection(port, event_callback, &mut stream) {
|
Ok(mut stream) => {
|
||||||
Ok(()) => {}
|
let peer = stream.peer_addr()?.to_string();
|
||||||
|
event_callback(ServerEvent::Connected(peer.clone()));
|
||||||
|
match server_accept_connection(port, &mut stream) {
|
||||||
|
Ok(()) => event_callback(ServerEvent::Disconnected(peer.clone())),
|
||||||
Err(error) => event_callback(ServerEvent::Err(error.to_string())),
|
Err(error) => event_callback(ServerEvent::Err(error.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(error) => match error.kind() {
|
||||||
|
_ => return Err(error.into()),
|
||||||
},
|
},
|
||||||
Err(error) => return Err(error.into()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn server_accept_connection(
|
enum Event {
|
||||||
port: &str,
|
Command((u8, [u32; 2], Vec<u8>)),
|
||||||
event_callback: fn(ServerEvent),
|
Response(Response),
|
||||||
stream: &mut TcpStream,
|
Packet(Packet),
|
||||||
|
KeepAlive,
|
||||||
|
Closed(Option<Error>),
|
||||||
|
}
|
||||||
|
|
||||||
|
fn server_accept_connection(port: &str, stream: &mut TcpStream) -> Result<(), Error> {
|
||||||
|
let (event_sender, event_receiver) = channel::<Event>();
|
||||||
|
let exit_flag = Arc::new(AtomicBool::new(false));
|
||||||
|
|
||||||
|
let mut stream_writer = BufWriter::new(stream.try_clone()?);
|
||||||
|
let mut stream_reader = stream.try_clone()?;
|
||||||
|
|
||||||
|
let stream_event_sender = event_sender.clone();
|
||||||
|
let stream_exit_flag = exit_flag.clone();
|
||||||
|
let stream_thread = thread::spawn(move || {
|
||||||
|
let closed_sender = stream_event_sender.clone();
|
||||||
|
match server_stream_thread(&mut stream_reader, stream_event_sender, stream_exit_flag) {
|
||||||
|
Ok(()) => closed_sender.send(Event::Closed(None)),
|
||||||
|
Err(error) => closed_sender.send(Event::Closed(Some(error))),
|
||||||
|
}
|
||||||
|
.ok();
|
||||||
|
});
|
||||||
|
|
||||||
|
let serial = Arc::new(new_serial(port)?);
|
||||||
|
let serial_writer = serial.clone();
|
||||||
|
let serial_reader = serial.clone();
|
||||||
|
|
||||||
|
let serial_event_sender = event_sender.clone();
|
||||||
|
let serial_exit_flag = exit_flag.clone();
|
||||||
|
let serial_thread = thread::spawn(move || {
|
||||||
|
let closed_sender = serial_event_sender.clone();
|
||||||
|
match server_serial_thread(serial_reader, serial_event_sender, serial_exit_flag) {
|
||||||
|
Ok(()) => closed_sender.send(Event::Closed(None)),
|
||||||
|
Err(error) => closed_sender.send(Event::Closed(Some(error))),
|
||||||
|
}
|
||||||
|
.ok();
|
||||||
|
});
|
||||||
|
|
||||||
|
let keepalive_event_sender = event_sender.clone();
|
||||||
|
let keepalive_exit_flag = exit_flag.clone();
|
||||||
|
let keepalive_thread = thread::spawn(move || {
|
||||||
|
server_keepalive_thread(keepalive_event_sender, keepalive_exit_flag);
|
||||||
|
});
|
||||||
|
|
||||||
|
let result = server_process_events(&mut stream_writer, serial_writer, event_receiver);
|
||||||
|
|
||||||
|
exit_flag.store(true, Ordering::Relaxed);
|
||||||
|
stream_thread.join().ok();
|
||||||
|
serial_thread.join().ok();
|
||||||
|
keepalive_thread.join().ok();
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn server_process_events(
|
||||||
|
stream_writer: &mut BufWriter<TcpStream>,
|
||||||
|
serial_writer: Arc<Serial>,
|
||||||
|
event_receiver: Receiver<Event>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let peer = stream.peer_addr()?.to_string();
|
for event in event_receiver.into_iter() {
|
||||||
event_callback(ServerEvent::Connected(peer.clone()));
|
match event {
|
||||||
|
Event::Command((id, args, data)) => {
|
||||||
stream.set_write_timeout(Some(Duration::from_secs(10)))?;
|
serial_writer.send_command(&Command {
|
||||||
stream.set_read_timeout(Some(Duration::from_secs(10)))?;
|
id,
|
||||||
|
|
||||||
let mut reader = BufReader::new(stream.try_clone()?);
|
|
||||||
let mut writer = BufWriter::new(stream.try_clone()?);
|
|
||||||
|
|
||||||
let mut serial_backend = new_serial_backend(port)?;
|
|
||||||
serial_backend.reset()?;
|
|
||||||
|
|
||||||
let mut packets: VecDeque<Packet> = VecDeque::new();
|
|
||||||
let mut keepalive = Instant::now();
|
|
||||||
let mut header_position = 0;
|
|
||||||
let mut header = [0u8; 4];
|
|
||||||
|
|
||||||
loop {
|
|
||||||
stream.set_nonblocking(true)?;
|
|
||||||
header_position += match stream.read(&mut header[header_position..4]) {
|
|
||||||
Ok(0) => {
|
|
||||||
event_callback(ServerEvent::Disconnected(peer.clone()));
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
Ok(length) => length,
|
|
||||||
Err(error) => match error.kind() {
|
|
||||||
ErrorKind::WouldBlock => 0,
|
|
||||||
_ => return Err(error.into()),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
stream.set_nonblocking(false)?;
|
|
||||||
|
|
||||||
if header_position == 4 {
|
|
||||||
header_position = 0;
|
|
||||||
|
|
||||||
let data_type: DataType = u32::from_be_bytes(header).try_into()?;
|
|
||||||
|
|
||||||
if !matches!(data_type, DataType::Command) {
|
|
||||||
return Err(Error::new("Received data type wasn't a command data type"));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut buffer = [0u8; 4];
|
|
||||||
let mut id_buffer = [0u8; 1];
|
|
||||||
let mut args = [0u32; 2];
|
|
||||||
|
|
||||||
reader.read_exact(&mut id_buffer)?;
|
|
||||||
reader.read_exact(&mut buffer)?;
|
|
||||||
args[0] = u32::from_be_bytes(buffer);
|
|
||||||
reader.read_exact(&mut buffer)?;
|
|
||||||
args[1] = u32::from_be_bytes(buffer);
|
|
||||||
|
|
||||||
reader.read_exact(&mut buffer)?;
|
|
||||||
let command_data_length = u32::from_be_bytes(buffer) as usize;
|
|
||||||
let mut data = vec![0u8; command_data_length];
|
|
||||||
reader.read_exact(&mut data)?;
|
|
||||||
|
|
||||||
serial_backend.send_command(&Command {
|
|
||||||
id: id_buffer[0],
|
|
||||||
args,
|
args,
|
||||||
data: &data,
|
data: &data,
|
||||||
})?;
|
})?;
|
||||||
} else if let Some(response) =
|
}
|
||||||
serial_backend.process_incoming_data(DataType::Packet, &mut packets)?
|
Event::Response(response) => {
|
||||||
{
|
stream_writer.write_all(&u32::to_be_bytes(DataType::Response.into()))?;
|
||||||
writer.write_all(&u32::to_be_bytes(DataType::Response.into()))?;
|
stream_writer.write_all(&[response.id])?;
|
||||||
writer.write_all(&[response.id])?;
|
stream_writer.write_all(&[response.error as u8])?;
|
||||||
writer.write_all(&[response.error as u8])?;
|
stream_writer.write_all(&(response.data.len() as u32).to_be_bytes())?;
|
||||||
writer.write_all(&(response.data.len() as u32).to_be_bytes())?;
|
stream_writer.write_all(&response.data)?;
|
||||||
writer.write_all(&response.data)?;
|
stream_writer.flush()?;
|
||||||
writer.flush()?;
|
}
|
||||||
} else if let Some(packet) = packets.pop_front() {
|
Event::Packet(packet) => {
|
||||||
writer.write_all(&u32::to_be_bytes(DataType::Packet.into()))?;
|
stream_writer.write_all(&u32::to_be_bytes(DataType::Packet.into()))?;
|
||||||
writer.write_all(&[packet.id])?;
|
stream_writer.write_all(&[packet.id])?;
|
||||||
writer.write_all(&(packet.data.len() as u32).to_be_bytes())?;
|
stream_writer.write_all(&(packet.data.len() as u32).to_be_bytes())?;
|
||||||
writer.write_all(&packet.data)?;
|
stream_writer.write_all(&packet.data)?;
|
||||||
writer.flush()?;
|
stream_writer.flush()?;
|
||||||
} else if keepalive.elapsed() > Duration::from_secs(5) {
|
}
|
||||||
|
Event::KeepAlive => {
|
||||||
|
stream_writer.write_all(&u32::to_be_bytes(DataType::KeepAlive.into()))?;
|
||||||
|
stream_writer.flush()?;
|
||||||
|
}
|
||||||
|
Event::Closed(result) => match result {
|
||||||
|
Some(error) => return Err(error),
|
||||||
|
None => {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn server_stream_thread(
|
||||||
|
stream: &mut TcpStream,
|
||||||
|
event_sender: Sender<Event>,
|
||||||
|
exit_flag: Arc<AtomicBool>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let mut stream_reader = BufReader::new(stream.try_clone()?);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let mut header = [0u8; 4];
|
||||||
|
let header_length = header.len();
|
||||||
|
let mut header_position = 0;
|
||||||
|
|
||||||
|
stream.set_read_timeout(Some(Duration::from_millis(10)))?;
|
||||||
|
while header_position < header_length {
|
||||||
|
if exit_flag.load(Ordering::Relaxed) {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
match stream_reader.read(&mut header[header_position..header_length]) {
|
||||||
|
Ok(0) => return Ok(()),
|
||||||
|
Ok(bytes) => header_position += bytes,
|
||||||
|
Err(error) => match error.kind() {
|
||||||
|
ErrorKind::Interrupted | ErrorKind::TimedOut => {}
|
||||||
|
_ => return Err(error.into()),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stream.set_read_timeout(None)?;
|
||||||
|
|
||||||
|
let data_type: DataType = u32::from_be_bytes(header).try_into()?;
|
||||||
|
if !matches!(data_type, DataType::Command) {
|
||||||
|
return Err(Error::new("Received data type was not a command data type"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buffer = [0u8; 4];
|
||||||
|
let mut id = [0u8; 1];
|
||||||
|
let mut args = [0u32; 2];
|
||||||
|
|
||||||
|
stream_reader.read_exact(&mut id)?;
|
||||||
|
stream_reader.read_exact(&mut buffer)?;
|
||||||
|
args[0] = u32::from_be_bytes(buffer);
|
||||||
|
stream_reader.read_exact(&mut buffer)?;
|
||||||
|
args[1] = u32::from_be_bytes(buffer);
|
||||||
|
|
||||||
|
stream_reader.read_exact(&mut buffer)?;
|
||||||
|
let command_data_length = u32::from_be_bytes(buffer) as usize;
|
||||||
|
let mut data = vec![0u8; command_data_length];
|
||||||
|
stream_reader.read_exact(&mut data)?;
|
||||||
|
|
||||||
|
let event = Event::Command((id[0], args, data));
|
||||||
|
if event_sender.send(event).is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn server_serial_thread(
|
||||||
|
serial_reader: Arc<Serial>,
|
||||||
|
event_sender: Sender<Event>,
|
||||||
|
exit_flag: Arc<AtomicBool>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
let mut packets: VecDeque<Packet> = VecDeque::new();
|
||||||
|
|
||||||
|
while !exit_flag.load(Ordering::Relaxed) {
|
||||||
|
let response = serial_reader.process_incoming_data(DataType::Packet, &mut packets)?;
|
||||||
|
if let Some(response) = response {
|
||||||
|
let event = Event::Response(response);
|
||||||
|
if event_sender.send(event).is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(packet) = packets.pop_front() {
|
||||||
|
let event = Event::Packet(packet);
|
||||||
|
if event_sender.send(event).is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn server_keepalive_thread(event_sender: Sender<Event>, exit_flag: Arc<AtomicBool>) {
|
||||||
|
let mut keepalive = Instant::now();
|
||||||
|
|
||||||
|
while !exit_flag.load(Ordering::Relaxed) {
|
||||||
|
if keepalive.elapsed() >= Duration::from_secs(5) {
|
||||||
|
let event = Event::KeepAlive;
|
||||||
|
if event_sender.send(event).is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
keepalive = Instant::now();
|
keepalive = Instant::now();
|
||||||
writer.write_all(&u32::to_be_bytes(DataType::KeepAlive.into()))?;
|
|
||||||
writer.flush()?;
|
|
||||||
} else {
|
} else {
|
||||||
std::thread::sleep(Duration::from_millis(1));
|
thread::sleep(Duration::from_millis(10));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -617,13 +617,15 @@ impl SC64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_firmware_version(&mut self) -> Result<(u16, u16, u32), Error> {
|
pub fn check_firmware_version(&mut self) -> Result<(u16, u16, u32), Error> {
|
||||||
|
let unsupported_version_message = format!(
|
||||||
|
"Unsupported SC64 firmware version, minimum supported version: {}.{}.x",
|
||||||
|
SUPPORTED_MAJOR_VERSION, SUPPORTED_MINOR_VERSION
|
||||||
|
);
|
||||||
let (major, minor, revision) = self
|
let (major, minor, revision) = self
|
||||||
.command_version_get()
|
.command_version_get()
|
||||||
.map_err(|_| Error::new("Outdated SC64 firmware version, please update firmware"))?;
|
.map_err(|_| Error::new(unsupported_version_message.as_str()))?;
|
||||||
if major != SUPPORTED_MAJOR_VERSION || minor < SUPPORTED_MINOR_VERSION {
|
if major != SUPPORTED_MAJOR_VERSION || minor < SUPPORTED_MINOR_VERSION {
|
||||||
return Err(Error::new(
|
return Err(Error::new(unsupported_version_message.as_str()));
|
||||||
"Unsupported SC64 firmware version, please update firmware",
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
Ok((major, minor, revision))
|
Ok((major, minor, revision))
|
||||||
}
|
}
|
||||||
|
@ -579,7 +579,7 @@ pub enum DataPacket {
|
|||||||
Button,
|
Button,
|
||||||
Debug(DebugPacket),
|
Debug(DebugPacket),
|
||||||
Disk(DiskPacket),
|
Disk(DiskPacket),
|
||||||
IsViewer(String),
|
IsViewer64(String),
|
||||||
UpdateStatus(UpdateStatus),
|
UpdateStatus(UpdateStatus),
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -590,7 +590,7 @@ impl TryFrom<Packet> for DataPacket {
|
|||||||
b'B' => Self::Button,
|
b'B' => Self::Button,
|
||||||
b'U' => Self::Debug(value.data.try_into()?),
|
b'U' => Self::Debug(value.data.try_into()?),
|
||||||
b'D' => Self::Disk(value.data.try_into()?),
|
b'D' => Self::Disk(value.data.try_into()?),
|
||||||
b'I' => Self::IsViewer(EUC_JP.decode(&value.data).0.into()),
|
b'I' => Self::IsViewer64(EUC_JP.decode(&value.data).0.into()),
|
||||||
b'F' => {
|
b'F' => {
|
||||||
if value.data.len() != 4 {
|
if value.data.len() != 4 {
|
||||||
return Err(Error::new(
|
return Err(Error::new(
|
||||||
|
Loading…
Reference in New Issue
Block a user