Expand description
Pure-Rust EN 50221 DVB Common Interface runtime — the driver loop over
the dvb_ci codecs.
dvb_ci is no_std and owns the wire layer (TPDU / SPDU / APDU
parse+serialize, CA_PMT building, CI Plus extension APDUs). This crate adds the
runtime: device I/O, the TPDU poll loop, SPDU session management, and the
per-resource state machines that together drive a physical CAM, per
ETSI EN 50221.
§What it does / what it does not
Does: drives a CI module end to end — slot reset, transport connection,
Resource Manager handshake, the six host-provided resources, ca_pmt for the
services you add, and (with a ci0 data device) scrambled-in /
descrambled-out TS. Sync and sans-IO at the core: the caller owns the clock.
Does not: run CI Plus (authentication, Content Control, multi-stream), serve
Low-Speed Communications or any TS 101 699 extension resource, re-tune on a
host_control request (it surfaces the request), or descramble itself.
§Standards supported
| Standard | Edition | Scope | Status |
|---|---|---|---|
| CENELEC EN 50221 | February 1997 | TPDU poll loop, session layer, host-provided Resource Manager / Application Information / Conditional Access / Date-Time / MMI / Host Control | Partial (no Low-Speed Communications; Host Control surfaced, not acted on) |
| ETSI TS 101 699 V1.1.1 | 1999-11 | none at runtime (typed in dvb-ci) | Not implemented |
Linux DVB CA API (dvb_ca_en50221) | kernel ABI | CA_RESET, CA_GET_SLOT_INFO, [slot, connection_id, ...] frames, ciM data plane | Full for the calls used |
§Features
| Feature | Default | Effect |
|---|---|---|
| (none) | yes | Portable sync core and mocks; needs std |
linux | no | LinuxCaDevice, LinuxCiDataDevice, DeviceOpError, the ci-probe binary |
§Design
The whole runtime is written against the CaDevice trait (the
hardware-abstraction boundary), so it runs against either:
- a real Linux CA device (
/dev/dvb/adapterN/caM, thelinuxfeature), or - the in-memory
MockCaDevice, which makes the state machines testable without hardware.
#![deny(unsafe_code)]: only the Linux device leaf uses unsafe. Long-form
length_fields follow dvb-ci’s preserved LengthForm; PID accessors are
typed mpeg_ts::pid::Pid.
§What’s implemented
- Transport (TPDU, Annex A):
Create_T_Chandshake, empty-T_Data_Lastpoll cadence (half-duplex),T_SBdata-available →T_RCV,T_Data_More/Lastreassembly, reply timeout. - Session (SPDU): session table;
open_session_request/response, host-initiatedcreate_session,close_session;session_number+ APDU routing. - Resources (all host-provided): Resource Manager handshake (profile
exchange →
Notification::CamReady), application_information, conditional_access (ca_pmt/ca_pmt_reply), date_time (MJD + BCD), mmi (menus/enquiries asNotification::Mmi, answered viaDriver::mmi_menu_answer/mmi_enquiry_answer/mmi_cancel), andresource::HostControl(tune/replace/clear_replace/ask_releasesurfaced asNotification::HostControl). - Descramble helper:
Driver::descramble/HostRequest::Descrambleruns theca_pmtquery → reply → ok_descrambling sequence, CAID-filtered to the CAM’sca_info. - Devices: the in-memory
MockCaDevice+MockCiDataDevice, and the LinuxcaM(control) +ciM(TS data-plane) devices behind thelinuxfeature. The data plane (CiDataDevice) carries the scrambled-in / descrambled-out TS for separate-CI hardware. - Diagnostics:
RecordingCaDevicecaptures the link in both directions;trace::decode_frame/decode_logannotate a capture (TPDU → SPDU → APDU).
§Managed CAS layer
A single-slot CA orchestration layer sits on top of the raw ca_pmt /
ca_pmt_reply surface, fed parsed dvb-si structs (never raw bytes):
Driver::add_service/remove_service— build + send theca_pmtfrom advb_si::tables::pmt::PmtSectionand track the slot’s active service set.Driver::set_cat— feed the CAT; the EMM-PID set becomes the CAT’s EMM PIDs ∩ the CAM’s advertisedca_infoCAIDs.Driver::emm_pids/descramble_pids/ca_pids/required_pids— the PIDs to route into theci0data plane (EMM ∪ ES ∪ ECM ∪ PCR ∪ CAT =required_pids).Driver::set_requery_interval— opt-in periodicca_pmtre-query; a per-programme status transition surfaces as an edge-triggeredNotification::Entitlement.CaDescrambler— turnkey wrapper that also owns theci0CiDataDevice:feed_tsfilters a scrambled TS chunk torequired_pids()and returns the descrambled TS. OneCaDescrambler= one CI slot = one TS path.
§Hardware verification
Only what the CHANGELOG records: an AlphaCrypt / Irdeto module (live) for the
Resource Manager handshake, application_information and ca_info (18
CA_system_ids); a Digital Devices CXD2099 ci0 for the split-fd data plane
(150 s, 111k feed_ts calls, 0 errors). The periodic re-query is not
verified on any CAM.
§ci-probe
With the linux feature this crate also builds a ci-probe binary that
discovers and engages an installed CAM: ci-probe list / info /
descramble <pmt> / mmi, with --trace for an annotated link dump.
§Related crates
Depends on dvb_ci (re-exported), dvb-si, mpeg-ts and
broadcast-common. MSRV 1.95.0; MIT OR Apache-2.0.
§Example
Drive a CAM with the MockCaDevice — the same Driver API works against
the real Linux device:
use std::time::Duration;
use dvb_ci_runtime::{Driver, HotPlug, MockCaDevice, Notification};
use dvb_ci_runtime::dvb_ci::tpdu::tags;
// Script a module that accepts the transport connection.
let dev = MockCaDevice::new([vec![tags::C_T_C_REPLY, 0x01, 0x01]]);
let mut driver = Driver::new(dev);
driver.init()?; // reset + open the transport connection
// Pump the device: reads frames when readable, otherwise advances the
// EN 50221 poll cadence by the timeout.
for _ in 0..4 {
driver.pump(Duration::from_millis(100))?;
}
// Host-facing events (CamReady, ApplicationInfo, CaInfo, Mmi, HotPlug, …)
// surface here — either poll-drained:
for note in driver.take_notifications() {
match note {
Notification::CamReady => { /* now safe to send a ca_pmt */ }
other => { let _ = other; }
}
}
// …or, since this crate is sync/sans-IO (no channels), delivered by a
// closure callback per pump — `pump_with` for every notification, or
// `pump_hotplug` to react only to CAM/card hot-plug transitions:
driver.pump_hotplug(Duration::from_millis(100), |hp| match hp {
HotPlug::CamPresent => { /* CAM (re)inserted — re-send any pending ca_pmt */ }
HotPlug::CamRemoved => { /* CAM removed — stop descrambling */ }
_ => {}
})?;Re-exports§
pub use dataplane::CiDataDevice;pub use dataplane::MockCiDataDevice;pub use dataplane::PartialWrite;pub use dataplane::TS_PACKET_LEN;pub use dataplane::partial_write_progress;pub use descrambler::CaDescrambler;pub use device::CaDevice;pub use device::DeviceOp;pub use device::DeviceOpError;pub use device::LinkEvent;pub use device::MockCaDevice;pub use device::RecordingCaDevice;pub use device::SlotInfo;pub use driver::Driver;pub use event::Action;pub use event::Event;pub use event::HostRequest;pub use event::HotPlug;pub use event::Notification;pub use linux::LinuxCaDevice;Linux and linuxpub use linux::LinuxCiDataDevice;Linux and linuxpub use managed::CaError;pub use managed::ManagedCa;pub use managed::ManagedService;pub use managed::REQUERY_DEFAULT;pub use stack::CiStack;pub use dvb_ci;
Modules§
- dataplane
- The CI TS data-plane device:
CiDataDevice. - descrambler
- Turnkey CAS descrambler — #763 Layer 2.
- device
- The hardware-abstraction boundary:
CaDevice. - driver
- The driver — the one place I/O happens. It pumps a
CaDeviceagainst the sans-IOCiStack: reads frames in, executes the stack’sActions (writes/ioctls) out, tracks the requested poll timer, and collectsNotifications for the host application. - event
- The sans-IO event/action model.
- linux
Linux and linux - Linux
/dev/dvb/adapterN/caMCaDeviceimplementation (thelinuxfeature). - managed
- Managed CAS-layer state (#763) — the
Driver’s owned view of the slot’s active descrambled-service set. - resource
- The resource layer — application-layer state machines (ETSI EN 50221 §8), one per resource, driven by the session layer’s APDUs.
- session
- SPDU session layer — a sans-IO mechanism over the transport layer (ETSI EN 50221 §7.2).
- stack
- The CI protocol stack — composes the transport + session layers and the resource state machines (Resource Manager, application_information, conditional_access, date_time, mmi, host_control) into one sans-IO core.
- trace
- Human-readable decoding of CI link frames, for diagnosing live-CAM exchanges (e.g. issue #337).
- transport
- TPDU transport layer — a sans-IO state machine for the single transport connection per CI slot (ETSI EN 50221 §A.4).