Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/devices/src/serial.rs
5394 views
1
// Copyright 2017 The ChromiumOS Authors
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
pub(crate) mod sys;
6
7
use std::collections::VecDeque;
8
use std::io;
9
use std::sync::atomic::AtomicU8;
10
use std::sync::atomic::Ordering;
11
use std::sync::mpsc::channel;
12
use std::sync::mpsc::Receiver;
13
use std::sync::mpsc::TryRecvError;
14
use std::sync::Arc;
15
use std::time::Duration;
16
use std::time::Instant;
17
18
use anyhow::Context;
19
use base::error;
20
use base::warn;
21
use base::Event;
22
use base::EventToken;
23
use base::Result;
24
use base::WaitContext;
25
use base::WorkerThread;
26
use serde::Deserialize;
27
use serde::Serialize;
28
use snapshot::AnySnapshot;
29
use vm_control::DeviceId;
30
use vm_control::PlatformDeviceId;
31
32
use crate::bus::BusAccessInfo;
33
use crate::serial_device::SerialInput;
34
use crate::suspendable::DeviceState;
35
use crate::suspendable::Suspendable;
36
use crate::BusDevice;
37
38
const LOOP_SIZE: usize = 0x40;
39
40
const DATA: u8 = 0;
41
const IER: u8 = 1;
42
const IIR: u8 = 2;
43
const LCR: u8 = 3;
44
const MCR: u8 = 4;
45
const LSR: u8 = 5;
46
const MSR: u8 = 6;
47
const SCR: u8 = 7;
48
const DLAB_LOW: u8 = 0;
49
const DLAB_HIGH: u8 = 1;
50
51
const IER_RECV_BIT: u8 = 0x1;
52
const IER_THR_BIT: u8 = 0x2;
53
const IER_FIFO_BITS: u8 = 0x0f;
54
55
const IIR_FIFO_BITS: u8 = 0xc0;
56
const IIR_NONE_BIT: u8 = 0x1;
57
const IIR_THR_BIT: u8 = 0x2;
58
const IIR_RECV_BIT: u8 = 0x4;
59
60
const LSR_DATA_BIT: u8 = 0x1;
61
const LSR_EMPTY_BIT: u8 = 0x20;
62
const LSR_IDLE_BIT: u8 = 0x40;
63
64
const MCR_DTR_BIT: u8 = 0x01; // Data Terminal Ready
65
const MCR_RTS_BIT: u8 = 0x02; // Request to Send
66
const MCR_OUT1_BIT: u8 = 0x04;
67
const MCR_OUT2_BIT: u8 = 0x08;
68
const MCR_LOOP_BIT: u8 = 0x10;
69
70
const MSR_CTS_BIT: u8 = 0x10; // Clear to Send
71
const MSR_DSR_BIT: u8 = 0x20; // Data Set Ready
72
const MSR_RI_BIT: u8 = 0x40; // Ring Indicator
73
const MSR_DCD_BIT: u8 = 0x80; // Data Carrier Detect
74
75
const DEFAULT_INTERRUPT_IDENTIFICATION: u8 = IIR_NONE_BIT; // no pending interrupt
76
const DEFAULT_LINE_STATUS: u8 = LSR_EMPTY_BIT | LSR_IDLE_BIT; // THR empty and line is idle
77
const DEFAULT_LINE_CONTROL: u8 = 0x3; // 8-bits per character
78
const DEFAULT_MODEM_CONTROL: u8 = MCR_OUT2_BIT;
79
const DEFAULT_MODEM_STATUS: u8 = MSR_DSR_BIT | MSR_CTS_BIT | MSR_DCD_BIT;
80
const DEFAULT_BAUD_DIVISOR: u16 = 12; // 9600 bps
81
82
const TIMESTAMP_PREFIX_FMT: &str = "[ %F %T%.9f ]: ";
83
84
/// Emulates serial COM ports commonly seen on x86 I/O ports 0x3f8/0x2f8/0x3e8/0x2e8.
85
///
86
/// This can optionally write the guest's output to a Write trait object. To send input to the
87
/// guest, use `queue_input_bytes` directly, or give a Read trait object which will be used queue
88
/// bytes when `used_command` is called.
89
pub struct Serial {
90
// Serial port registers
91
interrupt_enable: Arc<AtomicU8>,
92
interrupt_identification: u8,
93
interrupt_evt: Event,
94
line_control: u8,
95
line_status: u8,
96
modem_control: u8,
97
modem_status: u8,
98
scratch: u8,
99
baud_divisor: u16,
100
101
// Host input/output
102
in_buffer: VecDeque<u8>,
103
in_channel: Option<Receiver<u8>>,
104
input: Option<Box<dyn SerialInput>>,
105
out: Option<Box<dyn io::Write + Send>>,
106
out_timestamp: bool,
107
last_write_was_newline: bool,
108
#[cfg(windows)]
109
pub system_params: sys::windows::SystemSerialParams,
110
device_state: DeviceState,
111
worker: Option<WorkerThread<Box<dyn SerialInput>>>,
112
}
113
114
impl Serial {
115
fn new_common(
116
interrupt_evt: Event,
117
input: Option<Box<dyn SerialInput>>,
118
out: Option<Box<dyn io::Write + Send>>,
119
out_timestamp: bool,
120
#[cfg(windows)] system_params: sys::windows::SystemSerialParams,
121
) -> Serial {
122
Serial {
123
interrupt_enable: Default::default(),
124
interrupt_identification: DEFAULT_INTERRUPT_IDENTIFICATION,
125
interrupt_evt,
126
line_control: DEFAULT_LINE_CONTROL,
127
line_status: DEFAULT_LINE_STATUS,
128
modem_control: DEFAULT_MODEM_CONTROL,
129
modem_status: DEFAULT_MODEM_STATUS,
130
scratch: 0,
131
baud_divisor: DEFAULT_BAUD_DIVISOR,
132
in_buffer: Default::default(),
133
in_channel: None,
134
input,
135
out,
136
out_timestamp,
137
last_write_was_newline: true,
138
#[cfg(windows)]
139
system_params,
140
device_state: DeviceState::Awake,
141
worker: None,
142
}
143
}
144
145
/// Returns a unique ID for the serial device.
146
pub fn device_id() -> DeviceId {
147
PlatformDeviceId::Serial.into()
148
}
149
150
/// Returns a debug label for the serial device. Used when setting up `IrqEventSource`.
151
pub fn debug_label() -> String {
152
"serial".to_owned()
153
}
154
155
/// Queues raw bytes for the guest to read and signals the interrupt if the line status would
156
/// change. These bytes will be read by the guest before any bytes from the input stream that
157
/// have not already been queued.
158
pub fn queue_input_bytes(&mut self, c: &[u8]) -> Result<()> {
159
if !c.is_empty() && !self.is_loop() {
160
self.in_buffer.extend(c);
161
self.set_data_bit();
162
self.trigger_recv_interrupt()?;
163
}
164
165
Ok(())
166
}
167
168
fn spawn_input_thread(&mut self) {
169
let mut rx = match self.input.take() {
170
Some(input) => input,
171
None => return,
172
};
173
174
let (send_channel, recv_channel) = channel();
175
176
// The interrupt enable and interrupt event are used to trigger the guest serial driver to
177
// read the serial device, which will give the VCPU threads time to queue input bytes from
178
// the input thread's buffer, changing the serial device state accordingly.
179
let interrupt_enable = self.interrupt_enable.clone();
180
let interrupt_evt = match self.interrupt_evt.try_clone() {
181
Ok(e) => e,
182
Err(e) => {
183
error!("failed to clone interrupt event: {}", e);
184
return;
185
}
186
};
187
188
self.worker = Some(WorkerThread::start(
189
format!("{} input thread", self.debug_label()),
190
move |kill_evt| {
191
let mut rx_buf = [0u8; 1];
192
193
#[derive(EventToken)]
194
enum Token {
195
Kill,
196
SerialEvent,
197
}
198
199
let wait_ctx_res: Result<WaitContext<Token>> = WaitContext::build_with(&[
200
(&kill_evt, Token::Kill),
201
(rx.get_read_notifier(), Token::SerialEvent),
202
]);
203
let wait_ctx = match wait_ctx_res {
204
Ok(wait_context) => wait_context,
205
Err(e) => {
206
error!("Failed to create wait context. {}", e);
207
return rx;
208
}
209
};
210
let mut kill_timeout = None;
211
loop {
212
let events = match wait_ctx.wait() {
213
Ok(events) => events,
214
Err(e) => {
215
error!("Failed to wait for events. {}", e);
216
return rx;
217
}
218
};
219
for event in events.iter() {
220
match event.token {
221
Token::Kill => {
222
// Ignore the kill event until there are no other events to process
223
// so that we drain `rx` as much as possible. The next
224
// `wait_ctx.wait()` call will immediately re-entry this case since
225
// we don't call `kill_evt.wait()`.
226
if events.iter().all(|e| matches!(e.token, Token::Kill)) {
227
return rx;
228
}
229
const TIMEOUT_DURATION: Duration = Duration::from_millis(500);
230
match kill_timeout {
231
None => {
232
kill_timeout = Some(Instant::now() + TIMEOUT_DURATION);
233
}
234
Some(t) => {
235
if Instant::now() >= t {
236
error!(
237
"failed to drain serial input within {:?}, giving up",
238
TIMEOUT_DURATION
239
);
240
return rx;
241
}
242
}
243
}
244
}
245
Token::SerialEvent => {
246
// Matches both is_readable and is_hungup.
247
// In the case of is_hungup, there might still be data in the
248
// buffer, and a regular read would occur. When the buffer is
249
// empty, is_hungup would read EOF.
250
match rx.read(&mut rx_buf) {
251
// Assume the stream of input has ended.
252
Ok(0) => {
253
return rx;
254
}
255
Ok(_n) => {
256
if send_channel.send(rx_buf[0]).is_err() {
257
// The receiver has disconnected.
258
return rx;
259
}
260
if (interrupt_enable.load(Ordering::SeqCst) & IER_RECV_BIT)
261
!= 0
262
{
263
interrupt_evt.signal().unwrap();
264
}
265
}
266
Err(e) => {
267
// Being interrupted is not an error, but everything else
268
// is.
269
if e.kind() != io::ErrorKind::Interrupted {
270
error!(
271
"failed to read for bytes to queue into serial device: {}",
272
e
273
);
274
return rx;
275
}
276
}
277
}
278
}
279
}
280
}
281
}
282
},
283
));
284
self.in_channel = Some(recv_channel);
285
}
286
287
fn drain_in_channel(&mut self) {
288
loop {
289
let in_channel = match self.in_channel.as_ref() {
290
Some(v) => v,
291
None => return,
292
};
293
match in_channel.try_recv() {
294
Ok(byte) => {
295
self.queue_input_bytes(&[byte]).unwrap();
296
}
297
Err(TryRecvError::Empty) => break,
298
Err(TryRecvError::Disconnected) => {
299
self.in_channel = None;
300
return;
301
}
302
}
303
}
304
}
305
306
/// Gets the interrupt event used to interrupt the driver when it needs to respond to this
307
/// device.
308
pub fn interrupt_event(&self) -> &Event {
309
&self.interrupt_evt
310
}
311
312
fn is_dlab_set(&self) -> bool {
313
(self.line_control & 0x80) != 0
314
}
315
316
fn is_recv_intr_enabled(&self) -> bool {
317
(self.interrupt_enable.load(Ordering::SeqCst) & IER_RECV_BIT) != 0
318
}
319
320
fn is_thr_intr_enabled(&self) -> bool {
321
(self.interrupt_enable.load(Ordering::SeqCst) & IER_THR_BIT) != 0
322
}
323
324
fn is_thr_intr_changed(&self, bit: u8) -> bool {
325
(self.interrupt_enable.load(Ordering::SeqCst) ^ bit) & IER_FIFO_BITS != 0
326
}
327
328
fn is_loop(&self) -> bool {
329
(self.modem_control & MCR_LOOP_BIT) != 0
330
}
331
332
fn add_intr_bit(&mut self, bit: u8) {
333
self.interrupt_identification &= !IIR_NONE_BIT;
334
self.interrupt_identification |= bit;
335
}
336
337
fn del_intr_bit(&mut self, bit: u8) {
338
self.interrupt_identification &= !bit;
339
if self.interrupt_identification == 0x0 {
340
self.interrupt_identification = IIR_NONE_BIT;
341
}
342
}
343
344
fn trigger_thr_empty(&mut self) -> Result<()> {
345
if self.is_thr_intr_enabled() {
346
self.add_intr_bit(IIR_THR_BIT);
347
self.trigger_interrupt()?
348
}
349
Ok(())
350
}
351
352
fn trigger_recv_interrupt(&mut self) -> Result<()> {
353
if self.is_recv_intr_enabled() {
354
// Only bother triggering the interrupt if the identification bit wasn't set or
355
// acknowledged.
356
if self.interrupt_identification & IIR_RECV_BIT == 0 {
357
self.add_intr_bit(IIR_RECV_BIT);
358
self.trigger_interrupt()?
359
}
360
}
361
Ok(())
362
}
363
364
fn trigger_interrupt(&mut self) -> Result<()> {
365
self.interrupt_evt.signal()
366
}
367
368
fn set_data_bit(&mut self) {
369
self.line_status |= LSR_DATA_BIT;
370
}
371
372
fn is_data_avaiable(&self) -> bool {
373
(self.line_status & LSR_DATA_BIT) != 0
374
}
375
376
fn iir_reset(&mut self) {
377
self.interrupt_identification = DEFAULT_INTERRUPT_IDENTIFICATION;
378
}
379
380
fn handle_write(&mut self, offset: u8, v: u8) -> Result<()> {
381
match offset {
382
DLAB_LOW if self.is_dlab_set() => {
383
self.baud_divisor = (self.baud_divisor & 0xff00) | v as u16
384
}
385
DLAB_HIGH if self.is_dlab_set() => {
386
self.baud_divisor = (self.baud_divisor & 0x00ff) | ((v as u16) << 8)
387
}
388
DATA => {
389
if self.is_loop() {
390
if self.in_buffer.len() < LOOP_SIZE {
391
self.in_buffer.push_back(v);
392
self.set_data_bit();
393
self.trigger_recv_interrupt()?;
394
}
395
} else {
396
self.handle_write_data(v)?;
397
self.trigger_thr_empty()?;
398
}
399
}
400
IER => {
401
let tx_changed = self.is_thr_intr_changed(v);
402
self.interrupt_enable
403
.store(v & IER_FIFO_BITS, Ordering::SeqCst);
404
405
if self.is_data_avaiable() {
406
self.trigger_recv_interrupt()?;
407
}
408
409
if tx_changed {
410
self.trigger_thr_empty()?;
411
}
412
}
413
LCR => self.line_control = v,
414
MCR => self.modem_control = v,
415
SCR => self.scratch = v,
416
_ => {}
417
}
418
Ok(())
419
}
420
421
// Write a single byte of data to `self.out`.
422
fn handle_write_data(&mut self, v: u8) -> Result<()> {
423
let out = match self.out.as_mut() {
424
Some(out) => out,
425
None => return Ok(()),
426
};
427
428
if self.out_timestamp && self.last_write_was_newline {
429
write!(out, "{}", chrono::Utc::now().format(TIMESTAMP_PREFIX_FMT))?;
430
}
431
432
self.last_write_was_newline = v == b'\n';
433
434
out.write_all(&[v])?;
435
out.flush()?;
436
Ok(())
437
}
438
}
439
440
impl BusDevice for Serial {
441
fn device_id(&self) -> DeviceId {
442
PlatformDeviceId::Serial.into()
443
}
444
445
fn debug_label(&self) -> String {
446
"serial".to_owned()
447
}
448
449
fn write(&mut self, info: BusAccessInfo, data: &[u8]) {
450
if matches!(self.device_state, DeviceState::Sleep) {
451
panic!("Unexpected action: Attempt to write to serial when device is in sleep mode");
452
}
453
454
if data.len() != 1 {
455
return;
456
}
457
458
#[cfg(windows)]
459
self.handle_sync_thread();
460
461
if let Err(e) = self.handle_write(info.offset as u8, data[0]) {
462
error!("serial failed write: {}", e);
463
}
464
}
465
466
fn read(&mut self, info: BusAccessInfo, data: &mut [u8]) {
467
if matches!(self.device_state, DeviceState::Sleep) {
468
panic!("Unexpected action: Attempt to write to serial when device is in sleep mode");
469
}
470
471
if data.len() != 1 {
472
return;
473
}
474
475
if self.input.is_some() {
476
self.spawn_input_thread();
477
}
478
self.drain_in_channel();
479
480
data[0] = match info.offset as u8 {
481
DLAB_LOW if self.is_dlab_set() => self.baud_divisor as u8,
482
DLAB_HIGH if self.is_dlab_set() => (self.baud_divisor >> 8) as u8,
483
DATA => {
484
self.del_intr_bit(IIR_RECV_BIT);
485
if self.in_buffer.len() <= 1 {
486
self.line_status &= !LSR_DATA_BIT;
487
}
488
self.in_buffer.pop_front().unwrap_or_default()
489
}
490
IER => self.interrupt_enable.load(Ordering::SeqCst),
491
IIR => {
492
let v = self.interrupt_identification | IIR_FIFO_BITS;
493
self.iir_reset();
494
v
495
}
496
LCR => self.line_control,
497
MCR => self.modem_control,
498
LSR => self.line_status,
499
MSR => {
500
if self.is_loop() {
501
let mut msr =
502
self.modem_status & !(MSR_DSR_BIT | MSR_CTS_BIT | MSR_RI_BIT | MSR_DCD_BIT);
503
if self.modem_control & MCR_DTR_BIT != 0 {
504
msr |= MSR_DSR_BIT;
505
}
506
if self.modem_control & MCR_RTS_BIT != 0 {
507
msr |= MSR_CTS_BIT;
508
}
509
if self.modem_control & MCR_OUT1_BIT != 0 {
510
msr |= MSR_RI_BIT;
511
}
512
if self.modem_control & MCR_OUT2_BIT != 0 {
513
msr |= MSR_DCD_BIT;
514
}
515
msr
516
} else {
517
self.modem_status
518
}
519
}
520
SCR => self.scratch,
521
_ => 0,
522
};
523
}
524
}
525
526
#[derive(Serialize, Deserialize)]
527
struct SerialSnapshot {
528
interrupt_enable: u8,
529
interrupt_identification: u8,
530
line_control: u8,
531
line_status: u8,
532
modem_control: u8,
533
modem_status: u8,
534
scratch: u8,
535
baud_divisor: u16,
536
537
in_buffer: VecDeque<u8>,
538
539
has_input: bool,
540
has_output: bool,
541
542
last_write_was_newline: bool,
543
}
544
545
impl Suspendable for Serial {
546
fn snapshot(&mut self) -> anyhow::Result<AnySnapshot> {
547
self.spawn_input_thread();
548
if let Some(worker) = self.worker.take() {
549
self.input = Some(worker.stop());
550
}
551
self.drain_in_channel();
552
let snap = SerialSnapshot {
553
interrupt_enable: self.interrupt_enable.load(Ordering::SeqCst),
554
interrupt_identification: self.interrupt_identification,
555
line_control: self.line_control,
556
line_status: self.line_status,
557
modem_control: self.modem_control,
558
modem_status: self.modem_status,
559
scratch: self.scratch,
560
baud_divisor: self.baud_divisor,
561
in_buffer: self.in_buffer.clone(),
562
has_input: self.input.is_some(),
563
has_output: self.out.is_some(),
564
last_write_was_newline: self.last_write_was_newline,
565
};
566
567
let serialized = AnySnapshot::to_any(snap).context("error serializing")?;
568
Ok(serialized)
569
}
570
571
fn restore(&mut self, data: AnySnapshot) -> anyhow::Result<()> {
572
let serial_snapshot: SerialSnapshot =
573
AnySnapshot::from_any(data).context("error deserializing")?;
574
self.interrupt_enable = Arc::new(AtomicU8::new(serial_snapshot.interrupt_enable));
575
self.interrupt_identification = serial_snapshot.interrupt_identification;
576
self.line_control = serial_snapshot.line_control;
577
self.line_status = serial_snapshot.line_status;
578
self.modem_control = serial_snapshot.modem_control;
579
self.modem_status = serial_snapshot.modem_status;
580
self.scratch = serial_snapshot.scratch;
581
self.baud_divisor = serial_snapshot.baud_divisor;
582
self.in_buffer = serial_snapshot.in_buffer;
583
if serial_snapshot.has_input && self.input.is_none() {
584
warn!("Restore serial input missing when restore expected an input");
585
}
586
if serial_snapshot.has_output && self.out.is_none() {
587
warn!("Restore serial out missing when restore expected an out");
588
}
589
self.last_write_was_newline = serial_snapshot.last_write_was_newline;
590
Ok(())
591
}
592
593
fn sleep(&mut self) -> anyhow::Result<()> {
594
if !matches!(self.device_state, DeviceState::Sleep) {
595
self.device_state = DeviceState::Sleep;
596
if let Some(worker) = self.worker.take() {
597
self.input = Some(worker.stop());
598
}
599
600
self.drain_in_channel();
601
self.in_channel = None;
602
}
603
Ok(())
604
}
605
606
fn wake(&mut self) -> anyhow::Result<()> {
607
if !matches!(self.device_state, DeviceState::Awake) {
608
self.device_state = DeviceState::Awake;
609
if self.input.is_some() {
610
self.spawn_input_thread();
611
}
612
}
613
Ok(())
614
}
615
}
616
617
#[cfg(test)]
618
mod tests {
619
use std::io;
620
use std::sync::Arc;
621
622
use hypervisor::ProtectionType;
623
use sync::Mutex;
624
625
use super::*;
626
use crate::serial_device::SerialOptions;
627
use crate::suspendable_tests;
628
pub use crate::sys::serial_device::SerialDevice;
629
630
#[derive(Clone)]
631
pub(super) struct SharedBuffer {
632
pub(super) buf: Arc<Mutex<Vec<u8>>>,
633
}
634
635
/// Empties the in_buffer.
636
impl Serial {
637
pub fn clear_in_buffer(&mut self) {
638
self.in_buffer.clear()
639
}
640
}
641
642
impl SharedBuffer {
643
pub(super) fn new() -> SharedBuffer {
644
SharedBuffer {
645
buf: Arc::new(Mutex::new(Vec::new())),
646
}
647
}
648
}
649
650
impl io::Write for SharedBuffer {
651
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
652
self.buf.lock().write(buf)
653
}
654
fn flush(&mut self) -> io::Result<()> {
655
self.buf.lock().flush()
656
}
657
}
658
659
pub(super) fn serial_bus_address(offset: u8) -> BusAccessInfo {
660
// Serial devices only use the offset of the BusAccessInfo
661
BusAccessInfo {
662
offset: offset as u64,
663
address: 0,
664
id: 0,
665
}
666
}
667
668
#[test]
669
fn serial_output() {
670
let intr_evt = Event::new().unwrap();
671
let serial_out = SharedBuffer::new();
672
673
let mut serial = Serial::new(
674
ProtectionType::Unprotected,
675
intr_evt,
676
None,
677
Some(Box::new(serial_out.clone())),
678
None,
679
Default::default(),
680
Vec::new(),
681
);
682
683
serial.write(serial_bus_address(DATA), b"a");
684
serial.write(serial_bus_address(DATA), b"b");
685
serial.write(serial_bus_address(DATA), b"c");
686
assert_eq!(serial_out.buf.lock().as_slice(), b"abc");
687
}
688
689
#[test]
690
fn serial_input() {
691
let intr_evt = Event::new().unwrap();
692
let serial_out = SharedBuffer::new();
693
694
let mut serial = Serial::new(
695
ProtectionType::Unprotected,
696
intr_evt.try_clone().unwrap(),
697
None,
698
Some(Box::new(serial_out)),
699
None,
700
Default::default(),
701
Vec::new(),
702
);
703
704
serial.write(serial_bus_address(IER), &[IER_RECV_BIT]);
705
serial.queue_input_bytes(b"abc").unwrap();
706
707
assert_eq!(intr_evt.wait(), Ok(()));
708
let mut data = [0u8; 1];
709
serial.read(serial_bus_address(DATA), &mut data[..]);
710
assert_eq!(data[0], b'a');
711
serial.read(serial_bus_address(DATA), &mut data[..]);
712
assert_eq!(data[0], b'b');
713
serial.read(serial_bus_address(DATA), &mut data[..]);
714
assert_eq!(data[0], b'c');
715
}
716
717
#[test]
718
fn serial_input_sleep_snapshot_restore_wake() {
719
let intr_evt = Event::new().unwrap();
720
let serial_out = SharedBuffer::new();
721
722
let mut serial = Serial::new(
723
ProtectionType::Unprotected,
724
intr_evt.try_clone().unwrap(),
725
None,
726
Some(Box::new(serial_out)),
727
None,
728
Default::default(),
729
Vec::new(),
730
);
731
732
serial.write(serial_bus_address(IER), &[IER_RECV_BIT]);
733
serial.queue_input_bytes(b"abc").unwrap();
734
735
assert_eq!(intr_evt.wait(), Ok(()));
736
let mut data = [0u8; 1];
737
serial.read(serial_bus_address(DATA), &mut data[..]);
738
assert_eq!(data[0], b'a');
739
let sleep_res = serial.sleep();
740
match sleep_res {
741
Ok(_res) => (),
742
Err(e) => println!("{e}"),
743
}
744
let snap_res = serial.snapshot();
745
match snap_res {
746
Ok(snap) => {
747
let restore_res = serial.restore(snap);
748
match restore_res {
749
Ok(_rest) => (),
750
Err(e) => println!("{e}"),
751
}
752
}
753
Err(e) => println!("{e}"),
754
}
755
let wake_res = serial.wake();
756
match wake_res {
757
Ok(_res) => (),
758
Err(e) => println!("{e}"),
759
}
760
serial.read(serial_bus_address(DATA), &mut data[..]);
761
assert_eq!(data[0], b'b');
762
serial.read(serial_bus_address(DATA), &mut data[..]);
763
assert_eq!(data[0], b'c');
764
}
765
766
#[test]
767
fn serial_input_snapshot_restore() {
768
let intr_evt = Event::new().unwrap();
769
let serial_out = SharedBuffer::new();
770
771
let mut serial = Serial::new(
772
ProtectionType::Unprotected,
773
intr_evt.try_clone().unwrap(),
774
None,
775
Some(Box::new(serial_out)),
776
None,
777
Default::default(),
778
Vec::new(),
779
);
780
781
serial.write(serial_bus_address(IER), &[IER_RECV_BIT]);
782
serial.queue_input_bytes(b"abc").unwrap();
783
784
assert_eq!(intr_evt.wait(), Ok(()));
785
let mut data = [0u8; 1];
786
serial.read(serial_bus_address(DATA), &mut data[..]);
787
assert_eq!(data[0], b'a');
788
// Take snapshot after reading b'a'. Serial still contains b'b' and b'c'.
789
let snap = serial.snapshot().expect("failed to snapshot serial");
790
serial.read(serial_bus_address(DATA), &mut data[..]);
791
assert_eq!(data[0], b'b');
792
// Restore snapshot taken after reading b'a'. New reading should give us b'b' since it was
793
// the saved state at the moment of taking a snapshot.
794
let restore_res = serial.restore(snap);
795
match restore_res {
796
Ok(()) => (),
797
Err(e) => println!("Error: {e}"),
798
}
799
serial.read(serial_bus_address(DATA), &mut data[..]);
800
assert_eq!(data[0], b'b');
801
serial.read(serial_bus_address(DATA), &mut data[..]);
802
assert_eq!(data[0], b'c');
803
}
804
805
#[test]
806
fn serial_input_snapshot_write_restore() {
807
let intr_evt = Event::new().unwrap();
808
let serial_out = SharedBuffer::new();
809
810
let mut serial = Serial::new(
811
ProtectionType::Unprotected,
812
intr_evt.try_clone().unwrap(),
813
None,
814
Some(Box::new(serial_out)),
815
None,
816
Default::default(),
817
Vec::new(),
818
);
819
820
serial.write(serial_bus_address(IER), &[IER_RECV_BIT]);
821
serial.queue_input_bytes(b"abc").unwrap();
822
823
assert_eq!(intr_evt.wait(), Ok(()));
824
let mut data = [0u8; 1];
825
serial.read(serial_bus_address(DATA), &mut data[..]);
826
assert_eq!(data[0], b'a');
827
// Take snapshot after reading b'a'. Serial still contains b'b' and b'c'.
828
let snap = serial.snapshot().expect("failed to snapshot serial");
829
serial.clear_in_buffer();
830
serial.queue_input_bytes(b"abc").unwrap();
831
serial.read(serial_bus_address(DATA), &mut data[..]);
832
assert_eq!(data[0], b'a');
833
serial.read(serial_bus_address(DATA), &mut data[..]);
834
assert_eq!(data[0], b'b');
835
serial.read(serial_bus_address(DATA), &mut data[..]);
836
assert_eq!(data[0], b'c');
837
// Restore snapshot taken after reading b'a'. New reading should give us b'b' since it was
838
// the saved state at the moment of taking a snapshot.
839
let restore_res = serial.restore(snap);
840
match restore_res {
841
Ok(()) => (),
842
Err(e) => println!("Error: {e}"),
843
}
844
serial.read(serial_bus_address(DATA), &mut data[..]);
845
assert_eq!(data[0], b'b');
846
serial.read(serial_bus_address(DATA), &mut data[..]);
847
assert_eq!(data[0], b'c');
848
}
849
850
// Test should panic. Sleep, try to read while sleeping.
851
#[test]
852
#[should_panic]
853
fn serial_input_sleep_read_panic() {
854
let intr_evt = Event::new().unwrap();
855
let serial_out = SharedBuffer::new();
856
857
let mut serial = Serial::new(
858
ProtectionType::Unprotected,
859
intr_evt.try_clone().unwrap(),
860
None,
861
Some(Box::new(serial_out)),
862
None,
863
Default::default(),
864
Vec::new(),
865
);
866
867
serial.write(serial_bus_address(IER), &[IER_RECV_BIT]);
868
serial.queue_input_bytes(b"abc").unwrap();
869
870
assert_eq!(intr_evt.wait(), Ok(()));
871
let mut data = [0u8; 1];
872
serial.read(serial_bus_address(DATA), &mut data[..]);
873
assert_eq!(data[0], b'a');
874
serial.read(serial_bus_address(DATA), &mut data[..]);
875
assert_eq!(data[0], b'b');
876
let sleep_res = serial.sleep();
877
match sleep_res {
878
Ok(_res) => (),
879
Err(e) => println!("{e}"),
880
}
881
// Test should panic when trying to read after sleep.
882
serial.read(serial_bus_address(DATA), &mut data[..]);
883
assert_eq!(data[0], b'b');
884
}
885
886
// Test should panic. Sleep, try to read while sleeping.
887
#[test]
888
#[should_panic]
889
fn serial_input_sleep_write_panic() {
890
let intr_evt = Event::new().unwrap();
891
let serial_out = SharedBuffer::new();
892
893
let mut serial = Serial::new(
894
ProtectionType::Unprotected,
895
intr_evt.try_clone().unwrap(),
896
None,
897
Some(Box::new(serial_out)),
898
None,
899
Default::default(),
900
Vec::new(),
901
);
902
903
let sleep_res = serial.sleep();
904
match sleep_res {
905
Ok(_res) => (),
906
Err(e) => println!("{e}"),
907
}
908
// Test should panic when trying to read after sleep.
909
serial.write(serial_bus_address(IER), &[IER_RECV_BIT]);
910
}
911
912
#[test]
913
fn serial_input_sleep_wake() {
914
let intr_evt = Event::new().unwrap();
915
let serial_out = SharedBuffer::new();
916
917
let mut serial = Serial::new(
918
ProtectionType::Unprotected,
919
intr_evt.try_clone().unwrap(),
920
None,
921
Some(Box::new(serial_out)),
922
None,
923
Default::default(),
924
Vec::new(),
925
);
926
927
serial.write(serial_bus_address(IER), &[IER_RECV_BIT]);
928
serial.queue_input_bytes(b"abc").unwrap();
929
930
assert_eq!(intr_evt.wait(), Ok(()));
931
let mut data = [0u8; 1];
932
serial.read(serial_bus_address(DATA), &mut data[..]);
933
assert_eq!(data[0], b'a');
934
serial.read(serial_bus_address(DATA), &mut data[..]);
935
assert_eq!(data[0], b'b');
936
let sleep_res = serial.sleep();
937
match sleep_res {
938
Ok(_res) => (),
939
Err(e) => println!("{e}"),
940
}
941
let wake_res = serial.wake();
942
match wake_res {
943
Ok(_res) => (),
944
Err(e) => println!("{e}"),
945
}
946
serial.read(serial_bus_address(DATA), &mut data[..]);
947
assert_eq!(data[0], b'c');
948
}
949
950
fn modify_device(serial: &mut Serial) {
951
serial.clear_in_buffer();
952
serial.queue_input_bytes(b"abc").unwrap();
953
}
954
955
suspendable_tests!(
956
serial,
957
Serial::new(
958
ProtectionType::Unprotected,
959
Event::new().unwrap(),
960
None,
961
Some(Box::new(SharedBuffer::new())),
962
None,
963
Default::default(),
964
Vec::new(),
965
),
966
modify_device
967
);
968
969
fn assert_timestamp_is_present(data: &[u8], serial_message: &str) {
970
const TIMESTAMP_START: &str = "[";
971
const TIMESTAMP_END: &str = "]: ";
972
973
let data_str = std::str::from_utf8(data).unwrap();
974
let timestamp_bracket = data_str
975
.find(TIMESTAMP_END)
976
.expect("missing timestamp end bracket");
977
let (timestamp, message) = data_str.split_at(timestamp_bracket + TIMESTAMP_END.len());
978
979
assert!(timestamp.starts_with(TIMESTAMP_START));
980
assert!(timestamp.ends_with(TIMESTAMP_END));
981
982
assert_eq!(message.trim_end(), serial_message);
983
}
984
985
#[test]
986
fn serial_output_timestamp() {
987
let intr_evt = Event::new().unwrap();
988
let serial_out = SharedBuffer::new();
989
990
let mut serial = Serial::new(
991
ProtectionType::Unprotected,
992
intr_evt,
993
None,
994
Some(Box::new(serial_out.clone())),
995
None,
996
SerialOptions {
997
out_timestamp: true,
998
..Default::default()
999
},
1000
Vec::new(),
1001
);
1002
1003
serial.write(serial_bus_address(DATA), b"a");
1004
serial.write(serial_bus_address(DATA), b"\n");
1005
assert_timestamp_is_present(serial_out.buf.lock().as_slice(), "a");
1006
serial_out.buf.lock().clear();
1007
1008
serial.write(serial_bus_address(DATA), b"b");
1009
serial.write(serial_bus_address(DATA), b"\n");
1010
assert_timestamp_is_present(serial_out.buf.lock().as_slice(), "b");
1011
serial_out.buf.lock().clear();
1012
1013
serial.write(serial_bus_address(DATA), b"c");
1014
serial.write(serial_bus_address(DATA), b"\n");
1015
assert_timestamp_is_present(serial_out.buf.lock().as_slice(), "c");
1016
serial_out.buf.lock().clear();
1017
}
1018
}
1019
1020