firmware for my Touchscreen E-Paper Input Module for Framework Laptop 16
1use std::fs::File;
2use std::io::{Read, Write};
3use std::path::PathBuf;
4use std::time::Duration;
5use clap::{Parser, Subcommand};
6use serialport::SerialPort;
7use tar::Archive;
8use eepy_serial::{Event, Response, SerialCommand, SerialError};
9
10#[derive(Parser, Debug)]
11#[command(version, about, long_about = None)]
12struct Args {
13 #[arg(short = 'p', long)]
14 serial_port: String,
15
16 #[command(subcommand)]
17 command: Subcommands,
18}
19
20#[derive(Subcommand, Debug)]
21enum Subcommands {
22 EnterHostApp,
23 ExitHostApp,
24
25 Refresh {
26 #[arg(long, action)]
27 fast: bool,
28 #[arg(short, long)]
29 image: PathBuf,
30 },
31
32 DisableTouch,
33 EnableTouch,
34 NextEvent,
35
36 UploadProgram {
37 package: PathBuf,
38 },
39}
40
41use Subcommands::*;
42
43fn write(serial: &mut Box<dyn SerialPort>, command: SerialCommand, data: &[u8]) -> Result<(), SerialError> {
44 serial.write_all(&[command as u8]).unwrap();
45 serial.write_all(data).unwrap();
46 let mut response_buf = [0u8];
47 serial.read_exact(&mut response_buf).unwrap();
48 Response::try_from(response_buf[0]).unwrap().into()
49}
50
51fn next_event(serial: &mut Box<dyn SerialPort>) -> Result<Option<Event>, SerialError> {
52 write(serial, SerialCommand::NextEvent, &[])?;
53 let mut event_buf = [0u8; 32];
54 serial.read(&mut event_buf).unwrap();
55 Ok(postcard::from_bytes(&event_buf).unwrap())
56}
57
58fn upload_program(serial: &mut Box<dyn SerialPort>, path: PathBuf) -> Result<(), SerialError> {
59 write(serial, SerialCommand::GetProgramSlot, &[])?;
60 let mut slot_n = [0u8];
61 serial.read_exact(&mut slot_n).unwrap();
62 let slot_n = slot_n[0];
63
64 let file = File::open(path).unwrap();
65 let zstd_reader = zstd::stream::read::Decoder::new(file).unwrap();
66 let mut tar = Archive::new(zstd_reader);
67 for file in tar.entries().unwrap() {
68 let mut file = file.unwrap();
69 if file.path().unwrap().to_str().unwrap().ends_with(&format!(".s{slot_n:02}.epb")) {
70 println!("Uploading {}", file.path().unwrap().to_str().unwrap());
71 let mut buf = vec![0u8; file.size() as usize];
72 file.read_exact(&mut buf).unwrap();
73 write(serial, SerialCommand::UploadProgram, &buf)?;
74 return Ok(());
75 }
76 }
77
78 panic!("App package did not contain binary for slot {slot_n}");
79}
80
81fn main() {
82 let args = Args::parse();
83
84 // Baud rate setting doesn't matter for pure USB serial so use 0
85 let mut port = serialport::new(&args.serial_port, 0)
86 .timeout(Duration::from_secs(60))
87 .open()
88 .expect(&format!("Failed to open serial port {}", args.serial_port));
89
90 match args.command {
91 EnterHostApp => write(&mut port, SerialCommand::EnterHostApp, &[]).unwrap(),
92 ExitHostApp => write(&mut port, SerialCommand::ExitHostApp, &[]).unwrap(),
93 Refresh { fast, image } => {
94 let data = std::fs::read(image).unwrap();
95 let cmd = if fast { SerialCommand::RefreshFast } else { SerialCommand::RefreshNormal };
96 write(&mut port, cmd, &data).unwrap();
97 },
98 DisableTouch => write(&mut port, SerialCommand::DisableTouch, &[]).unwrap(),
99 EnableTouch => write(&mut port, SerialCommand::EnableTouch, &[]).unwrap(),
100 NextEvent => println!("{:?}", next_event(&mut port).unwrap()),
101 UploadProgram { package } => upload_program(&mut port, package).unwrap(),
102 };
103}