2022-11-18 14:33:19 +00:00
|
|
|
use std::{
|
|
|
|
sync::{
|
|
|
|
atomic::{AtomicBool, Ordering::SeqCst},
|
|
|
|
Mutex,
|
|
|
|
},
|
|
|
|
thread,
|
|
|
|
};
|
2022-10-26 05:28:59 +00:00
|
|
|
|
2022-11-07 07:02:12 +00:00
|
|
|
use gtk::{prelude::*, PolicyType, TextView};
|
2022-10-26 05:28:59 +00:00
|
|
|
use gtk::{Application, ApplicationWindow};
|
|
|
|
|
2022-11-07 07:02:12 +00:00
|
|
|
use gtk::{Button, Entry, Orientation, ScrolledWindow};
|
2022-10-26 05:28:59 +00:00
|
|
|
|
2022-10-27 06:08:19 +00:00
|
|
|
use glib;
|
|
|
|
|
2022-10-26 05:28:59 +00:00
|
|
|
mod port;
|
|
|
|
use port::*;
|
|
|
|
|
|
|
|
static CONNECTED: AtomicBool = AtomicBool::new(false);
|
2022-11-18 14:33:19 +00:00
|
|
|
static PORT: Mutex<Option<Port>> = Mutex::new(None);
|
2022-10-26 05:28:59 +00:00
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let app = Application::builder()
|
|
|
|
.application_id("org.example.HelloWorld")
|
|
|
|
.build();
|
|
|
|
|
2022-10-27 06:08:19 +00:00
|
|
|
app.connect_activate(move |app| {
|
2022-10-26 05:28:59 +00:00
|
|
|
// We create the main window.
|
|
|
|
let window = ApplicationWindow::builder()
|
|
|
|
.application(app)
|
|
|
|
.default_width(320)
|
|
|
|
.default_height(200)
|
|
|
|
.title("Hello, World!")
|
|
|
|
.build();
|
|
|
|
|
|
|
|
let master_box = gtk::Box::new(Orientation::Vertical, 5);
|
|
|
|
let top_bar_box = gtk::Box::new(Orientation::Horizontal, 5);
|
|
|
|
let pid = Entry::builder().text("0x27dd").editable(true).build();
|
|
|
|
let vid = Entry::builder().text("0x16c0").editable(true).build();
|
|
|
|
let connect_button = Button::with_label("Connect");
|
2022-11-18 14:33:19 +00:00
|
|
|
let reset_button = Button::with_label("Reset");
|
2022-10-27 06:08:19 +00:00
|
|
|
let serial_info = TextView::new();
|
2022-11-07 07:02:12 +00:00
|
|
|
let scrolled_window = ScrolledWindow::builder()
|
|
|
|
.vscrollbar_policy(PolicyType::Automatic)
|
|
|
|
.child(&serial_info)
|
|
|
|
.build();
|
2022-10-26 05:28:59 +00:00
|
|
|
|
|
|
|
top_bar_box.pack_end(&connect_button, true, true, 3);
|
2022-11-18 14:33:19 +00:00
|
|
|
top_bar_box.pack_end(&reset_button, true, true, 3);
|
2022-10-26 05:28:59 +00:00
|
|
|
top_bar_box.pack_end(&vid, true, true, 3);
|
|
|
|
top_bar_box.pack_end(&pid, true, true, 3);
|
|
|
|
|
2022-11-07 07:02:12 +00:00
|
|
|
master_box.pack_end(&scrolled_window, true, true, 3);
|
2022-10-26 05:28:59 +00:00
|
|
|
master_box.pack_end(&top_bar_box, false, true, 3);
|
|
|
|
|
2022-10-27 06:08:19 +00:00
|
|
|
let (tx, rx) = glib::MainContext::channel(glib::PRIORITY_DEFAULT);
|
|
|
|
|
|
|
|
std::thread::spawn(move || {
|
|
|
|
// loop forever
|
|
|
|
loop {
|
2022-11-18 14:33:19 +00:00
|
|
|
let mut port_lock = PORT.lock().unwrap();
|
|
|
|
|
|
|
|
if let Some(port) = &mut *port_lock {
|
|
|
|
// handle incoming message
|
|
|
|
match port.read().unwrap() {
|
|
|
|
SerialReadResult::Message(msg) => {
|
|
|
|
if !msg.is_empty() {
|
|
|
|
tx.send(msg).unwrap();
|
2022-10-27 06:08:19 +00:00
|
|
|
}
|
|
|
|
}
|
2022-11-18 14:33:19 +00:00
|
|
|
SerialReadResult::UtfConversion(err) => println!("{:?}", err),
|
|
|
|
SerialReadResult::Timeout => (),
|
2022-10-27 06:08:19 +00:00
|
|
|
}
|
|
|
|
}
|
2022-11-18 14:33:19 +00:00
|
|
|
|
2022-11-19 05:16:03 +00:00
|
|
|
drop(port_lock);
|
|
|
|
|
2022-11-18 14:33:19 +00:00
|
|
|
thread::sleep(Duration::from_millis(10));
|
2022-10-27 06:08:19 +00:00
|
|
|
}
|
|
|
|
});
|
2022-10-26 05:28:59 +00:00
|
|
|
|
|
|
|
connect_button.connect_clicked(move |_| {
|
|
|
|
if !CONNECTED.load(SeqCst) {
|
|
|
|
let usb_id = UsbId {
|
|
|
|
vendor_id: u16::from_str_radix(
|
|
|
|
vid.buffer().text().trim_start_matches("0x"),
|
|
|
|
16,
|
|
|
|
)
|
|
|
|
.unwrap(),
|
|
|
|
product_id: u16::from_str_radix(
|
|
|
|
pid.buffer().text().trim_start_matches("0x"),
|
|
|
|
16,
|
|
|
|
)
|
|
|
|
.unwrap(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let serialport_settings = SerialPortSettings {
|
2022-10-27 06:08:19 +00:00
|
|
|
baud_rate: 9600,
|
2022-10-26 05:28:59 +00:00
|
|
|
data_bits: DataBits::Eight,
|
|
|
|
parity: Parity::None,
|
|
|
|
stop_bits: StopBits::One,
|
|
|
|
flow_control: FlowControl::None,
|
|
|
|
timeout: Duration::from_millis(2500),
|
|
|
|
};
|
|
|
|
|
2022-10-27 06:08:19 +00:00
|
|
|
if let Ok(port) = Port::open(usb_id, serialport_settings) {
|
2022-10-26 05:28:59 +00:00
|
|
|
CONNECTED.store(true, SeqCst);
|
2022-11-07 07:02:12 +00:00
|
|
|
|
2022-11-18 14:33:19 +00:00
|
|
|
*PORT.lock().unwrap() = Some(port);
|
2022-10-26 05:28:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2022-11-18 14:33:19 +00:00
|
|
|
reset_button.connect_clicked(move |_| {
|
|
|
|
if CONNECTED.load(SeqCst) {
|
|
|
|
CONNECTED.store(false, SeqCst);
|
|
|
|
|
|
|
|
let mut port_lock = PORT.lock().unwrap();
|
|
|
|
|
|
|
|
if let Some(port) = &mut *port_lock {
|
|
|
|
port.write("reset").unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
*port_lock = None;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2022-10-27 06:08:19 +00:00
|
|
|
let buffer = serial_info.buffer().unwrap();
|
|
|
|
|
|
|
|
rx.attach(None, move |message| {
|
|
|
|
if !message.is_empty() {
|
|
|
|
buffer.insert(&mut buffer.end_iter(), &format!("{}\n", message));
|
2022-11-07 07:02:12 +00:00
|
|
|
serial_info.scroll_to_iter(&mut buffer.end_iter(), 0.0, true, 0.0, 0.0);
|
2022-10-27 06:08:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
glib::Continue(true)
|
|
|
|
});
|
|
|
|
|
|
|
|
window.add(&master_box);
|
|
|
|
|
2022-10-26 05:28:59 +00:00
|
|
|
// Don't forget to make all widgets visible.
|
|
|
|
window.show_all();
|
|
|
|
});
|
|
|
|
|
|
|
|
app.run();
|
|
|
|
}
|