sccp_protocol/message/values.rs
1//! Typed numeric values used by SCCP messages.
2//!
3//! Most Skinny numeric fields are extensible firmware contracts. Data-bearing
4//! `Unknown` variants keep them type-safe without making newer phones fail to
5//! decode. Convert from the wire with `From<u32>`, inspect known values through
6//! `ALL_KNOWN`, and use `wire_value` (or `Into<u32>`) when encoding.
7
8use std::fmt;
9
10use bitflags::bitflags;
11
12use super::wire::CodecError;
13
14macro_rules! wire_enum {
15 ($(#[$meta:meta])* pub enum $name:ident { $($(#[$variant_meta:meta])* $variant:ident = $value:expr),+ $(,)? }) => {
16 $(#[$meta])*
17 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
18 pub enum $name {
19 $($(#[$variant_meta])* $variant,)+
20 /// Preserves an SCCP numeric value not recognized by this crate.
21 /// Allows newer or vendor-specific values to round-trip without loss.
22 Unknown(u32),
23 }
24
25 impl $name {
26 pub const ALL_KNOWN: &'static [Self] = &[$(Self::$variant,)+];
27
28 pub const fn wire_value(self) -> u32 {
29 match self {
30 $(Self::$variant => $value,)+
31 Self::Unknown(value) => value,
32 }
33 }
34
35 pub const fn is_known(self) -> bool {
36 !matches!(self, Self::Unknown(_))
37 }
38 }
39
40 impl From<u32> for $name {
41 fn from(value: u32) -> Self {
42 match value {
43 $($value => Self::$variant,)+
44 value => Self::Unknown(value),
45 }
46 }
47 }
48
49 impl From<$name> for u32 {
50 fn from(value: $name) -> Self {
51 value.wire_value()
52 }
53 }
54 };
55}
56
57/// A negotiated SCCP protocol version in the supported 3..=22 range.
58#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
59pub struct ProtocolVersion(u8);
60
61impl ProtocolVersion {
62 pub const MIN: Self = Self(3);
63 pub const MAX: Self = Self(22);
64 pub const V3: Self = Self(3);
65 pub const V5: Self = Self(5);
66 pub const V7: Self = Self(7);
67 pub const V8: Self = Self(8);
68 pub const V9: Self = Self(9);
69 pub const V10: Self = Self(10);
70 pub const V11: Self = Self(11);
71 pub const V12: Self = Self(12);
72 pub const V13: Self = Self(13);
73 pub const V14: Self = Self(14);
74 pub const V15: Self = Self(15);
75 pub const V16: Self = Self(16);
76 pub const V17: Self = Self(17);
77 pub const V18: Self = Self(18);
78 pub const V19: Self = Self(19);
79 pub const V20: Self = Self(20);
80 pub const V21: Self = Self(21);
81 pub const V22: Self = Self(22);
82
83 /// Validates and constructs an exact supported protocol version.
84 pub fn new(value: u32) -> Result<Self, CodecError> {
85 let value = u8::try_from(value).map_err(|_| CodecError::UnsupportedProtocol(value))?;
86 if !(Self::MIN.0..=Self::MAX.0).contains(&value) {
87 return Err(CodecError::UnsupportedProtocol(u32::from(value)));
88 }
89 Ok(Self(value))
90 }
91
92 /// Negotiate the highest version supported by both peers.
93 pub fn negotiate(advertised: u32) -> Result<Self, CodecError> {
94 if advertised < u32::from(Self::MIN.0) {
95 return Err(CodecError::UnsupportedProtocol(advertised));
96 }
97 Self::new(advertised.min(u32::from(Self::MAX.0)))
98 }
99
100 pub const fn wire(self) -> u32 {
101 self.0 as u32
102 }
103
104 /// Returns the group of version-dependent wire layouts selected by this version.
105 pub const fn layout(self) -> LayoutProfile {
106 match self.0 {
107 3..=4 => LayoutProfile::V3,
108 5..=7 => LayoutProfile::V5,
109 8..=10 => LayoutProfile::V8,
110 11..=14 => LayoutProfile::V11,
111 15 => LayoutProfile::V15,
112 16 => LayoutProfile::V16,
113 17 => LayoutProfile::V17,
114 18 => LayoutProfile::V18,
115 19..=21 => LayoutProfile::V19,
116 _ => LayoutProfile::V22,
117 }
118 }
119
120 /// General station UI messages use dynamic text layouts from version 9.
121 pub const fn uses_dynamic_general_ui(self) -> bool {
122 self.0 >= Self::V9.0
123 }
124
125 /// Returns the number of strings in this version's dynamic call-info body.
126 pub const fn dynamic_call_info_layout(self) -> DynamicCallInfoLayout {
127 match self.0 {
128 ..=15 => DynamicCallInfoLayout::Fields12,
129 16..=18 => DynamicCallInfoLayout::Fields13,
130 _ => DynamicCallInfoLayout::Fields15,
131 }
132 }
133
134 /// Reports whether dynamic speed-dial status is selected by protocol version.
135 pub const fn uses_dynamic_speed_dial_status(self) -> bool {
136 self.0 >= Self::V9.0
137 }
138}
139
140/// Version-selected shape of a dynamic call-information payload.
141#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
142pub enum DynamicCallInfoLayout {
143 Fields12,
144 Fields13,
145 Fields15,
146}
147
148impl DynamicCallInfoLayout {
149 pub const fn string_count(self) -> usize {
150 match self {
151 Self::Fields12 => 12,
152 Self::Fields13 => 13,
153 Self::Fields15 => 15,
154 }
155 }
156}
157
158impl fmt::Debug for ProtocolVersion {
159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160 write!(f, "V{}", self.0)
161 }
162}
163
164impl fmt::Display for ProtocolVersion {
165 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166 write!(f, "v{}", self.0)
167 }
168}
169
170impl TryFrom<u32> for ProtocolVersion {
171 type Error = CodecError;
172
173 fn try_from(value: u32) -> Result<Self, Self::Error> {
174 Self::new(value)
175 }
176}
177
178impl From<ProtocolVersion> for u32 {
179 fn from(value: ProtocolVersion) -> Self {
180 value.wire()
181 }
182}
183
184/// Wire-layout transitions used between SCCP versions 3 and 22.
185#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
186pub enum LayoutProfile {
187 /// Layouts used by versions 3 and 4.
188 V3,
189 /// Layouts used by versions 5 through 7.
190 V5,
191 /// Layouts used by versions 8 through 10.
192 V8,
193 /// Layouts used by versions 11 through 14.
194 V11,
195 /// Layouts specific to version 15.
196 V15,
197 /// Layouts specific to version 16.
198 V16,
199 /// Layouts specific to version 17.
200 V17,
201 /// Layouts specific to version 18.
202 V18,
203 /// Layouts used by versions 19 through 21.
204 V19,
205 /// Layouts used by version 22.
206 V22,
207}
208
209wire_enum! {
210 /// Station device model identifier.
211 pub enum DeviceType {
212 /// No concrete device model was supplied; used as the zero/default device type.
213 Undefined = 0,
214 /// Legacy Cisco 30-button SP+ hardware station.
215 Phone30SpPlus = 1,
216 /// Legacy Cisco 12-button SP+ hardware station.
217 Phone12SpPlus = 2,
218 /// Legacy Cisco 12-button SP hardware station.
219 Phone12Sp = 3,
220 /// Legacy Cisco 12-button station without the SP feature set.
221 Phone12 = 4,
222 /// Legacy Cisco 30-button VIP hardware station.
223 Phone30Vip = 5,
224 /// Cisco Unified IP Phone 7910, an early basic SCCP desk phone.
225 Cisco7910 = 6,
226 /// Cisco Unified IP Phone 7960, a six-line SCCP desk phone.
227 Cisco7960 = 7,
228 /// Cisco Unified IP Phone 7940, a two-line SCCP desk phone.
229 Cisco7940 = 8,
230 /// Cisco Unified IP Conference Station 7935.
231 Cisco7935 = 9,
232 /// A Cisco Voice Gateway Controller phone endpoint representing an analog gateway port.
233 Vgc = 10,
234 /// Cisco ATA 186 analog telephone adapter.
235 Ata186 = 12,
236 /// Cisco ATA 188 two-port analog telephone adapter with an Ethernet pass-through port.
237 Ata188 = 13,
238 /// The virtual counterpart of the legacy 30 SP+ station, used without matching physical hardware.
239 Virtual30SpPlus = 20,
240 /// A software or application-controlled phone endpoint represented as a station device.
241 PhoneApplication = 21,
242 /// A generic analog-access gateway resource.
243 AnalogAccess = 30,
244 /// A first-generation digital-access PRI resource, historically named DigitalAccessTitan1.
245 DigitalAccessPri = 40,
246 /// A digital-access resource for a channelized T1 interface.
247 DigitalAccessT1 = 41,
248 /// A second-generation digital-access gateway resource carrying Cisco's Titan2 codename.
249 DigitalAccessTitan2 = 42,
250 /// Historical Cisco tables identify this device type as DigitalAccessLennon or WS-X6608 digital access.
251 /// The Rust variant name appears to be swapped with `DigitalAccessLennon`.
252 AnalogAccessElvis = 43,
253 /// Historical Cisco tables identify this device type as AnalogAccessElvis or WS-X6624 analog access.
254 /// The Rust variant name appears to be swapped with `AnalogAccessElvis`.
255 DigitalAccessLennon = 47,
256 /// A generic conference-bridge media resource rather than a handset.
257 ConferenceBridge = 50,
258 /// A conference-bridge implementation generation carrying Cisco's Yoko codename.
259 ConferenceBridgeYoko = 51,
260 /// A conference-bridge implementation generation carrying Cisco's Dixieland codename.
261 ConferenceBridgeDixieland = 52,
262 /// A conference-bridge implementation generation carrying Cisco's Summit codename.
263 ConferenceBridgeSummit = 53,
264 /// An H.225 call-signaling endpoint used by the H.323 stack.
265 H225 = 60,
266 /// An H.323 telephone endpoint represented in the device table.
267 H323Phone = 61,
268 /// An H.323 gateway or trunk endpoint rather than an SCCP station.
269 H323Trunk = 62,
270 /// A music-on-hold media resource.
271 MusicOnHold = 70,
272 /// A logical call-routing pilot rather than a physical endpoint.
273 Pilot = 71,
274 /// A CTI/TAPI-controlled port used by telephony applications.
275 TapiPort = 72,
276 /// A CTI/TAPI route point that applications use to receive and redirect calls.
277 TapiRoutePoint = 73,
278 /// A voicemail or voice-inbox port represented as a callable device.
279 VoiceInbox = 80,
280 /// The administrative endpoint associated with a voice-inbox service.
281 VoiceInboxAdmin = 81,
282 /// A media resource that injects announcements or call-progress prompts on a line.
283 LineAnnunciator = 82,
284 /// A software media-termination-point implementation carrying Cisco's Dixieland codename.
285 SoftwareMtpDixieland = 83,
286 /// A Cisco media-server resource providing media processing rather than station service.
287 CiscoMediaServer = 84,
288 /// A conference-bridge implementation generation carrying Cisco's Flint codename.
289 ConferenceBridgeFlint = 85,
290 /// A logical route list used to select trunks and gateways.
291 RouteList = 90,
292 /// Cisco's synthetic station type for registration and call-load testing.
293 LoadSimulator = 100,
294 /// A generic media termination point used to relay or adapt media signaling.
295 MediaTerminationPoint = 110,
296 /// A hardware media termination point carrying Cisco's Yoko generation name.
297 MediaTerminationPointYoko = 111,
298 /// A media termination point carrying Cisco's Dixieland generation name.
299 MediaTerminationPointDixieland = 112,
300 /// A media termination point carrying Cisco's Summit generation name.
301 MediaTerminationPointSummit = 113,
302 /// Cisco Unified IP Phone 7941G, a two-line programmable SCCP desk phone.
303 Cisco7941 = 115,
304 /// Cisco Unified IP Phone 7971G-GE, a color touch-screen SCCP desk phone with Gigabit Ethernet.
305 Cisco7971 = 119,
306 /// An analog station port controlled through MGCP.
307 MgcpStation = 120,
308 /// A trunk endpoint controlled through MGCP.
309 MgcpTrunk = 121,
310 /// An H.323 Registration, Admission, and Status proxy resource.
311 RasProxy = 122,
312 /// Cisco 7914 fourteen-button line expansion module attached to a compatible desk phone.
313 CiscoAddon7914 = 124,
314 /// A generic call-routing trunk whose more specific signaling family is not encoded here.
315 Trunk = 125,
316 /// An annunciator media resource that plays tones and recorded prompts.
317 Annunciator = 126,
318 /// A media bridge used to fork call audio for monitoring.
319 MonitorBridge = 127,
320 /// A recording media resource represented as a call-control device.
321 Recorder = 128,
322 /// A monitoring bridge implementation carrying Cisco's Yoko generation name.
323 MonitorBridgeYoko = 129,
324 /// A SIP signaling trunk represented in the common device-type namespace.
325 SipTrunk = 131,
326 /// Cisco 7915 expansion module operating in its 12-button layout.
327 CiscoAddon7915_12 = 227,
328 /// Cisco 7915 expansion module operating in its 24-button layout.
329 CiscoAddon7915_24 = 228,
330 /// Cisco 7916 expansion module operating in its 12-button layout.
331 CiscoAddon7916_12 = 229,
332 /// Cisco 7916 expansion module operating in its 24-button layout.
333 CiscoAddon7916_24 = 230,
334 /// Nokia E-series mobile phone running a Cisco-compatible SCCP client.
335 NokiaESeries = 275,
336 /// Cisco Unified IP Phone 7985G desktop video phone.
337 Cisco7985 = 302,
338 /// Cisco Unified IP Phone 7911G, a basic single-line SCCP desk phone.
339 Cisco7911 = 307,
340 /// Cisco Unified IP Phone 7961G-GE, the Gigabit Ethernet six-line model.
341 Cisco7961Ge = 308,
342 /// Cisco Unified IP Phone 7941G-GE, the Gigabit Ethernet two-line model.
343 Cisco7941Ge = 309,
344 /// Cisco Unified IP Phone 7931G, a desk phone with a large set of programmable line and feature keys.
345 Cisco7931 = 348,
346 /// Cisco Unified Wireless IP Phone 7921G.
347 Cisco7921 = 365,
348 /// Cisco Unified IP Phone 7906G, a basic single-line SCCP desk phone.
349 Cisco7906 = 369,
350 /// Nokia Internet Call Client acting as an SCCP software endpoint.
351 NokiaIcc = 376,
352 /// Cisco Unified IP Phone 7962G, a six-line monochrome SCCP desk phone.
353 Cisco7962 = 404,
354 /// Cisco Unified IP Conference Station 7937G.
355 Cisco7937 = 431,
356 /// Cisco Unified IP Phone 7942G, a two-line monochrome SCCP desk phone.
357 Cisco7942 = 434,
358 /// Cisco Unified IP Phone 7945G, a two-line color SCCP desk phone with Gigabit Ethernet.
359 Cisco7945 = 435,
360 /// Cisco Unified IP Phone 7965G, a six-line color SCCP desk phone with Gigabit Ethernet.
361 Cisco7965 = 436,
362 /// Cisco Unified IP Phone 7975G, an eight-line color touch-screen SCCP desk phone.
363 Cisco7975 = 437,
364 /// Cisco Unified Wireless IP Phone 7925G.
365 Cisco7925 = 484,
366 /// Cisco Unified IP Phone 6921, a two-line entry-level desk phone.
367 Cisco6921 = 495,
368 /// Cisco Unified IP Phone 6941, a four-line desk phone.
369 Cisco6941 = 496,
370 /// Cisco Unified IP Phone 6961, a twelve-line desk phone.
371 Cisco6961 = 497,
372 /// Cisco Unified SIP Phone 6901, a displayless single-line endpoint represented in the common device table.
373 Cisco6901 = 547,
374 /// Cisco Unified IP Phone 6911, a basic single-line endpoint.
375 Cisco6911 = 548,
376 /// Cisco Unified IP Phone 6945, a four-line desk phone with Gigabit Ethernet.
377 Cisco6945 = 564,
378 /// Cisco Unified Wireless IP Phone 7926G with an integrated barcode scanner.
379 Cisco7926 = 577,
380 /// Cisco Unified IP Phone 8945, a color video desk phone with Gigabit Ethernet.
381 Cisco8945 = 585,
382 /// Cisco Unified IP Phone 8941, a color video desk phone.
383 Cisco8941 = 586,
384 /// Cisco IP Communicator, the Windows software-phone implementation of a Cisco desk phone.
385 CiscoIpCommunicator = 30016,
386 /// Cisco Unified IP Phone 7905G, a basic single-line SCCP desk phone.
387 Cisco7905 = 20000,
388 /// Cisco Wireless IP Phone 7920, the first-generation Cisco SCCP Wi-Fi handset.
389 Cisco7920 = 30002,
390 /// Cisco Unified IP Phone 7970G, an eight-line color touch-screen SCCP desk phone.
391 Cisco7970 = 30006,
392 /// Cisco Unified IP Phone 7912G, a basic single-line SCCP desk phone with an Ethernet switch.
393 Cisco7912 = 30007,
394 /// Cisco Unified IP Phone 7902G, a displayless single-line SCCP desk phone.
395 Cisco7902 = 30008,
396 /// Cisco Unified IP Phone 7961G, a six-line programmable SCCP desk phone.
397 Cisco7961 = 30018,
398 /// Cisco Unified IP Conference Station 7936.
399 Cisco7936 = 30019,
400 /// A virtual SCCP phone endpoint representing an analog gateway port.
401 AnalogGateway = 30027,
402 /// A virtual SCCP phone endpoint representing an ISDN BRI gateway port.
403 BriGateway = 30028,
404 /// Cisco SPA521S small-business IP desk phone.
405 Spa521s = 80000,
406 /// Cisco SPA524SG small-business IP desk phone with Gigabit Ethernet.
407 Spa524sg = 80001,
408 /// Cisco SPA502G one-line small-business IP desk phone.
409 Spa502g = 80003,
410 /// Cisco SPA504G four-line small-business IP desk phone.
411 Spa504g = 80004,
412 /// Cisco SPA525G five-line small-business color IP desk phone.
413 Spa525g = 80005,
414 /// Cisco SPA508G eight-line small-business IP desk phone.
415 Spa508g = 80006,
416 /// Cisco SPA509G twelve-line small-business IP desk phone.
417 Spa509g = 80007,
418 /// Second-generation Cisco SPA525G2 five-line color IP desk phone.
419 Spa525g2 = 80009,
420 /// Cisco SPA303G three-line small-business IP desk phone.
421 Spa303g = 80011,
422 /// Cisco SPA512G one-line small-business IP desk phone with Gigabit Ethernet.
423 Spa512g = 80012,
424 /// Cisco SPA514G four-line small-business IP desk phone with Gigabit Ethernet.
425 Spa514g = 80013,
426 /// Cisco SPA500S 32-button sidecar expansion module.
427 AddonSpa500s = 99991,
428 /// Cisco SPA500DS digital sidecar expansion module.
429 AddonSpa500ds = 99992,
430 /// Cisco SPA932DS attendant-console expansion module.
431 AddonSpa932ds = 99993,
432 /// Cisco's explicit “not defined” sentinel used when no registered device type applies.
433 NotDefined = 99999
434 }
435}
436
437/// Broad media class for a codec capability.
438#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
439pub enum CodecKind {
440 Audio,
441 Video,
442 Text,
443 Data,
444 TelephoneEvent,
445 Unknown,
446}
447
448wire_enum! {
449 /// Skinny payload capability / codec identifier.
450 pub enum Codec {
451 /// Indicates that no media encoding is selected or advertised.
452 None = 0x0000,
453 /// Marks an implementation-specific media format.
454 /// The identifier alone does not define an interoperable encoding.
455 NonStandard = 0x0001,
456 /// G.711 A-law PCM at 64 kbit/s, commonly used by E-carrier telephony systems.
457 Pcma = 0x0002,
458 /// G.711 A-law PCM carried through a 56 kbit/s bearer rather than a full 64 kbit/s channel.
459 G711Alaw56k = 0x0003,
460 /// G.711 µ-law PCM at 64 kbit/s, commonly used by North American and Japanese telephony systems.
461 Pcmu = 0x0004,
462 /// G.711 µ-law PCM carried through a 56 kbit/s bearer rather than a full 64 kbit/s channel.
463 G711Ulaw56k = 0x0005,
464 /// G.722 sub-band wideband speech using its 64 kbit/s mode.
465 G72264k = 0x0006,
466 /// G.722 sub-band wideband speech using its 56 kbit/s mode.
467 G72256k = 0x0007,
468 /// G.722 sub-band wideband speech using its 48 kbit/s mode.
469 G72248k = 0x0008,
470 /// G.723.1 low-bit-rate narrowband speech, normally encoded at 5.3 or 6.3 kbit/s.
471 G7231 = 0x0009,
472 /// G.728 low-delay CELP narrowband speech encoded at 16 kbit/s.
473 G728 = 0x000a,
474 /// Base G.729 CS-ACELP narrowband speech encoded at 8 kbit/s.
475 G729 = 0x000b,
476 /// The reduced-complexity Annex A profile of G.729 at 8 kbit/s.
477 G729A = 0x000c,
478 /// ISO/IEC 11172 MPEG-1 audio, retained as a legacy SCCP audio capability.
479 Is11172 = 0x000d,
480 /// ISO/IEC 13818 MPEG-2 audio, retained as a legacy SCCP audio capability.
481 Is13818 = 0x000e,
482 /// G.729 with Annex B voice-activity detection and comfort-noise generation.
483 G729B = 0x000f,
484 /// The reduced-complexity G.729 Annex A profile combined with Annex B silence suppression.
485 G729Ab = 0x0010,
486 /// GSM Full Rate cellular speech coding.
487 /// This is distinct from the RTP GSM 06.10 capability represented by `Gsm`.
488 GsmFullRate = 0x0012,
489 /// GSM Half Rate cellular speech coding, trading speech quality for reduced radio bandwidth.
490 GsmHalfRate = 0x0013,
491 /// GSM Enhanced Full Rate cellular speech coding with improved quality over GSM Full Rate.
492 GsmEnhancedFullRate = 0x0014,
493 /// Uncompressed 16-bit linear wideband PCM at 16 kHz, producing a 256 kbit/s audio stream.
494 Wideband256k = 0x0019,
495 /// A transparent 64 kbit/s data bearer rather than an audio or video encoding.
496 Data64k = 0x0020,
497 /// A transparent 56 kbit/s data bearer for rate-limited digital trunks.
498 Data56k = 0x0021,
499 /// G.722.1 wideband transform audio at 32 kbit/s, commonly known as the Siren 7 family.
500 G7221_32k = 0x0028,
501 /// G.722.1 wideband transform audio at 24 kbit/s, commonly known as the Siren 7 family.
502 G7221_24k = 0x0029,
503 /// Generic Advanced Audio Coding capability without a fixed SCCP LATM bit-rate selector.
504 Aac = 0x002a,
505 /// AAC audio transported with MPEG-4 LATM at a nominal 128 kbit/s.
506 /// Cisco capability tables associate this family with low-delay AAC.
507 Mp4aLatm128 = 0x002b,
508 /// AAC audio transported with MPEG-4 LATM at a nominal 64 kbit/s.
509 Mp4aLatm64 = 0x002c,
510 /// AAC audio transported with MPEG-4 LATM at a nominal 56 kbit/s.
511 Mp4aLatm56 = 0x002d,
512 /// AAC audio transported with MPEG-4 LATM at a nominal 48 kbit/s.
513 Mp4aLatm48 = 0x002e,
514 /// AAC audio transported with MPEG-4 LATM at a nominal 32 kbit/s.
515 Mp4aLatm32 = 0x002f,
516 /// AAC audio transported with MPEG-4 LATM at a nominal 24 kbit/s.
517 Mp4aLatm24 = 0x0030,
518 /// AAC audio transported with MPEG-4 LATM when the bit rate is negotiated elsewhere or unspecified.
519 Mp4aLatm = 0x0031,
520 /// The RTP GSM 06.10 full-rate narrowband speech format.
521 /// This is the interoperable RTP profile rather than a cellular bearer-mode selector.
522 Gsm = 0x0050,
523 /// A Cisco-defined narrowband `ActiveVoice` audio capability.
524 /// The audited SCCP sources name it but do not establish a public encoding specification.
525 ActiveVoice = 0x0051,
526 /// G.726 ADPCM narrowband speech encoded at 32 kbit/s.
527 G726_32k = 0x0052,
528 /// G.726 ADPCM narrowband speech encoded at 24 kbit/s.
529 G726_24k = 0x0053,
530 /// G.726 ADPCM narrowband speech encoded at 16 kbit/s.
531 G726_16k = 0x0054,
532 /// A later SCCP identifier for G.729 Annex B silence suppression.
533 /// It remains wire-distinct from the legacy `G729B` identifier.
534 G729AnnexB = 0x0055,
535 /// iLBC packet-loss-resilient narrowband speech, normally using 20 ms or 30 ms frames.
536 Ilbc = 0x0056,
537 /// iSAC adaptive wideband speech coding designed for variable IP-network conditions.
538 Isac = 0x0059,
539 /// Opus interactive audio, supporting speech and full-band audio with adaptive bit rate.
540 Opus = 0x005a,
541 /// Adaptive Multi-Rate narrowband cellular speech coding.
542 Amr = 0x0061,
543 /// Adaptive Multi-Rate Wideband speech coding, also standardized as G.722.2.
544 AmrWb = 0x0062,
545 /// H.261 video for audiovisual services over constant-rate digital channels.
546 H261 = 0x0064,
547 /// Base H.263 low-bit-rate video coding.
548 H263 = 0x0065,
549 /// H.263+ video, incorporating the optional enhancements standardized in H.263 version 2.
550 H263Plus = 0x0066,
551 /// Base H.264/AVC video capability.
552 H264 = 0x0067,
553 /// The scalable-video-coding extension of H.264/AVC, allowing layered temporal, spatial, or quality streams.
554 H264Svc = 0x0068,
555 /// T.120 real-time data-conferencing traffic such as shared whiteboards and application data.
556 /// It is a data capability, not a speech codec.
557 T120 = 0x0069,
558 /// H.224 low-rate data-link traffic used by applications such as H.281 far-end camera control.
559 H224 = 0x006a,
560 /// T.38 real-time facsimile relay, transporting decoded fax data instead of modem audio.
561 T38Fax = 0x006b,
562 /// A Cisco-defined `TOTE` payload capability with no public encoding semantics established here.
563 /// Available SCCP sources disagree on whether to classify it as video or data.
564 Tote = 0x006c,
565 /// H.265/HEVC video, the successor to H.264/AVC with improved compression efficiency.
566 H265 = 0x006d,
567 /// Cisco's distinct `H264_UC` video capability.
568 /// The audited sources do not define what the UC profile adds, so it is not treated as base H.264.
569 H264Uc = 0x006e,
570 /// Cisco X-V.150 modem relay associated with a G.711 µ-law voiceband-data path.
571 /// Legacy chan-sccp sources identify it with modem traffic on VG224 gateways.
572 Xv150ModemRelay711u = 0x006f,
573 /// Cisco named-signaling-event mode for voiceband data carried over G.711 µ-law.
574 NseVbd711u = 0x0070,
575 /// Cisco X-V.150 modem relay associated with a G.729 Annex A voice path.
576 /// Legacy chan-sccp sources identify it with modem traffic on VG224 gateways.
577 Xv150ModemRelay729a = 0x0071,
578 /// Cisco named-signaling-event mode for voiceband data associated with G.729 Annex A.
579 NseVbd729a = 0x0072,
580 /// Cisco's H.264 capability variant carrying forward-error-correction support.
581 /// It is negotiated separately because the backend has no equivalent base-H.264 flag.
582 H264Fec = 0x0073,
583 /// A transparent clear-channel bearer that preserves arbitrary digital data without transcoding.
584 ClearChannel = 0x0078,
585 /// A Cisco media-resource capability representing a universal transcoder.
586 /// It identifies a transformation service rather than a media encoding.
587 UniversalTranscoder = 0x00de,
588 /// DTMF carried as RTP `telephone-event` packets using a dynamically negotiated payload type.
589 /// The historical name references RFC 2833; RFC 4733 later replaced it.
590 DtmfOutOfBandRfc2833 = 0x0101,
591 /// Cisco's proprietary RTP DTMF passthrough payload rather than audible in-band tones.
592 DtmfPassthrough = 0x0102,
593 /// A Cisco DTMF event capability whose RTP payload number is negotiated dynamically.
594 DtmfDynamic = 0x0103,
595 /// Cisco out-of-band DTMF signaling, carrying digits separately from the voice samples.
596 DtmfOutOfBand = 0x0104,
597 /// Cisco's historical “in-band RFC 2833” event-payload mode.
598 /// Despite the label, it represents packetized digit events rather than acoustic DTMF audio.
599 DtmfInBandRfc2833 = 0x0105,
600 /// Conference-bridge tone events used by Cisco media resources.
601 /// This is a control/event payload, not an audio codec.
602 CfbTones = 0x0106,
603 /// DTMF event signaling without a companion audio stream.
604 DtmfNoAudio = 0x012b,
605 /// The V.150.1 modem-relay media mode, carrying demodulated modem data across an IP network.
606 V150ModemRelay = 0x012c,
607 /// The V.150.1 Simple Packet Relay Transport used for reliable modem-relay data.
608 V150Sprt = 0x012d,
609 /// The V.150.1 State Signalling Events channel used to coordinate transitions among audio, VBD, and relay modes.
610 V150Sse = 0x012e
611 }
612}
613
614impl Codec {
615 /// Backward-compatible name for the SCCP numeric value.
616 pub const fn skinny(self) -> u32 {
617 self.wire_value()
618 }
619
620 /// Classifies this capability into its broad media family.
621 pub const fn kind(self) -> CodecKind {
622 match self {
623 Self::H261
624 | Self::H263
625 | Self::H263Plus
626 | Self::H264
627 | Self::H264Svc
628 | Self::H265
629 | Self::H264Uc
630 | Self::H264Fec => CodecKind::Video,
631 Self::T120 | Self::H224 => CodecKind::Text,
632 Self::Data64k
633 | Self::Data56k
634 | Self::T38Fax
635 | Self::Tote
636 | Self::Xv150ModemRelay711u
637 | Self::NseVbd711u
638 | Self::Xv150ModemRelay729a
639 | Self::NseVbd729a
640 | Self::ClearChannel
641 | Self::UniversalTranscoder
642 | Self::V150ModemRelay
643 | Self::V150Sprt
644 | Self::V150Sse => CodecKind::Data,
645 Self::DtmfOutOfBandRfc2833
646 | Self::DtmfPassthrough
647 | Self::DtmfDynamic
648 | Self::DtmfOutOfBand
649 | Self::DtmfInBandRfc2833
650 | Self::DtmfNoAudio
651 | Self::CfbTones => CodecKind::TelephoneEvent,
652 Self::None | Self::NonStandard | Self::Unknown(_) => CodecKind::Unknown,
653 _ => CodecKind::Audio,
654 }
655 }
656
657 /// Returns the nominal clock rate in hertz for supported audio codecs.
658 ///
659 /// Non-audio, unrecognized, and codecs without a defined mapping return
660 /// `None`.
661 pub const fn sample_rate(self) -> Option<u32> {
662 match self {
663 Self::G72264k
664 | Self::G72256k
665 | Self::G72248k
666 | Self::G7221_32k
667 | Self::G7221_24k
668 | Self::Wideband256k
669 | Self::AmrWb => Some(16_000),
670 Self::Opus | Self::Isac => Some(48_000),
671 codec if matches!(codec.kind(), CodecKind::Audio) => Some(8_000),
672 _ => None,
673 }
674 }
675
676 /// Returns the codec's default RTP payload type when statically assigned.
677 ///
678 /// Dynamically assigned codecs return `None` and require negotiated
679 /// payload metadata.
680 pub const fn rtp_payload_type(self) -> Option<u8> {
681 match self {
682 Self::Pcmu | Self::G711Ulaw56k => Some(0),
683 Self::Gsm => Some(3),
684 Self::G7231 => Some(4),
685 Self::Pcma | Self::G711Alaw56k => Some(8),
686 Self::G72264k | Self::G72256k | Self::G72248k => Some(9),
687 Self::G729 | Self::G729A | Self::G729B | Self::G729Ab | Self::G729AnnexB => Some(18),
688 Self::Wideband256k => Some(25),
689 Self::Ilbc => Some(97),
690 Self::G7221_32k => Some(102),
691 Self::Opus => Some(107),
692 Self::G726_32k => Some(112),
693 _ => None,
694 }
695 }
696}
697
698wire_enum! {
699 /// Station call-state indication shown by the call plane.
700 pub enum CallState {
701 OffHook = 1,
702 OnHook = 2,
703 RingOut = 3,
704 RingIn = 4,
705 Connected = 5,
706 Busy = 6,
707 Congestion = 7,
708 Hold = 8,
709 CallWaiting = 9,
710 Transfer = 10,
711 Park = 11,
712 Proceed = 12,
713 RemoteMultiline = 13,
714 InvalidNumber = 14,
715 HoldYellow = 15,
716 IntercomOneWay = 16,
717 HoldRed = 17
718 }
719}
720
721wire_enum! {
722 /// Direction and origin classification attached to call information.
723 pub enum CallType {
724 Inbound = 1,
725 Outbound = 2,
726 Forward = 3
727 }
728}
729
730wire_enum! {
731 /// Operational severity attached to a station alarm report.
732 pub enum AlarmSeverity {
733 Critical = 0,
734 Warning = 1,
735 Informational = 2,
736 ProtocolUnknown = 4,
737 Major = 7,
738 Minor = 8,
739 Marginal = 10,
740 TraceInfo = 20
741 }
742}
743
744wire_enum! {
745 /// Result status returned by media-channel operations.
746 pub enum MediaStatus {
747 Ok = 0,
748 UnspecifiedError = 1,
749 OutOfChannels = 2,
750 CodecTooComplex = 3,
751 InvalidPartyId = 4,
752 InvalidCallReference = 5,
753 InvalidCodec = 6,
754 InvalidPacketSize = 7,
755 OutOfSockets = 8,
756 EncoderOrDecoderFailed = 9,
757 InvalidDynamicPayload = 10,
758 RequestedAddressTypeUnavailable = 11,
759 DeviceOnHook = 12
760 }
761}
762
763wire_enum! {
764 /// Physical or logical button stimulus reported by a station.
765 pub enum Stimulus {
766 /// Reports an unassigned or inactive station control; no feature action is implied.
767 Unused = 0x00,
768 /// Reports use of the redial control to call the most recently dialed destination.
769 LastNumberRedial = 0x01,
770 /// Reports activation of a provisioned speed-dial entry.
771 SpeedDial = 0x02,
772 /// Reports use of the hold control for the addressed call.
773 Hold = 0x03,
774 /// Reports use of the transfer control to start or complete a call transfer.
775 Transfer = 0x04,
776 /// Reports use of the call-forward-all control.
777 ForwardAll = 0x05,
778 /// Reports use of the call-forward-on-busy control.
779 ForwardBusy = 0x06,
780 /// Reports use of the call-forward-on-no-answer control.
781 ForwardNoAnswer = 0x07,
782 /// Reports activation of a legacy display-oriented station control.
783 Display = 0x08,
784 /// Reports selection of a line appearance or a call on that appearance.
785 Line = 0x09,
786 /// Reports activation of the T.120 text-chat application.
787 T120Chat = 0x0a,
788 /// Reports activation of the T.120 shared-whiteboard application.
789 T120Whiteboard = 0x0b,
790 /// Reports activation of T.120 application sharing.
791 T120ApplicationSharing = 0x0c,
792 /// Reports activation of T.120 conference file transfer.
793 T120FileTransfer = 0x0d,
794 /// Reports use of the station's video control.
795 Video = 0x0e,
796 /// Reports activation of a voicemail access key.
797 Voicemail = 0x0f,
798 /// Reports use of a combined answer/release control.
799 AnswerRelease = 0x10,
800 /// Reports use of the station's automatic-answer control.
801 AutoAnswer = 0x11,
802 /// Reports use of the call-selection control for multi-call operations.
803 Select = 0x12,
804 /// Reports use of the call-privacy control.
805 Privacy = 0x13,
806 /// Reports activation of a provisioned phone-service URL.
807 ServiceUrl = 0x14,
808 /// Reports activation of a speed dial that also monitors its target through BLF.
809 BlfSpeedDial = 0x15,
810 /// Reports a directed-park request targeting a specific park destination.
811 DirectedPark = 0x16,
812 /// Reports activation of an intercom appearance or intercom call.
813 Intercom = 0x17,
814 /// Reports use of the malicious-call identification feature.
815 MaliciousCall = 0x1b,
816 /// Reports application-defined programmable control B1; SCCP assigns no universal action.
817 GenericAppB1 = 0x21,
818 /// Reports application-defined programmable control B2; SCCP assigns no universal action.
819 GenericAppB2 = 0x22,
820 /// Reports application-defined programmable control B3; SCCP assigns no universal action.
821 GenericAppB3 = 0x23,
822 /// Reports application-defined programmable control B4; SCCP assigns no universal action.
823 GenericAppB4 = 0x24,
824 /// Reports application-defined programmable control B5; SCCP assigns no universal action.
825 GenericAppB5 = 0x25,
826 /// Reports activation of a generic feature whose lamp can expose multiple blink states.
827 MultiblinkFeature = 0x26,
828 /// Reports activation of the dial-in Meet-Me conference workflow.
829 MeetMeConference = 0x7b,
830 /// Reports use of the station conference control for an active call.
831 Conference = 0x7d,
832 /// Reports a request to park the current call.
833 CallPark = 0x7e,
834 /// Reports a request to answer a ringing call in the configured pickup scope.
835 CallPickup = 0x7f,
836 /// Reports a group-pickup request for a ringing call in another pickup group.
837 GroupCallPickup = 0x80,
838 /// Reports activation of the extension-mobility login or logout feature.
839 Mobility = 0x81,
840 /// Reports use of the do-not-disturb control.
841 DoNotDisturb = 0x82,
842 /// Reports a request to show or operate on the conference participant list.
843 ConferenceList = 0x83,
844 /// Reports a request to remove the most recently added conference participant.
845 RemoveLastParticipant = 0x84,
846 /// Reports activation of Cisco's call-quality reporting tool.
847 QualityReportTool = 0x85,
848 /// Reports a callback request for a busy or unavailable destination.
849 Callback = 0x86,
850 /// Reports use of Cisco's alternate call-pickup feature.
851 OtherPickup = 0x87,
852 /// Reports a request to change the call's video mode.
853 VideoMode = 0x88,
854 /// Reports use of the new-call control to allocate an outbound call.
855 NewCall = 0x89,
856 /// Reports use of the end-call control to release the addressed call.
857 EndCall = 0x8a,
858 /// Reports a hunt-group login or logout request.
859 HuntGroupLogin = 0x8b,
860 /// Reports activation of Cisco's call-queuing feature.
861 Queuing = 0x8f,
862 /// Reports activation of a parking-lot view or retrieval workflow.
863 ParkingLot = 0xc0,
864 /// Reports use of the station's fixed Messages key.
865 Messages = 0xc2,
866 /// Reports use of the station's fixed Directories key.
867 Directory = 0xc3,
868 /// Reports use of the station's fixed Applications or Services key.
869 Application = 0xc5,
870 /// Reports a headset-control state change from the station.
871 Headset = 0xc6,
872 /// Identifies input originating from the station's physical keypad control block.
873 Keypad = 0xf0,
874 /// Reports use of the station acoustic-echo-cancellation control.
875 AcousticEchoCancellation = 0xfd,
876 /// Preserves a station stimulus that Cisco marks as undefined rather than unassigned.
877 Undefined = 0xff
878 }
879}
880
881wire_enum! {
882 /// Soft-key events are one-based positions in the advertised template.
883 pub enum SoftKey {
884 Redial = 1,
885 NewCall = 2,
886 Hold = 3,
887 Transfer = 4,
888 ForwardAll = 5,
889 ForwardBusy = 6,
890 ForwardNoAnswer = 7,
891 Backspace = 8,
892 EndCall = 9,
893 Resume = 10,
894 Answer = 11,
895 Info = 12,
896 Conference = 13,
897 Park = 14,
898 Join = 15,
899 MeetMe = 16,
900 Pickup = 17,
901 GroupPickup = 18,
902 Monitor = 19,
903 Callback = 20,
904 Barge = 21,
905 DoNotDisturb = 22,
906 ConferenceList = 23,
907 Select = 24,
908 Private = 25,
909 TransferToVoicemail = 26,
910 DirectTransfer = 27,
911 ImmediateDivert = 28,
912 VideoMode = 29,
913 Intercept = 30,
914 Empty = 31,
915 Dial = 32
916 }
917}
918
919wire_enum! {
920 /// Call-state context used to select an advertised soft-key set.
921 pub enum KeyMode {
922 OnHook = 0,
923 Connected = 1,
924 OnHold = 2,
925 RingIn = 3,
926 OffHook = 4,
927 ConnectedTransfer = 5,
928 DigitsFollowing = 6,
929 ConnectedConference = 7,
930 RingOut = 8,
931 OffHookFeature = 9,
932 InUseHint = 10,
933 OnHookStealable = 11,
934 HoldConference = 12,
935 Empty = 13
936 }
937}
938
939wire_enum! {
940 /// Audible ringer pattern selected for the station.
941 pub enum RingerMode {
942 Off = 1,
943 Inside = 2,
944 Outside = 3,
945 Feature = 4,
946 Silent = 5,
947 Urgent = 6,
948 Bellcore1 = 7,
949 Bellcore2 = 8,
950 Bellcore3 = 9,
951 Bellcore4 = 10,
952 Bellcore5 = 11
953 }
954}
955
956wire_enum! {
957 /// Whether a ringer command applies once or continuously.
958 pub enum RingDuration {
959 Normal = 1,
960 Single = 2
961 }
962}
963
964wire_enum! {
965 /// Visual state selected for a station lamp.
966 pub enum LampMode {
967 Off = 1,
968 On = 2,
969 Wink = 3,
970 Flash = 4,
971 Blink = 5,
972 Hold = 6,
973 Ring = 7,
974 Custom1 = 8,
975 Custom2 = 9
976 }
977}
978
979wire_enum! {
980 /// Tone identifier used by tone and announcement commands.
981 pub enum Tone {
982 /// Stops any current station tone; the server uses this as the explicit silent tone request.
983 Silence = 0x00,
984 /// The DTMF `1` signal: 697 Hz row tone combined with a 1,209 Hz column tone.
985 Dtmf1 = 0x01,
986 /// The DTMF `2` signal: 697 Hz row tone combined with a 1,336 Hz column tone.
987 Dtmf2 = 0x02,
988 /// The DTMF `3` signal: 697 Hz row tone combined with a 1,477 Hz column tone.
989 Dtmf3 = 0x03,
990 /// The DTMF `4` signal: 770 Hz row tone combined with a 1,209 Hz column tone.
991 Dtmf4 = 0x04,
992 /// The DTMF `5` signal: 770 Hz row tone combined with a 1,336 Hz column tone.
993 Dtmf5 = 0x05,
994 /// The DTMF `6` signal: 770 Hz row tone combined with a 1,477 Hz column tone.
995 Dtmf6 = 0x06,
996 /// The DTMF `7` signal: 852 Hz row tone combined with a 1,209 Hz column tone.
997 Dtmf7 = 0x07,
998 /// The DTMF `8` signal: 852 Hz row tone combined with a 1,336 Hz column tone.
999 Dtmf8 = 0x08,
1000 /// The DTMF `9` signal: 852 Hz row tone combined with a 1,477 Hz column tone.
1001 Dtmf9 = 0x09,
1002 /// The DTMF `0` signal: 941 Hz row tone combined with a 1,336 Hz column tone.
1003 Dtmf0 = 0x0a,
1004 /// The DTMF `*` signal: 941 Hz row tone combined with a 1,209 Hz column tone.
1005 DtmfStar = 0x0e,
1006 /// The DTMF `#` signal: 941 Hz row tone combined with a 1,477 Hz column tone.
1007 DtmfPound = 0x0f,
1008 /// The DTMF `A` signal from the fourth keypad column used by AUTOVON and control systems.
1009 /// Combines a 697 Hz row tone with a 1,633 Hz column tone.
1010 DtmfA = 0x10,
1011 /// The DTMF `B` signal from the fourth keypad column used by AUTOVON and control systems.
1012 /// Combines a 770 Hz row tone with a 1,633 Hz column tone.
1013 DtmfB = 0x11,
1014 /// The DTMF `C` signal from the fourth keypad column used by AUTOVON and control systems.
1015 /// Combines an 852 Hz row tone with a 1,633 Hz column tone.
1016 DtmfC = 0x12,
1017 /// The DTMF `D` signal from the fourth keypad column used by AUTOVON and control systems.
1018 /// Combines a 941 Hz row tone with a 1,633 Hz column tone.
1019 DtmfD = 0x13,
1020 /// Dial tone indicating that the caller may dial an internal extension.
1021 InsideDial = 0x21,
1022 /// Dial tone indicating access to an external or public telephone network.
1023 OutsideDial = 0x22,
1024 /// Busy tone indicating that the called line cannot accept the call.
1025 LineBusy = 0x23,
1026 /// Audible ringback indicating that the remote endpoint is being alerted.
1027 Alerting = 0x24,
1028 /// Fast-busy or reorder tone indicating congestion or an unusable dialing sequence.
1029 Reorder = 0x25,
1030 /// Periodic warning beep informing participants that the call is being recorded.
1031 RecorderWarning = 0x26,
1032 /// Station feedback indicating that a recording device or recording service was detected.
1033 RecorderDetected = 0x27,
1034 /// Recall tone used when a held, parked, or transferred call reverts to the station.
1035 Reverting = 0x28,
1036 /// Loud off-hook warning tone played when the handset remains off hook without a call.
1037 ReceiverOffHook = 0x29,
1038 /// Intercept tone indicating that the supplied address or digit sequence is incomplete.
1039 PartialDial = 0x2a,
1040 /// Intercept tone indicating that the dialed number does not exist.
1041 NoSuchNumber = 0x2b,
1042 /// Special tone used while an operator performs busy-line verification.
1043 BusyVerification = 0x2c,
1044 /// Brief in-call alert indicating that another call is waiting.
1045 CallWaiting = 0x2d,
1046 /// Positive confirmation tone indicating that a requested feature was accepted.
1047 Confirmation = 0x2e,
1048 /// Tone indicating that the call is camped on a busy destination awaiting availability.
1049 CampOn = 0x2f,
1050 /// Dial tone presented after recall or hook flash so the caller can enter another destination.
1051 RecallDial = 0x30,
1052 /// Cisco's two-part “zip-zip” feature alert.
1053 /// The exact user-facing meaning depends on the call feature that requests it.
1054 ZipZip = 0x31,
1055 /// Cisco's short “zip” feature alert.
1056 /// The exact user-facing meaning depends on the call feature that requests it.
1057 Zip = 0x32,
1058 /// Cisco's paired positive/negative feature-feedback sound.
1059 BeepBonk = 0x33,
1060 /// Requests the station's built-in music tone rather than an RTP music-on-hold stream.
1061 Music = 0x34,
1062 /// Audible indication associated with placing or leaving a call on hold.
1063 Hold = 0x35,
1064 /// A station test tone used for diagnostics rather than normal call progress.
1065 Test = 0x36,
1066 /// Warning tone indicating that the call is being monitored.
1067 MonitorWarning = 0x37,
1068 /// Call-waiting alert used when another waiting call is added.
1069 AddCallWaiting = 0x40,
1070 /// Higher-priority call-waiting alert for precedence-aware call handling.
1071 PriorityCallWaiting = 0x41,
1072 /// Warning tone indicating that another party has barged into the call.
1073 BargeIn = 0x43,
1074 /// Distinctive alerting cadence used to distinguish a call class from normal ringing.
1075 DistinctAlert = 0x44,
1076 /// Priority alerting cadence used for a higher-precedence incoming call.
1077 PriorityAlert = 0x45,
1078 /// Short reminder ring for a held, parked, forwarded, or otherwise pending call.
1079 ReminderRing = 0x46,
1080 /// Ringback used by Multilevel Precedence and Preemption calls.
1081 PrecedenceRingback = 0x47,
1082 /// Warning tone indicating that a lower-precedence call is being preempted.
1083 Preemption = 0x48,
1084 /// Sentinel indicating that no call-progress tone is assigned.
1085 /// Unlike `Silence`, it does not request an active silence tone.
1086 NoTone = 0x7f,
1087 /// Conference-service greeting played when entering a Meet-Me flow.
1088 MeetMeGreeting = 0x80,
1089 /// Conference prompt indicating that the entered Meet-Me number is invalid.
1090 MeetMeNumberInvalid = 0x81,
1091 /// Conference prompt indicating that the entered Meet-Me number could not be used.
1092 MeetMeNumberFailed = 0x82,
1093 /// Conference prompt requesting the participant PIN.
1094 MeetMeEnterPin = 0x83,
1095 /// Conference prompt indicating that the participant PIN is invalid.
1096 MeetMeInvalidPin = 0x84,
1097 /// Conference prompt indicating that PIN validation failed.
1098 MeetMeFailedPin = 0x85,
1099 /// Conference prompt indicating that allocation of the conference bridge failed.
1100 MeetMeCfbFailed = 0x86,
1101 /// Conference prompt requesting an access code.
1102 MeetMeEnterAccessCode = 0x87,
1103 /// Conference prompt indicating that the supplied access code is invalid.
1104 MeetMeAccessCodeInvalid = 0x88,
1105 /// Conference prompt indicating that access-code validation failed.
1106 MeetMeAccessCodeFailed = 0x89
1107 }
1108}
1109
1110wire_enum! {
1111 /// Media direction in which a station should play a tone.
1112 pub enum ToneDirection {
1113 User = 0,
1114 Network = 1,
1115 Both = 2
1116 }
1117}
1118
1119wire_enum! {
1120 /// Station audio-path component named by a media-path event.
1121 pub enum MediaPathId {
1122 None = 0,
1123 Headset = 1,
1124 Handset = 2,
1125 Speaker = 3
1126 }
1127}
1128
1129wire_enum! {
1130 /// Availability transition reported for a station media path.
1131 pub enum MediaPathEvent {
1132 None = 0,
1133 On = 1,
1134 Off = 2
1135 }
1136}
1137
1138wire_enum! {
1139 /// Capability state reported for a station media path.
1140 pub enum MediaPathCapability {
1141 None = 0,
1142 Enable = 1,
1143 Disable = 2,
1144 Monitor = 3
1145 }
1146}
1147
1148wire_enum! {
1149 /// Media class used when allocating or closing ports.
1150 pub enum MediaType {
1151 Invalid = 0,
1152 Audio = 1,
1153 MainVideo = 2,
1154 Fecc = 3,
1155 PresentationVideo = 4,
1156 Bfcp = 5,
1157 IxChannel = 6,
1158 T38 = 7
1159 }
1160}
1161
1162wire_enum! {
1163 /// Transport family requested for a media endpoint.
1164 pub enum MediaTransport {
1165 Rtp = 1,
1166 Udp = 2,
1167 Tcp = 3
1168 }
1169}
1170
1171wire_enum! {
1172 /// RSVP reservation direction carried by SCCP QoS service messages.
1173 pub enum QosDirection {
1174 Send = 1,
1175 Receive = 2,
1176 SendReceive = 3
1177 }
1178}
1179
1180wire_enum! {
1181 /// RSVP reservation style used by QoS path setup.
1182 pub enum QosReservationStyle {
1183 FixedFilter = 1,
1184 SharedExplicit = 2,
1185 WildcardFilter = 3
1186 }
1187}
1188
1189wire_enum! {
1190 /// QoS service failure reported independently of RSVP protocol errors.
1191 pub enum QosErrorCode {
1192 ReservationTimeout = 0,
1193 PathFailed = 1,
1194 ReservationFailed = 2,
1195 ListenFailed = 3,
1196 ResourceUnavailable = 4,
1197 ListenTimeout = 5,
1198 ReservationRetriesFailed = 6,
1199 PathRetriesFailed = 7,
1200 ReservationPreempted = 8,
1201 PathPreempted = 9,
1202 ReservationModifyFailed = 10,
1203 PathModifyFailed = 11,
1204 ReservationTornDown = 12
1205 }
1206}
1207
1208wire_enum! {
1209 /// RSVP protocol error returned by a failed QoS reservation.
1210 pub enum RsvpErrorCode {
1211 Confirm = 0,
1212 Admission = 1,
1213 Administrative = 2,
1214 NoPathInformation = 3,
1215 NoSenderInformation = 4,
1216 ConflictingStyle = 5,
1217 UnknownStyle = 6,
1218 ConflictingDestinationPorts = 7,
1219 ConflictingSourcePorts = 8,
1220 ServicePreempted = 12,
1221 UnknownObjectClass = 13,
1222 UnknownClassType = 14,
1223 Api = 20,
1224 Traffic = 21,
1225 TrafficSystem = 22,
1226 System = 23,
1227 RoutingProblem = 24
1228 }
1229}
1230
1231wire_enum! {
1232 /// Requested acknowledgement behavior at the end of an announcement.
1233 pub enum EndOfAnnouncementAck {
1234 NotRequired = 0,
1235 Required = 1
1236 }
1237}
1238
1239wire_enum! {
1240 /// Ordering policy for playing an announcement sequence.
1241 pub enum AnnouncementPlayMode {
1242 XmlConfigured = 0,
1243 OneShot = 1,
1244 Continuous = 2
1245 }
1246}
1247
1248wire_enum! {
1249 /// Completion status returned when announcement playback finishes.
1250 pub enum AnnouncementPlayStatus {
1251 Ok = 0,
1252 Error = 1
1253 }
1254}
1255
1256wire_enum! {
1257 /// Result returned for a message-waiting notification.
1258 pub enum MessageWaitingResult {
1259 Ok = 0,
1260 GeneralError = 1,
1261 RequestRejected = 2,
1262 VoicemailCountOutOfBounds = 3,
1263 FaxCountOutOfBounds = 4,
1264 InvalidPriorityVoicemailCount = 5,
1265 InvalidPriorityFaxCount = 6
1266 }
1267}
1268
1269wire_enum! {
1270 /// Whether a connection-statistics response clears the station counters.
1271 pub enum StatisticsProcessing {
1272 Clear = 0,
1273 DoNotClear = 1
1274 }
1275}
1276
1277wire_enum! {
1278 /// Network-address family selected by a versioned media layout.
1279 pub enum IpAddressType {
1280 Ipv4 = 0,
1281 Ipv6 = 1,
1282 Ipv4AndIpv6 = 2,
1283 Invalid = 3
1284 }
1285}
1286
1287wire_enum! {
1288 /// Restart scope requested from a station.
1289 pub enum ResetType {
1290 Reset = 1,
1291 Restart = 2,
1292 ApplyConfiguration = 3
1293 }
1294}
1295
1296wire_enum! {
1297 /// Policy used to transport connected-call DTMF digits.
1298 pub enum DtmfMode {
1299 Auto = 0,
1300 Rfc2833 = 1,
1301 Skinny = 2
1302 }
1303}
1304
1305wire_enum! {
1306 /// Call-forwarding condition represented by a forwarding entry.
1307 pub enum CallForwardKind {
1308 None = 0,
1309 All = 1,
1310 Busy = 2,
1311 NoAnswer = 3
1312 }
1313}
1314
1315wire_enum! {
1316 /// Precedence assigned to a call or media request.
1317 pub enum CallPriority {
1318 Highest = 0,
1319 High = 1,
1320 Medium = 2,
1321 Low = 3,
1322 Normal = 4
1323 }
1324}
1325
1326wire_enum! {
1327 /// Ordered status-line notification slots. Larger values take precedence.
1328 pub enum NotificationPriority {
1329 Idle = 0,
1330 Voicemail = 1,
1331 Monitor = 2,
1332 Privacy = 3,
1333 DoNotDisturb = 4,
1334 CallForward = 5,
1335 Timed = 6
1336 }
1337}
1338
1339wire_enum! {
1340 /// Visibility policy for call-information presentation.
1341 pub enum CallInfoVisibility {
1342 Default = 0,
1343 Collapsed = 1,
1344 Hidden = 2
1345 }
1346}
1347
1348wire_enum! {
1349 /// Security indication presented for a call.
1350 pub enum CallSecurityState {
1351 UnknownState = 0,
1352 NotAuthenticated = 1,
1353 Authenticated = 2
1354 }
1355}
1356
1357wire_enum! {
1358 /// Busy-lamp-field availability reported by a subscription notification.
1359 pub enum BusyLampFieldState {
1360 UnknownState = 0,
1361 Idle = 1,
1362 InUse = 2,
1363 DoNotDisturb = 3,
1364 Alerting = 4
1365 }
1366}
1367
1368wire_enum! {
1369 /// Result of a phone-book/BLF subscription request.
1370 pub enum SubscriptionCause {
1371 Ok = 0,
1372 RouteFailure = 1,
1373 AuthenticationFailure = 2,
1374 Timeout = 3,
1375 TrunkTerminated = 4,
1376 TrunkForbidden = 5,
1377 Throttled = 6
1378 }
1379}
1380
1381wire_enum! {
1382 /// Picture-size profile used by a video capability.
1383 pub enum VideoFormat {
1384 Undefined = 0,
1385 Sqcif = 1,
1386 Qcif = 2,
1387 Cif = 3,
1388 Cif4 = 4,
1389 Cif16 = 5,
1390 Custom = 6,
1391 ProtocolUnknown = 232
1392 }
1393}
1394
1395wire_enum! {
1396 /// Codec-specific operation carried by a miscellaneous multimedia command.
1397 pub enum MiscCommandType {
1398 VideoFreezePicture = 0,
1399 VideoFastUpdatePicture = 1,
1400 VideoFastUpdateGob = 2,
1401 VideoFastUpdateMacroblock = 3,
1402 LostPicture = 4,
1403 LostPartialPicture = 5,
1404 RecoveryReferencePicture = 6,
1405 TemporalSpatialTradeoff = 7
1406 }
1407}
1408
1409wire_enum! {
1410 /// Station echo-cancellation policy for an audio channel.
1411 pub enum EchoCancellation {
1412 Off = 0,
1413 On = 1
1414 }
1415}
1416
1417wire_enum! {
1418 /// Station-side voice-activity detection/silence suppression policy.
1419 pub enum SilenceSuppression {
1420 Off = 0,
1421 On = 1
1422 }
1423}
1424
1425wire_enum! {
1426 /// Bit-rate selector occupying the codec qualifier word for G.723.
1427 pub enum G723BitRate {
1428 Rate5_3 = 1,
1429 Rate6_3 = 2
1430 }
1431}
1432
1433wire_enum! {
1434 /// Station result attached to an unregister acknowledgement.
1435 pub enum UnregisterStatus {
1436 Ok = 0,
1437 Error = 1,
1438 ActiveCall = 2
1439 }
1440}
1441
1442wire_enum! {
1443 /// Button definitions use the stimulus values plus provisioning-only
1444 /// placeholder values in the 0xf1..=0xf5 range.
1445 pub enum ButtonType {
1446 /// An unassigned physical slot that should not present an actionable station key.
1447 Unused = 0x00,
1448 /// A key that redials the most recently dialed destination.
1449 LastNumberRedial = 0x01,
1450 /// A programmable key bound to a configured speed-dial destination.
1451 SpeedDial = 0x02,
1452 /// The station hold key used to hold or resume the current call.
1453 Hold = 0x03,
1454 /// The station transfer key used to start or complete a call transfer.
1455 Transfer = 0x04,
1456 /// A feature key for configuring or toggling call-forward-all.
1457 ForwardAll = 0x05,
1458 /// A feature key for configuring or toggling call-forward-on-busy.
1459 ForwardBusy = 0x06,
1460 /// A feature key for configuring or toggling call-forward-on-no-answer.
1461 ForwardNoAnswer = 0x07,
1462 /// A legacy display-oriented station key whose behavior is phone-model specific.
1463 Display = 0x08,
1464 /// A line-appearance key representing a directory number and its calls.
1465 Line = 0x09,
1466 /// A key launching the T.120 text-chat application.
1467 T120Chat = 0x0a,
1468 /// A key launching the T.120 shared-whiteboard application.
1469 T120Whiteboard = 0x0b,
1470 /// A key launching T.120 application sharing.
1471 T120ApplicationSharing = 0x0c,
1472 /// A key launching T.120 conference file transfer.
1473 T120FileTransfer = 0x0d,
1474 /// A station key assigned to video control.
1475 Video = 0x0e,
1476 /// A programmable voicemail-access key, commonly paired with message-waiting indication.
1477 Voicemail = 0x0f,
1478 /// A combined key that answers an offered call or releases the current call.
1479 AnswerRelease = 0x10,
1480 /// A feature key controlling automatic call answer.
1481 AutoAnswer = 0x11,
1482 /// A key that selects calls for transfer, conference, or other multi-call operations.
1483 Select = 0x12,
1484 /// A generic programmable feature key whose concrete action is supplied by provisioning.
1485 Feature = 0x13,
1486 /// A programmable key opening a provisioned phone-service URL.
1487 ServiceUrl = 0x14,
1488 /// A speed-dial key whose lamp also displays the target's busy-lamp-field state.
1489 BlfSpeedDial = 0x15,
1490 /// A feature key that parks a call at a specified destination.
1491 DirectedPark = 0x16,
1492 /// A key representing an intercom appearance or intercom destination.
1493 Intercom = 0x17,
1494 /// A feature key for malicious-call identification.
1495 MaliciousCall = 0x1b,
1496 /// Application-defined programmable key B1; SCCP assigns no universal action.
1497 GenericAppB1 = 0x21,
1498 /// Application-defined programmable key B2; SCCP assigns no universal action.
1499 GenericAppB2 = 0x22,
1500 /// Application-defined programmable key B3; SCCP assigns no universal action.
1501 GenericAppB3 = 0x23,
1502 /// Application-defined programmable key B4; SCCP assigns no universal action.
1503 GenericAppB4 = 0x24,
1504 /// Application-defined programmable key B5; SCCP assigns no universal action.
1505 GenericAppB5 = 0x25,
1506 /// A generic feature key whose lamp can display multiple blink states.
1507 MultiblinkFeature = 0x26,
1508 /// A feature key entering the dial-in Meet-Me conference workflow.
1509 MeetMeConference = 0x7b,
1510 /// The station conference key used to build or manage an ad-hoc conference.
1511 Conference = 0x7d,
1512 /// A feature key that parks the current call.
1513 CallPark = 0x7e,
1514 /// A feature key that answers a ringing call in the configured pickup scope.
1515 CallPickup = 0x7f,
1516 /// A feature key for group pickup outside the station's immediate pickup group.
1517 GroupCallPickup = 0x80,
1518 /// A feature key for extension-mobility login, logout, or appearance control.
1519 Mobility = 0x81,
1520 /// A feature key that exposes and changes do-not-disturb state.
1521 DoNotDisturb = 0x82,
1522 /// A feature key opening the conference participant list.
1523 ConferenceList = 0x83,
1524 /// A conference key that removes the most recently added participant.
1525 RemoveLastParticipant = 0x84,
1526 /// A feature key launching Cisco's call-quality reporting tool.
1527 QualityReportTool = 0x85,
1528 /// A feature key requesting callback when a busy or unavailable destination becomes reachable.
1529 Callback = 0x86,
1530 /// A feature key for Cisco's alternate call-pickup workflow.
1531 OtherPickup = 0x87,
1532 /// A feature key that changes the call's video mode.
1533 VideoMode = 0x88,
1534 /// A key that creates a new outbound call appearance.
1535 NewCall = 0x89,
1536 /// A key that releases the selected call.
1537 EndCall = 0x8a,
1538 /// A feature key that logs the station into or out of a hunt group.
1539 HuntGroupLogin = 0x8b,
1540 /// A feature key for Cisco call-queuing behavior.
1541 Queuing = 0x8f,
1542 /// A feature key opening a parking-lot view or retrieval workflow.
1543 ParkingLot = 0xc0,
1544 /// The station's fixed Messages key rather than a programmable voicemail slot.
1545 Messages = 0xc2,
1546 /// The station's fixed Directories key.
1547 Directory = 0xc3,
1548 /// The station's fixed Applications or Services key.
1549 Application = 0xc5,
1550 /// The station's fixed headset-control key.
1551 Headset = 0xc6,
1552 /// A template entry representing the physical dialing keypad rather than one programmable key.
1553 Keypad = 0xf0,
1554 /// Cisco template placeholder for a multi-purpose programmable position.
1555 /// Provisioning is expected to replace it with a concrete button definition.
1556 PlaceholderMulti = 0xf1,
1557 /// Cisco template placeholder reserved for a line appearance.
1558 /// Provisioning is expected to replace it with a concrete line definition.
1559 PlaceholderLine = 0xf2,
1560 /// Cisco template placeholder reserved for a speed dial.
1561 /// Provisioning is expected to replace it with a concrete speed-dial definition.
1562 PlaceholderSpeedDial = 0xf3,
1563 /// Cisco template placeholder reserved for a monitored hint or BLF target.
1564 /// Provisioning is expected to replace it with a concrete definition.
1565 PlaceholderHint = 0xf4,
1566 /// Cisco template placeholder reserved for abbreviated dialing.
1567 /// Provisioning is expected to replace it with a concrete definition.
1568 PlaceholderAbbreviatedDial = 0xf5,
1569 /// A station control for acoustic echo-cancellation behavior.
1570 AcousticEchoCancellation = 0xfd,
1571 /// A button definition Cisco marks as undefined; it is distinct from an intentionally unused slot.
1572 Undefined = 0xff
1573 }
1574}
1575
1576wire_enum! {
1577 /// SRTP encryption algorithm selected for a media channel.
1578 pub enum EncryptionMethod {
1579 None = 0,
1580 Aes128HmacSha1_32 = 1,
1581 Aes128HmacSha1_80 = 2,
1582 F8_128HmacSha1_32 = 3,
1583 F8_128HmacSha1_80 = 4,
1584 AeadAes128Gcm = 5,
1585 AeadAes256Gcm = 6
1586 }
1587}
1588
1589wire_enum! {
1590 /// SRTP algorithm support advertised by a media capability.
1591 pub enum EncryptionCapability {
1592 NotCapable = 0,
1593 Capable = 1
1594 }
1595}
1596
1597wire_enum! {
1598 /// History bucket assigned to a completed call.
1599 pub enum CallHistoryDisposition {
1600 Ignore = 0,
1601 Placed = 1,
1602 Received = 2,
1603 Missed = 3,
1604 ProtocolUnknown = 0xffff_fffe
1605 }
1606}
1607
1608wire_enum! {
1609 /// Station speaker state selected by call control.
1610 pub enum SpeakerMode {
1611 On = 1,
1612 Off = 2
1613 }
1614}
1615
1616wire_enum! {
1617 /// Station microphone state selected by call control.
1618 pub enum MicrophoneMode {
1619 On = 1,
1620 Off = 2
1621 }
1622}
1623
1624wire_enum! {
1625 /// Media resource allocated for a station-managed conference.
1626 pub enum ConferenceResourceType {
1627 Conference = 0,
1628 InteractiveVoiceResponse = 1
1629 }
1630}
1631
1632wire_enum! {
1633 /// Outcome returned by conference creation.
1634 pub enum CreateConferenceResult {
1635 Ok = 0,
1636 ResourceNotAvailable = 1,
1637 ConferenceAlreadyExists = 2,
1638 SystemError = 3
1639 }
1640}
1641
1642wire_enum! {
1643 /// Outcome returned by conference deletion.
1644 pub enum DeleteConferenceResult {
1645 Ok = 0,
1646 ConferenceDoesNotExist = 1,
1647 SystemError = 2
1648 }
1649}
1650
1651wire_enum! {
1652 /// Outcome returned by conference modification.
1653 pub enum ModifyConferenceResult {
1654 Ok = 0,
1655 ResourceNotAvailable = 1,
1656 ConferenceDoesNotExist = 2,
1657 InvalidParameter = 3,
1658 MoreActiveCallsThanReserved = 4,
1659 InvalidResourceType = 5,
1660 SystemError = 6
1661 }
1662}
1663
1664wire_enum! {
1665 /// Outcome returned when attaching a conference participant.
1666 pub enum AddParticipantResult {
1667 Ok = 0,
1668 ResourceNotAvailable = 1,
1669 ConferenceDoesNotExist = 2,
1670 DuplicateCallReference = 3,
1671 SystemError = 4
1672 }
1673}
1674
1675wire_enum! {
1676 /// Outcome returned by a conference-participant audit.
1677 pub enum AuditParticipantResult {
1678 Ok = 0,
1679 ConferenceDoesNotExist = 1
1680 }
1681}
1682
1683bitflags! {
1684 /// Identity fields a station must suppress for a conference participant.
1685 #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1686 pub struct PartyInformationRestrictions: u32 {
1687 const CALLING_NAME = 1 << 0;
1688 const CALLING_NUMBER = 1 << 1;
1689 const CALLED_NAME = 1 << 2;
1690 const CALLED_NUMBER = 1 << 3;
1691 const ORIGINAL_CALLED_NAME = 1 << 4;
1692 const ORIGINAL_CALLED_NUMBER = 1 << 5;
1693 const LAST_REDIRECT_NAME = 1 << 6;
1694 const LAST_REDIRECT_NUMBER = 1 << 7;
1695 }
1696}
1697
1698/// Negotiated inputs that select station-facing message layouts.
1699#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1700pub struct StationSessionContext {
1701 /// Negotiated frame and payload version.
1702 pub protocol: ProtocolVersion,
1703 /// Station feature bits that can select layouts independently of version.
1704 pub features: PhoneFeatures,
1705}
1706
1707impl StationSessionContext {
1708 /// Creates the layout-selection context for a registered station session.
1709 pub const fn new(protocol: ProtocolVersion, features: PhoneFeatures) -> Self {
1710 Self { protocol, features }
1711 }
1712
1713 /// Reports whether general UI responses use their dynamic string layouts.
1714 pub const fn uses_dynamic_general_ui(self) -> bool {
1715 self.protocol.uses_dynamic_general_ui()
1716 || self.features.contains(PhoneFeatures::DYNAMIC_MESSAGES)
1717 }
1718
1719 /// Reports whether feature status uses its dynamic response identifier.
1720 pub const fn uses_dynamic_feature_status(self) -> bool {
1721 self.features.contains(PhoneFeatures::DYNAMIC_MESSAGES)
1722 }
1723
1724 /// Reports whether speed-dial status uses the dynamic identifier and
1725 /// variable-string payload selected by the registered station session.
1726 pub const fn uses_dynamic_speed_dial_status(self) -> bool {
1727 self.protocol.uses_dynamic_speed_dial_status()
1728 || self.features.contains(PhoneFeatures::DYNAMIC_MESSAGES)
1729 }
1730
1731 /// Returns the call-info string layout selected by the negotiated version.
1732 pub const fn dynamic_call_info_layout(self) -> DynamicCallInfoLayout {
1733 self.protocol.dynamic_call_info_layout()
1734 }
1735
1736 /// Returns the dynamic service-URL string count selected by the session.
1737 pub const fn dynamic_service_url_string_count(self) -> usize {
1738 if self.protocol.wire() >= ProtocolVersion::V19.wire() {
1739 3
1740 } else {
1741 2
1742 }
1743 }
1744}
1745
1746impl From<ProtocolVersion> for StationSessionContext {
1747 fn from(protocol: ProtocolVersion) -> Self {
1748 Self::new(protocol, PhoneFeatures::empty())
1749 }
1750}
1751
1752/// Dynamic RTP payload type used for telephone-event DTMF when a station is
1753/// configured to send digits through the media stream.
1754pub const RFC2833_TELEPHONE_EVENT_PAYLOAD: u8 = 101;
1755
1756impl DtmfMode {
1757 /// Resolves the automatic policy against the feature bits advertised by
1758 /// the registered station. Explicit policies are always preserved.
1759 pub const fn resolve(self, features: PhoneFeatures) -> Self {
1760 match self {
1761 Self::Auto if features.contains(PhoneFeatures::RFC2833) => Self::Rfc2833,
1762 Self::Auto => Self::Skinny,
1763 explicit => explicit,
1764 }
1765 }
1766
1767 /// Returns the wire payload type for the resolved policy. A zero payload
1768 /// tells the station to report connected-call digits as signaling events.
1769 pub const fn telephone_event_payload(self, features: PhoneFeatures) -> u8 {
1770 match self.resolve(features) {
1771 Self::Rfc2833 => RFC2833_TELEPHONE_EVENT_PAYLOAD,
1772 Self::Skinny | Self::Unknown(_) => 0,
1773 Self::Auto => unreachable!(),
1774 }
1775 }
1776}
1777
1778bitflags! {
1779 /// Feature flags advertised in the three-byte station protocol field.
1780 #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1781 pub struct PhoneFeatures: u32 {
1782 // The low byte contains the protocol version. Feature bits occupy the
1783 // following three bytes.
1784 const PORT_REQUEST = 1 << 17;
1785 const UTF8 = 1 << 20;
1786 const DYNAMIC_MESSAGES = 1 << 24;
1787 const RFC2833 = 1 << 26;
1788 const INTERNAL_CM_MEDIA = 1 << 28;
1789 const MULTIPLE_ACTIVE_CALLS = 1 << 30;
1790 const ABBREVIATED_DIAL = 1 << 31;
1791 }
1792}
1793
1794bitflags! {
1795 /// Permitted media directions in a capability entry.
1796 #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1797 pub struct ReceiveTransmit: u32 {
1798 const RECEIVE = 1;
1799 const TRANSMIT = 2;
1800 }
1801}
1802
1803#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1804/// One keypad digit, including the extended A-D symbols.
1805pub enum Digit {
1806 /// A numeric digit; valid decoded values are zero through nine.
1807 Number(u8),
1808 Star,
1809 Pound,
1810 A,
1811 B,
1812 C,
1813 D,
1814 /// An unrecognized keypad word retained from the wire.
1815 Unknown(u32),
1816}
1817
1818impl Digit {
1819 /// Converts a keypad wire word to a typed digit without discarding unknowns.
1820 pub const fn from_keypad(value: u32) -> Self {
1821 match value {
1822 0..=9 => Self::Number(value as u8),
1823 10 => Self::Star,
1824 11 => Self::Pound,
1825 12 => Self::A,
1826 13 => Self::B,
1827 14 => Self::C,
1828 15 => Self::D,
1829 value => Self::Unknown(value),
1830 }
1831 }
1832
1833 /// Returns the numeric keypad word used on the wire.
1834 pub const fn keypad_value(self) -> u32 {
1835 match self {
1836 Self::Number(number) => number as u32,
1837 Self::Star => 10,
1838 Self::Pound => 11,
1839 Self::A => 12,
1840 Self::B => 13,
1841 Self::C => 14,
1842 Self::D => 15,
1843 Self::Unknown(value) => value,
1844 }
1845 }
1846
1847 /// Returns the printable digit, or `?` for an invalid/unknown value.
1848 pub fn as_char(self) -> char {
1849 match self {
1850 Self::Number(n) if n <= 9 => char::from(b'0' + n),
1851 Self::Number(_) => '?',
1852 Self::Star => '*',
1853 Self::Pound => '#',
1854 Self::A => 'A',
1855 Self::B => 'B',
1856 Self::C => 'C',
1857 Self::D => 'D',
1858 Self::Unknown(_) => '?',
1859 }
1860 }
1861}
1862
1863impl From<u32> for Digit {
1864 fn from(value: u32) -> Self {
1865 Self::from_keypad(value)
1866 }
1867}
1868
1869impl From<Digit> for u32 {
1870 fn from(value: Digit) -> Self {
1871 value.keypad_value()
1872 }
1873}
1874
1875#[cfg(test)]
1876mod tests {
1877 use super::*;
1878
1879 #[test]
1880 fn protocol_versions_select_layout_profiles() {
1881 assert_eq!(ProtocolVersion::new(3).unwrap().layout(), LayoutProfile::V3);
1882 assert_eq!(
1883 ProtocolVersion::new(14).unwrap().layout(),
1884 LayoutProfile::V11
1885 );
1886 assert_eq!(ProtocolVersion::new(13).unwrap(), ProtocolVersion::V13);
1887 assert_eq!(ProtocolVersion::new(14).unwrap(), ProtocolVersion::V14);
1888 assert_eq!(
1889 ProtocolVersion::new(18).unwrap().layout(),
1890 LayoutProfile::V18
1891 );
1892 assert_eq!(
1893 ProtocolVersion::new(21).unwrap().layout(),
1894 LayoutProfile::V19
1895 );
1896 assert_eq!(
1897 ProtocolVersion::new(22).unwrap().layout(),
1898 LayoutProfile::V22
1899 );
1900 assert_eq!(
1901 ProtocolVersion::negotiate(99).unwrap(),
1902 ProtocolVersion::V22
1903 );
1904 assert!(ProtocolVersion::new(2).is_err());
1905 }
1906
1907 #[test]
1908 fn dynamic_station_layout_boundaries_follow_session_negotiation() {
1909 assert!(!ProtocolVersion::V8.uses_dynamic_general_ui());
1910 assert!(ProtocolVersion::V9.uses_dynamic_general_ui());
1911 assert!(!ProtocolVersion::V8.uses_dynamic_speed_dial_status());
1912 assert!(ProtocolVersion::V9.uses_dynamic_speed_dial_status());
1913
1914 assert_eq!(
1915 ProtocolVersion::V15.dynamic_call_info_layout(),
1916 DynamicCallInfoLayout::Fields12
1917 );
1918 assert_eq!(
1919 ProtocolVersion::V16.dynamic_call_info_layout(),
1920 DynamicCallInfoLayout::Fields13
1921 );
1922 assert_eq!(
1923 ProtocolVersion::V18.dynamic_call_info_layout(),
1924 DynamicCallInfoLayout::Fields13
1925 );
1926 assert_eq!(
1927 ProtocolVersion::V19.dynamic_call_info_layout(),
1928 DynamicCallInfoLayout::Fields15
1929 );
1930
1931 let baseline = StationSessionContext::from(ProtocolVersion::V8);
1932 assert!(!baseline.uses_dynamic_general_ui());
1933 assert!(!baseline.uses_dynamic_feature_status());
1934 let negotiated =
1935 StationSessionContext::new(ProtocolVersion::V8, PhoneFeatures::DYNAMIC_MESSAGES);
1936 assert!(negotiated.uses_dynamic_general_ui());
1937 assert!(negotiated.uses_dynamic_feature_status());
1938 assert!(negotiated.uses_dynamic_speed_dial_status());
1939 }
1940
1941 #[test]
1942 fn extensible_values_preserve_unknown_numbers() {
1943 let codec = Codec::from(0xfeed);
1944 assert_eq!(codec, Codec::Unknown(0xfeed));
1945 assert_eq!(codec.wire_value(), 0xfeed);
1946 let state = CallState::from(1000);
1947 assert_eq!(state.wire_value(), 1000);
1948 }
1949
1950 #[test]
1951 fn soft_key_events_are_template_positions() {
1952 assert_eq!(SoftKey::from(1), SoftKey::Redial);
1953 assert_eq!(SoftKey::from(13), SoftKey::Conference);
1954 assert_eq!(SoftKey::from(32), SoftKey::Dial);
1955 assert_eq!(SoftKey::from(201), SoftKey::Unknown(201));
1956 }
1957
1958 #[test]
1959 fn automatic_dtmf_uses_only_an_advertised_rfc2833_capability() {
1960 assert_eq!(
1961 DtmfMode::Auto.resolve(PhoneFeatures::RFC2833),
1962 DtmfMode::Rfc2833
1963 );
1964 assert_eq!(
1965 DtmfMode::Auto.telephone_event_payload(PhoneFeatures::RFC2833),
1966 RFC2833_TELEPHONE_EVENT_PAYLOAD
1967 );
1968 assert_eq!(
1969 DtmfMode::Auto.resolve(PhoneFeatures::empty()),
1970 DtmfMode::Skinny
1971 );
1972 assert_eq!(
1973 DtmfMode::Auto.telephone_event_payload(PhoneFeatures::empty()),
1974 0
1975 );
1976 assert_eq!(
1977 DtmfMode::Skinny.telephone_event_payload(PhoneFeatures::RFC2833),
1978 0
1979 );
1980 assert_eq!(
1981 DtmfMode::Rfc2833.telephone_event_payload(PhoneFeatures::empty()),
1982 RFC2833_TELEPHONE_EVENT_PAYLOAD
1983 );
1984 }
1985
1986 #[test]
1987 fn phone_feature_bits_match_the_three_register_feature_bytes() {
1988 // CP-7961G firmware SCCP41.9-4-2SR3-1S advertises protocol/features
1989 // 16 00 72 85. The final feature byte carries dynamic messages,
1990 // RFC2833, and abbreviated dial.
1991 let advertised = PhoneFeatures::from_bits_retain(0x8572_0000);
1992 assert!(advertised.contains(PhoneFeatures::PORT_REQUEST));
1993 assert!(advertised.contains(PhoneFeatures::UTF8));
1994 assert!(advertised.contains(PhoneFeatures::DYNAMIC_MESSAGES));
1995 assert!(advertised.contains(PhoneFeatures::RFC2833));
1996 assert!(advertised.contains(PhoneFeatures::ABBREVIATED_DIAL));
1997 assert!(!advertised.contains(PhoneFeatures::INTERNAL_CM_MEDIA));
1998 assert!(!advertised.contains(PhoneFeatures::MULTIPLE_ACTIVE_CALLS));
1999 assert!(
2000 PhoneFeatures::from_bits_retain(1 << 30).contains(PhoneFeatures::MULTIPLE_ACTIVE_CALLS)
2001 );
2002 }
2003
2004 #[test]
2005 fn every_named_wire_enum_value_is_unique_and_round_trips() {
2006 macro_rules! assert_wire_enum {
2007 ($type:ty) => {{
2008 let mut values = std::collections::HashSet::new();
2009 for value in <$type>::ALL_KNOWN {
2010 assert!(
2011 values.insert(value.wire_value()),
2012 "duplicate {} value {value:?}",
2013 stringify!($type)
2014 );
2015 assert_eq!(<$type>::from(value.wire_value()), *value);
2016 assert!(value.is_known());
2017 }
2018 }};
2019 }
2020
2021 assert_wire_enum!(DeviceType);
2022 assert_wire_enum!(Codec);
2023 assert_wire_enum!(CallState);
2024 assert_wire_enum!(CallType);
2025 assert_wire_enum!(AlarmSeverity);
2026 assert_wire_enum!(MediaStatus);
2027 assert_wire_enum!(Stimulus);
2028 assert_wire_enum!(SoftKey);
2029 assert_wire_enum!(KeyMode);
2030 assert_wire_enum!(RingerMode);
2031 assert_wire_enum!(RingDuration);
2032 assert_wire_enum!(LampMode);
2033 assert_wire_enum!(Tone);
2034 assert_wire_enum!(ToneDirection);
2035 assert_wire_enum!(MediaPathId);
2036 assert_wire_enum!(MediaPathEvent);
2037 assert_wire_enum!(MediaPathCapability);
2038 assert_wire_enum!(MediaType);
2039 assert_wire_enum!(MediaTransport);
2040 assert_wire_enum!(QosDirection);
2041 assert_wire_enum!(QosReservationStyle);
2042 assert_wire_enum!(QosErrorCode);
2043 assert_wire_enum!(RsvpErrorCode);
2044 assert_wire_enum!(EndOfAnnouncementAck);
2045 assert_wire_enum!(AnnouncementPlayMode);
2046 assert_wire_enum!(AnnouncementPlayStatus);
2047 assert_wire_enum!(MessageWaitingResult);
2048 assert_wire_enum!(IpAddressType);
2049 assert_wire_enum!(ResetType);
2050 assert_wire_enum!(DtmfMode);
2051 assert_wire_enum!(CallForwardKind);
2052 assert_wire_enum!(CallPriority);
2053 assert_wire_enum!(NotificationPriority);
2054 assert_wire_enum!(CallInfoVisibility);
2055 assert_wire_enum!(CallSecurityState);
2056 assert_wire_enum!(BusyLampFieldState);
2057 assert_wire_enum!(SubscriptionCause);
2058 assert_wire_enum!(VideoFormat);
2059 assert_wire_enum!(MiscCommandType);
2060 assert_wire_enum!(EchoCancellation);
2061 assert_wire_enum!(SilenceSuppression);
2062 assert_wire_enum!(G723BitRate);
2063 assert_wire_enum!(UnregisterStatus);
2064 assert_wire_enum!(ButtonType);
2065 assert_wire_enum!(EncryptionMethod);
2066 assert_wire_enum!(EncryptionCapability);
2067 assert_wire_enum!(CallHistoryDisposition);
2068 assert_wire_enum!(SpeakerMode);
2069 assert_wire_enum!(MicrophoneMode);
2070 assert_wire_enum!(ConferenceResourceType);
2071 assert_wire_enum!(CreateConferenceResult);
2072 assert_wire_enum!(DeleteConferenceResult);
2073 assert_wire_enum!(ModifyConferenceResult);
2074 assert_wire_enum!(AddParticipantResult);
2075 assert_wire_enum!(AuditParticipantResult);
2076 }
2077
2078 #[test]
2079 fn codec_metadata_covers_static_and_cisco_dynamic_payloads() {
2080 assert_eq!(Codec::Pcmu.rtp_payload_type(), Some(0));
2081 assert_eq!(Codec::G711Ulaw56k.rtp_payload_type(), Some(0));
2082 assert_eq!(Codec::Pcma.rtp_payload_type(), Some(8));
2083 assert_eq!(Codec::G72248k.rtp_payload_type(), Some(9));
2084 assert_eq!(Codec::Wideband256k.rtp_payload_type(), Some(25));
2085 assert_eq!(Codec::Ilbc.rtp_payload_type(), Some(97));
2086 assert_eq!(Codec::G7221_32k.rtp_payload_type(), Some(102));
2087 assert_eq!(Codec::Opus.rtp_payload_type(), Some(107));
2088 assert_eq!(Codec::G726_32k.rtp_payload_type(), Some(112));
2089 assert_eq!(Codec::Wideband256k.sample_rate(), Some(16_000));
2090 assert_eq!(Codec::H264.kind(), CodecKind::Video);
2091 assert_eq!(Codec::ClearChannel.kind(), CodecKind::Data);
2092 }
2093}