Skip to content

Commit 85c8eb8

Browse files
committed
Refactor get_serial_port function to return SerialPortInfo instead of port name
1 parent cc1c850 commit 85c8eb8

File tree

4 files changed

+74
-64
lines changed

4 files changed

+74
-64
lines changed

espflash/src/cli/mod.rs

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,38 @@
1-
use self::clap::ConnectArgs;
21
/// CLI utilities shared between espflash and cargo-espflash
32
///
4-
/// No stability guaranties applies
3+
/// No stability guaranties apply
54
use config::Config;
65
use miette::{Result, WrapErr};
7-
use serialport::FlowControl;
6+
use serialport::{FlowControl, SerialPortType};
87

9-
use crate::cli::serial::get_serial_port;
10-
use crate::{error::Error, Flasher};
8+
use self::clap::ConnectArgs;
9+
use crate::{cli::serial::get_serial_port_info, error::Error, Flasher};
1110

1211
pub mod clap;
1312
pub mod config;
14-
mod line_endings;
1513
pub mod monitor;
14+
15+
mod line_endings;
1616
mod serial;
1717

1818
pub fn connect(matches: &ConnectArgs, config: &Config) -> Result<Flasher> {
19-
let port = get_serial_port(matches, config)?;
19+
let port_info = get_serial_port_info(matches, config)?;
2020

2121
// Attempt to open the serial port and set its initial baud rate.
22-
println!("Serial port: {}", port);
22+
println!("Serial port: {}", port_info.port_name);
2323
println!("Connecting...\n");
24-
let serial = serialport::new(&port, 115_200)
24+
let serial = serialport::new(&port_info.port_name, 115_200)
2525
.flow_control(FlowControl::None)
2626
.open()
2727
.map_err(Error::from)
28-
.wrap_err_with(|| format!("Failed to open serial port {}", port))?;
28+
.wrap_err_with(|| format!("Failed to open serial port {}", port_info.port_name))?;
29+
30+
// NOTE: since `get_serial_port_info` filters out all non-USB serial ports, we
31+
// can just pretend the remaining types don't exist here.
32+
let port_info = match port_info.port_type {
33+
SerialPortType::UsbPort(info) => info,
34+
_ => unreachable!(),
35+
};
2936

30-
Ok(Flasher::connect(serial, matches.speed)?)
37+
Ok(Flasher::connect(serial, port_info, matches.speed)?)
3138
}

espflash/src/cli/serial.rs

Lines changed: 42 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,33 @@
1-
use super::config::Config;
21
use crossterm::style::Stylize;
32
use dialoguer::{theme::ColorfulTheme, Confirm, Select};
43
use miette::{IntoDiagnostic, Result};
54
use serialport::{available_ports, SerialPortInfo, SerialPortType};
65

7-
use super::clap::ConnectArgs;
8-
use crate::cli::config::UsbDevice;
9-
use crate::error::Error;
6+
use super::{clap::ConnectArgs, config::Config};
7+
use crate::{cli::config::UsbDevice, error::Error};
108

11-
pub fn get_serial_port(matches: &ConnectArgs, config: &Config) -> Result<String, Error> {
9+
pub fn get_serial_port_info(
10+
matches: &ConnectArgs,
11+
config: &Config,
12+
) -> Result<SerialPortInfo, Error> {
1213
// A serial port should be specified either as a command-line argument or in a
1314
// configuration file. In the case that both have been provided the command-line
1415
// argument takes precedence.
1516
//
1617
// Users may optionally specify the device's VID and PID in the configuration
17-
// file. If no VID/PID have been provided, the user will always be prompted to
18-
// select a serial device. If some VID/PID have been provided the user will be
19-
// prompted to select a serial device, unless there is only one found and its
20-
// VID/PID matches the configured values.
21-
if let Some(serial) = &matches.serial {
22-
Ok(serial.to_owned())
18+
// file. If no VID/PID has been provided, the user will always be prompted to
19+
// select a serial port. If some VID and PID were provided then the user will
20+
// also be prompted to select a port, unless there is only one found and its VID
21+
// and PID match the configured values.
22+
let ports = detect_usb_serial_ports().unwrap_or_default();
23+
24+
let maybe_port = if let Some(serial) = &matches.serial {
25+
find_serial_port(&ports, serial.to_owned())
2326
} else if let Some(serial) = &config.connection.serial {
24-
Ok(serial.to_owned())
25-
} else if let Ok(ports) = detect_usb_serial_ports() {
27+
find_serial_port(&ports, serial.to_owned())
28+
} else if ports.len() > 0 {
2629
let (port, matches) = select_serial_port(ports, config)?;
27-
match port.port_type {
30+
match &port.port_type {
2831
SerialPortType::UsbPort(usb_info) if !matches => {
2932
if Confirm::with_theme(&ColorfulTheme::default())
3033
.with_prompt("Remember this serial port for future use?")
@@ -43,20 +46,39 @@ pub fn get_serial_port(matches: &ConnectArgs, config: &Config) -> Result<String,
4346
}
4447
_ => {}
4548
}
46-
Ok(port.port_name)
49+
50+
Some(port)
51+
} else {
52+
None
53+
};
54+
55+
if let Some(port_info) = maybe_port {
56+
Ok(port_info)
4757
} else {
4858
Err(Error::NoSerial)
4959
}
5060
}
5161

52-
/// serialport's autodetect doesn't provide any port information when using musl linux
53-
/// we can do some manual parsing of sysfs to get the relevant bits without udev
62+
/// Given a vector of `SerialPortInfo` structs, attempt to find and return one
63+
/// whose `port_name` field matches the provided `name` argument.
64+
fn find_serial_port(ports: &Vec<SerialPortInfo>, name: String) -> Option<SerialPortInfo> {
65+
ports
66+
.iter()
67+
.find(|port| port.port_name == name)
68+
.map(|port| port.to_owned())
69+
}
70+
71+
/// serialport's autodetect doesn't provide any port information when using musl
72+
/// linux we can do some manual parsing of sysfs to get the relevant bits
73+
/// without udev
5474
#[cfg(all(target_os = "linux", target_env = "musl"))]
5575
fn detect_usb_serial_ports() -> Result<Vec<SerialPortInfo>> {
76+
use std::{
77+
fs::{read_link, read_to_string},
78+
path::PathBuf,
79+
};
80+
5681
use serialport::UsbPortInfo;
57-
use std::fs::read_link;
58-
use std::fs::read_to_string;
59-
use std::path::PathBuf;
6082

6183
let ports = available_ports().into_diagnostic()?;
6284
let ports = ports

espflash/src/connection.rs

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::{
66

77
use binread::{io::Cursor, BinRead, BinReaderExt};
88
use bytemuck::{Pod, Zeroable};
9-
use serialport::{available_ports, SerialPort, SerialPortType};
9+
use serialport::{SerialPort, UsbPortInfo};
1010
use slip_codec::SlipDecoder;
1111

1212
use crate::{
@@ -29,6 +29,7 @@ pub struct CommandResponse {
2929

3030
pub struct Connection {
3131
serial: Box<dyn SerialPort>,
32+
port_info: UsbPortInfo,
3233
decoder: SlipDecoder,
3334
}
3435

@@ -42,9 +43,10 @@ struct WriteRegParams {
4243
}
4344

4445
impl Connection {
45-
pub fn new(serial: Box<dyn SerialPort>) -> Self {
46+
pub fn new(serial: Box<dyn SerialPort>, port_info: UsbPortInfo) -> Self {
4647
Connection {
4748
serial,
49+
port_info,
4850
decoder: SlipDecoder::new(),
4951
}
5052
}
@@ -62,33 +64,8 @@ impl Connection {
6264
Ok(())
6365
}
6466

65-
// This function is probably redundant there should be another way how to get
66-
// PID in src/cli/mod.rs
67-
pub fn get_pid(&self) -> u16 {
68-
match available_ports() {
69-
Ok(ports) => {
70-
for p in ports {
71-
match p.port_type {
72-
SerialPortType::UsbPort(info) => {
73-
if self.serial.name().unwrap() == p.port_name {
74-
return info.pid;
75-
}
76-
}
77-
_ => {}
78-
}
79-
}
80-
}
81-
Err(e) => {
82-
eprintln!("{:?}", e);
83-
eprintln!("Error listing serial ports");
84-
}
85-
}
86-
87-
0
88-
}
89-
9067
pub fn reset_to_flash(&mut self, extra_delay: bool) -> Result<(), Error> {
91-
if Connection::get_pid(&self) == USB_SERIAL_JTAG_PID {
68+
if self.port_info.pid == USB_SERIAL_JTAG_PID {
9269
self.serial.write_data_terminal_ready(false)?;
9370
self.serial.write_request_to_send(false)?;
9471

espflash/src/flasher.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{borrow::Cow, thread::sleep};
22

33
use bytemuck::{Pod, Zeroable, __core::time::Duration};
4-
use serialport::SerialPort;
4+
use serialport::{SerialPort, UsbPortInfo};
55
use strum_macros::Display;
66

77
use crate::{
@@ -151,10 +151,14 @@ pub struct Flasher {
151151
}
152152

153153
impl Flasher {
154-
pub fn connect(serial: Box<dyn SerialPort>, speed: Option<u32>) -> Result<Self, Error> {
154+
pub fn connect(
155+
serial: Box<dyn SerialPort>,
156+
port_info: UsbPortInfo,
157+
speed: Option<u32>,
158+
) -> Result<Self, Error> {
155159
let mut flasher = Flasher {
156-
connection: Connection::new(serial), // default baud is always 115200
157-
chip: Chip::Esp8266, // dummy, set properly later
160+
connection: Connection::new(serial, port_info), // default baud is always 115200
161+
chip: Chip::Esp8266, // dummy, set properly later
158162
flash_size: FlashSize::Flash4Mb,
159163
spi_params: SpiAttachParams::default(), // may be set when trying to attach to flash
160164
};
@@ -165,7 +169,7 @@ impl Flasher {
165169

166170
if let Some(b) = speed {
167171
match flasher.chip {
168-
Chip::Esp8266 => (), /* Not available */
172+
Chip::Esp8266 => (), // Not available
169173
_ => {
170174
if b > 115_200 {
171175
println!("WARN setting baud rate higher than 115200 can cause issues.");

0 commit comments

Comments
 (0)