Skip to main content

lab_proxy_core/
protocol_resource_adapter.rs

1// Copyright 2026 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! Protocol resource adapters for GPIO, I2C, and SPI.
6//!
7//! Provides representative hardware backends and fakes for protocol-backed
8//! resources (Spec 8.1, 9.5, 11.6; Milestone P4). Protocol resources preserve
9//! their production request/response semantics rather than being flattened into
10//! generic byte writes or MMIO offsets.
11
12use crate::hardware_backend::{BackendError, FakeMmio, MmioBackend};
13use std::collections::VecDeque;
14
15/// Hardware access abstraction for a GPIO pin.
16pub trait GpioBackend: Send {
17    /// Reads the current voltage level (high = true, low = false).
18    fn read(&mut self) -> Result<bool, BackendError>;
19
20    /// Sets the output voltage level.
21    fn write(&mut self, value: bool) -> Result<(), BackendError>;
22}
23
24/// Hardware access abstraction for an I2C bus device.
25pub trait I2cBackend: Send {
26    /// Executes an I2C transfer with optional write and read phases.
27    fn transfer(&mut self, write_data: &[u8], read_length: usize) -> Result<Vec<u8>, BackendError>;
28}
29
30/// Hardware access abstraction for a SPI bus device.
31pub trait SpiBackend: Send {
32    /// Transmits data to a SPI device, returning received data of matching or specified length.
33    fn transmit(&mut self, tx_data: &[u8]) -> Result<Vec<u8>, BackendError>;
34}
35
36/// Hardware access abstraction for a Clock device.
37pub trait ClockBackend: Send {
38    fn enable(&mut self) -> Result<(), BackendError>;
39    fn disable(&mut self) -> Result<(), BackendError>;
40    fn is_enabled(&mut self) -> Result<bool, BackendError>;
41    fn set_rate(&mut self, hz: u64) -> Result<(), BackendError>;
42    fn query_rate(&mut self, hz_in: u64) -> Result<u64, BackendError>;
43    fn get_rate(&mut self) -> Result<u64, BackendError>;
44}
45
46/// Hardware access abstraction for a Reset device.
47pub trait ResetBackend: Send {
48    fn assert(&mut self) -> Result<(), BackendError>;
49    fn deassert(&mut self) -> Result<(), BackendError>;
50    fn toggle(&mut self) -> Result<(), BackendError>;
51    fn status(&mut self) -> Result<bool, BackendError>;
52}
53
54/// Hardware access abstraction for a Serial device.
55pub trait SerialBackend: Send {
56    fn read(&mut self) -> Result<Vec<u8>, BackendError>;
57    fn write(&mut self, data: &[u8]) -> Result<(), BackendError>;
58}
59
60/// Unified hardware access trait covering MMIO and protocol resources.
61pub trait ResourceBackend: Send {
62    fn read32(&mut self, _offset: u64) -> Result<u32, BackendError> {
63        Err(BackendError::Fault)
64    }
65    fn write32(&mut self, _offset: u64, _value: u32) -> Result<(), BackendError> {
66        Err(BackendError::Fault)
67    }
68    fn barrier(&mut self) {}
69    fn gpio_read(&mut self) -> Result<bool, BackendError> {
70        Err(BackendError::Fault)
71    }
72    fn gpio_write(&mut self, _value: bool) -> Result<(), BackendError> {
73        Err(BackendError::Fault)
74    }
75    fn i2c_transfer(
76        &mut self,
77        _write_data: &[u8],
78        _read_length: usize,
79    ) -> Result<Vec<u8>, BackendError> {
80        Err(BackendError::Fault)
81    }
82    fn spi_transmit(&mut self, _tx_data: &[u8]) -> Result<Vec<u8>, BackendError> {
83        Err(BackendError::Fault)
84    }
85    fn clock_enable(&mut self) -> Result<(), BackendError> {
86        Err(BackendError::Fault)
87    }
88    fn clock_disable(&mut self) -> Result<(), BackendError> {
89        Err(BackendError::Fault)
90    }
91    fn clock_is_enabled(&mut self) -> Result<bool, BackendError> {
92        Err(BackendError::Fault)
93    }
94    fn clock_set_rate(&mut self, _hz: u64) -> Result<(), BackendError> {
95        Err(BackendError::Fault)
96    }
97    fn clock_query_rate(&mut self, _hz_in: u64) -> Result<u64, BackendError> {
98        Err(BackendError::Fault)
99    }
100    fn clock_get_rate(&mut self) -> Result<u64, BackendError> {
101        Err(BackendError::Fault)
102    }
103    fn reset_assert(&mut self) -> Result<(), BackendError> {
104        Err(BackendError::Fault)
105    }
106    fn reset_deassert(&mut self) -> Result<(), BackendError> {
107        Err(BackendError::Fault)
108    }
109    fn reset_toggle(&mut self) -> Result<(), BackendError> {
110        Err(BackendError::Fault)
111    }
112    fn reset_status(&mut self) -> Result<bool, BackendError> {
113        Err(BackendError::Fault)
114    }
115    fn serial_read(&mut self) -> Result<Vec<u8>, BackendError> {
116        Err(BackendError::Fault)
117    }
118    fn serial_write(&mut self, _data: &[u8]) -> Result<(), BackendError> {
119        Err(BackendError::Fault)
120    }
121}
122
123impl ResourceBackend for FakeMmio {
124    fn read32(&mut self, offset: u64) -> Result<u32, BackendError> {
125        MmioBackend::read32(self, offset)
126    }
127    fn write32(&mut self, offset: u64, value: u32) -> Result<(), BackendError> {
128        MmioBackend::write32(self, offset, value)
129    }
130    fn barrier(&mut self) {
131        MmioBackend::barrier(self);
132    }
133}
134
135/// In-memory fake GPIO pin for tests.
136#[derive(Clone, Debug, Default)]
137pub struct FakeGpio {
138    pub value: bool,
139    pub reads: usize,
140    pub writes: Vec<bool>,
141    pub fault: bool,
142}
143
144impl FakeGpio {
145    pub fn new(initial: bool) -> Self {
146        Self { value: initial, reads: 0, writes: Vec::new(), fault: false }
147    }
148
149    pub fn set_state(&mut self, value: bool) {
150        self.value = value;
151    }
152
153    pub fn fail(&mut self, fault: bool) {
154        self.fault = fault;
155    }
156}
157
158impl GpioBackend for FakeGpio {
159    fn read(&mut self) -> Result<bool, BackendError> {
160        if self.fault {
161            return Err(BackendError::Fault);
162        }
163        self.reads += 1;
164        Ok(self.value)
165    }
166
167    fn write(&mut self, value: bool) -> Result<(), BackendError> {
168        if self.fault {
169            return Err(BackendError::Fault);
170        }
171        self.value = value;
172        self.writes.push(value);
173        Ok(())
174    }
175}
176
177impl ResourceBackend for FakeGpio {
178    fn gpio_read(&mut self) -> Result<bool, BackendError> {
179        GpioBackend::read(self)
180    }
181    fn gpio_write(&mut self, value: bool) -> Result<(), BackendError> {
182        GpioBackend::write(self, value)
183    }
184}
185
186/// In-memory fake I2C device for tests.
187#[derive(Clone, Debug, Default)]
188pub struct FakeI2c {
189    pub responses: VecDeque<Vec<u8>>,
190    pub recorded_transfers: Vec<(Vec<u8>, usize)>,
191    pub fault: bool,
192}
193
194impl FakeI2c {
195    pub fn new() -> Self {
196        Self::default()
197    }
198
199    pub fn push_response(&mut self, response: Vec<u8>) {
200        self.responses.push_back(response);
201    }
202
203    pub fn set_read_response(&mut self, response: Vec<u8>) {
204        self.push_response(response);
205    }
206
207    pub fn fail(&mut self, fault: bool) {
208        self.fault = fault;
209    }
210}
211
212impl I2cBackend for FakeI2c {
213    fn transfer(&mut self, write_data: &[u8], read_length: usize) -> Result<Vec<u8>, BackendError> {
214        if self.fault {
215            return Err(BackendError::Fault);
216        }
217        self.recorded_transfers.push((write_data.to_vec(), read_length));
218        if let Some(resp) = self.responses.pop_front() {
219            let mut out = resp;
220            out.resize(read_length, 0);
221            return Ok(out);
222        }
223        Ok(vec![0u8; read_length])
224    }
225}
226
227impl ResourceBackend for FakeI2c {
228    fn i2c_transfer(
229        &mut self,
230        write_data: &[u8],
231        read_length: usize,
232    ) -> Result<Vec<u8>, BackendError> {
233        I2cBackend::transfer(self, write_data, read_length)
234    }
235}
236
237/// In-memory fake SPI device for tests.
238#[derive(Clone, Debug, Default)]
239pub struct FakeSpi {
240    pub responses: VecDeque<Vec<u8>>,
241    pub recorded_transmits: Vec<Vec<u8>>,
242    pub loopback: bool,
243    pub fault: bool,
244}
245
246impl FakeSpi {
247    pub fn new() -> Self {
248        Self::default()
249    }
250
251    pub fn with_loopback(mut self) -> Self {
252        self.loopback = true;
253        self
254    }
255
256    pub fn push_response(&mut self, response: Vec<u8>) {
257        self.responses.push_back(response);
258    }
259
260    pub fn set_rx_response(&mut self, response: Vec<u8>) {
261        self.push_response(response);
262    }
263
264    pub fn fail(&mut self, fault: bool) {
265        self.fault = fault;
266    }
267}
268
269impl SpiBackend for FakeSpi {
270    fn transmit(&mut self, tx_data: &[u8]) -> Result<Vec<u8>, BackendError> {
271        if self.fault {
272            return Err(BackendError::Fault);
273        }
274        self.recorded_transmits.push(tx_data.to_vec());
275        if self.loopback {
276            return Ok(tx_data.to_vec());
277        }
278        if let Some(resp) = self.responses.pop_front() {
279            return Ok(resp);
280        }
281        Ok(vec![0u8; tx_data.len()])
282    }
283}
284
285impl ResourceBackend for FakeSpi {
286    fn spi_transmit(&mut self, tx_data: &[u8]) -> Result<Vec<u8>, BackendError> {
287        SpiBackend::transmit(self, tx_data)
288    }
289}
290
291/// In-memory fake Clock for tests.
292#[derive(Clone, Debug, Default)]
293pub struct FakeClock {
294    pub enabled: bool,
295    pub rate: u64,
296    pub fault: bool,
297}
298
299impl FakeClock {
300    pub fn new(enabled: bool, rate: u64) -> Self {
301        Self { enabled, rate, fault: false }
302    }
303
304    pub fn fail(&mut self, fault: bool) {
305        self.fault = fault;
306    }
307}
308
309impl ClockBackend for FakeClock {
310    fn enable(&mut self) -> Result<(), BackendError> {
311        if self.fault {
312            return Err(BackendError::Fault);
313        }
314        self.enabled = true;
315        Ok(())
316    }
317
318    fn disable(&mut self) -> Result<(), BackendError> {
319        if self.fault {
320            return Err(BackendError::Fault);
321        }
322        self.enabled = false;
323        Ok(())
324    }
325
326    fn is_enabled(&mut self) -> Result<bool, BackendError> {
327        if self.fault {
328            return Err(BackendError::Fault);
329        }
330        Ok(self.enabled)
331    }
332
333    fn set_rate(&mut self, hz: u64) -> Result<(), BackendError> {
334        if self.fault {
335            return Err(BackendError::Fault);
336        }
337        self.rate = hz;
338        Ok(())
339    }
340
341    fn query_rate(&mut self, hz_in: u64) -> Result<u64, BackendError> {
342        if self.fault {
343            return Err(BackendError::Fault);
344        }
345        Ok(hz_in)
346    }
347
348    fn get_rate(&mut self) -> Result<u64, BackendError> {
349        if self.fault {
350            return Err(BackendError::Fault);
351        }
352        Ok(self.rate)
353    }
354}
355
356impl ResourceBackend for FakeClock {
357    fn clock_enable(&mut self) -> Result<(), BackendError> {
358        ClockBackend::enable(self)
359    }
360    fn clock_disable(&mut self) -> Result<(), BackendError> {
361        ClockBackend::disable(self)
362    }
363    fn clock_is_enabled(&mut self) -> Result<bool, BackendError> {
364        ClockBackend::is_enabled(self)
365    }
366    fn clock_set_rate(&mut self, hz: u64) -> Result<(), BackendError> {
367        ClockBackend::set_rate(self, hz)
368    }
369    fn clock_query_rate(&mut self, hz_in: u64) -> Result<u64, BackendError> {
370        ClockBackend::query_rate(self, hz_in)
371    }
372    fn clock_get_rate(&mut self) -> Result<u64, BackendError> {
373        ClockBackend::get_rate(self)
374    }
375}
376
377/// In-memory fake Reset for tests.
378#[derive(Clone, Debug, Default)]
379pub struct FakeReset {
380    pub asserted: bool,
381    pub fault: bool,
382}
383
384impl FakeReset {
385    pub fn new(asserted: bool) -> Self {
386        Self { asserted, fault: false }
387    }
388
389    pub fn fail(&mut self, fault: bool) {
390        self.fault = fault;
391    }
392}
393
394impl ResetBackend for FakeReset {
395    fn assert(&mut self) -> Result<(), BackendError> {
396        if self.fault {
397            return Err(BackendError::Fault);
398        }
399        self.asserted = true;
400        Ok(())
401    }
402
403    fn deassert(&mut self) -> Result<(), BackendError> {
404        if self.fault {
405            return Err(BackendError::Fault);
406        }
407        self.asserted = false;
408        Ok(())
409    }
410
411    fn toggle(&mut self) -> Result<(), BackendError> {
412        if self.fault {
413            return Err(BackendError::Fault);
414        }
415        self.asserted = !self.asserted;
416        Ok(())
417    }
418
419    fn status(&mut self) -> Result<bool, BackendError> {
420        if self.fault {
421            return Err(BackendError::Fault);
422        }
423        Ok(self.asserted)
424    }
425}
426
427impl ResourceBackend for FakeReset {
428    fn reset_assert(&mut self) -> Result<(), BackendError> {
429        ResetBackend::assert(self)
430    }
431    fn reset_deassert(&mut self) -> Result<(), BackendError> {
432        ResetBackend::deassert(self)
433    }
434    fn reset_toggle(&mut self) -> Result<(), BackendError> {
435        ResetBackend::toggle(self)
436    }
437    fn reset_status(&mut self) -> Result<bool, BackendError> {
438        ResetBackend::status(self)
439    }
440}
441
442/// In-memory fake Serial for tests.
443#[derive(Clone, Debug, Default)]
444pub struct FakeSerial {
445    pub rx_queue: VecDeque<u8>,
446    pub tx_log: Vec<Vec<u8>>,
447    pub loopback: bool,
448    pub fault: bool,
449}
450
451impl FakeSerial {
452    pub fn new() -> Self {
453        Self::default()
454    }
455
456    pub fn with_loopback(mut self) -> Self {
457        self.loopback = true;
458        self
459    }
460
461    pub fn push_rx(&mut self, data: &[u8]) {
462        self.rx_queue.extend(data);
463    }
464
465    pub fn fail(&mut self, fault: bool) {
466        self.fault = fault;
467    }
468}
469
470impl SerialBackend for FakeSerial {
471    fn read(&mut self) -> Result<Vec<u8>, BackendError> {
472        if self.fault {
473            return Err(BackendError::Fault);
474        }
475        let data: Vec<u8> = self.rx_queue.drain(..).collect();
476        Ok(data)
477    }
478
479    fn write(&mut self, data: &[u8]) -> Result<(), BackendError> {
480        if self.fault {
481            return Err(BackendError::Fault);
482        }
483        self.tx_log.push(data.to_vec());
484        if self.loopback {
485            self.rx_queue.extend(data);
486        }
487        Ok(())
488    }
489}
490
491impl ResourceBackend for FakeSerial {
492    fn serial_read(&mut self) -> Result<Vec<u8>, BackendError> {
493        SerialBackend::read(self)
494    }
495    fn serial_write(&mut self, data: &[u8]) -> Result<(), BackendError> {
496        SerialBackend::write(self, data)
497    }
498}
499
500/// Unified enum backend allowing heterogeneous resources to coexist in one proxy instance.
501#[derive(Clone, Debug)]
502pub enum DeviceBackend<
503    M = FakeMmio,
504    G = FakeGpio,
505    I = FakeI2c,
506    S = FakeSpi,
507    C = FakeClock,
508    R = FakeReset,
509    U = FakeSerial,
510> {
511    Mmio(M),
512    Gpio(G),
513    I2c(I),
514    Spi(S),
515    Clock(C),
516    Reset(R),
517    Serial(U),
518}
519
520impl<M, G, I, S, C, R, U> DeviceBackend<M, G, I, S, C, R, U> {
521    pub fn new_mmio(mmio: M) -> Self {
522        Self::Mmio(mmio)
523    }
524
525    pub fn new_gpio(gpio: G) -> Self {
526        Self::Gpio(gpio)
527    }
528
529    pub fn new_i2c(i2c: I) -> Self {
530        Self::I2c(i2c)
531    }
532
533    pub fn new_spi(spi: S) -> Self {
534        Self::Spi(spi)
535    }
536
537    pub fn new_clock(clock: C) -> Self {
538        Self::Clock(clock)
539    }
540
541    pub fn new_reset(reset: R) -> Self {
542        Self::Reset(reset)
543    }
544
545    pub fn new_serial(serial: U) -> Self {
546        Self::Serial(serial)
547    }
548}
549
550impl<
551    M: ResourceBackend,
552    G: ResourceBackend,
553    I: ResourceBackend,
554    S: ResourceBackend,
555    C: ResourceBackend,
556    R: ResourceBackend,
557    U: ResourceBackend,
558> ResourceBackend for DeviceBackend<M, G, I, S, C, R, U>
559{
560    fn read32(&mut self, offset: u64) -> Result<u32, BackendError> {
561        match self {
562            Self::Mmio(m) => m.read32(offset),
563            _ => Err(BackendError::Fault),
564        }
565    }
566
567    fn write32(&mut self, offset: u64, value: u32) -> Result<(), BackendError> {
568        match self {
569            Self::Mmio(m) => m.write32(offset, value),
570            _ => Err(BackendError::Fault),
571        }
572    }
573
574    fn barrier(&mut self) {
575        if let Self::Mmio(m) = self {
576            m.barrier();
577        }
578    }
579
580    fn gpio_read(&mut self) -> Result<bool, BackendError> {
581        match self {
582            Self::Gpio(g) => g.gpio_read(),
583            _ => Err(BackendError::Fault),
584        }
585    }
586
587    fn gpio_write(&mut self, value: bool) -> Result<(), BackendError> {
588        match self {
589            Self::Gpio(g) => g.gpio_write(value),
590            _ => Err(BackendError::Fault),
591        }
592    }
593
594    fn i2c_transfer(
595        &mut self,
596        write_data: &[u8],
597        read_length: usize,
598    ) -> Result<Vec<u8>, BackendError> {
599        match self {
600            Self::I2c(i) => i.i2c_transfer(write_data, read_length),
601            _ => Err(BackendError::Fault),
602        }
603    }
604
605    fn spi_transmit(&mut self, tx_data: &[u8]) -> Result<Vec<u8>, BackendError> {
606        match self {
607            Self::Spi(s) => s.spi_transmit(tx_data),
608            _ => Err(BackendError::Fault),
609        }
610    }
611
612    fn clock_enable(&mut self) -> Result<(), BackendError> {
613        match self {
614            Self::Clock(c) => c.clock_enable(),
615            _ => Err(BackendError::Fault),
616        }
617    }
618
619    fn clock_disable(&mut self) -> Result<(), BackendError> {
620        match self {
621            Self::Clock(c) => c.clock_disable(),
622            _ => Err(BackendError::Fault),
623        }
624    }
625
626    fn clock_is_enabled(&mut self) -> Result<bool, BackendError> {
627        match self {
628            Self::Clock(c) => c.clock_is_enabled(),
629            _ => Err(BackendError::Fault),
630        }
631    }
632
633    fn clock_set_rate(&mut self, hz: u64) -> Result<(), BackendError> {
634        match self {
635            Self::Clock(c) => c.clock_set_rate(hz),
636            _ => Err(BackendError::Fault),
637        }
638    }
639
640    fn clock_query_rate(&mut self, hz_in: u64) -> Result<u64, BackendError> {
641        match self {
642            Self::Clock(c) => c.clock_query_rate(hz_in),
643            _ => Err(BackendError::Fault),
644        }
645    }
646
647    fn clock_get_rate(&mut self) -> Result<u64, BackendError> {
648        match self {
649            Self::Clock(c) => c.clock_get_rate(),
650            _ => Err(BackendError::Fault),
651        }
652    }
653
654    fn reset_assert(&mut self) -> Result<(), BackendError> {
655        match self {
656            Self::Reset(r) => r.reset_assert(),
657            _ => Err(BackendError::Fault),
658        }
659    }
660
661    fn reset_deassert(&mut self) -> Result<(), BackendError> {
662        match self {
663            Self::Reset(r) => r.reset_deassert(),
664            _ => Err(BackendError::Fault),
665        }
666    }
667
668    fn reset_toggle(&mut self) -> Result<(), BackendError> {
669        match self {
670            Self::Reset(r) => r.reset_toggle(),
671            _ => Err(BackendError::Fault),
672        }
673    }
674
675    fn reset_status(&mut self) -> Result<bool, BackendError> {
676        match self {
677            Self::Reset(r) => r.reset_status(),
678            _ => Err(BackendError::Fault),
679        }
680    }
681
682    fn serial_read(&mut self) -> Result<Vec<u8>, BackendError> {
683        match self {
684            Self::Serial(u) => u.serial_read(),
685            _ => Err(BackendError::Fault),
686        }
687    }
688
689    fn serial_write(&mut self, data: &[u8]) -> Result<(), BackendError> {
690        match self {
691            Self::Serial(u) => u.serial_write(data),
692            _ => Err(BackendError::Fault),
693        }
694    }
695}