use cxx::{type_id, CxxString, ExternType};
#[cxx::bridge]
pub mod lib {
#[repr(u32)]
enum Parity {
ParityNone,
ParityOdd,
ParityEven,
}
#[repr(u32)]
enum StopBit {
StopBitOne,
StopBitOneFive,
StopBitTwo,
}
#[derive(Debug, Clone, Default)]
pub struct FlasherInfoRs {
name: String,
chipId: u32,
extChipId: u32,
version: String,
address: u32,
numPages: u32,
pageSize: u32,
totalSize: u32,
numPlanes: u32,
security: bool,
bootFlash: bool,
bod: bool,
bor: bool,
canBootFlash: bool,
canBod: bool,
canBor: bool,
canChipErase: bool,
canWriteBuffer: bool,
canChecksumBuffer: bool,
lockRegions: Vec<bool>,
uniqueId: Vec<u32>,
}
unsafe extern "C++" {
include!("bossa/src/BossaObserver.h");
include!("bossa/src/Device.h");
include!("bossa/src/Flash.h");
include!("bossa/src/Flasher.h");
include!("bossa/src/Info.h");
include!("bossa/src/PortFactory.h");
include!("bossa/src/Samba.h");
include!("bossa/src/SerialPort.h");
type SerialPort;
type Parity;
type StopBit;
fn open(
self: Pin<&mut SerialPort>,
baud: i32,
data: i32,
parity: Parity,
stop: StopBit,
) -> bool;
fn close(self: Pin<&mut SerialPort>);
fn setDTR(self: Pin<&mut SerialPort>, dtr: bool);
fn setRTS(self: Pin<&mut SerialPort>, rts: bool);
type PortFactory;
fn new_port_factory() -> UniquePtr<PortFactory>;
fn default_name(self: Pin<&mut PortFactory>) -> &CxxString;
fn create_port(
self: Pin<&mut PortFactory>,
name: &CxxString,
is_usb: bool,
) -> UniquePtr<SerialPort>;
type Device;
fn new_device(samba: Pin<&mut Samba>) -> UniquePtr<Device>;
fn create(self: Pin<&mut Device>);
fn getFlash(self: Pin<&mut Device>) -> &UniquePtr<Flash>;
type FlasherObserver;
type ObserverCallback = crate::ObserverCallback;
unsafe fn new_bossa_observer(callback: ObserverCallback) -> UniquePtr<FlasherObserver>;
type Flash;
type Flasher;
fn new_flasher(
samba: Pin<&mut Samba>,
device: Pin<&mut Device>,
observer: Pin<&mut FlasherObserver>,
) -> UniquePtr<Flasher>;
fn erase(self: Pin<&mut Flasher>, foffset: u32);
unsafe fn write(self: Pin<&mut Flasher>, filename: *const c_char, foffset: u32);
unsafe fn verify(
self: Pin<&mut Flasher>,
filename: *const c_char,
pageErrors: &mut u32,
totalErrors: &mut u32,
foffset: u32,
) -> bool;
unsafe fn read(self: Pin<&mut Flasher>, filename: *const c_char, fsize: u32, foffset: u32);
fn lock(self: Pin<&mut Flasher>, regionArg: &CxxString, enable: bool);
fn info(self: Pin<&mut Flasher>, info: Pin<&mut FlasherInfo>);
fn setBod(self: Pin<&mut Flasher>, enable: bool);
fn setBootFlash(self: Pin<&mut Flasher>, enable: bool);
fn setBor(self: Pin<&mut Flasher>, enable: bool);
fn setSecurity(self: Pin<&mut Flasher>);
fn writeOptions(self: Pin<&mut Flasher>);
fn reset(self: Pin<&mut Flasher>);
type FlasherInfo;
fn print(self: Pin<&mut FlasherInfo>);
fn new_flasher_info() -> UniquePtr<FlasherInfo>;
fn flasherinfo2flasherinfors(info: &FlasherInfo, rsinfo: &mut FlasherInfoRs);
type Samba;
pub fn new_samba() -> UniquePtr<Samba>;
fn connect(self: Pin<&mut Samba>, port: UniquePtr<SerialPort>, bps: i32) -> bool;
fn setDebug(self: Pin<&mut Samba>, debug: bool);
}
}
#[repr(transparent)]
pub struct ObserverCallback(pub extern "C" fn(message: &CxxString));
unsafe impl ExternType for ObserverCallback {
type Id = type_id!("ObserverCallback");
type Kind = cxx::kind::Trivial;
}
impl lib::FlasherInfoRs {
pub fn unique_id(&self) -> String {
let mut id = String::new();
for i in 0..self.uniqueId.len() {
id.push_str(&format!("{:08x}", self.uniqueId[i]));
}
id
}
pub fn info(&self) -> String {
let mut out = String::new();
let align = 12;
out.push_str(
format!(
"{key:<align$} : {value}\n",
align = align,
key = "Device",
value = self.name
)
.as_str(),
);
out.push_str(
format!(
"{key:<align$} : {value}\n",
align = align,
key = "Version",
value = self.version
)
.as_str(),
);
out.push_str(
format!(
"{key:<align$} : {value:#x}\n",
align = align,
key = "Address",
value = self.address
)
.as_str(),
);
out.push_str(
format!(
"{key:<align$} : {value}\n",
align = align,
key = "Pages",
value = self.numPages
)
.as_str(),
);
out.push_str(
format!(
"{key:<align$} : {value} bytes\n",
align = align,
key = "Page Size",
value = self.pageSize,
)
.as_str(),
);
out.push_str(
format!(
"{key:<align$} : {value} bytes\n",
align = align,
key = "Total Size",
value = self.totalSize
)
.as_str(),
);
out.push_str(
format!(
"{key:<align$} : {value}\n",
align = align,
key = "Planes",
value = self.numPlanes
)
.as_str(),
);
out.push_str(
format!(
"{key:<align$} : {value}\n",
align = align,
key = "Lock Regions",
value = self.lockRegions.len()
)
.as_str(),
);
out.push_str(
format!(
"{key:<align$} : {value}\n",
align = align,
key = "Locked",
value = self.locked_regions(),
)
.as_str(),
);
out.push_str(
format!(
"{key:<align$} : {value}\n",
align = align,
key = "Security",
value = self.security
)
.as_str(),
);
out.push_str(
format!(
"{key:<align$} : {value}\n",
align = align,
key = "Boot Flash",
value = self.bootFlash
)
.as_str(),
);
out.push_str(
format!(
"{key:<align$} : {value}\n",
align = align,
key = "Unique Id",
value = self.unique_id()
)
.as_str(),
);
out
}
fn locked_regions(&self) -> String {
let mut out = String::new();
let mut any_locked = false;
for (i, locked) in self.lockRegions.iter().enumerate() {
if *locked {
if !any_locked {
any_locked = true;
out.push_str(format!("{}", i).as_str());
} else {
out.push_str(format!(",{}", i).as_str());
}
}
}
if !any_locked {
out = "none".to_string();
}
out
}
}