Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .fusa-reqs.json
Original file line number Diff line number Diff line change
Expand Up @@ -5055,6 +5055,26 @@
"asil": "ASIL-B",
"verificationMethod": "test"
},
{
"id": "REQ-MDIO-007",
"title": "MdioRequest enumerates the decoded shape of a Row-2 MDIO request after evt[2:0] validation, wrapping an already-decoded MdioTransfer",
"text": "MdioRequest's two variants (Plain(MdioTransfer), ConfigWrite) give an incoming MDIO request's decoded shape after its evt.sub_opcode has been validated against evt_row2_kind_of's Table 33 Row-2 rule; MdioRequest::from_evt_sub_opcode is the request-decode entry point that performs that validation and dispatch. Unlike I2cRequest::from_evt_sub_opcode/LinRequest::from_evt_sub_opcode/AdcRequest::from_evt_sub_opcode/PwmInRequest::from_evt_sub_opcode/UartRequest::from_evt_sub_opcode (each of which take raw byte_msg_payload bytes and decode them internally), MdioRequest::from_evt_sub_opcode takes an already-decoded MdioTransfer, matching CanRequest::from_evt_sub_opcode's/IseledRequest::from_evt_sub_opcode's own shape rather than those five siblings' -- MdioTransfer already has its own dedicated decode entry point (MdioTransfer::decode, pre-existing this item and unchanged by it), so this evt[2:0]-classification entry point does not re-derive that byte-layout logic a second time internally",
"standard": "iso26262",
"level": "HLR",
"asil": "ASIL-B",
"verificationMethod": "test",
"tc18": "§13.5 Table 33's Row-2 row (MDIO is one of its eight endpoint types), TC18.txt L4085-4092, and §13.7.13.3 MDIO request handling, TC18.txt L6065-6066"
},
{
"id": "REQ-MDIO-008",
"title": "MdioRequest::from_evt_sub_opcode accepts Plain and ConfigWrite, rejects Reserved sub_opcodes with UnsupportedCmd, and keeps the Ok(Self::ConfigWrite) precedent rather than CanRequest/IseledRequest's ConfigWriteNotImplemented departure, never panicking",
"text": "MdioRequest::from_evt_sub_opcode wraps the caller-supplied MdioTransfer unchanged in MdioRequest::Plain for a Plain (sub_opcode 0) request, and returns Ok(MdioRequest::ConfigWrite) without interpreting the supplied MdioTransfer for a ConfigWrite (sub_opcode 7) request -- deliberately keeping the Ok(Self::ConfigWrite) precedent I2cRequest/LinRequest/AdcRequest/PwmInRequest/UartRequest each follow rather than following CanRequest::from_evt_sub_opcode's/IseledRequest::from_evt_sub_opcode's own Err(RcpError::ConfigWriteNotImplemented) departure, because MdioTransfer::decode is infallible and interprets no structure at all (every byte slice is a valid MdioTransfer, matching I2cByteTransfer's own raw pass-through discipline), so unlike CanDataFrame/IseledFrame a caller can honestly construct an MdioTransfer from a genuine TC18 §12.7.1 config-write payload with zero misrepresentation -- the 'no caller can honestly construct one' pressure that drove CAN's/ISELED's own departure does not apply to MDIO. Every Reserved sub_opcode value (evt[2:0] in 001b..=110b, or any value outside the 3-bit field's representable range) returns Err(RcpError::UnsupportedCmd), matching TC18 Table 33's Row-2 error-code requirement and every prior Row-2 endpoint-type module's identical refusal of their own table's reserved code. Never panics for any sub_opcode/transfer combination",
"standard": "iso26262",
"level": "HLR",
"asil": "ASIL-B",
"verificationMethod": "test",
"tc18": "§13.5 Table 33 (\"000b to 110b reserved – request to be rejected with error code = UNSUPPORTED_CMD\" / \"111b: ... used to change the configuration of the endpoint (see 12.7.1)\"), TC18.txt L4085-4092"
},
{
"id": "REQ-WAKE-001",
"title": "SleepCmdRequest's fixed 0xA5 discriminant round-trips through encode/decode",
Expand Down
2 changes: 1 addition & 1 deletion ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ shared with go-RCP, c-RCP, and cpp-RCP.
| Canonical choice | Status |
|---|---|
| Response classification (evt-first) | **not conformant** — no classifier exists at all; tracked |
| Table 30 centralization | **partial** — `evtgroup.rs`'s `EvtRow2Kind`/`evt_row2_kind_of` implement Table 33's unambiguous Row-2 `evt[2:0]` rule (`{ADC, PWM_IN, I2C, LIN, CAN, UART, ISELED, MDIO}`); `i2c.rs` (v5.4.0 pilot), `adc.rs` (v5.5.0), `pwm.rs` (v5.6.0, PWM_IN only — PWM_OUT is not a Row-2 endpoint type), `lin.rs` (v5.7.0), `can.rs` (v5.8.0 — the first of these whose `evt[2:0] == 111b`/`ConfigWrite` arm returns a new dedicated error, `RcpError::ConfigWriteNotImplemented`, rather than `Ok(Self::ConfigWrite)`; see `can.rs`'s own doc comment "Provenance note: evt[2:0] request validation" for why), `uart.rs` (v5.9.0 — reverts to the `Ok(Self::ConfigWrite)` precedent I2C/LIN/ADC/PWM_IN share rather than following `can.rs`'s departure, since `UartRequest`'s own `ConfigWrite` arm constructs no UART-specific value and is under no equivalent pressure; `UartRequest`'s `evt[2:0] == 000b`/`Plain` case additionally splits into `Write`/`Read` variants reflecting UART's own independent TX/RX EP-request-storage split, TC18 §13.7.8.1, confirmed orthogonal to `evt[2:0]` classification — see `uart.rs`'s own doc comment "Provenance note: evt[2:0] request validation" for why), and `iseled.rs` (v5.10.0 — follows `can.rs`'s `Err(RcpError::ConfigWriteNotImplemented)` departure rather than the majority `Ok(Self::ConfigWrite)` precedent, since `IseledRequest::from_evt_sub_opcode` takes an already-decoded `IseledFrame` — matching `can.rs`'s `CanDataFrame`-accepting shape, not `i2c.rs`/`lin.rs`/`adc.rs`/`pwm.rs`/`uart.rs`'s own raw-bytes shape — so the same "no caller can honestly construct a config-write payload as one" pressure `can.rs`'s own doc comment names applies here too; see `iseled.rs`'s own doc comment "Provenance note: evt[2:0] request validation" for the full reasoning) are its callers so far; the remaining one Row-2 endpoint type (`MDIO`) doesn't call it yet, GPIO/SPI's own `sub_opcode` readers remain their own private, unclassified reading, and the broader roadmap-named "Groups A/B/C" classification (`EvtGroup`/`classify_evt_sub_opcode`) is still unresolved. This entry previously read "conformant", which was stale: `classify_evt_sub_opcode` was a stub that always returned `Ok(None)`, by its own doc comment's admission |
| Table 30 centralization | **partial** — `evtgroup.rs`'s `EvtRow2Kind`/`evt_row2_kind_of` implement Table 33's unambiguous Row-2 `evt[2:0]` rule (`{ADC, PWM_IN, I2C, LIN, CAN, UART, ISELED, MDIO}`); `i2c.rs` (v5.4.0 pilot), `adc.rs` (v5.5.0), `pwm.rs` (v5.6.0, PWM_IN only — PWM_OUT is not a Row-2 endpoint type), `lin.rs` (v5.7.0), `can.rs` (v5.8.0 — the first of these whose `evt[2:0] == 111b`/`ConfigWrite` arm returns a new dedicated error, `RcpError::ConfigWriteNotImplemented`, rather than `Ok(Self::ConfigWrite)`; see `can.rs`'s own doc comment "Provenance note: evt[2:0] request validation" for why), `uart.rs` (v5.9.0 — reverts to the `Ok(Self::ConfigWrite)` precedent I2C/LIN/ADC/PWM_IN share rather than following `can.rs`'s departure, since `UartRequest`'s own `ConfigWrite` arm constructs no UART-specific value and is under no equivalent pressure; `UartRequest`'s `evt[2:0] == 000b`/`Plain` case additionally splits into `Write`/`Read` variants reflecting UART's own independent TX/RX EP-request-storage split, TC18 §13.7.8.1, confirmed orthogonal to `evt[2:0]` classification — see `uart.rs`'s own doc comment "Provenance note: evt[2:0] request validation" for why), and `iseled.rs` (v5.10.0 — follows `can.rs`'s `Err(RcpError::ConfigWriteNotImplemented)` departure rather than the majority `Ok(Self::ConfigWrite)` precedent, since `IseledRequest::from_evt_sub_opcode` takes an already-decoded `IseledFrame` — matching `can.rs`'s `CanDataFrame`-accepting shape, not `i2c.rs`/`lin.rs`/`adc.rs`/`pwm.rs`/`uart.rs`'s own raw-bytes shape — so the same "no caller can honestly construct a config-write payload as one" pressure `can.rs`'s own doc comment names applies here too; see `iseled.rs`'s own doc comment "Provenance note: evt[2:0] request validation" for the full reasoning), and `mdio.rs` (v5.11.0 — the eighth and last Row-2 endpoint type; `MdioRequest::from_evt_sub_opcode` takes an already-decoded `MdioTransfer`, matching `can.rs`'s/`iseled.rs`'s own decoded-frame shape rather than `i2c.rs`/`lin.rs`/`adc.rs`/`pwm.rs`/`uart.rs`'s raw-bytes shape, but its `evt[2:0] == 111b`/`ConfigWrite` arm stays `Ok(Self::ConfigWrite)` — the majority precedent — rather than following `can.rs`'s/`iseled.rs`'s `Err(RcpError::ConfigWriteNotImplemented)` departure, since `MdioTransfer::decode` is infallible and interprets no structure at all, so the "no caller can honestly construct one" pressure that drove that departure does not apply to MDIO's own always-valid, opaque-bytes shape; see `mdio.rs`'s own doc comment "Provenance note: evt[2:0] request validation" for the full reasoning) are its callers. All eight Row-2 endpoint types (`{ADC, PWM_IN, I2C, LIN, CAN, UART, ISELED, MDIO}`) now call `evt_row2_kind_of`; GPIO/SPI's own `sub_opcode` readers remain their own private, unclassified reading, and the broader roadmap-named "Groups A/B/C" classification (`EvtGroup`/`classify_evt_sub_opcode`) is still unresolved. This entry previously read "conformant", which was stale: `classify_evt_sub_opcode` was a stub that always returned `Ok(None)`, by its own doc comment's admission |
| Conditional-request module unification | **conformant** (this repo is a reference shape, alongside cpp-RCP) |
| Per-function requirement tagging | **not conformant** — tags are collected at file level (top of each `.rs`), not per-function |
| `.fusa-reqs.json` schema (`tc18`/`tc18_master_id`/`status`) | **partial** — has `verificationMethod` but no citation field (TC18 citations live only in code doc-comments); has a working `status: "not-implemented"` exemption mechanism (`scripts/fusa-gap-check.sh`) that go-RCP/cpp-RCP lack |
Expand Down
85 changes: 85 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,91 @@ OPEN Alliance TC18 core replacement; from `v1.0.0` on, each entry is a real
release. See `docs/SEMVER.md` for the versioning scheme, including why a
wire-format change is a MAJOR bump even when it is a fix.

## v5.11.0 (Table 30/33 Row-2 evt[2:0] validation — MDIO, 8th and last endpoint type) — closed

Direct follow-up to v5.10.0: `mdio.rs` becomes the eighth and last of the
TC18 §13.5 Table 33 Row-2 endpoint types (`{ADC, PWM_IN, I2C, LIN, CAN,
UART, ISELED, MDIO}`) to call the shared `evtgroup::evt_row2_kind_of`
predicate. `evtgroup.rs` itself is unchanged — this release only adds
`mdio.rs`'s own caller. This item touches only `evt[2:0]` request
classification; `MdioAddressingMode`'s own (already spec-divergent — see
`mdio.rs`'s pre-existing "Divergence note") `mdio_mode` mapping,
`MdioFunctionalConfig`, and `MdioTransfer`/`MdioTransferResult`'s own
field layout are all unchanged.

New, purely additive `pub` items (MINOR bump per `docs/SEMVER.md`):

- `mdio::MdioRequest` / `mdio::MdioRequest::from_evt_sub_opcode` — MDIO's
own request-decode entry point, structurally mirroring `can::CanRequest`/
`iseled::IseledRequest` in one way and `i2c::I2cRequest`/
`lin::LinRequest`/`adc::AdcRequest`/`pwm::PwmInRequest`/
`uart::UartRequest` in another:
- Like `can.rs`/`iseled.rs`, `from_evt_sub_opcode` takes an
already-decoded `MdioTransfer`, not raw `byte_msg_payload` bytes.
`MdioTransfer` already has its own dedicated decode entry point
(`MdioTransfer::decode`, pre-existing this item and unchanged by it),
so this evt[2:0]-classification entry point does not re-derive that
(trivial) byte-layout logic a second time internally.
- Unlike `can.rs`/`iseled.rs`, `evt[2:0] == 111b` still returns
`Ok(MdioRequest::ConfigWrite)` — the majority precedent
`i2c::I2cRequest`/`lin::LinRequest`/`adc::AdcRequest`/
`pwm::PwmInRequest`/`uart::UartRequest` each already follow — rather
than `Err(RcpError::ConfigWriteNotImplemented)`. This is a deliberate,
independently-reasoned judgment call, not a mechanical copy of either
prior precedent: `can.rs`'s/`iseled.rs`'s own departure rests on their
frame types (`CanDataFrame`, `IseledFrame`) making a real, specific
structural claim about their bytes (a parsed `FrameFormat`/`id`/`data`
or `chain_address`/`command`/`data` shape, either of which can fail to
decode or silently misinterpret unrelated bytes) that a genuine TC18
§12.7.1 config-write payload cannot honestly satisfy. `MdioTransfer`
makes no such claim: `MdioTransfer::decode` is infallible and totally
uninterpreted — every byte slice, including an empty one, is a valid
`MdioTransfer`, matching `i2c::I2cByteTransfer`'s own raw pass-through
discipline. A caller can therefore decode a genuine config-write
payload through `MdioTransfer::decode` with zero information loss or
misrepresentation, so the "no caller can honestly construct one"
pressure that drove `can.rs`'s/`iseled.rs`'s own departure does not
apply here.
See `mdio.rs`'s own doc comment "Provenance note: evt[2:0] request
validation" for the full citation and reasoning behind both choices.

Every `Reserved` sub_opcode value is rejected with
`Err(RcpError::UnsupportedCmd)`, unchanged from every prior Row-2
endpoint-type module — this part of the rule is identical for MDIO.

Also in this release: while independently re-verifying the TC18.txt
citations this item adds (Table 33 Row-2, §13.7.13.3, Figure 43), a
pre-existing citation drift was found in `mdio.rs`'s own "Divergence note"
and "Provenance note: register-access framing is carried opaque" sections
— the same class of drift `iseled.rs`'s own v5.10.0 item found and flagged
for ISELED. `mdio.rs` cites "Table 57"/"TC18.txt line 5676" and "Figure
42"/"TC18.txt line 5664" for MDIO's own request-format/`mdio_mode` field
table, and "Table 56"/"TC18.txt line 5639" for MDIO's functional-config
register layout; against the current `TC18.txt`, those are actually
**Table 60**/line 6088, **Figure 43**/line 6077, and **Table 59**/line
6061 respectively — both the line numbers and the table/figure numbers
have drifted, by roughly the same ~400-line/3-number offset already found
for ISELED. This item deliberately does **not** correct those pre-existing
citations (that is separate, later work, out of scope for this
evt[2:0]-classification item) — it only flags the drift, documented in
`mdio.rs`'s own new "Editorial note: pre-existing §13.7.13 citation drift"
section. The citations newly added by this item were independently
re-verified against `TC18.txt` rather than copied from `mdio.rs`'s own
pre-existing, now-known-stale citations.

Not in this release: wiring `MdioRequest::from_evt_sub_opcode` into
`mock::RcServer`'s actual dispatch — `mock::Endpoint`'s trait signature
still does not carry an `evt` value to any implementation at all, the same
gap v5.4.0's pilot found and left as-is (confirmed unchanged here). This
release also does not touch `MdioAddressingMode`, `MdioFunctionalConfig`,
or any of `mdio.rs`'s own pre-existing "Divergence note"/"Provenance
note" content beyond the new "Editorial note" flagging citation drift
described above — all pre-existing, additive standalone plumbing left
untouched. This closes out the full Table 30/33 Row-2 `evt[2:0]`
validation rollout: all eight Row-2 endpoint types
(`{ADC, PWM_IN, I2C, LIN, CAN, UART, ISELED, MDIO}`) now call
`evtgroup::evt_row2_kind_of`.

## v5.10.0 (Table 30/33 Row-2 evt[2:0] validation — ISELED, 7th endpoint type) — closed

Direct follow-up to v5.9.0: `iseled.rs` becomes the seventh of the eight
Expand Down
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "rcp"
version = "5.10.0"
version = "5.11.0"
edition = "2021"
rust-version = "1.75"
license = "MPL-2.0"
Expand Down
20 changes: 20 additions & 0 deletions docs/PUBLIC_API.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2163,6 +2163,26 @@ impl core::marker::Unpin for rcp::mdio::MdioAddressingMode
impl core::marker::UnsafeUnpin for rcp::mdio::MdioAddressingMode
impl core::panic::unwind_safe::RefUnwindSafe for rcp::mdio::MdioAddressingMode
impl core::panic::unwind_safe::UnwindSafe for rcp::mdio::MdioAddressingMode
pub enum rcp::mdio::MdioRequest
pub rcp::mdio::MdioRequest::ConfigWrite
pub rcp::mdio::MdioRequest::Plain(rcp::mdio::MdioTransfer)
impl rcp::mdio::MdioRequest
pub fn rcp::mdio::MdioRequest::from_evt_sub_opcode(u8, rcp::mdio::MdioTransfer) -> core::result::Result<Self, rcp::RcpError>
impl core::clone::Clone for rcp::mdio::MdioRequest
pub fn rcp::mdio::MdioRequest::clone(&self) -> rcp::mdio::MdioRequest
impl core::cmp::Eq for rcp::mdio::MdioRequest
impl core::cmp::PartialEq for rcp::mdio::MdioRequest
pub fn rcp::mdio::MdioRequest::eq(&self, &rcp::mdio::MdioRequest) -> bool
impl core::fmt::Debug for rcp::mdio::MdioRequest
pub fn rcp::mdio::MdioRequest::fmt(&self, &mut core::fmt::Formatter<'_>) -> core::fmt::Result
impl core::marker::StructuralPartialEq for rcp::mdio::MdioRequest
impl core::marker::Freeze for rcp::mdio::MdioRequest
impl core::marker::Send for rcp::mdio::MdioRequest
impl core::marker::Sync for rcp::mdio::MdioRequest
impl core::marker::Unpin for rcp::mdio::MdioRequest
impl core::marker::UnsafeUnpin for rcp::mdio::MdioRequest
impl core::panic::unwind_safe::RefUnwindSafe for rcp::mdio::MdioRequest
impl core::panic::unwind_safe::UnwindSafe for rcp::mdio::MdioRequest
pub struct rcp::mdio::MdioFunctionalConfig
pub rcp::mdio::MdioFunctionalConfig::addressing_mode: rcp::mdio::MdioAddressingMode
impl rcp::mdio::MdioFunctionalConfig
Expand Down
Loading
Loading