@@ -49,19 +49,72 @@ pub fn get_serial_port(matches: &ConnectArgs, config: &Config) -> Result<String,
49
49
}
50
50
}
51
51
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
54
+ #[ cfg( all( target_os = "linux" , target_env = "musl" ) ) ]
52
55
fn detect_usb_serial_ports ( ) -> Result < Vec < SerialPortInfo > > {
56
+ use serialport:: UsbPortInfo ;
57
+ use std:: fs:: read_link;
58
+ use std:: fs:: read_to_string;
59
+ use std:: path:: PathBuf ;
60
+
53
61
let ports = available_ports ( ) . into_diagnostic ( ) ?;
54
62
let ports = ports
55
- . iter ( )
56
- . filter_map ( |port_info| match port_info. port_type {
57
- SerialPortType :: UsbPort ( ..) => Some ( port_info. to_owned ( ) ) ,
58
- _ => None ,
63
+ . into_iter ( )
64
+ . filter_map ( |port_info| {
65
+ // with musl, the paths we get are `/sys/class/tty/*`
66
+ let path = PathBuf :: from ( & port_info. port_name ) ;
67
+
68
+ // this will give something like `/sys/devices/pci0000:00/0000:00:07.1/0000:0c:00.3/usb5/5-3/5-3.1/5-3.1:1.0/ttyUSB0/tty/ttyUSB0`
69
+ let mut parent_dev = path. canonicalize ( ) . ok ( ) ?;
70
+
71
+ // walk up 3 dirs to get to the device hosting the tty `/sys/devices/pci0000:00/0000:00:07.1/0000:0c:00.3/usb5/5-3/5-3.1/5-3.1:1.0`
72
+ parent_dev. pop ( ) ;
73
+ parent_dev. pop ( ) ;
74
+ parent_dev. pop ( ) ;
75
+
76
+ // check that the device is using the usb subsystem
77
+ read_link ( parent_dev. join ( "subsystem" ) )
78
+ . ok ( )
79
+ . filter ( |subsystem| subsystem. ends_with ( "usb" ) ) ?;
80
+
81
+ let interface = read_to_string ( parent_dev. join ( "interface" ) )
82
+ . ok ( )
83
+ . map ( |s| s. trim ( ) . to_string ( ) ) ;
84
+
85
+ // /sys/devices/pci0000:00/0000:00:07.1/0000:0c:00.3/usb5/5-3/5-3.1
86
+ parent_dev. pop ( ) ;
87
+
88
+ let vid = read_to_string ( parent_dev. join ( "idVendor" ) ) . ok ( ) ?;
89
+ let pid = read_to_string ( parent_dev. join ( "idProduct" ) ) . ok ( ) ?;
90
+
91
+ Some ( SerialPortInfo {
92
+ port_type : SerialPortType :: UsbPort ( UsbPortInfo {
93
+ vid : u16:: from_str_radix ( vid. trim ( ) , 16 ) . ok ( ) ?,
94
+ pid : u16:: from_str_radix ( pid. trim ( ) , 16 ) . ok ( ) ?,
95
+ product : interface,
96
+ serial_number : None ,
97
+ manufacturer : None ,
98
+ } ) ,
99
+ port_name : format ! ( "/dev/{}" , path. file_name( ) ?. to_str( ) ?) ,
100
+ } )
59
101
} )
60
102
. collect :: < Vec < _ > > ( ) ;
61
103
62
104
Ok ( ports)
63
105
}
64
106
107
+ #[ cfg( not( all( target_os = "linux" , target_env = "musl" ) ) ) ]
108
+ fn detect_usb_serial_ports ( ) -> Result < Vec < SerialPortInfo > > {
109
+ let ports = available_ports ( ) . into_diagnostic ( ) ?;
110
+ let ports = ports
111
+ . into_iter ( )
112
+ . filter ( |port_info| matches ! ( & port_info. port_type, SerialPortType :: UsbPort ( ..) ) )
113
+ . collect :: < Vec < _ > > ( ) ;
114
+
115
+ Ok ( ports)
116
+ }
117
+
65
118
/// USB UART adapters which are known to be on common dev boards
66
119
const KNOWN_DEVICES : & [ UsbDevice ] = & [
67
120
UsbDevice {
0 commit comments