1use crate::platform_provider::MappedMmio;
8use fidl_fuchsia_hardware_clock as fclock;
9use fidl_fuchsia_hardware_gpio as fgpio;
10use fidl_fuchsia_hardware_i2c as fi2c;
11use fidl_fuchsia_hardware_reset as freset;
12use fidl_fuchsia_hardware_serial as fserial;
13use fidl_fuchsia_hardware_spi as fspi;
14use lab_proxy_core::hardware_backend::BackendError;
15use lab_proxy_core::protocol_resource_adapter::{
16 ClockBackend, GpioBackend, I2cBackend, ResetBackend, ResourceBackend, SerialBackend, SpiBackend,
17};
18use lab_proxy_core::state_bank::StateBank;
19
20pub struct FuchsiaGpio {
22 proxy: fgpio::GpioSynchronousProxy,
23}
24
25impl FuchsiaGpio {
26 pub fn new(proxy: fgpio::GpioSynchronousProxy) -> Self {
27 Self { proxy }
28 }
29}
30
31impl std::fmt::Debug for FuchsiaGpio {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 f.debug_struct("FuchsiaGpio").finish()
34 }
35}
36
37impl GpioBackend for FuchsiaGpio {
38 fn read(&mut self) -> Result<bool, BackendError> {
39 match self.proxy.read(zx::MonotonicInstant::INFINITE) {
40 Ok(Ok(val)) => Ok(val),
41 Ok(Err(status)) => {
42 log::warn!("Gpio.read error: {status}");
43 Err(BackendError::Fault)
44 }
45 Err(e) => {
46 log::warn!("Gpio.read fidl error: {e:?}");
47 Err(BackendError::Fault)
48 }
49 }
50 }
51
52 fn write(&mut self, value: bool) -> Result<(), BackendError> {
53 let mode = if value { fgpio::BufferMode::OutputHigh } else { fgpio::BufferMode::OutputLow };
54 match self.proxy.set_buffer_mode(mode, zx::MonotonicInstant::INFINITE) {
55 Ok(Ok(())) => Ok(()),
56 Ok(Err(status)) => {
57 log::warn!("Gpio.set_buffer_mode error: {status}");
58 Err(BackendError::Fault)
59 }
60 Err(e) => {
61 log::warn!("Gpio.set_buffer_mode fidl error: {e:?}");
62 Err(BackendError::Fault)
63 }
64 }
65 }
66}
67
68impl ResourceBackend for FuchsiaGpio {
69 fn gpio_read(&mut self) -> Result<bool, BackendError> {
70 self.read()
71 }
72
73 fn gpio_write(&mut self, value: bool) -> Result<(), BackendError> {
74 self.write(value)
75 }
76}
77
78pub struct FuchsiaI2c {
80 proxy: fi2c::DeviceSynchronousProxy,
81}
82
83impl FuchsiaI2c {
84 pub fn new(proxy: fi2c::DeviceSynchronousProxy) -> Self {
85 Self { proxy }
86 }
87}
88
89impl std::fmt::Debug for FuchsiaI2c {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 f.debug_struct("FuchsiaI2c").finish()
92 }
93}
94
95impl I2cBackend for FuchsiaI2c {
96 fn transfer(&mut self, write_data: &[u8], read_length: usize) -> Result<Vec<u8>, BackendError> {
97 let mut transactions = Vec::new();
98 if !write_data.is_empty() {
99 transactions.push(fi2c::Transaction {
100 data_transfer: Some(fi2c::DataTransfer::WriteData(write_data.to_vec())),
101 stop: Some(read_length == 0),
102 ..Default::default()
103 });
104 }
105 if read_length > 0 {
106 transactions.push(fi2c::Transaction {
107 data_transfer: Some(fi2c::DataTransfer::ReadSize(read_length as u32)),
108 stop: Some(true),
109 ..Default::default()
110 });
111 }
112 if transactions.is_empty() {
113 return Ok(Vec::new());
114 }
115 match self.proxy.transfer(&transactions, zx::MonotonicInstant::INFINITE) {
116 Ok(Ok(mut read_data)) => {
117 if read_length > 0 {
118 if let Some(data) = read_data.pop() {
119 return Ok(data);
120 }
121 Ok(Vec::new())
122 } else {
123 Ok(Vec::new())
124 }
125 }
126 Ok(Err(status)) => {
127 log::warn!("I2c.transfer error: {status}");
128 Err(BackendError::Fault)
129 }
130 Err(e) => {
131 log::warn!("I2c.transfer fidl error: {e:?}");
132 Err(BackendError::Fault)
133 }
134 }
135 }
136}
137
138impl ResourceBackend for FuchsiaI2c {
139 fn i2c_transfer(
140 &mut self,
141 write_data: &[u8],
142 read_length: usize,
143 ) -> Result<Vec<u8>, BackendError> {
144 self.transfer(write_data, read_length)
145 }
146}
147
148pub struct FuchsiaSpi {
150 proxy: fspi::DeviceSynchronousProxy,
151}
152
153impl FuchsiaSpi {
154 pub fn new(proxy: fspi::DeviceSynchronousProxy) -> Self {
155 Self { proxy }
156 }
157}
158
159impl std::fmt::Debug for FuchsiaSpi {
160 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
161 f.debug_struct("FuchsiaSpi").finish()
162 }
163}
164
165impl SpiBackend for FuchsiaSpi {
166 fn transmit(&mut self, tx_data: &[u8]) -> Result<Vec<u8>, BackendError> {
167 match self.proxy.exchange_vector(tx_data, zx::MonotonicInstant::INFINITE) {
168 Ok((status, rxdata)) => {
169 if status == 0 {
170 Ok(rxdata)
171 } else {
172 log::warn!("Spi.exchange_vector error: {status}");
173 Err(BackendError::Fault)
174 }
175 }
176 Err(e) => {
177 log::warn!("Spi.exchange_vector fidl error: {e:?}");
178 Err(BackendError::Fault)
179 }
180 }
181 }
182}
183
184impl ResourceBackend for FuchsiaSpi {
185 fn spi_transmit(&mut self, tx_data: &[u8]) -> Result<Vec<u8>, BackendError> {
186 self.transmit(tx_data)
187 }
188}
189
190pub struct FuchsiaClock {
192 proxy: fclock::ClockSynchronousProxy,
193}
194
195impl FuchsiaClock {
196 pub fn new(proxy: fclock::ClockSynchronousProxy) -> Self {
197 Self { proxy }
198 }
199}
200
201impl std::fmt::Debug for FuchsiaClock {
202 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
203 f.debug_struct("FuchsiaClock").finish()
204 }
205}
206
207impl ClockBackend for FuchsiaClock {
208 fn enable(&mut self) -> Result<(), BackendError> {
209 match self.proxy.enable(zx::MonotonicInstant::INFINITE) {
210 Ok(Ok(())) => Ok(()),
211 Ok(Err(status)) => {
212 log::warn!("Clock.enable error: {status}");
213 Err(BackendError::Fault)
214 }
215 Err(e) => {
216 log::warn!("Clock.enable fidl error: {e:?}");
217 Err(BackendError::Fault)
218 }
219 }
220 }
221
222 fn disable(&mut self) -> Result<(), BackendError> {
223 match self.proxy.disable(zx::MonotonicInstant::INFINITE) {
224 Ok(Ok(())) => Ok(()),
225 Ok(Err(status)) => {
226 log::warn!("Clock.disable error: {status}");
227 Err(BackendError::Fault)
228 }
229 Err(e) => {
230 log::warn!("Clock.disable fidl error: {e:?}");
231 Err(BackendError::Fault)
232 }
233 }
234 }
235
236 fn is_enabled(&mut self) -> Result<bool, BackendError> {
237 match self.proxy.is_enabled(zx::MonotonicInstant::INFINITE) {
238 Ok(Ok(val)) => Ok(val),
239 Ok(Err(status)) => {
240 log::warn!("Clock.is_enabled error: {status}");
241 Err(BackendError::Fault)
242 }
243 Err(e) => {
244 log::warn!("Clock.is_enabled fidl error: {e:?}");
245 Err(BackendError::Fault)
246 }
247 }
248 }
249
250 fn set_rate(&mut self, hz: u64) -> Result<(), BackendError> {
251 match self.proxy.set_rate(hz, zx::MonotonicInstant::INFINITE) {
252 Ok(Ok(())) => Ok(()),
253 Ok(Err(status)) => {
254 log::warn!("Clock.set_rate error: {status}");
255 Err(BackendError::Fault)
256 }
257 Err(e) => {
258 log::warn!("Clock.set_rate fidl error: {e:?}");
259 Err(BackendError::Fault)
260 }
261 }
262 }
263
264 fn query_rate(&mut self, hz_in: u64) -> Result<u64, BackendError> {
265 match self.proxy.query_supported_rate(hz_in, zx::MonotonicInstant::INFINITE) {
266 Ok(Ok(val)) => Ok(val),
267 Ok(Err(status)) => {
268 log::warn!("Clock.query_supported_rate error: {status}");
269 Err(BackendError::Fault)
270 }
271 Err(e) => {
272 log::warn!("Clock.query_supported_rate fidl error: {e:?}");
273 Err(BackendError::Fault)
274 }
275 }
276 }
277
278 fn get_rate(&mut self) -> Result<u64, BackendError> {
279 match self.proxy.get_rate(zx::MonotonicInstant::INFINITE) {
280 Ok(Ok(val)) => Ok(val),
281 Ok(Err(status)) => {
282 log::warn!("Clock.get_rate error: {status}");
283 Err(BackendError::Fault)
284 }
285 Err(e) => {
286 log::warn!("Clock.get_rate fidl error: {e:?}");
287 Err(BackendError::Fault)
288 }
289 }
290 }
291}
292
293impl ResourceBackend for FuchsiaClock {
294 fn clock_enable(&mut self) -> Result<(), BackendError> {
295 self.enable()
296 }
297 fn clock_disable(&mut self) -> Result<(), BackendError> {
298 self.disable()
299 }
300 fn clock_is_enabled(&mut self) -> Result<bool, BackendError> {
301 self.is_enabled()
302 }
303 fn clock_set_rate(&mut self, hz: u64) -> Result<(), BackendError> {
304 self.set_rate(hz)
305 }
306 fn clock_query_rate(&mut self, hz_in: u64) -> Result<u64, BackendError> {
307 self.query_rate(hz_in)
308 }
309 fn clock_get_rate(&mut self) -> Result<u64, BackendError> {
310 self.get_rate()
311 }
312}
313
314pub struct FuchsiaReset {
316 proxy: freset::ResetSynchronousProxy,
317}
318
319impl FuchsiaReset {
320 pub fn new(proxy: freset::ResetSynchronousProxy) -> Self {
321 Self { proxy }
322 }
323}
324
325impl std::fmt::Debug for FuchsiaReset {
326 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
327 f.debug_struct("FuchsiaReset").finish()
328 }
329}
330
331impl ResetBackend for FuchsiaReset {
332 fn assert(&mut self) -> Result<(), BackendError> {
333 match self.proxy.assert(zx::MonotonicInstant::INFINITE) {
334 Ok(Ok(())) => Ok(()),
335 Ok(Err(status)) => {
336 log::warn!("Reset.assert error: {status}");
337 Err(BackendError::Fault)
338 }
339 Err(e) => {
340 log::warn!("Reset.assert fidl error: {e:?}");
341 Err(BackendError::Fault)
342 }
343 }
344 }
345
346 fn deassert(&mut self) -> Result<(), BackendError> {
347 match self.proxy.deassert(zx::MonotonicInstant::INFINITE) {
348 Ok(Ok(())) => Ok(()),
349 Ok(Err(status)) => {
350 log::warn!("Reset.deassert error: {status}");
351 Err(BackendError::Fault)
352 }
353 Err(e) => {
354 log::warn!("Reset.deassert fidl error: {e:?}");
355 Err(BackendError::Fault)
356 }
357 }
358 }
359
360 fn toggle(&mut self) -> Result<(), BackendError> {
361 match self.proxy.toggle(zx::MonotonicInstant::INFINITE) {
362 Ok(Ok(())) => Ok(()),
363 Ok(Err(status)) => {
364 log::warn!("Reset.toggle error: {status}");
365 Err(BackendError::Fault)
366 }
367 Err(e) => {
368 log::warn!("Reset.toggle fidl error: {e:?}");
369 Err(BackendError::Fault)
370 }
371 }
372 }
373
374 fn status(&mut self) -> Result<bool, BackendError> {
375 match self.proxy.status(zx::MonotonicInstant::INFINITE) {
376 Ok(Ok(val)) => Ok(val),
377 Ok(Err(status)) => {
378 log::warn!("Reset.status error: {status}");
379 Err(BackendError::Fault)
380 }
381 Err(e) => {
382 log::warn!("Reset.status fidl error: {e:?}");
383 Err(BackendError::Fault)
384 }
385 }
386 }
387}
388
389impl ResourceBackend for FuchsiaReset {
390 fn reset_assert(&mut self) -> Result<(), BackendError> {
391 self.assert()
392 }
393 fn reset_deassert(&mut self) -> Result<(), BackendError> {
394 self.deassert()
395 }
396 fn reset_toggle(&mut self) -> Result<(), BackendError> {
397 self.toggle()
398 }
399 fn reset_status(&mut self) -> Result<bool, BackendError> {
400 self.status()
401 }
402}
403
404pub struct FuchsiaSerial {
406 proxy: fserial::DeviceSynchronousProxy,
407}
408
409impl FuchsiaSerial {
410 pub fn new(proxy: fserial::DeviceSynchronousProxy) -> Self {
411 Self { proxy }
412 }
413}
414
415impl std::fmt::Debug for FuchsiaSerial {
416 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
417 f.debug_struct("FuchsiaSerial").finish()
418 }
419}
420
421impl SerialBackend for FuchsiaSerial {
422 fn read(&mut self) -> Result<Vec<u8>, BackendError> {
423 match self.proxy.read(zx::MonotonicInstant::INFINITE) {
424 Ok(Ok(val)) => Ok(val),
425 Ok(Err(status)) => {
426 log::warn!("Serial.read error: {status}");
427 Err(BackendError::Fault)
428 }
429 Err(e) => {
430 log::warn!("Serial.read fidl error: {e:?}");
431 Err(BackendError::Fault)
432 }
433 }
434 }
435
436 fn write(&mut self, data: &[u8]) -> Result<(), BackendError> {
437 match self.proxy.write(data, zx::MonotonicInstant::INFINITE) {
438 Ok(Ok(())) => Ok(()),
439 Ok(Err(status)) => {
440 log::warn!("Serial.write error: {status}");
441 Err(BackendError::Fault)
442 }
443 Err(e) => {
444 log::warn!("Serial.write fidl error: {e:?}");
445 Err(BackendError::Fault)
446 }
447 }
448 }
449}
450
451impl ResourceBackend for FuchsiaSerial {
452 fn serial_read(&mut self) -> Result<Vec<u8>, BackendError> {
453 self.read()
454 }
455 fn serial_write(&mut self, data: &[u8]) -> Result<(), BackendError> {
456 self.write(data)
457 }
458}
459
460#[derive(Debug)]
462pub enum LiveBackend {
463 Mmio(MappedMmio),
464 State(StateBank),
465 Gpio(FuchsiaGpio),
466 I2c(FuchsiaI2c),
467 Spi(FuchsiaSpi),
468 Clock(FuchsiaClock),
469 Reset(FuchsiaReset),
470 Serial(FuchsiaSerial),
471 Interrupt,
472}
473
474impl ResourceBackend for LiveBackend {
475 fn read32(&mut self, offset: u64) -> Result<u32, BackendError> {
476 match self {
477 Self::Mmio(m) => m.read32(offset),
478 Self::State(s) => s.read32(offset),
479 _ => Err(BackendError::Fault),
480 }
481 }
482
483 fn write32(&mut self, offset: u64, value: u32) -> Result<(), BackendError> {
484 match self {
485 Self::Mmio(m) => m.write32(offset, value),
486 Self::State(s) => s.write32(offset, value),
487 _ => Err(BackendError::Fault),
488 }
489 }
490
491 fn barrier(&mut self) {
492 match self {
493 Self::Mmio(m) => m.barrier(),
494 Self::State(s) => s.barrier(),
495 _ => {}
496 }
497 }
498
499 fn gpio_read(&mut self) -> Result<bool, BackendError> {
500 match self {
501 Self::Gpio(g) => g.gpio_read(),
502 _ => Err(BackendError::Fault),
503 }
504 }
505
506 fn gpio_write(&mut self, value: bool) -> Result<(), BackendError> {
507 match self {
508 Self::Gpio(g) => g.gpio_write(value),
509 _ => Err(BackendError::Fault),
510 }
511 }
512
513 fn i2c_transfer(
514 &mut self,
515 write_data: &[u8],
516 read_length: usize,
517 ) -> Result<Vec<u8>, BackendError> {
518 match self {
519 Self::I2c(i) => i.i2c_transfer(write_data, read_length),
520 _ => Err(BackendError::Fault),
521 }
522 }
523
524 fn spi_transmit(&mut self, tx_data: &[u8]) -> Result<Vec<u8>, BackendError> {
525 match self {
526 Self::Spi(s) => s.spi_transmit(tx_data),
527 _ => Err(BackendError::Fault),
528 }
529 }
530
531 fn clock_enable(&mut self) -> Result<(), BackendError> {
532 match self {
533 Self::Clock(c) => c.clock_enable(),
534 _ => Err(BackendError::Fault),
535 }
536 }
537
538 fn clock_disable(&mut self) -> Result<(), BackendError> {
539 match self {
540 Self::Clock(c) => c.clock_disable(),
541 _ => Err(BackendError::Fault),
542 }
543 }
544
545 fn clock_is_enabled(&mut self) -> Result<bool, BackendError> {
546 match self {
547 Self::Clock(c) => c.clock_is_enabled(),
548 _ => Err(BackendError::Fault),
549 }
550 }
551
552 fn clock_set_rate(&mut self, hz: u64) -> Result<(), BackendError> {
553 match self {
554 Self::Clock(c) => c.clock_set_rate(hz),
555 _ => Err(BackendError::Fault),
556 }
557 }
558
559 fn clock_query_rate(&mut self, hz_in: u64) -> Result<u64, BackendError> {
560 match self {
561 Self::Clock(c) => c.clock_query_rate(hz_in),
562 _ => Err(BackendError::Fault),
563 }
564 }
565
566 fn clock_get_rate(&mut self) -> Result<u64, BackendError> {
567 match self {
568 Self::Clock(c) => c.clock_get_rate(),
569 _ => Err(BackendError::Fault),
570 }
571 }
572
573 fn reset_assert(&mut self) -> Result<(), BackendError> {
574 match self {
575 Self::Reset(r) => r.reset_assert(),
576 _ => Err(BackendError::Fault),
577 }
578 }
579
580 fn reset_deassert(&mut self) -> Result<(), BackendError> {
581 match self {
582 Self::Reset(r) => r.reset_deassert(),
583 _ => Err(BackendError::Fault),
584 }
585 }
586
587 fn reset_toggle(&mut self) -> Result<(), BackendError> {
588 match self {
589 Self::Reset(r) => r.reset_toggle(),
590 _ => Err(BackendError::Fault),
591 }
592 }
593
594 fn reset_status(&mut self) -> Result<bool, BackendError> {
595 match self {
596 Self::Reset(r) => r.reset_status(),
597 _ => Err(BackendError::Fault),
598 }
599 }
600
601 fn serial_read(&mut self) -> Result<Vec<u8>, BackendError> {
602 match self {
603 Self::Serial(s) => s.serial_read(),
604 _ => Err(BackendError::Fault),
605 }
606 }
607
608 fn serial_write(&mut self, data: &[u8]) -> Result<(), BackendError> {
609 match self {
610 Self::Serial(s) => s.serial_write(data),
611 _ => Err(BackendError::Fault),
612 }
613 }
614}