Skip to main content

scll_core/
transport.rs

1//! Transport abstraction — PDD §3.2.
2//!
3//! Blocking; per-APDU timeout owned by the transport. The caller owns the
4//! transport; the library borrows `&mut dyn Transport`. Reader enumeration is
5//! the transport's responsibility. Concrete adapters live in
6//! `scll-transport-pcsc` and `scll-transport-jcsim`.
7//!
8//! `no_std`: the trait is alloc-free even though the concrete PCSC/jcsim
9//! adapters are `std` host crates — they fill these bounded `heapless` buffers.
10//! `transmit` returns one short R-APDU (≤ `RAPDU_MAX`); `reset` returns ATR/ATS
11//! bytes (≤ `ATR_ATS_MAX`).
12
13use heapless::{String, Vec};
14
15use crate::limits::{ATR_ATS_MAX, OTHER_DETAIL_MAX, RAPDU_MAX};
16
17/// One short C-APDU in, one R-APDU out, plus capability/reset/liveness queries.
18pub trait Transport {
19    /// Send one short C-APDU, get one R-APDU. Per-call timeout enforced inside.
20    ///
21    /// # Errors
22    /// Returns a [`TransportError`] if the exchange fails — e.g.
23    /// [`TransportError::Timeout`], [`TransportError::CardRemoved`],
24    /// [`TransportError::ReaderGone`] or [`TransportError::ProtocolError`].
25    fn transmit(&mut self, capdu: &[u8]) -> Result<Vec<u8, RAPDU_MAX>, TransportError>;
26
27    /// Report transport capabilities (T=0 GET RESPONSE handling, protocol, contactless).
28    fn capabilities(&self) -> TransportCaps;
29
30    /// Cold/warm reset; return ATR (contact) or ATS (contactless).
31    ///
32    /// # Errors
33    /// Returns a [`TransportError`] if the card cannot be reset — e.g.
34    /// [`TransportError::ReaderGone`] or [`TransportError::ProtocolError`].
35    fn reset(&mut self) -> Result<AtrAts, TransportError>;
36
37    /// Currently negotiated protocol.
38    fn protocol(&self) -> TransportProtocol;
39
40    /// Liveness check without sending an APDU.
41    fn is_connected(&self) -> bool;
42}
43
44/// Transport-level failure taxonomy (PDD §3.2, minimum set).
45#[derive(Debug, Clone)]
46#[non_exhaustive]
47pub enum TransportError {
48    CardRemoved,
49    ReaderGone,
50    Timeout,
51    ProtocolError,
52    Other(String<OTHER_DETAIL_MAX>),
53}
54
55/// Self-reported transport capabilities.
56#[derive(Debug, Clone)]
57pub struct TransportCaps {
58    pub handles_t0_get_response: bool,
59    pub protocol: TransportProtocol,
60    pub contactless: bool,
61}
62
63/// Negotiated card protocol.
64#[derive(Debug, Clone, Copy, PartialEq, Eq)]
65pub enum TransportProtocol {
66    T0,
67    T1,
68    TCl,
69}
70
71/// Answer-To-Reset (contact) or Answer-To-Select (contactless) bytes.
72#[derive(Debug, Clone)]
73pub struct AtrAts {
74    pub bytes: Vec<u8, ATR_ATS_MAX>,
75    pub protocol: TransportProtocol,
76}