From d0fc64fe9fe6dbf3d5a6aba6cd7f976ce84649bd Mon Sep 17 00:00:00 2001 From: spacelin Date: Fri, 8 Jan 2021 16:58:20 +0800 Subject: [PATCH] feat: add fs, console_error_panic_hook --- .vscode/tasks.json | 21 +++++++ Cargo.lock | 1 + Cargo.toml | 3 + blflash/Cargo.toml | 1 + .../{async_serial.rs => async_serial/mod.rs} | 0 blflash/src/async_serial/native.rs | 2 +- blflash/src/async_serial/wasm.rs | 29 +++++++--- blflash/src/fs/mod.rs | 8 +++ blflash/src/fs/native.rs | 22 +++++++ blflash/src/fs/wasm.rs | 58 +++++++++++++++++++ blflash/src/lib.rs | 16 +++-- libblflash/.gitignore | 2 + libblflash/Cargo.toml | 1 + libblflash/index.html | 9 +++ libblflash/index.js | 18 ++++++ libblflash/src/lib.rs | 35 ++++++++++- libblflash/src/utils.rs | 3 + 17 files changed, 212 insertions(+), 17 deletions(-) create mode 100644 .vscode/tasks.json rename blflash/src/{async_serial.rs => async_serial/mod.rs} (100%) create mode 100644 blflash/src/fs/mod.rs create mode 100644 blflash/src/fs/native.rs create mode 100644 blflash/src/fs/wasm.rs create mode 100644 libblflash/.gitignore create mode 100644 libblflash/index.html create mode 100644 libblflash/index.js create mode 100644 libblflash/src/utils.rs diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..e5a1d2b --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,21 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "shell", + "command": "cargo watch -x check", + "problemMatcher": "$rustc-watch", + "group": "build", + "label": "watch native", + "isBackground": true + }, + { + "type": "shell", + "command": "cargo watch -x 'check --target wasm32-unknown-unknown'", + "problemMatcher": "$rustc-watch", + "group": "build", + "label": "watch wasm", + "isBackground": true + } + ] +} \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index c04cdb5..30497a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -97,6 +97,7 @@ dependencies = [ "js-sys", "log", "main_error", + "once_cell", "parse_int", "paw", "serde", diff --git a/Cargo.toml b/Cargo.toml index e0b7dda..01cc51b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,6 @@ members = [ "blflash", ] default-members = ["blflash"] +exclude = [ + "libblflash", +] diff --git a/blflash/Cargo.toml b/blflash/Cargo.toml index 83220ce..dc73110 100644 --- a/blflash/Cargo.toml +++ b/blflash/Cargo.toml @@ -38,6 +38,7 @@ futures = "0.3" [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen = "0.2" js-sys = "0.3" +once_cell = "1.5" [target.'cfg(target_arch = "wasm32")'.dependencies.web-sys] version = "0.3" diff --git a/blflash/src/async_serial.rs b/blflash/src/async_serial/mod.rs similarity index 100% rename from blflash/src/async_serial.rs rename to blflash/src/async_serial/mod.rs diff --git a/blflash/src/async_serial/native.rs b/blflash/src/async_serial/native.rs index 2151a19..85aeb18 100644 --- a/blflash/src/async_serial/native.rs +++ b/blflash/src/async_serial/native.rs @@ -16,7 +16,7 @@ pub struct AsyncSerial(Box); impl AsyncSerial { pub async fn open(port: &str) -> crate::Result { - Ok(AsyncSerial(Box::new(serial::open(port)))) + Ok(AsyncSerial(Box::new(serial::open(port)?))) } // pub fn new(serial: impl SerialPort + 'static) -> Self { // Self(Box::new(serial)) diff --git a/blflash/src/async_serial/wasm.rs b/blflash/src/async_serial/wasm.rs index fd28adf..506bc8d 100644 --- a/blflash/src/async_serial/wasm.rs +++ b/blflash/src/async_serial/wasm.rs @@ -2,8 +2,8 @@ use crate::Error; use futures::io::{AsyncRead, AsyncWrite}; -use js_sys::Reflect; -use serial::{Result, SerialPortSettings}; +use js_sys::{Promise, Reflect}; +use serial::SerialPortSettings; use std::{ io, pin::Pin, @@ -14,29 +14,40 @@ use std::{ use wasm_bindgen::prelude::*; use web_sys::window; +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(extends=js_sys::Object, js_name=Serial , typescript_type="Serial")] + pub type Serial; + #[wasm_bindgen(catch, method, structural, js_class="Serial" , js_name=requestPort)] + pub fn requestPort(this: &Serial) -> Result; +} + pub struct AsyncSerial(JsValue); impl AsyncSerial { - pub async fn open(port: &str) -> crate::Result { + pub async fn open(_port: &str) -> crate::Result { let window = window().ok_or(Error::WebError("Failed to get window"))?; let serial = Reflect::get(window.navigator().as_ref(), &"serial".into()) .map_err(|_| Error::WebError("Failed to get serial from navigator"))?; if serial.is_undefined() { - return Err(Error::WebError("serial is not supported on your browser")); + return Err(Error::WebError("serial is not supported on your browser. make sure you have enabled chrome://flags/#enable-experimental-web-platform-features")); } + let serial: Serial = serial.into(); + + // Reflect::get(serial.as_ref(), "requestPort".into()).expect("Failed to get requestPort"); todo!() } - pub async fn set_rts(&mut self, level: bool) -> Result<()> { + pub async fn set_rts(&mut self, level: bool) -> serial::Result<()> { todo!() } - pub async fn set_dtr(&mut self, level: bool) -> Result<()> { + pub async fn set_dtr(&mut self, level: bool) -> serial::Result<()> { todo!() } pub async fn sleep(&self, duration: Duration) { sleep(duration) } - pub async fn set_timeout(&mut self, timeout: Duration) -> Result<()> { + pub async fn set_timeout(&mut self, timeout: Duration) -> serial::Result<()> { todo!() } pub async fn timeout(&self) -> Duration { @@ -44,8 +55,8 @@ impl AsyncSerial { } pub async fn reconfigure( &mut self, - setup: &dyn Fn(&mut dyn SerialPortSettings) -> Result<()>, - ) -> Result<()> { + setup: &dyn Fn(&mut dyn SerialPortSettings) -> serial::Result<()>, + ) -> serial::Result<()> { todo!() } } diff --git a/blflash/src/fs/mod.rs b/blflash/src/fs/mod.rs new file mode 100644 index 0000000..faec621 --- /dev/null +++ b/blflash/src/fs/mod.rs @@ -0,0 +1,8 @@ +mod native; +mod wasm; + +#[cfg(target_arch = "wasm32")] +pub use wasm::*; + +#[cfg(not(target_arch = "wasm32"))] +pub use native::*; diff --git a/blflash/src/fs/native.rs b/blflash/src/fs/native.rs new file mode 100644 index 0000000..ef294c1 --- /dev/null +++ b/blflash/src/fs/native.rs @@ -0,0 +1,22 @@ +#![cfg(not(target_arch = "wasm32"))] + +use std::{ + fs, io, + path::{Path, PathBuf}, +}; + +pub fn read>(path: P) -> io::Result> { + fs::read(path) +} + +pub use fs::File; + +pub fn fs_read_file(path: PathBuf) -> Option> { + unimplemented!("only avaliable on wasm") +} +pub fn fs_write_file(path: PathBuf, content: Vec) { + unimplemented!("only avaliable on wasm") +} +pub fn fs_remove_file(path: PathBuf) { + unimplemented!("only avaliable on wasm") +} diff --git a/blflash/src/fs/wasm.rs b/blflash/src/fs/wasm.rs new file mode 100644 index 0000000..fda4ec7 --- /dev/null +++ b/blflash/src/fs/wasm.rs @@ -0,0 +1,58 @@ +#![cfg(target_arch = "wasm32")] + +use once_cell::sync::Lazy; +use std::{ + collections::HashMap, + fs, + io::{self, Cursor, Write}, + path::{Path, PathBuf}, + sync::Mutex, +}; + +static FS: Lazy>>> = Lazy::new(|| Mutex::new(HashMap::new())); + +pub struct File { + path: PathBuf, + buf: Option>>, +} + +impl File { + pub fn create(path: PathBuf) -> io::Result { + Ok(Self { + path, + buf: Some(Cursor::new(Vec::new())), + }) + } +} + +impl Write for File { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.buf.as_mut().unwrap().write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.buf.as_mut().unwrap().flush() + } +} + +impl Drop for File { + fn drop(&mut self) { + FS.lock() + .unwrap() + .insert(self.path.clone(), self.buf.take().unwrap().into_inner()); + } +} + +pub fn read>(path: P) -> io::Result> { + fs::read(path) +} + +pub fn fs_read_file(path: PathBuf) -> Option> { + FS.lock().unwrap().get(&path).map(Clone::clone) +} +pub fn fs_write_file(path: PathBuf, content: Vec) { + FS.lock().unwrap().insert(path, content); +} +pub fn fs_remove_file(path: PathBuf) { + FS.lock().unwrap().remove(&path); +} diff --git a/blflash/src/lib.rs b/blflash/src/lib.rs index 5da1adb..83a3acd 100644 --- a/blflash/src/lib.rs +++ b/blflash/src/lib.rs @@ -7,6 +7,7 @@ pub mod image; use async_serial::AsyncSerial; use serde::Deserialize; mod async_serial; +pub mod fs; pub type Result = std::result::Result; pub use error::{Error, RomError}; @@ -20,12 +21,9 @@ use crate::{ elf::{FirmwareImage, RomSegment}, image::BootHeaderCfgFile, }; +use fs::{read, File}; use serial::{BaudRate, CharSize, FlowControl, Parity, SerialPortSettings, StopBits}; -use std::{ - borrow::Cow, - fs::{read, File}, - path::PathBuf, -}; +use std::{borrow::Cow, path::PathBuf}; use structopt::StructOpt; #[derive(StructOpt, Deserialize)] @@ -41,7 +39,7 @@ pub struct Connection { pub initial_baud_rate: usize, } -#[derive(StructOpt, Deserialize)] +#[derive(StructOpt, Deserialize, Default)] pub struct Boot2Opt { /// Path to partition_cfg.toml, default to be partition/partition_cfg_2M.toml #[structopt(long, parse(from_os_str))] @@ -54,26 +52,31 @@ pub struct Boot2Opt { pub dtb: Option, /// Without boot2 #[structopt(short, long)] + #[serde(default)] pub without_boot2: bool, } #[derive(StructOpt, Deserialize)] pub struct FlashOpt { #[structopt(flatten)] + #[serde(flatten)] pub conn: Connection, /// Bin file #[structopt(parse(from_os_str))] pub image: PathBuf, /// Don't skip if hash matches #[structopt(short, long)] + #[serde(default)] pub force: bool, #[structopt(flatten)] + #[serde(default, flatten)] pub boot: Boot2Opt, } #[derive(StructOpt, Deserialize)] pub struct CheckOpt { #[structopt(flatten)] + #[serde(flatten)] pub conn: Connection, /// Bin file #[structopt(parse(from_os_str))] @@ -85,6 +88,7 @@ pub struct CheckOpt { #[derive(StructOpt, Deserialize)] pub struct DumpOpt { #[structopt(flatten)] + #[serde(flatten)] pub conn: Connection, /// Output file #[structopt(parse(from_os_str))] diff --git a/libblflash/.gitignore b/libblflash/.gitignore new file mode 100644 index 0000000..4fffb2f --- /dev/null +++ b/libblflash/.gitignore @@ -0,0 +1,2 @@ +/target +/Cargo.lock diff --git a/libblflash/Cargo.toml b/libblflash/Cargo.toml index 0b45240..3f4a247 100644 --- a/libblflash/Cargo.toml +++ b/libblflash/Cargo.toml @@ -13,3 +13,4 @@ blflash = { version = "0.3", path = "../blflash" } [target.'cfg(target_arch = "wasm32")'.dependencies] wasm-bindgen = { version = "0.2", features = ["serde-serialize"] } wasm-bindgen-futures = "0.4" +console_error_panic_hook = "0.1" diff --git a/libblflash/index.html b/libblflash/index.html new file mode 100644 index 0000000..390ca6f --- /dev/null +++ b/libblflash/index.html @@ -0,0 +1,9 @@ + + + + blflash web + + + + + diff --git a/libblflash/index.js b/libblflash/index.js new file mode 100644 index 0000000..658857c --- /dev/null +++ b/libblflash/index.js @@ -0,0 +1,18 @@ +import init, { dump, FS } from './pkg/libblflash.js' + +async function main() { + console.log('load wasm') + await init() + console.log('wasm loaded') + + const r = await dump({ + port: 'port', + baud_rate: 115200, + initial_baud_rate: 115200, + output: "output.bin", + start: 0, + end: 0x100000, + }) + console.log(r) +} +main() diff --git a/libblflash/src/lib.rs b/libblflash/src/lib.rs index 8ee7b3f..30f5d46 100644 --- a/libblflash/src/lib.rs +++ b/libblflash/src/lib.rs @@ -1,5 +1,7 @@ -use blflash::{Boot2Opt, Connection, Error, FlashOpt}; +use blflash::{Boot2Opt, Connection, Error, FlashOpt, DumpOpt, fs}; use wasm_bindgen::prelude::*; +use std::path::PathBuf; +mod utils; fn map_result(r: Result<(), Error>) -> JsValue { match r { @@ -10,7 +12,38 @@ fn map_result(r: Result<(), Error>) -> JsValue { #[wasm_bindgen] pub async fn flash(opt: JsValue) -> JsValue { + utils::set_panic_hook(); + let opt: FlashOpt = opt.into_serde().unwrap(); let result = blflash::flash(opt).await; map_result(result) } + +#[wasm_bindgen] +pub async fn dump(opt: JsValue) -> JsValue { + utils::set_panic_hook(); + + let opt: DumpOpt = opt.into_serde().unwrap(); + let result = blflash::dump(opt).await; + map_result(result) +} + +struct FS; + +#[wasm_bindgen] +impl FS { + #[wasm_bindgen] + pub fn read_file(path: String) -> Option> { + fs::fs_read_file(PathBuf::from(path)) + } + + #[wasm_bindgen] + pub fn write_file(path: String, content: Vec) { + fs::fs_write_file(PathBuf::from(path), content) + } + + #[wasm_bindgen] + pub fn remove_file(path: String) { + fs::fs_remove_file(PathBuf::from(path)) + } +} diff --git a/libblflash/src/utils.rs b/libblflash/src/utils.rs new file mode 100644 index 0000000..de02986 --- /dev/null +++ b/libblflash/src/utils.rs @@ -0,0 +1,3 @@ +pub fn set_panic_hook() { + console_error_panic_hook::set_once(); +}