Skip to main content

dvb_simulcrypt/
registry.rs

1//! Interface scoping + the message_type / parameter_type / error_status value
2//! registries for the two implemented SimulCrypt interfaces.
3//!
4//! ETSI TS 103 197 V1.5.1 — Table 2 (protocol_version, §4.4.1 p. 27),
5//! Table 3 (message_type, §4.4.1 pp. 27-28), Table 5/6 (ECMG⇔SCS parameter /
6//! error, §5.2/§5.6) and Table 7/8 (EMMG/PDG⇔MUX parameter / error,
7//! §6.2.2/§6.2.6), and Table 36 (C(P)SIG⇔(P)SIG parameter / §8).
8//!
9//! The `message_type` numeric space is **interface-scoped**: the same 16-bit
10//! value means different things on different interfaces (and on the wire the
11//! interface is fixed by which TCP connection the message arrived on — this
12//! crate takes it as the [`Interface`] hint to [`crate::SimulcryptMessage::parse_on`]).
13
14/// The SimulCrypt connection-oriented interface a message belongs to.
15///
16/// Only the two head-end CA interfaces + C(P)SIG⇔(P)SIG are implemented; the
17/// remaining TS 103 197 interfaces (EIS⇔SCS, (P)SIG⇔MUX, ACG⇔EIS,
18/// SIMCOMP⇔MUXCONFIG) share the same framing but are not modelled here.
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize))]
21#[non_exhaustive]
22pub enum Interface {
23    /// ECMG ⇔ SCS (TS 103 197 clause 5).
24    EcmgScs,
25    /// EMMG/PDG ⇔ MUX (TS 103 197 clause 6).
26    EmmgPdgMux,
27    /// C(P)SIG ⇔ (P)SIG (TS 103 197 clause 8).
28    CpSigPSig,
29}
30
31impl Interface {
32    /// The mandated `protocol_version` byte for this interface (Table 2).
33    ///
34    /// Both implemented interfaces use `0x03` (the `0x05` DVB-H variant of
35    /// annex N is not modelled).
36    pub const PROTOCOL_VERSION: u8 = 0x03;
37
38    /// `protocol_version` for this interface (Table 2, §4.4.1 p. 27).
39    #[must_use]
40    pub const fn protocol_version(self) -> u8 {
41        match self {
42            Self::EcmgScs | Self::EmmgPdgMux | Self::CpSigPSig => Self::PROTOCOL_VERSION,
43        }
44    }
45
46    /// Label per the project's `name()` convention.
47    #[must_use]
48    pub fn name(&self) -> &'static str {
49        match self {
50            Self::EcmgScs => "ECMG<->SCS",
51            Self::EmmgPdgMux => "EMMG/PDG<->MUX",
52            Self::CpSigPSig => "C(P)SIG<->(P)SIG",
53        }
54    }
55}
56dvb_common::impl_spec_display!(Interface);
57
58// ===========================================================================
59// message_type — ECMG ⇔ SCS (Table 3 subset, §5)
60// ===========================================================================
61
62/// ECMG⇔SCS `message_type` values (TS 103 197 Table 3, §4.4.1 pp. 27-28).
63///
64/// `Reserved(u16)` is the catch-all for any value outside the registry
65/// (DVB-reserved or user-defined); it preserves the raw 16-bit value so
66/// `Display`/serialize stay lossless.
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
68#[cfg_attr(feature = "serde", derive(serde::Serialize))]
69#[non_exhaustive]
70pub enum EcmgScsMessageType {
71    /// `0x0001` channel_setup.
72    ChannelSetup,
73    /// `0x0002` channel_test.
74    ChannelTest,
75    /// `0x0003` channel_status.
76    ChannelStatus,
77    /// `0x0004` channel_close.
78    ChannelClose,
79    /// `0x0005` channel_error.
80    ChannelError,
81    /// `0x0101` stream_setup.
82    StreamSetup,
83    /// `0x0102` stream_test.
84    StreamTest,
85    /// `0x0103` stream_status.
86    StreamStatus,
87    /// `0x0104` stream_close_request.
88    StreamCloseRequest,
89    /// `0x0105` stream_close_response.
90    StreamCloseResponse,
91    /// `0x0106` stream_error.
92    StreamError,
93    /// `0x0201` CW_provision.
94    CwProvision,
95    /// `0x0202` ECM_response.
96    EcmResponse,
97    /// Any value not in the ECMG⇔SCS registry (DVB-reserved / user-defined).
98    Reserved(u16),
99}
100
101impl EcmgScsMessageType {
102    /// Decode a 16-bit `message_type` for the ECMG⇔SCS interface.
103    #[must_use]
104    pub const fn from_u16(v: u16) -> Self {
105        match v {
106            0x0001 => Self::ChannelSetup,
107            0x0002 => Self::ChannelTest,
108            0x0003 => Self::ChannelStatus,
109            0x0004 => Self::ChannelClose,
110            0x0005 => Self::ChannelError,
111            0x0101 => Self::StreamSetup,
112            0x0102 => Self::StreamTest,
113            0x0103 => Self::StreamStatus,
114            0x0104 => Self::StreamCloseRequest,
115            0x0105 => Self::StreamCloseResponse,
116            0x0106 => Self::StreamError,
117            0x0201 => Self::CwProvision,
118            0x0202 => Self::EcmResponse,
119            other => Self::Reserved(other),
120        }
121    }
122
123    /// The 16-bit wire value.
124    #[must_use]
125    pub const fn to_u16(self) -> u16 {
126        match self {
127            Self::ChannelSetup => 0x0001,
128            Self::ChannelTest => 0x0002,
129            Self::ChannelStatus => 0x0003,
130            Self::ChannelClose => 0x0004,
131            Self::ChannelError => 0x0005,
132            Self::StreamSetup => 0x0101,
133            Self::StreamTest => 0x0102,
134            Self::StreamStatus => 0x0103,
135            Self::StreamCloseRequest => 0x0104,
136            Self::StreamCloseResponse => 0x0105,
137            Self::StreamError => 0x0106,
138            Self::CwProvision => 0x0201,
139            Self::EcmResponse => 0x0202,
140            Self::Reserved(v) => v,
141        }
142    }
143
144    /// Label per the project's `name()` convention.
145    #[must_use]
146    pub fn name(&self) -> &'static str {
147        match self {
148            Self::ChannelSetup => "channel_setup",
149            Self::ChannelTest => "channel_test",
150            Self::ChannelStatus => "channel_status",
151            Self::ChannelClose => "channel_close",
152            Self::ChannelError => "channel_error",
153            Self::StreamSetup => "stream_setup",
154            Self::StreamTest => "stream_test",
155            Self::StreamStatus => "stream_status",
156            Self::StreamCloseRequest => "stream_close_request",
157            Self::StreamCloseResponse => "stream_close_response",
158            Self::StreamError => "stream_error",
159            Self::CwProvision => "CW_provision",
160            Self::EcmResponse => "ECM_response",
161            Self::Reserved(_) => "reserved",
162        }
163    }
164}
165dvb_common::impl_spec_display!(EcmgScsMessageType, Reserved);
166
167// ===========================================================================
168// message_type — EMMG/PDG ⇔ MUX (Table 3 subset, §6)
169// ===========================================================================
170
171/// EMMG/PDG⇔MUX `message_type` values (TS 103 197 Table 3, §4.4.1 pp. 27-28).
172#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
173#[cfg_attr(feature = "serde", derive(serde::Serialize))]
174#[non_exhaustive]
175pub enum EmmgMuxMessageType {
176    /// `0x0011` channel_setup.
177    ChannelSetup,
178    /// `0x0012` channel_test.
179    ChannelTest,
180    /// `0x0013` channel_status.
181    ChannelStatus,
182    /// `0x0014` channel_close.
183    ChannelClose,
184    /// `0x0015` channel_error.
185    ChannelError,
186    /// `0x0111` stream_setup.
187    StreamSetup,
188    /// `0x0112` stream_test.
189    StreamTest,
190    /// `0x0113` stream_status.
191    StreamStatus,
192    /// `0x0114` stream_close_request.
193    StreamCloseRequest,
194    /// `0x0115` stream_close_response.
195    StreamCloseResponse,
196    /// `0x0116` stream_error.
197    StreamError,
198    /// `0x0117` stream_BW_request.
199    StreamBwRequest,
200    /// `0x0118` stream_BW_allocation.
201    StreamBwAllocation,
202    /// `0x0211` data_provision.
203    DataProvision,
204    /// Any value not in the EMMG/PDG⇔MUX registry (DVB-reserved / user-defined).
205    Reserved(u16),
206}
207
208impl EmmgMuxMessageType {
209    /// Decode a 16-bit `message_type` for the EMMG/PDG⇔MUX interface.
210    #[must_use]
211    pub const fn from_u16(v: u16) -> Self {
212        match v {
213            0x0011 => Self::ChannelSetup,
214            0x0012 => Self::ChannelTest,
215            0x0013 => Self::ChannelStatus,
216            0x0014 => Self::ChannelClose,
217            0x0015 => Self::ChannelError,
218            0x0111 => Self::StreamSetup,
219            0x0112 => Self::StreamTest,
220            0x0113 => Self::StreamStatus,
221            0x0114 => Self::StreamCloseRequest,
222            0x0115 => Self::StreamCloseResponse,
223            0x0116 => Self::StreamError,
224            0x0117 => Self::StreamBwRequest,
225            0x0118 => Self::StreamBwAllocation,
226            0x0211 => Self::DataProvision,
227            other => Self::Reserved(other),
228        }
229    }
230
231    /// The 16-bit wire value.
232    #[must_use]
233    pub const fn to_u16(self) -> u16 {
234        match self {
235            Self::ChannelSetup => 0x0011,
236            Self::ChannelTest => 0x0012,
237            Self::ChannelStatus => 0x0013,
238            Self::ChannelClose => 0x0014,
239            Self::ChannelError => 0x0015,
240            Self::StreamSetup => 0x0111,
241            Self::StreamTest => 0x0112,
242            Self::StreamStatus => 0x0113,
243            Self::StreamCloseRequest => 0x0114,
244            Self::StreamCloseResponse => 0x0115,
245            Self::StreamError => 0x0116,
246            Self::StreamBwRequest => 0x0117,
247            Self::StreamBwAllocation => 0x0118,
248            Self::DataProvision => 0x0211,
249            Self::Reserved(v) => v,
250        }
251    }
252
253    /// Label per the project's `name()` convention.
254    #[must_use]
255    pub fn name(&self) -> &'static str {
256        match self {
257            Self::ChannelSetup => "channel_setup",
258            Self::ChannelTest => "channel_test",
259            Self::ChannelStatus => "channel_status",
260            Self::ChannelClose => "channel_close",
261            Self::ChannelError => "channel_error",
262            Self::StreamSetup => "stream_setup",
263            Self::StreamTest => "stream_test",
264            Self::StreamStatus => "stream_status",
265            Self::StreamCloseRequest => "stream_close_request",
266            Self::StreamCloseResponse => "stream_close_response",
267            Self::StreamError => "stream_error",
268            Self::StreamBwRequest => "stream_BW_request",
269            Self::StreamBwAllocation => "stream_BW_allocation",
270            Self::DataProvision => "data_provision",
271            Self::Reserved(_) => "reserved",
272        }
273    }
274}
275dvb_common::impl_spec_display!(EmmgMuxMessageType, Reserved);
276
277// ===========================================================================
278// message_type — C(P)SIG ⇔ (P)SIG (Table 3 subset, §8)
279// ===========================================================================
280
281/// C(P)SIG⇔(P)SIG `message_type` values (TS 103 197 Table 3, §4.4.1 / §8).
282///
283/// `Reserved(u16)` is the catch-all for any value outside the registry
284/// (DVB-reserved or user-defined); it preserves the raw 16-bit value so
285/// `Display`/serialize stay lossless.
286#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
287#[cfg_attr(feature = "serde", derive(serde::Serialize))]
288#[non_exhaustive]
289pub enum CpSigMessageType {
290    /// `0x0301` channel_setup.
291    ChannelSetup,
292    /// `0x0302` channel_status.
293    ChannelStatus,
294    /// `0x0303` channel_test.
295    ChannelTest,
296    /// `0x0304` channel_close.
297    ChannelClose,
298    /// `0x0305` channel_error.
299    ChannelError,
300    /// `0x0311` stream_setup.
301    StreamSetup,
302    /// `0x0312` stream_status.
303    StreamStatus,
304    /// `0x0313` stream_test.
305    StreamTest,
306    /// `0x0314` stream_close.
307    StreamClose,
308    /// `0x0315` stream_close_request.
309    StreamCloseRequest,
310    /// `0x0316` stream_close_response.
311    StreamCloseResponse,
312    /// `0x0317` stream_error.
313    StreamError,
314    /// `0x0318` stream_service_change.
315    StreamServiceChange,
316    /// `0x0319` stream_trigger_enable_request.
317    StreamTriggerEnableRequest,
318    /// `0x031A` stream_trigger_enable_response.
319    StreamTriggerEnableResponse,
320    /// `0x031B` trigger.
321    Trigger,
322    /// `0x031C` table_request.
323    TableRequest,
324    /// `0x031D` table_response.
325    TableResponse,
326    /// `0x031E` descriptor_insert_request.
327    DescriptorInsertRequest,
328    /// `0x031F` descriptor_insert_response.
329    DescriptorInsertResponse,
330    /// `0x0320` PID_provision_request.
331    PidProvisionRequest,
332    /// `0x0321` PID_provision_response.
333    PidProvisionResponse,
334    /// Any value not in the C(P)SIG⇔(P)SIG registry (DVB-reserved / user-defined).
335    Reserved(u16),
336}
337
338impl CpSigMessageType {
339    /// Decode a 16-bit `message_type` for the C(P)SIG⇔(P)SIG interface.
340    #[must_use]
341    pub const fn from_u16(v: u16) -> Self {
342        match v {
343            0x0301 => Self::ChannelSetup,
344            0x0302 => Self::ChannelStatus,
345            0x0303 => Self::ChannelTest,
346            0x0304 => Self::ChannelClose,
347            0x0305 => Self::ChannelError,
348            0x0311 => Self::StreamSetup,
349            0x0312 => Self::StreamStatus,
350            0x0313 => Self::StreamTest,
351            0x0314 => Self::StreamClose,
352            0x0315 => Self::StreamCloseRequest,
353            0x0316 => Self::StreamCloseResponse,
354            0x0317 => Self::StreamError,
355            0x0318 => Self::StreamServiceChange,
356            0x0319 => Self::StreamTriggerEnableRequest,
357            0x031A => Self::StreamTriggerEnableResponse,
358            0x031B => Self::Trigger,
359            0x031C => Self::TableRequest,
360            0x031D => Self::TableResponse,
361            0x031E => Self::DescriptorInsertRequest,
362            0x031F => Self::DescriptorInsertResponse,
363            0x0320 => Self::PidProvisionRequest,
364            0x0321 => Self::PidProvisionResponse,
365            other => Self::Reserved(other),
366        }
367    }
368
369    /// The 16-bit wire value.
370    #[must_use]
371    pub const fn to_u16(self) -> u16 {
372        match self {
373            Self::ChannelSetup => 0x0301,
374            Self::ChannelStatus => 0x0302,
375            Self::ChannelTest => 0x0303,
376            Self::ChannelClose => 0x0304,
377            Self::ChannelError => 0x0305,
378            Self::StreamSetup => 0x0311,
379            Self::StreamStatus => 0x0312,
380            Self::StreamTest => 0x0313,
381            Self::StreamClose => 0x0314,
382            Self::StreamCloseRequest => 0x0315,
383            Self::StreamCloseResponse => 0x0316,
384            Self::StreamError => 0x0317,
385            Self::StreamServiceChange => 0x0318,
386            Self::StreamTriggerEnableRequest => 0x0319,
387            Self::StreamTriggerEnableResponse => 0x031A,
388            Self::Trigger => 0x031B,
389            Self::TableRequest => 0x031C,
390            Self::TableResponse => 0x031D,
391            Self::DescriptorInsertRequest => 0x031E,
392            Self::DescriptorInsertResponse => 0x031F,
393            Self::PidProvisionRequest => 0x0320,
394            Self::PidProvisionResponse => 0x0321,
395            Self::Reserved(v) => v,
396        }
397    }
398
399    /// Label per the project's `name()` convention.
400    #[must_use]
401    pub fn name(&self) -> &'static str {
402        match self {
403            Self::ChannelSetup => "channel_setup",
404            Self::ChannelStatus => "channel_status",
405            Self::ChannelTest => "channel_test",
406            Self::ChannelClose => "channel_close",
407            Self::ChannelError => "channel_error",
408            Self::StreamSetup => "stream_setup",
409            Self::StreamStatus => "stream_status",
410            Self::StreamTest => "stream_test",
411            Self::StreamClose => "stream_close",
412            Self::StreamCloseRequest => "stream_close_request",
413            Self::StreamCloseResponse => "stream_close_response",
414            Self::StreamError => "stream_error",
415            Self::StreamServiceChange => "stream_service_change",
416            Self::StreamTriggerEnableRequest => "stream_trigger_enable_request",
417            Self::StreamTriggerEnableResponse => "stream_trigger_enable_response",
418            Self::Trigger => "trigger",
419            Self::TableRequest => "table_request",
420            Self::TableResponse => "table_response",
421            Self::DescriptorInsertRequest => "descriptor_insert_request",
422            Self::DescriptorInsertResponse => "descriptor_insert_response",
423            Self::PidProvisionRequest => "PID_provision_request",
424            Self::PidProvisionResponse => "PID_provision_response",
425            Self::Reserved(_) => "reserved",
426        }
427    }
428}
429dvb_common::impl_spec_display!(CpSigMessageType, Reserved);
430
431/// Interface-tagged `message_type`: decode a raw value once the [`Interface`]
432/// is known.
433#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
434#[cfg_attr(feature = "serde", derive(serde::Serialize))]
435#[non_exhaustive]
436pub enum MessageType {
437    /// An ECMG⇔SCS message_type.
438    EcmgScs(EcmgScsMessageType),
439    /// An EMMG/PDG⇔MUX message_type.
440    EmmgPdgMux(EmmgMuxMessageType),
441    /// A C(P)SIG⇔(P)SIG message_type.
442    CpSigPSig(CpSigMessageType),
443}
444
445impl MessageType {
446    /// Decode a raw 16-bit `message_type` for the given interface.
447    #[must_use]
448    pub const fn from_u16(iface: Interface, v: u16) -> Self {
449        match iface {
450            Interface::EcmgScs => Self::EcmgScs(EcmgScsMessageType::from_u16(v)),
451            Interface::EmmgPdgMux => Self::EmmgPdgMux(EmmgMuxMessageType::from_u16(v)),
452            Interface::CpSigPSig => Self::CpSigPSig(CpSigMessageType::from_u16(v)),
453        }
454    }
455
456    /// The 16-bit wire value.
457    #[must_use]
458    pub const fn to_u16(self) -> u16 {
459        match self {
460            Self::EcmgScs(m) => m.to_u16(),
461            Self::EmmgPdgMux(m) => m.to_u16(),
462            Self::CpSigPSig(m) => m.to_u16(),
463        }
464    }
465
466    /// The interface this message_type was decoded against.
467    #[must_use]
468    pub const fn interface(self) -> Interface {
469        match self {
470            Self::EcmgScs(_) => Interface::EcmgScs,
471            Self::EmmgPdgMux(_) => Interface::EmmgPdgMux,
472            Self::CpSigPSig(_) => Interface::CpSigPSig,
473        }
474    }
475
476    /// Label per the project's `name()` convention.
477    #[must_use]
478    pub fn name(&self) -> &'static str {
479        match self {
480            Self::EcmgScs(m) => m.name(),
481            Self::EmmgPdgMux(m) => m.name(),
482            Self::CpSigPSig(m) => m.name(),
483        }
484    }
485}
486dvb_common::impl_spec_display!(MessageType);
487
488// ===========================================================================
489// parameter_type — ECMG ⇔ SCS (Table 5, §5.2 p. 31)
490// ===========================================================================
491
492/// ECMG⇔SCS `parameter_type` values (TS 103 197 Table 5, §5.2 p. 31).
493#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
494#[cfg_attr(feature = "serde", derive(serde::Serialize))]
495#[non_exhaustive]
496pub enum EcmgScsParameterType {
497    /// `0x0001` Super_CAS_id (uimsbf, 4 bytes).
498    SuperCasId,
499    /// `0x0002` section_TSpkt_flag (uimsbf, 1 byte).
500    SectionTspktFlag,
501    /// `0x0003` delay_start (tcimsbf/ms, 2 bytes).
502    DelayStart,
503    /// `0x0004` delay_stop (tcimsbf/ms, 2 bytes).
504    DelayStop,
505    /// `0x0005` transition_delay_start (tcimsbf/ms, 2 bytes).
506    TransitionDelayStart,
507    /// `0x0006` transition_delay_stop (tcimsbf/ms, 2 bytes).
508    TransitionDelayStop,
509    /// `0x0007` ECM_rep_period (uimsbf/ms, 2 bytes).
510    EcmRepPeriod,
511    /// `0x0008` max_streams (uimsbf, 2 bytes).
512    MaxStreams,
513    /// `0x0009` min_CP_duration (uimsbf/n×100ms, 2 bytes).
514    MinCpDuration,
515    /// `0x000A` lead_CW (uimsbf, 1 byte).
516    LeadCw,
517    /// `0x000B` CW_per_msg (uimsbf, 1 byte).
518    CwPerMsg,
519    /// `0x000C` max_comp_time (uimsbf/ms, 2 bytes).
520    MaxCompTime,
521    /// `0x000D` access_criteria (user defined, variable).
522    AccessCriteria,
523    /// `0x000E` ECM_channel_id (uimsbf, 2 bytes).
524    EcmChannelId,
525    /// `0x000F` ECM_stream_id (uimsbf, 2 bytes).
526    EcmStreamId,
527    /// `0x0010` nominal_CP_duration (uimsbf/n×100ms, 2 bytes).
528    NominalCpDuration,
529    /// `0x0011` access_criteria_transfer_mode (Boolean, 1 byte).
530    AccessCriteriaTransferMode,
531    /// `0x0012` CP_number (uimsbf, 2 bytes).
532    CpNumber,
533    /// `0x0013` CP_duration (uimsbf/n×100ms, 2 bytes).
534    CpDuration,
535    /// `0x0014` CP_CW_combination (CP uimsbf 2B + CW variable; compound, opaque CW).
536    CpCwCombination,
537    /// `0x0015` ECM_datagram (user defined, variable; opaque).
538    EcmDatagram,
539    /// `0x0016` AC_delay_start (tcimsbf/ms, 2 bytes).
540    AcDelayStart,
541    /// `0x0017` AC_delay_stop (tcimsbf/ms, 2 bytes).
542    AcDelayStop,
543    /// `0x0018` CW_encryption (user defined, variable; opaque).
544    CwEncryption,
545    /// `0x0019` ECM_id (uimsbf, 2 bytes).
546    EcmId,
547    /// `0x7000` error_status (2 bytes; see [`EcmgErrorStatus`]).
548    ErrorStatus,
549    /// `0x7001` error_information (user defined, variable).
550    ErrorInformation,
551    /// Any value not in the ECMG⇔SCS registry (DVB-reserved / user-defined).
552    Reserved(u16),
553}
554
555impl EcmgScsParameterType {
556    /// Decode a 16-bit `parameter_type` for the ECMG⇔SCS interface.
557    #[must_use]
558    pub const fn from_u16(v: u16) -> Self {
559        match v {
560            0x0001 => Self::SuperCasId,
561            0x0002 => Self::SectionTspktFlag,
562            0x0003 => Self::DelayStart,
563            0x0004 => Self::DelayStop,
564            0x0005 => Self::TransitionDelayStart,
565            0x0006 => Self::TransitionDelayStop,
566            0x0007 => Self::EcmRepPeriod,
567            0x0008 => Self::MaxStreams,
568            0x0009 => Self::MinCpDuration,
569            0x000A => Self::LeadCw,
570            0x000B => Self::CwPerMsg,
571            0x000C => Self::MaxCompTime,
572            0x000D => Self::AccessCriteria,
573            0x000E => Self::EcmChannelId,
574            0x000F => Self::EcmStreamId,
575            0x0010 => Self::NominalCpDuration,
576            0x0011 => Self::AccessCriteriaTransferMode,
577            0x0012 => Self::CpNumber,
578            0x0013 => Self::CpDuration,
579            0x0014 => Self::CpCwCombination,
580            0x0015 => Self::EcmDatagram,
581            0x0016 => Self::AcDelayStart,
582            0x0017 => Self::AcDelayStop,
583            0x0018 => Self::CwEncryption,
584            0x0019 => Self::EcmId,
585            0x7000 => Self::ErrorStatus,
586            0x7001 => Self::ErrorInformation,
587            other => Self::Reserved(other),
588        }
589    }
590
591    /// The 16-bit wire value.
592    #[must_use]
593    pub const fn to_u16(self) -> u16 {
594        match self {
595            Self::SuperCasId => 0x0001,
596            Self::SectionTspktFlag => 0x0002,
597            Self::DelayStart => 0x0003,
598            Self::DelayStop => 0x0004,
599            Self::TransitionDelayStart => 0x0005,
600            Self::TransitionDelayStop => 0x0006,
601            Self::EcmRepPeriod => 0x0007,
602            Self::MaxStreams => 0x0008,
603            Self::MinCpDuration => 0x0009,
604            Self::LeadCw => 0x000A,
605            Self::CwPerMsg => 0x000B,
606            Self::MaxCompTime => 0x000C,
607            Self::AccessCriteria => 0x000D,
608            Self::EcmChannelId => 0x000E,
609            Self::EcmStreamId => 0x000F,
610            Self::NominalCpDuration => 0x0010,
611            Self::AccessCriteriaTransferMode => 0x0011,
612            Self::CpNumber => 0x0012,
613            Self::CpDuration => 0x0013,
614            Self::CpCwCombination => 0x0014,
615            Self::EcmDatagram => 0x0015,
616            Self::AcDelayStart => 0x0016,
617            Self::AcDelayStop => 0x0017,
618            Self::CwEncryption => 0x0018,
619            Self::EcmId => 0x0019,
620            Self::ErrorStatus => 0x7000,
621            Self::ErrorInformation => 0x7001,
622            Self::Reserved(v) => v,
623        }
624    }
625
626    /// Label per the project's `name()` convention (the spec token).
627    #[must_use]
628    pub fn name(&self) -> &'static str {
629        match self {
630            Self::SuperCasId => "Super_CAS_id",
631            Self::SectionTspktFlag => "section_TSpkt_flag",
632            Self::DelayStart => "delay_start",
633            Self::DelayStop => "delay_stop",
634            Self::TransitionDelayStart => "transition_delay_start",
635            Self::TransitionDelayStop => "transition_delay_stop",
636            Self::EcmRepPeriod => "ECM_rep_period",
637            Self::MaxStreams => "max_streams",
638            Self::MinCpDuration => "min_CP_duration",
639            Self::LeadCw => "lead_CW",
640            Self::CwPerMsg => "CW_per_msg",
641            Self::MaxCompTime => "max_comp_time",
642            Self::AccessCriteria => "access_criteria",
643            Self::EcmChannelId => "ECM_channel_id",
644            Self::EcmStreamId => "ECM_stream_id",
645            Self::NominalCpDuration => "nominal_CP_duration",
646            Self::AccessCriteriaTransferMode => "access_criteria_transfer_mode",
647            Self::CpNumber => "CP_number",
648            Self::CpDuration => "CP_duration",
649            Self::CpCwCombination => "CP_CW_combination",
650            Self::EcmDatagram => "ECM_datagram",
651            Self::AcDelayStart => "AC_delay_start",
652            Self::AcDelayStop => "AC_delay_stop",
653            Self::CwEncryption => "CW_encryption",
654            Self::EcmId => "ECM_id",
655            Self::ErrorStatus => "error_status",
656            Self::ErrorInformation => "error_information",
657            Self::Reserved(_) => "reserved",
658        }
659    }
660}
661dvb_common::impl_spec_display!(EcmgScsParameterType, Reserved);
662
663// ===========================================================================
664// parameter_type — EMMG/PDG ⇔ MUX (Table 7, §6.2.2 p. 42)
665// ===========================================================================
666
667/// EMMG/PDG⇔MUX `parameter_type` values (TS 103 197 Table 7, §6.2.2 p. 42).
668#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
669#[cfg_attr(feature = "serde", derive(serde::Serialize))]
670#[non_exhaustive]
671pub enum EmmgMuxParameterType {
672    /// `0x0001` client_id (uimsbf, 4 bytes).
673    ClientId,
674    /// `0x0002` section_TSpkt_flag (uimsbf, 1 byte).
675    SectionTspktFlag,
676    /// `0x0003` data_channel_id (uimsbf, 2 bytes).
677    DataChannelId,
678    /// `0x0004` data_stream_id (uimsbf, 2 bytes).
679    DataStreamId,
680    /// `0x0005` datagram (user defined, variable; opaque).
681    Datagram,
682    /// `0x0006` bandwidth (uimsbf/kbit/s, 2 bytes).
683    Bandwidth,
684    /// `0x0007` data_type (uimsbf, 1 byte; see [`DataType`]).
685    DataType,
686    /// `0x0008` data_id (uimsbf, 2 bytes).
687    DataId,
688    /// `0x7000` error_status (2 bytes; see [`EmmgErrorStatus`]).
689    ErrorStatus,
690    /// `0x7001` error_information (user defined, variable).
691    ErrorInformation,
692    /// Any value not in the EMMG/PDG⇔MUX registry (DVB-reserved / user-defined).
693    Reserved(u16),
694}
695
696impl EmmgMuxParameterType {
697    /// Decode a 16-bit `parameter_type` for the EMMG/PDG⇔MUX interface.
698    #[must_use]
699    pub const fn from_u16(v: u16) -> Self {
700        match v {
701            0x0001 => Self::ClientId,
702            0x0002 => Self::SectionTspktFlag,
703            0x0003 => Self::DataChannelId,
704            0x0004 => Self::DataStreamId,
705            0x0005 => Self::Datagram,
706            0x0006 => Self::Bandwidth,
707            0x0007 => Self::DataType,
708            0x0008 => Self::DataId,
709            0x7000 => Self::ErrorStatus,
710            0x7001 => Self::ErrorInformation,
711            other => Self::Reserved(other),
712        }
713    }
714
715    /// The 16-bit wire value.
716    #[must_use]
717    pub const fn to_u16(self) -> u16 {
718        match self {
719            Self::ClientId => 0x0001,
720            Self::SectionTspktFlag => 0x0002,
721            Self::DataChannelId => 0x0003,
722            Self::DataStreamId => 0x0004,
723            Self::Datagram => 0x0005,
724            Self::Bandwidth => 0x0006,
725            Self::DataType => 0x0007,
726            Self::DataId => 0x0008,
727            Self::ErrorStatus => 0x7000,
728            Self::ErrorInformation => 0x7001,
729            Self::Reserved(v) => v,
730        }
731    }
732
733    /// Label per the project's `name()` convention (the spec token).
734    #[must_use]
735    pub fn name(&self) -> &'static str {
736        match self {
737            Self::ClientId => "client_id",
738            Self::SectionTspktFlag => "section_TSpkt_flag",
739            Self::DataChannelId => "data_channel_id",
740            Self::DataStreamId => "data_stream_id",
741            Self::Datagram => "datagram",
742            Self::Bandwidth => "bandwidth",
743            Self::DataType => "data_type",
744            Self::DataId => "data_id",
745            Self::ErrorStatus => "error_status",
746            Self::ErrorInformation => "error_information",
747            Self::Reserved(_) => "reserved",
748        }
749    }
750}
751dvb_common::impl_spec_display!(EmmgMuxParameterType, Reserved);
752
753// ===========================================================================
754// parameter_type — C(P)SIG ⇔ (P)SIG (Table 36, §8)
755// ===========================================================================
756
757/// C(P)SIG⇔(P)SIG `parameter_type` values (TS 103 197 Table 36, §8).
758///
759/// `Reserved(u16)` is the catch-all for any value outside the registry
760/// (DVB-reserved or user-defined); it preserves the raw 16-bit value so
761/// `Display`/serialize stay lossless.
762#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
763#[cfg_attr(feature = "serde", derive(serde::Serialize))]
764#[non_exhaustive]
765pub enum CpSigParameterType {
766    /// `0x000D` access_criteria (user defined, variable).
767    AccessCriteria,
768    /// `0x0100` bouquet_id (uimsbf, 2 bytes).
769    BouquetId,
770    /// `0x0101` CA_descriptor_insertion_mode (uimsbf, 1 byte).
771    CaDescriptorInsertionMode,
772    /// `0x0102` custom_CA_system_id (uimsbf, 4 bytes).
773    CustomCaSystemId,
774    /// `0x0103` custom_channel_id (uimsbf, 2 bytes).
775    CustomChannelId,
776    /// `0x0104` custom_stream_id (uimsbf, 2 bytes).
777    CustomStreamId,
778    /// `0x0105` descriptor (per MPEG/DVB, variable).
779    Descriptor,
780    /// `0x0106` descriptor_insert_status (uimsbf, 1 byte).
781    DescriptorInsertStatus,
782    /// `0x0107` duration (uimsbf, 3 bytes).
783    Duration,
784    /// `0x0108` ECM_related_data (—, variable).
785    EcmRelatedData,
786    /// `0x010B` ES_id (uimsbf, 2 bytes).
787    EsId,
788    /// `0x010C` event_id (uimsbf, 2 bytes).
789    EventId,
790    /// `0x010D` event_related_data (—, variable).
791    EventRelatedData,
792    /// `0x010E` flow_id (uimsbf, 2 bytes).
793    FlowId,
794    /// `0x010F` flow_PID (uimsbf, 2 bytes).
795    FlowPid,
796    /// `0x0110` flow_PID_change_related_data (—, 9 bytes).
797    FlowPidChangeRelatedData,
798    /// `0x0111` flow_super_CAS_id (uimsbf, 4 bytes).
799    FlowSuperCasId,
800    /// `0x0112` flow_type (uimsbf, 1 byte).
801    FlowType,
802    /// `0x0113` insertion_delay (tcimsbf/ms, 2 bytes).
803    InsertionDelay,
804    /// `0x0114` insertion_delay_type (uimsbf, 1 byte).
805    InsertionDelayType,
806    /// `0x0115` last_section_indicator (boolean, 1 byte).
807    LastSectionIndicator,
808    /// `0x0116` location_id (uimsbf, 1 byte).
809    LocationId,
810    /// `0x0117` max_comp_time (uimsbf/s, 2 bytes).
811    MaxCompTime,
812    /// `0x0118` max_streams (uimsbf, 2 bytes).
813    MaxStreams,
814    /// `0x0119` MPEG_section (per MPEG/DVB, variable).
815    MpegSection,
816    /// `0x011A` network_id (uimsbf, 2 bytes).
817    NetworkId,
818    /// `0x011B` original_network_id (uimsbf, 2 bytes).
819    OriginalNetworkId,
820    /// `0x011C` private_data (user-defined, variable).
821    PrivateData,
822    /// `0x011D` private_data_specifier (uimsbf, 4 bytes).
823    PrivateDataSpecifier,
824    /// `0x011E` (P)SIG_type (uimsbf, 1 byte).
825    PSigType,
826    /// `0x011F` segment_number (uimsbf, 1 byte).
827    SegmentNumber,
828    /// `0x0120` service_id (uimsbf, 2 bytes).
829    ServiceId,
830    /// `0x0121` service_parameters (—, 8 bytes).
831    ServiceParameters,
832    /// `0x0122` start_time (bslbf, 5 bytes).
833    StartTime,
834    /// `0x0123` stream_change_timestamp (bslbf, 5 bytes).
835    StreamChangeTimestamp,
836    /// `0x0124` stream_change_type (uimsbf, 1 byte).
837    StreamChangeType,
838    /// `0x0125` table_id (uimsbf, 1 byte).
839    TableId,
840    /// `0x0126` transaction_id (uimsbf, 2 bytes).
841    TransactionId,
842    /// `0x0127` transport_stream_id (uimsbf, 2 bytes).
843    TransportStreamId,
844    /// `0x0128` trigger_id (uimsbf, 2 bytes).
845    TriggerId,
846    /// `0x0129` trigger_list (bslbf, 4 bytes).
847    TriggerList,
848    /// `0x012A` trigger_type (uimsbf, 4 bytes).
849    TriggerType,
850    /// `0x012B` PD_related_data (—, variable).
851    PdRelatedData,
852    /// `0x012C` flow_stream_type (uimsbf, 1 byte).
853    FlowStreamType,
854    /// `0x7000` error_status (2 bytes).
855    ErrorStatus,
856    /// `0x7001` error_information (user defined, variable).
857    ErrorInformation,
858    /// Any value not in the C(P)SIG⇔(P)SIG registry (DVB-reserved / user-defined).
859    Reserved(u16),
860}
861
862impl CpSigParameterType {
863    /// Decode a 16-bit `parameter_type` for the C(P)SIG⇔(P)SIG interface.
864    #[must_use]
865    pub const fn from_u16(v: u16) -> Self {
866        match v {
867            0x000D => Self::AccessCriteria,
868            0x0100 => Self::BouquetId,
869            0x0101 => Self::CaDescriptorInsertionMode,
870            0x0102 => Self::CustomCaSystemId,
871            0x0103 => Self::CustomChannelId,
872            0x0104 => Self::CustomStreamId,
873            0x0105 => Self::Descriptor,
874            0x0106 => Self::DescriptorInsertStatus,
875            0x0107 => Self::Duration,
876            0x0108 => Self::EcmRelatedData,
877            0x010B => Self::EsId,
878            0x010C => Self::EventId,
879            0x010D => Self::EventRelatedData,
880            0x010E => Self::FlowId,
881            0x010F => Self::FlowPid,
882            0x0110 => Self::FlowPidChangeRelatedData,
883            0x0111 => Self::FlowSuperCasId,
884            0x0112 => Self::FlowType,
885            0x0113 => Self::InsertionDelay,
886            0x0114 => Self::InsertionDelayType,
887            0x0115 => Self::LastSectionIndicator,
888            0x0116 => Self::LocationId,
889            0x0117 => Self::MaxCompTime,
890            0x0118 => Self::MaxStreams,
891            0x0119 => Self::MpegSection,
892            0x011A => Self::NetworkId,
893            0x011B => Self::OriginalNetworkId,
894            0x011C => Self::PrivateData,
895            0x011D => Self::PrivateDataSpecifier,
896            0x011E => Self::PSigType,
897            0x011F => Self::SegmentNumber,
898            0x0120 => Self::ServiceId,
899            0x0121 => Self::ServiceParameters,
900            0x0122 => Self::StartTime,
901            0x0123 => Self::StreamChangeTimestamp,
902            0x0124 => Self::StreamChangeType,
903            0x0125 => Self::TableId,
904            0x0126 => Self::TransactionId,
905            0x0127 => Self::TransportStreamId,
906            0x0128 => Self::TriggerId,
907            0x0129 => Self::TriggerList,
908            0x012A => Self::TriggerType,
909            0x012B => Self::PdRelatedData,
910            0x012C => Self::FlowStreamType,
911            0x7000 => Self::ErrorStatus,
912            0x7001 => Self::ErrorInformation,
913            other => Self::Reserved(other),
914        }
915    }
916
917    /// The 16-bit wire value.
918    #[must_use]
919    pub const fn to_u16(self) -> u16 {
920        match self {
921            Self::AccessCriteria => 0x000D,
922            Self::BouquetId => 0x0100,
923            Self::CaDescriptorInsertionMode => 0x0101,
924            Self::CustomCaSystemId => 0x0102,
925            Self::CustomChannelId => 0x0103,
926            Self::CustomStreamId => 0x0104,
927            Self::Descriptor => 0x0105,
928            Self::DescriptorInsertStatus => 0x0106,
929            Self::Duration => 0x0107,
930            Self::EcmRelatedData => 0x0108,
931            Self::EsId => 0x010B,
932            Self::EventId => 0x010C,
933            Self::EventRelatedData => 0x010D,
934            Self::FlowId => 0x010E,
935            Self::FlowPid => 0x010F,
936            Self::FlowPidChangeRelatedData => 0x0110,
937            Self::FlowSuperCasId => 0x0111,
938            Self::FlowType => 0x0112,
939            Self::InsertionDelay => 0x0113,
940            Self::InsertionDelayType => 0x0114,
941            Self::LastSectionIndicator => 0x0115,
942            Self::LocationId => 0x0116,
943            Self::MaxCompTime => 0x0117,
944            Self::MaxStreams => 0x0118,
945            Self::MpegSection => 0x0119,
946            Self::NetworkId => 0x011A,
947            Self::OriginalNetworkId => 0x011B,
948            Self::PrivateData => 0x011C,
949            Self::PrivateDataSpecifier => 0x011D,
950            Self::PSigType => 0x011E,
951            Self::SegmentNumber => 0x011F,
952            Self::ServiceId => 0x0120,
953            Self::ServiceParameters => 0x0121,
954            Self::StartTime => 0x0122,
955            Self::StreamChangeTimestamp => 0x0123,
956            Self::StreamChangeType => 0x0124,
957            Self::TableId => 0x0125,
958            Self::TransactionId => 0x0126,
959            Self::TransportStreamId => 0x0127,
960            Self::TriggerId => 0x0128,
961            Self::TriggerList => 0x0129,
962            Self::TriggerType => 0x012A,
963            Self::PdRelatedData => 0x012B,
964            Self::FlowStreamType => 0x012C,
965            Self::ErrorStatus => 0x7000,
966            Self::ErrorInformation => 0x7001,
967            Self::Reserved(v) => v,
968        }
969    }
970
971    /// Label per the project's `name()` convention (the spec token).
972    #[must_use]
973    pub fn name(&self) -> &'static str {
974        match self {
975            Self::AccessCriteria => "access_criteria",
976            Self::BouquetId => "bouquet_id",
977            Self::CaDescriptorInsertionMode => "CA_descriptor_insertion_mode",
978            Self::CustomCaSystemId => "custom_CA_system_id",
979            Self::CustomChannelId => "custom_channel_id",
980            Self::CustomStreamId => "custom_stream_id",
981            Self::Descriptor => "descriptor",
982            Self::DescriptorInsertStatus => "descriptor_insert_status",
983            Self::Duration => "duration",
984            Self::EcmRelatedData => "ECM_related_data",
985            Self::EsId => "ES_id",
986            Self::EventId => "event_id",
987            Self::EventRelatedData => "event_related_data",
988            Self::FlowId => "flow_id",
989            Self::FlowPid => "flow_PID",
990            Self::FlowPidChangeRelatedData => "flow_PID_change_related_data",
991            Self::FlowSuperCasId => "flow_super_CAS_id",
992            Self::FlowType => "flow_type",
993            Self::InsertionDelay => "insertion_delay",
994            Self::InsertionDelayType => "insertion_delay_type",
995            Self::LastSectionIndicator => "last_section_indicator",
996            Self::LocationId => "location_id",
997            Self::MaxCompTime => "max_comp_time",
998            Self::MaxStreams => "max_streams",
999            Self::MpegSection => "MPEG_section",
1000            Self::NetworkId => "network_id",
1001            Self::OriginalNetworkId => "original_network_id",
1002            Self::PrivateData => "private_data",
1003            Self::PrivateDataSpecifier => "private_data_specifier",
1004            Self::PSigType => "(P)SIG_type",
1005            Self::SegmentNumber => "segment_number",
1006            Self::ServiceId => "service_id",
1007            Self::ServiceParameters => "service_parameters",
1008            Self::StartTime => "start_time",
1009            Self::StreamChangeTimestamp => "stream_change_timestamp",
1010            Self::StreamChangeType => "stream_change_type",
1011            Self::TableId => "table_id",
1012            Self::TransactionId => "transaction_id",
1013            Self::TransportStreamId => "transport_stream_id",
1014            Self::TriggerId => "trigger_id",
1015            Self::TriggerList => "trigger_list",
1016            Self::TriggerType => "trigger_type",
1017            Self::PdRelatedData => "PD_related_data",
1018            Self::FlowStreamType => "flow_stream_type",
1019            Self::ErrorStatus => "error_status",
1020            Self::ErrorInformation => "error_information",
1021            Self::Reserved(_) => "reserved",
1022        }
1023    }
1024}
1025dvb_common::impl_spec_display!(CpSigParameterType, Reserved);
1026
1027/// Interface-tagged `parameter_type`: decode a raw value once the [`Interface`]
1028/// is known.
1029#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1030#[cfg_attr(feature = "serde", derive(serde::Serialize))]
1031#[non_exhaustive]
1032pub enum ParameterType {
1033    /// An ECMG⇔SCS parameter_type.
1034    EcmgScs(EcmgScsParameterType),
1035    /// An EMMG/PDG⇔MUX parameter_type.
1036    EmmgPdgMux(EmmgMuxParameterType),
1037    /// A C(P)SIG⇔(P)SIG parameter_type.
1038    CpSigPSig(CpSigParameterType),
1039}
1040
1041impl ParameterType {
1042    /// Decode a raw 16-bit `parameter_type` for the given interface.
1043    #[must_use]
1044    pub const fn from_u16(iface: Interface, v: u16) -> Self {
1045        match iface {
1046            Interface::EcmgScs => Self::EcmgScs(EcmgScsParameterType::from_u16(v)),
1047            Interface::EmmgPdgMux => Self::EmmgPdgMux(EmmgMuxParameterType::from_u16(v)),
1048            Interface::CpSigPSig => Self::CpSigPSig(CpSigParameterType::from_u16(v)),
1049        }
1050    }
1051
1052    /// The 16-bit wire value.
1053    #[must_use]
1054    pub const fn to_u16(self) -> u16 {
1055        match self {
1056            Self::EcmgScs(p) => p.to_u16(),
1057            Self::EmmgPdgMux(p) => p.to_u16(),
1058            Self::CpSigPSig(p) => p.to_u16(),
1059        }
1060    }
1061
1062    /// The interface this parameter_type was decoded against.
1063    #[must_use]
1064    pub const fn interface(self) -> Interface {
1065        match self {
1066            Self::EcmgScs(_) => Interface::EcmgScs,
1067            Self::EmmgPdgMux(_) => Interface::EmmgPdgMux,
1068            Self::CpSigPSig(_) => Interface::CpSigPSig,
1069        }
1070    }
1071
1072    /// Label per the project's `name()` convention.
1073    #[must_use]
1074    pub fn name(&self) -> &'static str {
1075        match self {
1076            Self::EcmgScs(p) => p.name(),
1077            Self::EmmgPdgMux(p) => p.name(),
1078            Self::CpSigPSig(p) => p.name(),
1079        }
1080    }
1081}
1082dvb_common::impl_spec_display!(ParameterType);
1083
1084// ===========================================================================
1085// EMMG/PDG value sub-tables (§6.2.3)
1086// ===========================================================================
1087
1088/// `data_type` values (TS 103 197 §6.2.3 p. 42) — what a `datagram` carries.
1089#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1090#[cfg_attr(feature = "serde", derive(serde::Serialize))]
1091#[non_exhaustive]
1092pub enum DataType {
1093    /// `0x00` EMM.
1094    Emm,
1095    /// `0x01` private data.
1096    PrivateData,
1097    /// `0x02` DVB reserved (ECM).
1098    Ecm,
1099    /// Any other value (DVB reserved).
1100    Reserved(u8),
1101}
1102
1103impl DataType {
1104    /// Decode a `data_type` byte.
1105    #[must_use]
1106    pub const fn from_u8(v: u8) -> Self {
1107        match v {
1108            0x00 => Self::Emm,
1109            0x01 => Self::PrivateData,
1110            0x02 => Self::Ecm,
1111            other => Self::Reserved(other),
1112        }
1113    }
1114
1115    /// The wire byte.
1116    #[must_use]
1117    pub const fn to_u8(self) -> u8 {
1118        match self {
1119            Self::Emm => 0x00,
1120            Self::PrivateData => 0x01,
1121            Self::Ecm => 0x02,
1122            Self::Reserved(v) => v,
1123        }
1124    }
1125
1126    /// Label per the project's `name()` convention.
1127    #[must_use]
1128    pub fn name(&self) -> &'static str {
1129        match self {
1130            Self::Emm => "EMM",
1131            Self::PrivateData => "private data",
1132            Self::Ecm => "ECM",
1133            Self::Reserved(_) => "reserved",
1134        }
1135    }
1136}
1137dvb_common::impl_spec_display!(DataType, Reserved);
1138
1139/// `section_TSpkt_flag` values (TS 103 197 §6.2.3 p. 43) — the datagram framing
1140/// in `datagram` parameters. (The same flag, with the same meaning, is carried
1141/// on the ECMG⇔SCS interface for `ECM_datagram`.)
1142#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1143#[cfg_attr(feature = "serde", derive(serde::Serialize))]
1144#[non_exhaustive]
1145pub enum SectionTspktFlag {
1146    /// `0x00` EMMs / private datagrams in MPEG-2 section format.
1147    SectionFormat,
1148    /// `0x01` MPEG-2 TS packet format (all TS packets 188 bytes).
1149    TsPacketFormat,
1150    /// `0x02` arbitrary-length EMMs/KMMs per IP Datacast SPP (annex N).
1151    ArbitraryLength,
1152    /// Any other value (DVB reserved).
1153    Reserved(u8),
1154}
1155
1156impl SectionTspktFlag {
1157    /// Decode a `section_TSpkt_flag` byte.
1158    #[must_use]
1159    pub const fn from_u8(v: u8) -> Self {
1160        match v {
1161            0x00 => Self::SectionFormat,
1162            0x01 => Self::TsPacketFormat,
1163            0x02 => Self::ArbitraryLength,
1164            other => Self::Reserved(other),
1165        }
1166    }
1167
1168    /// The wire byte.
1169    #[must_use]
1170    pub const fn to_u8(self) -> u8 {
1171        match self {
1172            Self::SectionFormat => 0x00,
1173            Self::TsPacketFormat => 0x01,
1174            Self::ArbitraryLength => 0x02,
1175            Self::Reserved(v) => v,
1176        }
1177    }
1178
1179    /// Label per the project's `name()` convention.
1180    #[must_use]
1181    pub fn name(&self) -> &'static str {
1182        match self {
1183            Self::SectionFormat => "section_format",
1184            Self::TsPacketFormat => "ts_packet_format",
1185            Self::ArbitraryLength => "arbitrary_length",
1186            Self::Reserved(_) => "reserved",
1187        }
1188    }
1189}
1190dvb_common::impl_spec_display!(SectionTspktFlag, Reserved);
1191
1192// ===========================================================================
1193// error_status (Table 6 / Table 8)
1194// ===========================================================================
1195
1196/// ECMG⇔SCS `error_status` values (TS 103 197 Table 6, §5.6 p. 39).
1197#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1198#[cfg_attr(feature = "serde", derive(serde::Serialize))]
1199#[non_exhaustive]
1200pub enum EcmgErrorStatus {
1201    /// `0x0001` invalid message.
1202    InvalidMessage,
1203    /// `0x0002` unsupported protocol version.
1204    UnsupportedProtocolVersion,
1205    /// `0x0003` unknown message_type value.
1206    UnknownMessageType,
1207    /// `0x0004` message too long.
1208    MessageTooLong,
1209    /// `0x0005` unknown Super_CAS_id value.
1210    UnknownSuperCasId,
1211    /// `0x0006` unknown ECM_channel_id value.
1212    UnknownEcmChannelId,
1213    /// `0x0007` unknown ECM_stream_id value.
1214    UnknownEcmStreamId,
1215    /// `0x0008` too many channels on this ECMG.
1216    TooManyChannels,
1217    /// `0x0009` too many ECM streams on this channel.
1218    TooManyStreamsOnChannel,
1219    /// `0x000A` too many ECM streams on this ECMG.
1220    TooManyStreamsOnEcmg,
1221    /// `0x000B` not enough control words to compute ECM.
1222    NotEnoughControlWords,
1223    /// `0x000C` ECMG out of storage capacity.
1224    OutOfStorage,
1225    /// `0x000D` ECMG out of computational resources.
1226    OutOfResources,
1227    /// `0x000E` unknown parameter_type value.
1228    UnknownParameterType,
1229    /// `0x000F` inconsistent length for DVB parameter.
1230    InconsistentLength,
1231    /// `0x0010` missing mandatory DVB parameter.
1232    MissingMandatoryParameter,
1233    /// `0x0011` invalid value for DVB parameter.
1234    InvalidParameterValue,
1235    /// `0x0012` unknown ECM_id value.
1236    UnknownEcmId,
1237    /// `0x0013` ECM_channel_id value already in use.
1238    EcmChannelIdInUse,
1239    /// `0x0014` ECM_stream_id value already in use.
1240    EcmStreamIdInUse,
1241    /// `0x0015` ECM_id value already in use.
1242    EcmIdInUse,
1243    /// `0x7000` unknown error.
1244    UnknownError,
1245    /// `0x7001` unrecoverable error.
1246    UnrecoverableError,
1247    /// Any value not in the registry (DVB-reserved / CA-system / user-defined).
1248    Reserved(u16),
1249}
1250
1251impl EcmgErrorStatus {
1252    /// Decode a 16-bit `error_status` value.
1253    #[must_use]
1254    pub const fn from_u16(v: u16) -> Self {
1255        match v {
1256            0x0001 => Self::InvalidMessage,
1257            0x0002 => Self::UnsupportedProtocolVersion,
1258            0x0003 => Self::UnknownMessageType,
1259            0x0004 => Self::MessageTooLong,
1260            0x0005 => Self::UnknownSuperCasId,
1261            0x0006 => Self::UnknownEcmChannelId,
1262            0x0007 => Self::UnknownEcmStreamId,
1263            0x0008 => Self::TooManyChannels,
1264            0x0009 => Self::TooManyStreamsOnChannel,
1265            0x000A => Self::TooManyStreamsOnEcmg,
1266            0x000B => Self::NotEnoughControlWords,
1267            0x000C => Self::OutOfStorage,
1268            0x000D => Self::OutOfResources,
1269            0x000E => Self::UnknownParameterType,
1270            0x000F => Self::InconsistentLength,
1271            0x0010 => Self::MissingMandatoryParameter,
1272            0x0011 => Self::InvalidParameterValue,
1273            0x0012 => Self::UnknownEcmId,
1274            0x0013 => Self::EcmChannelIdInUse,
1275            0x0014 => Self::EcmStreamIdInUse,
1276            0x0015 => Self::EcmIdInUse,
1277            0x7000 => Self::UnknownError,
1278            0x7001 => Self::UnrecoverableError,
1279            other => Self::Reserved(other),
1280        }
1281    }
1282
1283    /// The 16-bit wire value.
1284    #[must_use]
1285    pub const fn to_u16(self) -> u16 {
1286        match self {
1287            Self::InvalidMessage => 0x0001,
1288            Self::UnsupportedProtocolVersion => 0x0002,
1289            Self::UnknownMessageType => 0x0003,
1290            Self::MessageTooLong => 0x0004,
1291            Self::UnknownSuperCasId => 0x0005,
1292            Self::UnknownEcmChannelId => 0x0006,
1293            Self::UnknownEcmStreamId => 0x0007,
1294            Self::TooManyChannels => 0x0008,
1295            Self::TooManyStreamsOnChannel => 0x0009,
1296            Self::TooManyStreamsOnEcmg => 0x000A,
1297            Self::NotEnoughControlWords => 0x000B,
1298            Self::OutOfStorage => 0x000C,
1299            Self::OutOfResources => 0x000D,
1300            Self::UnknownParameterType => 0x000E,
1301            Self::InconsistentLength => 0x000F,
1302            Self::MissingMandatoryParameter => 0x0010,
1303            Self::InvalidParameterValue => 0x0011,
1304            Self::UnknownEcmId => 0x0012,
1305            Self::EcmChannelIdInUse => 0x0013,
1306            Self::EcmStreamIdInUse => 0x0014,
1307            Self::EcmIdInUse => 0x0015,
1308            Self::UnknownError => 0x7000,
1309            Self::UnrecoverableError => 0x7001,
1310            Self::Reserved(v) => v,
1311        }
1312    }
1313
1314    /// Label per the project's `name()` convention.
1315    #[must_use]
1316    pub fn name(&self) -> &'static str {
1317        match self {
1318            Self::InvalidMessage => "invalid message",
1319            Self::UnsupportedProtocolVersion => "unsupported protocol version",
1320            Self::UnknownMessageType => "unknown message_type value",
1321            Self::MessageTooLong => "message too long",
1322            Self::UnknownSuperCasId => "unknown Super_CAS_id value",
1323            Self::UnknownEcmChannelId => "unknown ECM_channel_id value",
1324            Self::UnknownEcmStreamId => "unknown ECM_stream_id value",
1325            Self::TooManyChannels => "too many channels on this ECMG",
1326            Self::TooManyStreamsOnChannel => "too many ECM streams on this channel",
1327            Self::TooManyStreamsOnEcmg => "too many ECM streams on this ECMG",
1328            Self::NotEnoughControlWords => "not enough control words to compute ECM",
1329            Self::OutOfStorage => "ECMG out of storage capacity",
1330            Self::OutOfResources => "ECMG out of computational resources",
1331            Self::UnknownParameterType => "unknown parameter_type value",
1332            Self::InconsistentLength => "inconsistent length for DVB parameter",
1333            Self::MissingMandatoryParameter => "missing mandatory DVB parameter",
1334            Self::InvalidParameterValue => "invalid value for DVB parameter",
1335            Self::UnknownEcmId => "unknown ECM_id value",
1336            Self::EcmChannelIdInUse => "ECM_channel_id value already in use",
1337            Self::EcmStreamIdInUse => "ECM_stream_id value already in use",
1338            Self::EcmIdInUse => "ECM_id value already in use",
1339            Self::UnknownError => "unknown error",
1340            Self::UnrecoverableError => "unrecoverable error",
1341            Self::Reserved(_) => "reserved",
1342        }
1343    }
1344}
1345dvb_common::impl_spec_display!(EcmgErrorStatus, Reserved);
1346
1347/// EMMG/PDG⇔MUX `error_status` values (TS 103 197 Table 8, §6.2.6 p. 47).
1348#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1349#[cfg_attr(feature = "serde", derive(serde::Serialize))]
1350#[non_exhaustive]
1351pub enum EmmgErrorStatus {
1352    /// `0x0001` invalid message.
1353    InvalidMessage,
1354    /// `0x0002` unsupported protocol version.
1355    UnsupportedProtocolVersion,
1356    /// `0x0003` unknown message_type value.
1357    UnknownMessageType,
1358    /// `0x0004` message too long.
1359    MessageTooLong,
1360    /// `0x0005` unknown data_stream_id value.
1361    UnknownDataStreamId,
1362    /// `0x0006` unknown data_channel_id value.
1363    UnknownDataChannelId,
1364    /// `0x0007` too many channels on this MUX.
1365    TooManyChannels,
1366    /// `0x0008` too many data streams on this channel.
1367    TooManyStreamsOnChannel,
1368    /// `0x0009` too many data streams on this MUX.
1369    TooManyStreamsOnMux,
1370    /// `0x000A` unknown parameter_type.
1371    UnknownParameterType,
1372    /// `0x000B` inconsistent length for DVB parameter.
1373    InconsistentLength,
1374    /// `0x000C` missing mandatory DVB parameter.
1375    MissingMandatoryParameter,
1376    /// `0x000D` invalid value for DVB parameter.
1377    InvalidParameterValue,
1378    /// `0x000E` unknown client_id value.
1379    UnknownClientId,
1380    /// `0x000F` exceeded bandwidth.
1381    ExceededBandwidth,
1382    /// `0x0010` unknown data_id value.
1383    UnknownDataId,
1384    /// `0x0011` data_channel_id value already in use.
1385    DataChannelIdInUse,
1386    /// `0x0012` data_stream_id value already in use.
1387    DataStreamIdInUse,
1388    /// `0x0013` data_id value already in use.
1389    DataIdInUse,
1390    /// `0x0014` client_id value already in use.
1391    ClientIdInUse,
1392    /// `0x7000` unknown error.
1393    UnknownError,
1394    /// `0x7001` unrecoverable error.
1395    UnrecoverableError,
1396    /// Any value not in the registry (DVB-reserved / CA-system / user-defined).
1397    Reserved(u16),
1398}
1399
1400impl EmmgErrorStatus {
1401    /// Decode a 16-bit `error_status` value.
1402    #[must_use]
1403    pub const fn from_u16(v: u16) -> Self {
1404        match v {
1405            0x0001 => Self::InvalidMessage,
1406            0x0002 => Self::UnsupportedProtocolVersion,
1407            0x0003 => Self::UnknownMessageType,
1408            0x0004 => Self::MessageTooLong,
1409            0x0005 => Self::UnknownDataStreamId,
1410            0x0006 => Self::UnknownDataChannelId,
1411            0x0007 => Self::TooManyChannels,
1412            0x0008 => Self::TooManyStreamsOnChannel,
1413            0x0009 => Self::TooManyStreamsOnMux,
1414            0x000A => Self::UnknownParameterType,
1415            0x000B => Self::InconsistentLength,
1416            0x000C => Self::MissingMandatoryParameter,
1417            0x000D => Self::InvalidParameterValue,
1418            0x000E => Self::UnknownClientId,
1419            0x000F => Self::ExceededBandwidth,
1420            0x0010 => Self::UnknownDataId,
1421            0x0011 => Self::DataChannelIdInUse,
1422            0x0012 => Self::DataStreamIdInUse,
1423            0x0013 => Self::DataIdInUse,
1424            0x0014 => Self::ClientIdInUse,
1425            0x7000 => Self::UnknownError,
1426            0x7001 => Self::UnrecoverableError,
1427            other => Self::Reserved(other),
1428        }
1429    }
1430
1431    /// The 16-bit wire value.
1432    #[must_use]
1433    pub const fn to_u16(self) -> u16 {
1434        match self {
1435            Self::InvalidMessage => 0x0001,
1436            Self::UnsupportedProtocolVersion => 0x0002,
1437            Self::UnknownMessageType => 0x0003,
1438            Self::MessageTooLong => 0x0004,
1439            Self::UnknownDataStreamId => 0x0005,
1440            Self::UnknownDataChannelId => 0x0006,
1441            Self::TooManyChannels => 0x0007,
1442            Self::TooManyStreamsOnChannel => 0x0008,
1443            Self::TooManyStreamsOnMux => 0x0009,
1444            Self::UnknownParameterType => 0x000A,
1445            Self::InconsistentLength => 0x000B,
1446            Self::MissingMandatoryParameter => 0x000C,
1447            Self::InvalidParameterValue => 0x000D,
1448            Self::UnknownClientId => 0x000E,
1449            Self::ExceededBandwidth => 0x000F,
1450            Self::UnknownDataId => 0x0010,
1451            Self::DataChannelIdInUse => 0x0011,
1452            Self::DataStreamIdInUse => 0x0012,
1453            Self::DataIdInUse => 0x0013,
1454            Self::ClientIdInUse => 0x0014,
1455            Self::UnknownError => 0x7000,
1456            Self::UnrecoverableError => 0x7001,
1457            Self::Reserved(v) => v,
1458        }
1459    }
1460
1461    /// Label per the project's `name()` convention.
1462    #[must_use]
1463    pub fn name(&self) -> &'static str {
1464        match self {
1465            Self::InvalidMessage => "invalid message",
1466            Self::UnsupportedProtocolVersion => "unsupported protocol version",
1467            Self::UnknownMessageType => "unknown message_type value",
1468            Self::MessageTooLong => "message too long",
1469            Self::UnknownDataStreamId => "unknown data_stream_id value",
1470            Self::UnknownDataChannelId => "unknown data_channel_id value",
1471            Self::TooManyChannels => "too many channels on this MUX",
1472            Self::TooManyStreamsOnChannel => "too many data streams on this channel",
1473            Self::TooManyStreamsOnMux => "too many data streams on this MUX",
1474            Self::UnknownParameterType => "unknown parameter_type",
1475            Self::InconsistentLength => "inconsistent length for DVB parameter",
1476            Self::MissingMandatoryParameter => "missing mandatory DVB parameter",
1477            Self::InvalidParameterValue => "invalid value for DVB parameter",
1478            Self::UnknownClientId => "unknown client_id value",
1479            Self::ExceededBandwidth => "exceeded bandwidth",
1480            Self::UnknownDataId => "unknown data_id value",
1481            Self::DataChannelIdInUse => "data_channel_id value already in use",
1482            Self::DataStreamIdInUse => "data_stream_id value already in use",
1483            Self::DataIdInUse => "data_id value already in use",
1484            Self::ClientIdInUse => "client_id value already in use",
1485            Self::UnknownError => "unknown error",
1486            Self::UnrecoverableError => "unrecoverable error",
1487            Self::Reserved(_) => "reserved",
1488        }
1489    }
1490}
1491dvb_common::impl_spec_display!(EmmgErrorStatus, Reserved);