1
- use super :: logs:: advance;
2
1
use crate :: args:: MonitorArgs ;
3
2
use crate :: net:: connect;
3
+ use crate :: serial:: { is_timeout, SerialStream } ;
4
4
use anyhow:: { Context , Result } ;
5
5
use crossterm:: { cursor, event, execute, style, terminal} ;
6
6
use firefly_types:: { serial, Encode } ;
@@ -15,8 +15,6 @@ const RBORD: u16 = 21;
15
15
const KB : u32 = 1024 ;
16
16
const MB : u32 = 1024 * KB ;
17
17
18
- type Port = Box < dyn serialport:: SerialPort > ;
19
-
20
18
#[ derive( Default ) ]
21
19
struct Stats {
22
20
update : Option < serial:: Fuel > ,
@@ -54,35 +52,18 @@ pub fn cmd_monitor(_vfs: &Path, args: &MonitorArgs) -> Result<()> {
54
52
}
55
53
56
54
fn monitor_device ( port : & str , args : & MonitorArgs ) -> Result < ( ) > {
57
- let mut port = connect_device ( port, args) ?;
55
+ let mut stream = connect_device ( port, args) ?;
58
56
let mut stats = Stats :: default ( ) ;
59
- request_device_stats ( & mut port, & mut stats) ?;
60
- let mut buf = Vec :: new ( ) ;
57
+ request_device_stats ( & mut stream, & mut stats) ?;
61
58
loop {
62
59
if should_exit ( ) {
63
60
return Ok ( ( ) ) ;
64
61
}
65
- buf = read_device ( & mut port , buf , & mut stats) ?;
62
+ read_device ( & mut stream , & mut stats) ?;
66
63
render_stats ( & stats) . context ( "render stats" ) ?;
67
64
}
68
65
}
69
66
70
- /// Connect to running emulator using serial USB port (JTag-over-USB).
71
- fn connect_device ( port : & str , args : & MonitorArgs ) -> Result < Port > {
72
- let port = serialport:: new ( port, args. baud_rate )
73
- . timeout ( Duration :: from_millis ( 10 ) )
74
- . open ( )
75
- . context ( "open the serial port" ) ?;
76
-
77
- execute ! (
78
- io:: stdout( ) ,
79
- terminal:: Clear ( terminal:: ClearType :: All ) ,
80
- cursor:: MoveTo ( 0 , 0 ) ,
81
- style:: Print ( "waiting for stats..." ) ,
82
- ) ?;
83
- Ok ( port)
84
- }
85
-
86
67
fn monitor_emulator ( ) -> Result < ( ) > {
87
68
let mut stream = connect_emulator ( ) ?;
88
69
let mut stats = Stats :: default ( ) ;
@@ -103,39 +84,29 @@ fn read_emulator(mut stream: TcpStream, stats: &mut Stats) -> Result<TcpStream>
103
84
let stream = connect ( ) . context ( "reconnecting" ) ?;
104
85
return Ok ( stream) ;
105
86
}
106
- parse_stats ( stats, & buf[ ..size] ) ?;
87
+ let resp = serial:: Response :: decode ( & buf[ ..size] ) . context ( "decode response" ) ?;
88
+ parse_stats ( stats, resp) ;
107
89
Ok ( stream)
108
90
}
109
91
110
92
/// Receive and parse one stats message from device.
111
- fn read_device ( port : & mut Port , mut buf : Vec < u8 > , stats : & mut Stats ) -> Result < Vec < u8 > > {
112
- let mut chunk = vec ! [ 0 ; 64 ] ;
113
- let n = match port. read ( chunk. as_mut_slice ( ) ) {
114
- Ok ( n) => n,
93
+ fn read_device ( stream : & mut SerialStream , stats : & mut Stats ) -> Result < ( ) > {
94
+ match stream. next ( ) {
95
+ Ok ( resp) => {
96
+ parse_stats ( stats, resp) ;
97
+ stats. last_msg = Some ( Instant :: now ( ) ) ;
98
+ }
115
99
Err ( err) => {
116
- if err. kind ( ) == std:: io:: ErrorKind :: TimedOut {
117
- request_device_stats ( port, stats) ?;
118
- return Ok ( buf) ;
100
+ if !is_timeout ( & err) {
101
+ return Err ( err) ;
119
102
}
120
- return Err ( err) . context ( "read from serial port" ) ;
121
103
}
122
- } ;
123
-
124
- stats. last_msg = Some ( Instant :: now ( ) ) ;
125
- buf. extend_from_slice ( & chunk[ ..n] ) ;
126
- loop {
127
- let ( frame, rest) = advance ( & buf) ;
128
- buf = Vec :: from ( rest) ;
129
- if frame. is_empty ( ) {
130
- break ;
131
- }
132
- parse_stats ( stats, & frame) ?;
133
104
}
134
- Ok ( buf )
105
+ Ok ( ( ) )
135
106
}
136
107
137
108
/// Send a message into the running device requesting to enable stats collection.
138
- fn request_device_stats ( port : & mut Port , stats : & mut Stats ) -> Result < ( ) > {
109
+ fn request_device_stats ( stream : & mut SerialStream , stats : & mut Stats ) -> Result < ( ) > {
139
110
let now = Instant :: now ( ) ;
140
111
let should_update = match stats. last_msg {
141
112
Some ( last_msg) => {
@@ -148,16 +119,12 @@ fn request_device_stats(port: &mut Port, stats: &mut Stats) -> Result<()> {
148
119
if should_update {
149
120
stats. last_msg = Some ( now) ;
150
121
let req = serial:: Request :: Stats ( true ) ;
151
- let buf = req. encode_vec ( ) . context ( "encode request" ) ?;
152
- port. write_all ( & buf[ ..] ) . context ( "send request" ) ?;
153
- port. flush ( ) . context ( "flush request" ) ?;
122
+ stream. send ( & req) ?;
154
123
}
155
124
Ok ( ( ) )
156
125
}
157
126
158
- /// Parse raw stats message using postcard. Does NOT handle COBS frames.
159
- fn parse_stats ( stats : & mut Stats , buf : & [ u8 ] ) -> Result < ( ) > {
160
- let resp = serial:: Response :: decode ( buf) . context ( "decode response" ) ?;
127
+ fn parse_stats ( stats : & mut Stats , resp : serial:: Response ) {
161
128
match resp {
162
129
serial:: Response :: Cheat ( _) => { }
163
130
serial:: Response :: Log ( log) => {
@@ -180,7 +147,22 @@ fn parse_stats(stats: &mut Stats, buf: &[u8]) -> Result<()> {
180
147
}
181
148
serial:: Response :: Memory ( mem) => stats. mem = Some ( mem) ,
182
149
}
183
- Ok ( ( ) )
150
+ }
151
+
152
+ /// Connect to running emulator using serial USB port (JTag-over-USB).
153
+ fn connect_device ( port : & str , args : & MonitorArgs ) -> Result < SerialStream > {
154
+ let port = serialport:: new ( port, args. baud_rate )
155
+ . timeout ( Duration :: from_millis ( 10 ) )
156
+ . open ( )
157
+ . context ( "open the serial port" ) ?;
158
+
159
+ execute ! (
160
+ io:: stdout( ) ,
161
+ terminal:: Clear ( terminal:: ClearType :: All ) ,
162
+ cursor:: MoveTo ( 0 , 0 ) ,
163
+ style:: Print ( "waiting for stats..." ) ,
164
+ ) ?;
165
+ Ok ( SerialStream :: new ( port) )
184
166
}
185
167
186
168
/// Connect to a running emulator and enable stats.
0 commit comments