1use crate::frame::{Cmd, FrameWriter, WriteError};
23use crate::items::{self, ItemError};
24use crate::pui;
25use crate::status::Status;
26
27pub const ADDRESS_MAX: u8 = 0x7F;
29pub const SCAN_DEFAULT_FIRST: u8 = 0x08;
33pub const SCAN_DEFAULT_LAST: u8 = 0x77;
36
37#[derive(Clone, Copy, Debug, PartialEq, Eq)]
39pub enum I2cError {
40 Parse,
42 Invalid,
47}
48
49impl I2cError {
50 pub const fn status(self) -> Status {
52 match self {
53 Self::Parse => Status::PARSE_ERROR,
54 Self::Invalid => Status::INVALID_ARGUMENT,
55 }
56 }
57}
58
59#[derive(Clone, Copy, Debug, PartialEq, Eq)]
61#[repr(u8)]
62pub enum OpKind {
63 Write = 0,
64 Read = 1,
65}
66
67impl OpKind {
68 pub const fn code(self) -> u8 {
69 self as u8
70 }
71
72 pub const fn from_code(code: u8) -> Option<Self> {
73 match code {
74 0 => Some(Self::Write),
75 1 => Some(Self::Read),
76 _ => None,
77 }
78 }
79}
80
81#[derive(Clone, Copy, Debug, PartialEq, Eq)]
83pub enum Op<'a> {
84 Write(&'a [u8]),
86 Read(usize),
88}
89
90impl Op<'_> {
91 pub const fn kind(&self) -> OpKind {
92 match self {
93 Self::Write(_) => OpKind::Write,
94 Self::Read(_) => OpKind::Read,
95 }
96 }
97
98 pub const fn data_len(&self) -> usize {
100 match self {
101 Self::Write(data) => data.len(),
102 Self::Read(len) => *len,
103 }
104 }
105
106 pub const fn wire_len(&self) -> usize {
108 let len = self.data_len();
109 let body = match self {
110 Self::Write(_) => len,
111 Self::Read(_) => 0,
112 };
113 1 + pui::encoded_len(len as u32) + body
114 }
115
116 fn write(&self, writer: &mut FrameWriter<'_>) -> Result<(), WriteError> {
117 writer.write_u8(self.kind().code())?;
118 let len = u32::try_from(self.data_len()).map_err(|_| WriteError::ValueTooLarge)?;
119 writer.write_pui(len)?;
120 if let Self::Write(data) = self {
121 writer.write_bytes(data)?;
122 }
123 Ok(())
124 }
125}
126
127#[derive(Clone)]
131pub struct Ops<'a> {
132 rest: &'a [u8],
133}
134
135impl<'a> Iterator for Ops<'a> {
136 type Item = Result<Op<'a>, I2cError>;
137
138 fn next(&mut self) -> Option<Self::Item> {
139 let [kind, rest @ ..] = self.rest else {
140 return None;
141 };
142 let result = (|| {
143 let kind = OpKind::from_code(*kind).ok_or(I2cError::Invalid)?;
144 let (len, consumed) = pui::decode(rest).map_err(|_| I2cError::Parse)?;
145 let len = usize::try_from(len).map_err(|_| I2cError::Parse)?;
146 if len == 0 {
147 return Err(I2cError::Invalid);
148 }
149 let rest = &rest[consumed..];
150 match kind {
151 OpKind::Read => Ok((Op::Read(len), rest)),
152 OpKind::Write => {
153 if rest.len() < len {
154 return Err(I2cError::Parse);
155 }
156 let (data, rest) = rest.split_at(len);
157 Ok((Op::Write(data), rest))
158 }
159 }
160 })();
161 match result {
162 Ok((op, rest)) => {
163 self.rest = rest;
164 Some(Ok(op))
165 }
166 Err(error) => {
167 self.rest = &[];
168 Some(Err(error))
169 }
170 }
171 }
172}
173
174#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
176pub struct TransferShape {
177 pub ops: usize,
179 pub data_len: usize,
182 pub read_len: usize,
184}
185
186#[derive(Clone, Copy, Debug, PartialEq, Eq)]
188pub struct TransferRequest<'a> {
189 pub bus: u8,
190 pub addr: u8,
192 ops: &'a [u8],
193}
194
195impl<'a> TransferRequest<'a> {
196 pub fn parse(payload: &'a [u8]) -> Result<Self, I2cError> {
198 let [bus, addr, ops @ ..] = payload else {
199 return Err(I2cError::Parse);
200 };
201 if *addr > ADDRESS_MAX {
202 return Err(I2cError::Invalid);
203 }
204 let request = Self {
205 bus: *bus,
206 addr: *addr,
207 ops,
208 };
209 let mut count = 0usize;
210 for op in request.ops() {
211 op?;
212 count += 1;
213 }
214 if count == 0 {
215 return Err(I2cError::Invalid);
216 }
217 Ok(request)
218 }
219
220 pub const fn from_parts(bus: u8, addr: u8, ops: &'a [u8]) -> Self {
223 Self { bus, addr, ops }
224 }
225
226 pub const fn encoded_ops(&self) -> &'a [u8] {
228 self.ops
229 }
230
231 pub const fn ops(&self) -> Ops<'a> {
233 Ops { rest: self.ops }
234 }
235
236 pub fn shape(&self) -> TransferShape {
239 let mut shape = TransferShape::default();
240 for op in self.ops().flatten() {
241 shape.ops += 1;
242 shape.data_len += op.data_len();
243 if let Op::Read(len) = op {
244 shape.read_len += len;
245 }
246 }
247 shape
248 }
249}
250
251pub fn encode_transfer(
253 buf: &mut [u8],
254 tid: u8,
255 bus: u8,
256 addr: u8,
257 ops: &[Op<'_>],
258) -> Result<usize, WriteError> {
259 let mut writer = FrameWriter::new(buf, tid, Cmd::I2cTransfer)?;
260 writer.write_u8(bus)?;
261 writer.write_u8(addr)?;
262 for op in ops {
263 op.write(&mut writer)?;
264 }
265 Ok(writer.finish())
266}
267
268#[derive(Clone, Copy, Debug, PartialEq, Eq)]
271pub struct ScanRequest {
272 pub bus: u8,
273 pub first: u8,
274 pub last: u8,
275}
276
277impl ScanRequest {
278 pub const fn new(bus: u8) -> Self {
280 Self {
281 bus,
282 first: SCAN_DEFAULT_FIRST,
283 last: SCAN_DEFAULT_LAST,
284 }
285 }
286
287 pub fn parse(payload: &[u8]) -> Result<Self, I2cError> {
289 let request = match payload {
290 &[bus] => Self::new(bus),
291 &[bus, first, last] => Self { bus, first, last },
292 _ => return Err(I2cError::Parse),
293 };
294 if request.first > request.last || request.last > ADDRESS_MAX {
295 return Err(I2cError::Invalid);
296 }
297 Ok(request)
298 }
299
300 pub const fn len(&self) -> usize {
302 self.last as usize - self.first as usize + 1
303 }
304
305 pub const fn covers(&self, addr: u8) -> bool {
307 self.first <= addr && addr <= self.last
308 }
309}
310
311pub fn encode_scan(
313 buf: &mut [u8],
314 tid: u8,
315 bus: u8,
316 range: Option<(u8, u8)>,
317) -> Result<usize, WriteError> {
318 let mut writer = FrameWriter::new(buf, tid, Cmd::I2cScan)?;
319 writer.write_u8(bus)?;
320 if let Some((first, last)) = range {
321 writer.write_u8(first)?;
322 writer.write_u8(last)?;
323 }
324 Ok(writer.finish())
325}
326
327pub fn encode_result(buf: &mut [u8], tid: u8, data: &[u8]) -> Result<usize, WriteError> {
330 let mut writer = FrameWriter::new(buf, tid, Cmd::I2cResult)?;
331 writer.write_bytes(data)?;
332 Ok(writer.finish())
333}
334
335pub const RESULT_OVERHEAD: usize = 2;
338
339#[derive(Clone, Copy, Debug, PartialEq, Eq)]
345pub struct BusInfo<'a> {
346 pub bus: u8,
347 pub speed_khz: u16,
349 pub max_data: u16,
352 pub max_ops: u8,
354 pub name: &'a str,
356}
357
358impl<'a> BusInfo<'a> {
359 const FIXED_LEN: usize = 6;
360
361 pub const fn wire_len(&self) -> usize {
363 Self::FIXED_LEN + self.name.len()
364 }
365
366 pub fn encode(&self, out: &mut [u8]) -> Result<usize, ItemError> {
369 let mut item = [0u8; Self::FIXED_LEN + NAME_MAX_LEN];
370 let len = self.wire_len();
371 if len > item.len() {
372 return Err(ItemError::BadLength);
373 }
374 item[0] = self.bus;
375 item[1..3].copy_from_slice(&self.speed_khz.to_le_bytes());
376 item[3..5].copy_from_slice(&self.max_data.to_le_bytes());
377 item[5] = self.max_ops;
378 item[6..len].copy_from_slice(self.name.as_bytes());
379 items::encode_prefixed_item(&item[..len], out)
380 }
381
382 pub fn decode(item: &'a [u8]) -> Result<Self, I2cError> {
384 let [
385 bus,
386 speed_lo,
387 speed_hi,
388 max_data_lo,
389 max_data_hi,
390 max_ops,
391 name @ ..,
392 ] = item
393 else {
394 return Err(I2cError::Parse);
395 };
396 let name = core::str::from_utf8(name).map_err(|_| I2cError::Invalid)?;
397 Ok(Self {
398 bus: *bus,
399 speed_khz: u16::from_le_bytes([*speed_lo, *speed_hi]),
400 max_data: u16::from_le_bytes([*max_data_lo, *max_data_hi]),
401 max_ops: *max_ops,
402 name,
403 })
404 }
405}
406
407pub const NAME_MAX_LEN: usize = 64;
409
410#[derive(Clone, Copy, Debug, PartialEq, Eq)]
416pub struct DeviceInfo<'a> {
417 pub bus: u8,
418 pub addr: u8,
420 pub name: &'a str,
422}
423
424impl<'a> DeviceInfo<'a> {
425 const FIXED_LEN: usize = 2;
426
427 pub const fn wire_len(&self) -> usize {
429 Self::FIXED_LEN + self.name.len()
430 }
431
432 pub fn encode(&self, out: &mut [u8]) -> Result<usize, ItemError> {
435 let mut item = [0u8; Self::FIXED_LEN + NAME_MAX_LEN];
436 let len = self.wire_len();
437 if len > item.len() {
438 return Err(ItemError::BadLength);
439 }
440 item[0] = self.bus;
441 item[1] = self.addr;
442 item[2..len].copy_from_slice(self.name.as_bytes());
443 items::encode_prefixed_item(&item[..len], out)
444 }
445
446 pub fn decode(item: &'a [u8]) -> Result<Self, I2cError> {
448 let [bus, addr, name @ ..] = item else {
449 return Err(I2cError::Parse);
450 };
451 let name = core::str::from_utf8(name).map_err(|_| I2cError::Invalid)?;
452 Ok(Self {
453 bus: *bus,
454 addr: *addr,
455 name,
456 })
457 }
458}
459
460pub fn buses(value: &[u8]) -> impl Iterator<Item = Result<BusInfo<'_>, I2cError>> {
462 items::prefixed_items(value).map(|item| BusInfo::decode(item.map_err(|_| I2cError::Parse)?))
463}
464
465pub fn devices(value: &[u8]) -> impl Iterator<Item = Result<DeviceInfo<'_>, I2cError>> {
467 items::prefixed_items(value).map(|item| DeviceInfo::decode(item.map_err(|_| I2cError::Parse)?))
468}
469
470#[cfg(test)]
471mod tests {
472 use super::*;
473 use crate::frame::Frame;
474
475 fn payload(buf: &[u8], cmd: Cmd, tid: u8) -> &[u8] {
476 let frame = Frame::parse(buf).unwrap();
477 assert_eq!(frame.command(), Some(cmd));
478 assert_eq!(frame.header.tid(), tid);
479 frame.payload
480 }
481
482 #[test]
483 fn a_register_read_round_trips() {
484 let mut buf = [0u8; 32];
485 let ops = [Op::Write(&[0x08]), Op::Read(2)];
486 let len = encode_transfer(&mut buf, 3, 0, 0x55, &ops).unwrap();
487 assert_eq!(buf[1], Cmd::I2cTransfer as u8);
488 assert_eq!(&buf[2..len], &[0, 0x55, 0, 1, 0x08, 1, 2]);
489 let request = TransferRequest::parse(payload(&buf[..len], Cmd::I2cTransfer, 3)).unwrap();
490 assert_eq!((request.bus, request.addr), (0, 0x55));
491 let decoded: Vec<Op<'_>> = request.ops().collect::<Result<_, _>>().unwrap();
492 assert_eq!(decoded, ops);
493 assert_eq!(
494 request.shape(),
495 TransferShape {
496 ops: 2,
497 data_len: 3,
498 read_len: 2,
499 }
500 );
501 let staged = TransferRequest::from_parts(0, 0x55, request.encoded_ops());
503 assert_eq!(staged, request);
504 }
505
506 #[test]
507 fn long_operations_take_a_two_octet_length() {
508 let data = [0xA5u8; 200];
509 let ops = [Op::Write(&data), Op::Read(150)];
510 assert_eq!(ops[0].wire_len(), 1 + 2 + 200);
511 assert_eq!(ops[1].wire_len(), 1 + 2);
512 let mut buf = [0u8; 256];
513 let len = encode_transfer(&mut buf, 0, 1, 0x50, &ops).unwrap();
514 assert_eq!(len, 2 + 2 + ops[0].wire_len() + ops[1].wire_len());
515 let request = TransferRequest::parse(payload(&buf[..len], Cmd::I2cTransfer, 0)).unwrap();
516 let decoded: Vec<Op<'_>> = request.ops().collect::<Result<_, _>>().unwrap();
517 assert_eq!(decoded, ops);
518 assert_eq!(request.shape().data_len, 350);
519 assert_eq!(request.shape().read_len, 150);
520 }
521
522 #[test]
523 fn invalid_transfers_are_refused_before_the_bus() {
524 assert_eq!(
526 TransferRequest::parse(&[0, 0x80, 1, 1]),
527 Err(I2cError::Invalid)
528 );
529 assert_eq!(
531 TransferRequest::parse(&[0, 0x50, 2, 1]),
532 Err(I2cError::Invalid)
533 );
534 assert_eq!(
536 TransferRequest::parse(&[0, 0x50, 1, 0]),
537 Err(I2cError::Invalid)
538 );
539 assert_eq!(
540 TransferRequest::parse(&[0, 0x50, 0, 0]),
541 Err(I2cError::Invalid)
542 );
543 assert_eq!(TransferRequest::parse(&[0, 0x50]), Err(I2cError::Invalid));
545 assert_eq!(
547 TransferRequest::parse(&[0, 0x50, 1, 1, 7, 1]),
548 Err(I2cError::Invalid)
549 );
550 }
551
552 #[test]
553 fn truncated_transfers_are_parse_errors() {
554 assert_eq!(TransferRequest::parse(&[]), Err(I2cError::Parse));
555 assert_eq!(TransferRequest::parse(&[0]), Err(I2cError::Parse));
556 assert_eq!(TransferRequest::parse(&[0, 0x50, 1]), Err(I2cError::Parse));
558 assert_eq!(
560 TransferRequest::parse(&[0, 0x50, 0, 3, 0xAA]),
561 Err(I2cError::Parse)
562 );
563 assert_eq!(
565 TransferRequest::parse(&[0, 0x50, 1, 0x80]),
566 Err(I2cError::Parse)
567 );
568 assert_eq!(I2cError::Parse.status(), Status::PARSE_ERROR);
569 assert_eq!(I2cError::Invalid.status(), Status::INVALID_ARGUMENT);
570 }
571
572 #[test]
573 fn scan_requests_default_and_validate_their_range() {
574 let mut buf = [0u8; 8];
575 let len = encode_scan(&mut buf, 5, 2, None).unwrap();
576 assert_eq!(len, 3);
577 let request = ScanRequest::parse(payload(&buf[..len], Cmd::I2cScan, 5)).unwrap();
578 assert_eq!(request, ScanRequest::new(2));
579 assert_eq!(request.len(), 0x70);
580 assert!(request.covers(0x08));
581 assert!(request.covers(0x77));
582 assert!(!request.covers(0x78));
583
584 let len = encode_scan(&mut buf, 5, 0, Some((0x50, 0x57))).unwrap();
585 let request = ScanRequest::parse(payload(&buf[..len], Cmd::I2cScan, 5)).unwrap();
586 assert_eq!(
587 request,
588 ScanRequest {
589 bus: 0,
590 first: 0x50,
591 last: 0x57,
592 }
593 );
594 assert_eq!(request.len(), 8);
595
596 assert_eq!(ScanRequest::parse(&[]), Err(I2cError::Parse));
597 assert_eq!(ScanRequest::parse(&[0, 0x10]), Err(I2cError::Parse));
598 assert_eq!(
599 ScanRequest::parse(&[0, 0x10, 0x20, 0]),
600 Err(I2cError::Parse)
601 );
602 assert_eq!(ScanRequest::parse(&[0, 0x20, 0x10]), Err(I2cError::Invalid));
603 assert_eq!(ScanRequest::parse(&[0, 0x10, 0x80]), Err(I2cError::Invalid));
604 assert!(ScanRequest::parse(&[0, 0x55, 0x55]).is_ok());
606 }
607
608 #[test]
609 fn results_carry_their_data_verbatim() {
610 let mut buf = [0u8; 16];
611 let len = encode_result(&mut buf, 6, &[0x20, 0x28, 0x34]).unwrap();
612 assert_eq!(len, RESULT_OVERHEAD + 3);
613 assert_eq!(payload(&buf[..len], Cmd::I2cResult, 6), &[0x20, 0x28, 0x34]);
614 let len = encode_result(&mut buf, 6, &[]).unwrap();
615 assert_eq!(payload(&buf[..len], Cmd::I2cResult, 6), &[]);
616 }
617
618 #[test]
619 fn bus_and_device_tables_round_trip() {
620 let bus = BusInfo {
621 bus: 0,
622 speed_khz: 400,
623 max_data: 255,
624 max_ops: 16,
625 name: "I2C0 SDA GPIO3 SCL GPIO2",
626 };
627 let mut table = [0u8; 64];
628 let len = bus.encode(&mut table).unwrap();
629 assert_eq!(len, 1 + bus.wire_len());
630 assert_eq!(&table[1..7], &[0, 0x90, 0x01, 0xFF, 0x00, 16]);
631 let decoded: Vec<BusInfo<'_>> = buses(&table[..len]).collect::<Result<_, _>>().unwrap();
632 assert_eq!(decoded, [bus]);
633
634 let parts = [
635 DeviceInfo {
636 bus: 0,
637 addr: 0x55,
638 name: "BQ27220",
639 },
640 DeviceInfo {
641 bus: 0,
642 addr: 0x6B,
643 name: "",
644 },
645 ];
646 let mut len = 0;
647 for part in &parts {
648 len += part.encode(&mut table[len..]).unwrap();
649 }
650 let decoded: Vec<DeviceInfo<'_>> =
651 devices(&table[..len]).collect::<Result<_, _>>().unwrap();
652 assert_eq!(decoded, parts);
653 }
654
655 #[test]
656 fn malformed_tables_are_refused() {
657 assert_eq!(BusInfo::decode(&[0, 0x90, 0x01]), Err(I2cError::Parse));
659 assert_eq!(DeviceInfo::decode(&[0]), Err(I2cError::Parse));
660 assert_eq!(
662 BusInfo::decode(&[0, 0x90, 0x01, 0xFF, 0x00, 16, 0xFF]),
663 Err(I2cError::Invalid)
664 );
665 assert_eq!(DeviceInfo::decode(&[0, 0x55, 0xC0]), Err(I2cError::Invalid));
666 assert_eq!(buses(&[9, 0, 0]).next(), Some(Err(I2cError::Parse)));
668 let long = [b'x'; NAME_MAX_LEN + 1];
670 let bus = BusInfo {
671 bus: 0,
672 speed_khz: 100,
673 max_data: 32,
674 max_ops: 4,
675 name: core::str::from_utf8(&long).unwrap(),
676 };
677 assert_eq!(bus.encode(&mut [0u8; 128]), Err(ItemError::BadLength));
678 }
679}