Skip to main content

Crate dvb_ci_runtime

Crate dvb_ci_runtime 

Source
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

StandardEditionScopeStatus
CENELEC EN 50221February 1997TPDU poll loop, session layer, host-provided Resource Manager / Application Information / Conditional Access / Date-Time / MMI / Host ControlPartial (no Low-Speed Communications; Host Control surfaced, not acted on)
ETSI TS 101 699 V1.1.11999-11none at runtime (typed in dvb-ci)Not implemented
Linux DVB CA API (dvb_ca_en50221)kernel ABICA_RESET, CA_GET_SLOT_INFO, [slot, connection_id, ...] frames, ciM data planeFull for the calls used

§Features

FeatureDefaultEffect
(none)yesPortable sync core and mocks; needs std
linuxnoLinuxCaDevice, 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, the linux feature), 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_C handshake, empty-T_Data_Last poll cadence (half-duplex), T_SB data-available → T_RCV, T_Data_More/Last reassembly, reply timeout.
  • Session (SPDU): session table; open_session_request/response, host-initiated create_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 as Notification::Mmi, answered via Driver::mmi_menu_answer / mmi_enquiry_answer / mmi_cancel), and resource::HostControl (tune/replace/clear_replace/ask_release surfaced as Notification::HostControl).
  • Descramble helper: Driver::descramble / HostRequest::Descramble runs the ca_pmt query → reply → ok_descrambling sequence, CAID-filtered to the CAM’s ca_info.
  • Devices: the in-memory MockCaDevice + MockCiDataDevice, and the Linux caM (control) + ciM (TS data-plane) devices behind the linux feature. The data plane (CiDataDevice) carries the scrambled-in / descrambled-out TS for separate-CI hardware.
  • Diagnostics: RecordingCaDevice captures the link in both directions; trace::decode_frame/decode_log annotate 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):

§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.

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 linux
pub use linux::LinuxCiDataDevice;Linux and linux
pub 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 CaDevice against the sans-IO CiStack: reads frames in, executes the stack’s Actions (writes/ioctls) out, tracks the requested poll timer, and collects Notifications for the host application.
event
The sans-IO event/action model.
linuxLinux and linux
Linux /dev/dvb/adapterN/caM CaDevice implementation (the linux feature).
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).