1use std::fmt;
9
10use bitflags::bitflags;
11
12use super::wire::CodecError;
13
14macro_rules! wire_enum {
15 ($(#[$meta:meta])* pub enum $name:ident { $($variant:ident = $value:expr),+ $(,)? }) => {
16 $(#[$meta])*
17 #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
18 pub enum $name {
19 $($variant,)+
20 Unknown(u32),
21 }
22
23 impl $name {
24 pub const ALL_KNOWN: &'static [Self] = &[$(Self::$variant,)+];
25
26 pub const fn wire_value(self) -> u32 {
27 match self {
28 $(Self::$variant => $value,)+
29 Self::Unknown(value) => value,
30 }
31 }
32
33 pub const fn is_known(self) -> bool {
34 !matches!(self, Self::Unknown(_))
35 }
36 }
37
38 impl From<u32> for $name {
39 fn from(value: u32) -> Self {
40 match value {
41 $($value => Self::$variant,)+
42 value => Self::Unknown(value),
43 }
44 }
45 }
46
47 impl From<$name> for u32 {
48 fn from(value: $name) -> Self {
49 value.wire_value()
50 }
51 }
52 };
53}
54
55#[derive(Clone, Copy, Eq, Hash, Ord, PartialEq, PartialOrd)]
57pub struct ProtocolVersion(u8);
58
59impl ProtocolVersion {
60 pub const MIN: Self = Self(3);
61 pub const MAX: Self = Self(22);
62 pub const V3: Self = Self(3);
63 pub const V5: Self = Self(5);
64 pub const V7: Self = Self(7);
65 pub const V8: Self = Self(8);
66 pub const V9: Self = Self(9);
67 pub const V10: Self = Self(10);
68 pub const V11: Self = Self(11);
69 pub const V12: Self = Self(12);
70 pub const V13: Self = Self(13);
71 pub const V14: Self = Self(14);
72 pub const V15: Self = Self(15);
73 pub const V16: Self = Self(16);
74 pub const V17: Self = Self(17);
75 pub const V18: Self = Self(18);
76 pub const V19: Self = Self(19);
77 pub const V20: Self = Self(20);
78 pub const V21: Self = Self(21);
79 pub const V22: Self = Self(22);
80
81 pub fn new(value: u32) -> Result<Self, CodecError> {
83 let value = u8::try_from(value).map_err(|_| CodecError::UnsupportedProtocol(value))?;
84 if !(Self::MIN.0..=Self::MAX.0).contains(&value) {
85 return Err(CodecError::UnsupportedProtocol(u32::from(value)));
86 }
87 Ok(Self(value))
88 }
89
90 pub fn negotiate(advertised: u32) -> Result<Self, CodecError> {
92 if advertised < u32::from(Self::MIN.0) {
93 return Err(CodecError::UnsupportedProtocol(advertised));
94 }
95 Self::new(advertised.min(u32::from(Self::MAX.0)))
96 }
97
98 pub const fn wire(self) -> u32 {
99 self.0 as u32
100 }
101
102 pub const fn layout(self) -> LayoutProfile {
104 match self.0 {
105 3..=4 => LayoutProfile::V3,
106 5..=7 => LayoutProfile::V5,
107 8..=10 => LayoutProfile::V8,
108 11..=14 => LayoutProfile::V11,
109 15 => LayoutProfile::V15,
110 16 => LayoutProfile::V16,
111 17 => LayoutProfile::V17,
112 18 => LayoutProfile::V18,
113 19..=21 => LayoutProfile::V19,
114 _ => LayoutProfile::V22,
115 }
116 }
117
118 pub const fn uses_dynamic_general_ui(self) -> bool {
120 self.0 >= Self::V9.0
121 }
122
123 pub const fn dynamic_call_info_layout(self) -> DynamicCallInfoLayout {
125 match self.0 {
126 ..=15 => DynamicCallInfoLayout::Fields12,
127 16..=18 => DynamicCallInfoLayout::Fields13,
128 _ => DynamicCallInfoLayout::Fields15,
129 }
130 }
131
132 pub const fn uses_dynamic_speed_dial_status(self) -> bool {
134 self.0 >= Self::V15.0
135 }
136}
137
138#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
140pub enum DynamicCallInfoLayout {
141 Fields12,
142 Fields13,
143 Fields15,
144}
145
146impl DynamicCallInfoLayout {
147 pub const fn string_count(self) -> usize {
148 match self {
149 Self::Fields12 => 12,
150 Self::Fields13 => 13,
151 Self::Fields15 => 15,
152 }
153 }
154}
155
156impl fmt::Debug for ProtocolVersion {
157 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158 write!(f, "V{}", self.0)
159 }
160}
161
162impl fmt::Display for ProtocolVersion {
163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164 write!(f, "v{}", self.0)
165 }
166}
167
168impl TryFrom<u32> for ProtocolVersion {
169 type Error = CodecError;
170
171 fn try_from(value: u32) -> Result<Self, Self::Error> {
172 Self::new(value)
173 }
174}
175
176impl From<ProtocolVersion> for u32 {
177 fn from(value: ProtocolVersion) -> Self {
178 value.wire()
179 }
180}
181
182#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
184pub enum LayoutProfile {
185 V3,
187 V5,
189 V8,
191 V11,
193 V15,
195 V16,
197 V17,
199 V18,
201 V19,
203 V22,
205}
206
207wire_enum! {
208 pub enum DeviceType {
210 Undefined = 0,
211 Phone30SpPlus = 1,
212 Phone12SpPlus = 2,
213 Phone12Sp = 3,
214 Phone12 = 4,
215 Phone30Vip = 5,
216 Cisco7910 = 6,
217 Cisco7960 = 7,
218 Cisco7940 = 8,
219 Cisco7935 = 9,
220 Vgc = 10,
221 Ata186 = 12,
222 Ata188 = 13,
223 Virtual30SpPlus = 20,
224 PhoneApplication = 21,
225 AnalogAccess = 30,
226 DigitalAccessPri = 40,
227 DigitalAccessT1 = 41,
228 DigitalAccessTitan2 = 42,
229 AnalogAccessElvis = 43,
230 DigitalAccessLennon = 47,
231 ConferenceBridge = 50,
232 ConferenceBridgeYoko = 51,
233 ConferenceBridgeDixieland = 52,
234 ConferenceBridgeSummit = 53,
235 H225 = 60,
236 H323Phone = 61,
237 H323Trunk = 62,
238 MusicOnHold = 70,
239 Pilot = 71,
240 TapiPort = 72,
241 TapiRoutePoint = 73,
242 VoiceInbox = 80,
243 VoiceInboxAdmin = 81,
244 LineAnnunciator = 82,
245 SoftwareMtpDixieland = 83,
246 CiscoMediaServer = 84,
247 ConferenceBridgeFlint = 85,
248 RouteList = 90,
249 LoadSimulator = 100,
250 MediaTerminationPoint = 110,
251 MediaTerminationPointYoko = 111,
252 MediaTerminationPointDixieland = 112,
253 MediaTerminationPointSummit = 113,
254 Cisco7941 = 115,
255 Cisco7971 = 119,
256 MgcpStation = 120,
257 MgcpTrunk = 121,
258 RasProxy = 122,
259 CiscoAddon7914 = 124,
260 Trunk = 125,
261 Annunciator = 126,
262 MonitorBridge = 127,
263 Recorder = 128,
264 MonitorBridgeYoko = 129,
265 SipTrunk = 131,
266 CiscoAddon7915_12 = 227,
267 CiscoAddon7915_24 = 228,
268 CiscoAddon7916_12 = 229,
269 CiscoAddon7916_24 = 230,
270 NokiaESeries = 275,
271 Cisco7985 = 302,
272 Cisco7911 = 307,
273 Cisco7961Ge = 308,
274 Cisco7941Ge = 309,
275 Cisco7931 = 348,
276 Cisco7921 = 365,
277 Cisco7906 = 369,
278 NokiaIcc = 376,
279 Cisco7962 = 404,
280 Cisco7937 = 431,
281 Cisco7942 = 434,
282 Cisco7945 = 435,
283 Cisco7965 = 436,
284 Cisco7975 = 437,
285 Cisco7925 = 484,
286 Cisco6921 = 495,
287 Cisco6941 = 496,
288 Cisco6961 = 497,
289 Cisco6901 = 547,
290 Cisco6911 = 548,
291 Cisco6945 = 564,
292 Cisco7926 = 577,
293 Cisco8945 = 585,
294 Cisco8941 = 586,
295 CiscoIpCommunicator = 30016,
296 Cisco7905 = 20000,
297 Cisco7920 = 30002,
298 Cisco7970 = 30006,
299 Cisco7912 = 30007,
300 Cisco7902 = 30008,
301 Cisco7961 = 30018,
302 Cisco7936 = 30019,
303 AnalogGateway = 30027,
304 BriGateway = 30028,
305 Spa521s = 80000,
306 Spa524sg = 80001,
307 Spa502g = 80003,
308 Spa504g = 80004,
309 Spa525g = 80005,
310 Spa508g = 80006,
311 Spa509g = 80007,
312 Spa525g2 = 80009,
313 Spa303g = 80011,
314 Spa512g = 80012,
315 Spa514g = 80013,
316 AddonSpa500s = 99991,
317 AddonSpa500ds = 99992,
318 AddonSpa932ds = 99993,
319 NotDefined = 99999
320 }
321}
322
323#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
325pub enum CodecKind {
326 Audio,
327 Video,
328 Text,
329 Data,
330 TelephoneEvent,
331 Unknown,
332}
333
334wire_enum! {
335 pub enum Codec {
337 None = 0x0000,
338 NonStandard = 0x0001,
339 Pcma = 0x0002,
340 G711Alaw56k = 0x0003,
341 Pcmu = 0x0004,
342 G711Ulaw56k = 0x0005,
343 G72264k = 0x0006,
344 G72256k = 0x0007,
345 G72248k = 0x0008,
346 G7231 = 0x0009,
347 G728 = 0x000a,
348 G729 = 0x000b,
349 G729A = 0x000c,
350 Is11172 = 0x000d,
351 Is13818 = 0x000e,
352 G729B = 0x000f,
353 G729Ab = 0x0010,
354 GsmFullRate = 0x0012,
355 GsmHalfRate = 0x0013,
356 GsmEnhancedFullRate = 0x0014,
357 Wideband256k = 0x0019,
358 Data64k = 0x0020,
359 Data56k = 0x0021,
360 G7221_32k = 0x0028,
361 G7221_24k = 0x0029,
362 Aac = 0x002a,
363 Mp4aLatm128 = 0x002b,
364 Mp4aLatm64 = 0x002c,
365 Mp4aLatm56 = 0x002d,
366 Mp4aLatm48 = 0x002e,
367 Mp4aLatm32 = 0x002f,
368 Mp4aLatm24 = 0x0030,
369 Mp4aLatm = 0x0031,
370 Gsm = 0x0050,
371 ActiveVoice = 0x0051,
372 G726_32k = 0x0052,
373 G726_24k = 0x0053,
374 G726_16k = 0x0054,
375 G729AnnexB = 0x0055,
376 Ilbc = 0x0056,
377 Isac = 0x0059,
378 Opus = 0x005a,
379 Amr = 0x0061,
380 AmrWb = 0x0062,
381 H261 = 0x0064,
382 H263 = 0x0065,
383 H263Plus = 0x0066,
384 H264 = 0x0067,
385 H264Svc = 0x0068,
386 T120 = 0x0069,
387 H224 = 0x006a,
388 T38Fax = 0x006b,
389 Tote = 0x006c,
390 H265 = 0x006d,
391 H264Uc = 0x006e,
392 Xv150ModemRelay711u = 0x006f,
393 NseVbd711u = 0x0070,
394 Xv150ModemRelay729a = 0x0071,
395 NseVbd729a = 0x0072,
396 H264Fec = 0x0073,
397 ClearChannel = 0x0078,
398 UniversalTranscoder = 0x00de,
399 DtmfOutOfBandRfc2833 = 0x0101,
400 DtmfPassthrough = 0x0102,
401 DtmfDynamic = 0x0103,
402 DtmfOutOfBand = 0x0104,
403 DtmfInBandRfc2833 = 0x0105,
404 CfbTones = 0x0106,
405 DtmfNoAudio = 0x012b,
406 V150ModemRelay = 0x012c,
407 V150Sprt = 0x012d,
408 V150Sse = 0x012e
409 }
410}
411
412impl Codec {
413 pub const fn skinny(self) -> u32 {
415 self.wire_value()
416 }
417
418 pub const fn kind(self) -> CodecKind {
420 match self {
421 Self::H261
422 | Self::H263
423 | Self::H263Plus
424 | Self::H264
425 | Self::H264Svc
426 | Self::H265
427 | Self::H264Uc
428 | Self::H264Fec => CodecKind::Video,
429 Self::T120 | Self::H224 => CodecKind::Text,
430 Self::Data64k
431 | Self::Data56k
432 | Self::T38Fax
433 | Self::Tote
434 | Self::Xv150ModemRelay711u
435 | Self::NseVbd711u
436 | Self::Xv150ModemRelay729a
437 | Self::NseVbd729a
438 | Self::ClearChannel
439 | Self::UniversalTranscoder
440 | Self::V150ModemRelay
441 | Self::V150Sprt
442 | Self::V150Sse => CodecKind::Data,
443 Self::DtmfOutOfBandRfc2833
444 | Self::DtmfPassthrough
445 | Self::DtmfDynamic
446 | Self::DtmfOutOfBand
447 | Self::DtmfInBandRfc2833
448 | Self::DtmfNoAudio
449 | Self::CfbTones => CodecKind::TelephoneEvent,
450 Self::None | Self::NonStandard | Self::Unknown(_) => CodecKind::Unknown,
451 _ => CodecKind::Audio,
452 }
453 }
454
455 pub const fn sample_rate(self) -> Option<u32> {
460 match self {
461 Self::G72264k
462 | Self::G72256k
463 | Self::G72248k
464 | Self::G7221_32k
465 | Self::G7221_24k
466 | Self::Wideband256k
467 | Self::AmrWb => Some(16_000),
468 Self::Opus | Self::Isac => Some(48_000),
469 codec if matches!(codec.kind(), CodecKind::Audio) => Some(8_000),
470 _ => None,
471 }
472 }
473
474 pub const fn rtp_payload_type(self) -> Option<u8> {
479 match self {
480 Self::Pcmu | Self::G711Ulaw56k => Some(0),
481 Self::Gsm => Some(3),
482 Self::G7231 => Some(4),
483 Self::Pcma | Self::G711Alaw56k => Some(8),
484 Self::G72264k | Self::G72256k | Self::G72248k => Some(9),
485 Self::G729 | Self::G729A | Self::G729B | Self::G729Ab | Self::G729AnnexB => Some(18),
486 Self::Wideband256k => Some(25),
487 Self::Ilbc => Some(97),
488 Self::G7221_32k => Some(102),
489 Self::Opus => Some(107),
490 Self::G726_32k => Some(112),
491 _ => None,
492 }
493 }
494}
495
496wire_enum! {
497 pub enum CallState {
499 OffHook = 1,
500 OnHook = 2,
501 RingOut = 3,
502 RingIn = 4,
503 Connected = 5,
504 Busy = 6,
505 Congestion = 7,
506 Hold = 8,
507 CallWaiting = 9,
508 Transfer = 10,
509 Park = 11,
510 Proceed = 12,
511 RemoteMultiline = 13,
512 InvalidNumber = 14,
513 HoldYellow = 15,
514 IntercomOneWay = 16,
515 HoldRed = 17
516 }
517}
518
519wire_enum! {
520 pub enum CallType {
522 Inbound = 1,
523 Outbound = 2,
524 Forward = 3
525 }
526}
527
528wire_enum! {
529 pub enum AlarmSeverity {
531 Critical = 0,
532 Warning = 1,
533 Informational = 2,
534 ProtocolUnknown = 4,
535 Major = 7,
536 Minor = 8,
537 Marginal = 10,
538 TraceInfo = 20
539 }
540}
541
542wire_enum! {
543 pub enum MediaStatus {
545 Ok = 0,
546 UnspecifiedError = 1,
547 OutOfChannels = 2,
548 CodecTooComplex = 3,
549 InvalidPartyId = 4,
550 InvalidCallReference = 5,
551 InvalidCodec = 6,
552 InvalidPacketSize = 7,
553 OutOfSockets = 8,
554 EncoderOrDecoderFailed = 9,
555 InvalidDynamicPayload = 10,
556 RequestedAddressTypeUnavailable = 11,
557 DeviceOnHook = 12
558 }
559}
560
561wire_enum! {
562 pub enum Stimulus {
564 Unused = 0x00,
565 LastNumberRedial = 0x01,
566 SpeedDial = 0x02,
567 Hold = 0x03,
568 Transfer = 0x04,
569 ForwardAll = 0x05,
570 ForwardBusy = 0x06,
571 ForwardNoAnswer = 0x07,
572 Display = 0x08,
573 Line = 0x09,
574 T120Chat = 0x0a,
575 T120Whiteboard = 0x0b,
576 T120ApplicationSharing = 0x0c,
577 T120FileTransfer = 0x0d,
578 Video = 0x0e,
579 Voicemail = 0x0f,
580 AnswerRelease = 0x10,
581 AutoAnswer = 0x11,
582 Select = 0x12,
583 Privacy = 0x13,
584 ServiceUrl = 0x14,
585 BlfSpeedDial = 0x15,
586 DirectedPark = 0x16,
587 Intercom = 0x17,
588 MaliciousCall = 0x1b,
589 GenericAppB1 = 0x21,
590 GenericAppB2 = 0x22,
591 GenericAppB3 = 0x23,
592 GenericAppB4 = 0x24,
593 GenericAppB5 = 0x25,
594 MultiblinkFeature = 0x26,
595 MeetMeConference = 0x7b,
596 Conference = 0x7d,
597 CallPark = 0x7e,
598 CallPickup = 0x7f,
599 GroupCallPickup = 0x80,
600 Mobility = 0x81,
601 DoNotDisturb = 0x82,
602 ConferenceList = 0x83,
603 RemoveLastParticipant = 0x84,
604 QualityReportTool = 0x85,
605 Callback = 0x86,
606 OtherPickup = 0x87,
607 VideoMode = 0x88,
608 NewCall = 0x89,
609 EndCall = 0x8a,
610 HuntGroupLogin = 0x8b,
611 Queuing = 0x8f,
612 ParkingLot = 0xc0,
613 Messages = 0xc2,
614 Directory = 0xc3,
615 Application = 0xc5,
616 Headset = 0xc6,
617 Keypad = 0xf0,
618 AcousticEchoCancellation = 0xfd,
619 Undefined = 0xff
620 }
621}
622
623wire_enum! {
624 pub enum SoftKey {
626 Redial = 1,
627 NewCall = 2,
628 Hold = 3,
629 Transfer = 4,
630 ForwardAll = 5,
631 ForwardBusy = 6,
632 ForwardNoAnswer = 7,
633 Backspace = 8,
634 EndCall = 9,
635 Resume = 10,
636 Answer = 11,
637 Info = 12,
638 Conference = 13,
639 Park = 14,
640 Join = 15,
641 MeetMe = 16,
642 Pickup = 17,
643 GroupPickup = 18,
644 Monitor = 19,
645 Callback = 20,
646 Barge = 21,
647 DoNotDisturb = 22,
648 ConferenceList = 23,
649 Select = 24,
650 Private = 25,
651 TransferToVoicemail = 26,
652 DirectTransfer = 27,
653 ImmediateDivert = 28,
654 VideoMode = 29,
655 Intercept = 30,
656 Empty = 31,
657 Dial = 32
658 }
659}
660
661wire_enum! {
662 pub enum KeyMode {
664 OnHook = 0,
665 Connected = 1,
666 OnHold = 2,
667 RingIn = 3,
668 OffHook = 4,
669 ConnectedTransfer = 5,
670 DigitsFollowing = 6,
671 ConnectedConference = 7,
672 RingOut = 8,
673 OffHookFeature = 9,
674 InUseHint = 10,
675 OnHookStealable = 11,
676 HoldConference = 12,
677 Empty = 13
678 }
679}
680
681wire_enum! {
682 pub enum RingerMode {
684 Off = 1,
685 Inside = 2,
686 Outside = 3,
687 Feature = 4,
688 Silent = 5,
689 Urgent = 6,
690 Bellcore1 = 7,
691 Bellcore2 = 8,
692 Bellcore3 = 9,
693 Bellcore4 = 10,
694 Bellcore5 = 11
695 }
696}
697
698wire_enum! {
699 pub enum RingDuration {
701 Normal = 1,
702 Single = 2
703 }
704}
705
706wire_enum! {
707 pub enum LampMode {
709 Off = 1,
710 On = 2,
711 Wink = 3,
712 Flash = 4,
713 Blink = 5,
714 Hold = 6,
715 Ring = 7,
716 Custom1 = 8,
717 Custom2 = 9
718 }
719}
720
721wire_enum! {
722 pub enum Tone {
724 Silence = 0x00,
725 Dtmf1 = 0x01,
726 Dtmf2 = 0x02,
727 Dtmf3 = 0x03,
728 Dtmf4 = 0x04,
729 Dtmf5 = 0x05,
730 Dtmf6 = 0x06,
731 Dtmf7 = 0x07,
732 Dtmf8 = 0x08,
733 Dtmf9 = 0x09,
734 Dtmf0 = 0x0a,
735 DtmfStar = 0x0e,
736 DtmfPound = 0x0f,
737 DtmfA = 0x10,
738 DtmfB = 0x11,
739 DtmfC = 0x12,
740 DtmfD = 0x13,
741 InsideDial = 0x21,
742 OutsideDial = 0x22,
743 LineBusy = 0x23,
744 Alerting = 0x24,
745 Reorder = 0x25,
746 RecorderWarning = 0x26,
747 RecorderDetected = 0x27,
748 Reverting = 0x28,
749 ReceiverOffHook = 0x29,
750 PartialDial = 0x2a,
751 NoSuchNumber = 0x2b,
752 BusyVerification = 0x2c,
753 CallWaiting = 0x2d,
754 Confirmation = 0x2e,
755 CampOn = 0x2f,
756 RecallDial = 0x30,
757 ZipZip = 0x31,
758 Zip = 0x32,
759 BeepBonk = 0x33,
760 Music = 0x34,
761 Hold = 0x35,
762 Test = 0x36,
763 MonitorWarning = 0x37,
764 AddCallWaiting = 0x40,
765 PriorityCallWaiting = 0x41,
766 BargeIn = 0x43,
767 DistinctAlert = 0x44,
768 PriorityAlert = 0x45,
769 ReminderRing = 0x46,
770 PrecedenceRingback = 0x47,
771 Preemption = 0x48,
772 NoTone = 0x7f,
773 MeetMeGreeting = 0x80,
774 MeetMeNumberInvalid = 0x81,
775 MeetMeNumberFailed = 0x82,
776 MeetMeEnterPin = 0x83,
777 MeetMeInvalidPin = 0x84,
778 MeetMeFailedPin = 0x85,
779 MeetMeCfbFailed = 0x86,
780 MeetMeEnterAccessCode = 0x87,
781 MeetMeAccessCodeInvalid = 0x88,
782 MeetMeAccessCodeFailed = 0x89
783 }
784}
785
786wire_enum! {
787 pub enum ToneDirection {
789 User = 0,
790 Network = 1,
791 Both = 2
792 }
793}
794
795wire_enum! {
796 pub enum MediaPathId {
798 None = 0,
799 Headset = 1,
800 Handset = 2,
801 Speaker = 3
802 }
803}
804
805wire_enum! {
806 pub enum MediaPathEvent {
808 None = 0,
809 On = 1,
810 Off = 2
811 }
812}
813
814wire_enum! {
815 pub enum MediaPathCapability {
817 None = 0,
818 Enable = 1,
819 Disable = 2,
820 Monitor = 3
821 }
822}
823
824wire_enum! {
825 pub enum MediaType {
827 Invalid = 0,
828 Audio = 1,
829 MainVideo = 2,
830 Fecc = 3,
831 PresentationVideo = 4,
832 Bfcp = 5,
833 IxChannel = 6,
834 T38 = 7
835 }
836}
837
838wire_enum! {
839 pub enum MediaTransport {
841 Rtp = 1,
842 Udp = 2,
843 Tcp = 3
844 }
845}
846
847wire_enum! {
848 pub enum QosDirection {
850 Send = 1,
851 Receive = 2,
852 SendReceive = 3
853 }
854}
855
856wire_enum! {
857 pub enum QosReservationStyle {
859 FixedFilter = 1,
860 SharedExplicit = 2,
861 WildcardFilter = 3
862 }
863}
864
865wire_enum! {
866 pub enum QosErrorCode {
868 ReservationTimeout = 0,
869 PathFailed = 1,
870 ReservationFailed = 2,
871 ListenFailed = 3,
872 ResourceUnavailable = 4,
873 ListenTimeout = 5,
874 ReservationRetriesFailed = 6,
875 PathRetriesFailed = 7,
876 ReservationPreempted = 8,
877 PathPreempted = 9,
878 ReservationModifyFailed = 10,
879 PathModifyFailed = 11,
880 ReservationTornDown = 12
881 }
882}
883
884wire_enum! {
885 pub enum RsvpErrorCode {
887 Confirm = 0,
888 Admission = 1,
889 Administrative = 2,
890 NoPathInformation = 3,
891 NoSenderInformation = 4,
892 ConflictingStyle = 5,
893 UnknownStyle = 6,
894 ConflictingDestinationPorts = 7,
895 ConflictingSourcePorts = 8,
896 ServicePreempted = 12,
897 UnknownObjectClass = 13,
898 UnknownClassType = 14,
899 Api = 20,
900 Traffic = 21,
901 TrafficSystem = 22,
902 System = 23,
903 RoutingProblem = 24
904 }
905}
906
907wire_enum! {
908 pub enum EndOfAnnouncementAck {
910 NotRequired = 0,
911 Required = 1
912 }
913}
914
915wire_enum! {
916 pub enum AnnouncementPlayMode {
918 XmlConfigured = 0,
919 OneShot = 1,
920 Continuous = 2
921 }
922}
923
924wire_enum! {
925 pub enum AnnouncementPlayStatus {
927 Ok = 0,
928 Error = 1
929 }
930}
931
932wire_enum! {
933 pub enum MessageWaitingResult {
935 Ok = 0,
936 GeneralError = 1,
937 RequestRejected = 2,
938 VoicemailCountOutOfBounds = 3,
939 FaxCountOutOfBounds = 4,
940 InvalidPriorityVoicemailCount = 5,
941 InvalidPriorityFaxCount = 6
942 }
943}
944
945wire_enum! {
946 pub enum StatisticsProcessing {
948 Clear = 0,
949 DoNotClear = 1
950 }
951}
952
953wire_enum! {
954 pub enum IpAddressType {
956 Ipv4 = 0,
957 Ipv6 = 1,
958 Ipv4AndIpv6 = 2,
959 Invalid = 3
960 }
961}
962
963wire_enum! {
964 pub enum ResetType {
966 Reset = 1,
967 Restart = 2,
968 ApplyConfiguration = 3
969 }
970}
971
972wire_enum! {
973 pub enum DtmfMode {
975 Auto = 0,
976 Rfc2833 = 1,
977 Skinny = 2
978 }
979}
980
981wire_enum! {
982 pub enum CallForwardKind {
984 None = 0,
985 All = 1,
986 Busy = 2,
987 NoAnswer = 3
988 }
989}
990
991wire_enum! {
992 pub enum CallPriority {
994 Highest = 0,
995 High = 1,
996 Medium = 2,
997 Low = 3,
998 Normal = 4
999 }
1000}
1001
1002wire_enum! {
1003 pub enum NotificationPriority {
1005 Idle = 0,
1006 Voicemail = 1,
1007 Monitor = 2,
1008 Privacy = 3,
1009 DoNotDisturb = 4,
1010 CallForward = 5,
1011 Timed = 6
1012 }
1013}
1014
1015wire_enum! {
1016 pub enum CallInfoVisibility {
1018 Default = 0,
1019 Collapsed = 1,
1020 Hidden = 2
1021 }
1022}
1023
1024wire_enum! {
1025 pub enum CallSecurityState {
1027 UnknownState = 0,
1028 NotAuthenticated = 1,
1029 Authenticated = 2
1030 }
1031}
1032
1033wire_enum! {
1034 pub enum BusyLampFieldState {
1036 UnknownState = 0,
1037 Idle = 1,
1038 InUse = 2,
1039 DoNotDisturb = 3,
1040 Alerting = 4
1041 }
1042}
1043
1044wire_enum! {
1045 pub enum SubscriptionCause {
1047 Ok = 0,
1048 RouteFailure = 1,
1049 AuthenticationFailure = 2,
1050 Timeout = 3,
1051 TrunkTerminated = 4,
1052 TrunkForbidden = 5,
1053 Throttled = 6
1054 }
1055}
1056
1057wire_enum! {
1058 pub enum VideoFormat {
1060 Undefined = 0,
1061 Sqcif = 1,
1062 Qcif = 2,
1063 Cif = 3,
1064 Cif4 = 4,
1065 Cif16 = 5,
1066 Custom = 6,
1067 ProtocolUnknown = 232
1068 }
1069}
1070
1071wire_enum! {
1072 pub enum MiscCommandType {
1074 VideoFreezePicture = 0,
1075 VideoFastUpdatePicture = 1,
1076 VideoFastUpdateGob = 2,
1077 VideoFastUpdateMacroblock = 3,
1078 LostPicture = 4,
1079 LostPartialPicture = 5,
1080 RecoveryReferencePicture = 6,
1081 TemporalSpatialTradeoff = 7
1082 }
1083}
1084
1085wire_enum! {
1086 pub enum EchoCancellation {
1088 Off = 0,
1089 On = 1
1090 }
1091}
1092
1093wire_enum! {
1094 pub enum SilenceSuppression {
1096 Off = 0,
1097 On = 1
1098 }
1099}
1100
1101wire_enum! {
1102 pub enum G723BitRate {
1104 Rate5_3 = 1,
1105 Rate6_3 = 2
1106 }
1107}
1108
1109wire_enum! {
1110 pub enum UnregisterStatus {
1112 Ok = 0,
1113 Error = 1,
1114 ActiveCall = 2
1115 }
1116}
1117
1118wire_enum! {
1119 pub enum ButtonType {
1122 Unused = 0x00,
1123 LastNumberRedial = 0x01,
1124 SpeedDial = 0x02,
1125 Hold = 0x03,
1126 Transfer = 0x04,
1127 ForwardAll = 0x05,
1128 ForwardBusy = 0x06,
1129 ForwardNoAnswer = 0x07,
1130 Display = 0x08,
1131 Line = 0x09,
1132 T120Chat = 0x0a,
1133 T120Whiteboard = 0x0b,
1134 T120ApplicationSharing = 0x0c,
1135 T120FileTransfer = 0x0d,
1136 Video = 0x0e,
1137 Voicemail = 0x0f,
1138 AnswerRelease = 0x10,
1139 AutoAnswer = 0x11,
1140 Select = 0x12,
1141 Feature = 0x13,
1142 ServiceUrl = 0x14,
1143 BlfSpeedDial = 0x15,
1144 DirectedPark = 0x16,
1145 Intercom = 0x17,
1146 MaliciousCall = 0x1b,
1147 GenericAppB1 = 0x21,
1148 GenericAppB2 = 0x22,
1149 GenericAppB3 = 0x23,
1150 GenericAppB4 = 0x24,
1151 GenericAppB5 = 0x25,
1152 MultiblinkFeature = 0x26,
1153 MeetMeConference = 0x7b,
1154 Conference = 0x7d,
1155 CallPark = 0x7e,
1156 CallPickup = 0x7f,
1157 GroupCallPickup = 0x80,
1158 Mobility = 0x81,
1159 DoNotDisturb = 0x82,
1160 ConferenceList = 0x83,
1161 RemoveLastParticipant = 0x84,
1162 QualityReportTool = 0x85,
1163 Callback = 0x86,
1164 OtherPickup = 0x87,
1165 VideoMode = 0x88,
1166 NewCall = 0x89,
1167 EndCall = 0x8a,
1168 HuntGroupLogin = 0x8b,
1169 Queuing = 0x8f,
1170 ParkingLot = 0xc0,
1171 Messages = 0xc2,
1172 Directory = 0xc3,
1173 Application = 0xc5,
1174 Headset = 0xc6,
1175 Keypad = 0xf0,
1176 PlaceholderMulti = 0xf1,
1177 PlaceholderLine = 0xf2,
1178 PlaceholderSpeedDial = 0xf3,
1179 PlaceholderHint = 0xf4,
1180 PlaceholderAbbreviatedDial = 0xf5,
1181 AcousticEchoCancellation = 0xfd,
1182 Undefined = 0xff
1183 }
1184}
1185
1186wire_enum! {
1187 pub enum EncryptionMethod {
1189 None = 0,
1190 Aes128HmacSha1_32 = 1,
1191 Aes128HmacSha1_80 = 2,
1192 F8_128HmacSha1_32 = 3,
1193 F8_128HmacSha1_80 = 4,
1194 AeadAes128Gcm = 5,
1195 AeadAes256Gcm = 6
1196 }
1197}
1198
1199wire_enum! {
1200 pub enum EncryptionCapability {
1202 NotCapable = 0,
1203 Capable = 1
1204 }
1205}
1206
1207wire_enum! {
1208 pub enum CallHistoryDisposition {
1210 Ignore = 0,
1211 Placed = 1,
1212 Received = 2,
1213 Missed = 3,
1214 ProtocolUnknown = 0xffff_fffe
1215 }
1216}
1217
1218wire_enum! {
1219 pub enum SpeakerMode {
1221 On = 1,
1222 Off = 2
1223 }
1224}
1225
1226wire_enum! {
1227 pub enum MicrophoneMode {
1229 On = 1,
1230 Off = 2
1231 }
1232}
1233
1234wire_enum! {
1235 pub enum ConferenceResourceType {
1237 Conference = 0,
1238 InteractiveVoiceResponse = 1
1239 }
1240}
1241
1242wire_enum! {
1243 pub enum CreateConferenceResult {
1245 Ok = 0,
1246 ResourceNotAvailable = 1,
1247 ConferenceAlreadyExists = 2,
1248 SystemError = 3
1249 }
1250}
1251
1252wire_enum! {
1253 pub enum DeleteConferenceResult {
1255 Ok = 0,
1256 ConferenceDoesNotExist = 1,
1257 SystemError = 2
1258 }
1259}
1260
1261wire_enum! {
1262 pub enum ModifyConferenceResult {
1264 Ok = 0,
1265 ResourceNotAvailable = 1,
1266 ConferenceDoesNotExist = 2,
1267 InvalidParameter = 3,
1268 MoreActiveCallsThanReserved = 4,
1269 InvalidResourceType = 5,
1270 SystemError = 6
1271 }
1272}
1273
1274wire_enum! {
1275 pub enum AddParticipantResult {
1277 Ok = 0,
1278 ResourceNotAvailable = 1,
1279 ConferenceDoesNotExist = 2,
1280 DuplicateCallReference = 3,
1281 SystemError = 4
1282 }
1283}
1284
1285wire_enum! {
1286 pub enum AuditParticipantResult {
1288 Ok = 0,
1289 ConferenceDoesNotExist = 1
1290 }
1291}
1292
1293bitflags! {
1294 #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1296 pub struct PartyInformationRestrictions: u32 {
1297 const CALLING_NAME = 1 << 0;
1298 const CALLING_NUMBER = 1 << 1;
1299 const CALLED_NAME = 1 << 2;
1300 const CALLED_NUMBER = 1 << 3;
1301 const ORIGINAL_CALLED_NAME = 1 << 4;
1302 const ORIGINAL_CALLED_NUMBER = 1 << 5;
1303 const LAST_REDIRECT_NAME = 1 << 6;
1304 const LAST_REDIRECT_NUMBER = 1 << 7;
1305 }
1306}
1307
1308#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
1310pub struct StationSessionContext {
1311 pub protocol: ProtocolVersion,
1313 pub features: PhoneFeatures,
1315}
1316
1317impl StationSessionContext {
1318 pub const fn new(protocol: ProtocolVersion, features: PhoneFeatures) -> Self {
1320 Self { protocol, features }
1321 }
1322
1323 pub const fn uses_dynamic_general_ui(self) -> bool {
1325 self.protocol.uses_dynamic_general_ui()
1326 || self.features.contains(PhoneFeatures::DYNAMIC_MESSAGES)
1327 }
1328
1329 pub const fn uses_dynamic_feature_status(self) -> bool {
1331 self.features.contains(PhoneFeatures::DYNAMIC_MESSAGES)
1332 }
1333
1334 pub const fn dynamic_call_info_layout(self) -> DynamicCallInfoLayout {
1336 self.protocol.dynamic_call_info_layout()
1337 }
1338
1339 pub const fn dynamic_service_url_string_count(self) -> usize {
1341 if self.protocol.wire() >= ProtocolVersion::V19.wire() {
1342 3
1343 } else {
1344 2
1345 }
1346 }
1347}
1348
1349impl From<ProtocolVersion> for StationSessionContext {
1350 fn from(protocol: ProtocolVersion) -> Self {
1351 Self::new(protocol, PhoneFeatures::empty())
1352 }
1353}
1354
1355pub const RFC2833_TELEPHONE_EVENT_PAYLOAD: u8 = 101;
1358
1359impl DtmfMode {
1360 pub const fn resolve(self, features: PhoneFeatures) -> Self {
1363 match self {
1364 Self::Auto if features.contains(PhoneFeatures::RFC2833) => Self::Rfc2833,
1365 Self::Auto => Self::Skinny,
1366 explicit => explicit,
1367 }
1368 }
1369
1370 pub const fn telephone_event_payload(self, features: PhoneFeatures) -> u8 {
1373 match self.resolve(features) {
1374 Self::Rfc2833 => RFC2833_TELEPHONE_EVENT_PAYLOAD,
1375 Self::Skinny | Self::Unknown(_) => 0,
1376 Self::Auto => unreachable!(),
1377 }
1378 }
1379}
1380
1381bitflags! {
1382 #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1384 pub struct PhoneFeatures: u32 {
1385 const PORT_REQUEST = 1 << 17;
1388 const UTF8 = 1 << 20;
1389 const DYNAMIC_MESSAGES = 1 << 24;
1390 const RFC2833 = 1 << 26;
1391 const INTERNAL_CM_MEDIA = 1 << 28;
1392 const ABBREVIATED_DIAL = 1 << 31;
1393 }
1394}
1395
1396bitflags! {
1397 #[derive(Clone, Copy, Debug, Default, Eq, Hash, PartialEq)]
1399 pub struct ReceiveTransmit: u32 {
1400 const RECEIVE = 1;
1401 const TRANSMIT = 2;
1402 }
1403}
1404
1405#[derive(Clone, Copy, Debug, Eq, PartialEq)]
1406pub enum Digit {
1408 Number(u8),
1410 Star,
1411 Pound,
1412 A,
1413 B,
1414 C,
1415 D,
1416 Unknown(u32),
1418}
1419
1420impl Digit {
1421 pub const fn from_keypad(value: u32) -> Self {
1423 match value {
1424 0..=9 => Self::Number(value as u8),
1425 10 => Self::Star,
1426 11 => Self::Pound,
1427 12 => Self::A,
1428 13 => Self::B,
1429 14 => Self::C,
1430 15 => Self::D,
1431 value => Self::Unknown(value),
1432 }
1433 }
1434
1435 pub const fn keypad_value(self) -> u32 {
1437 match self {
1438 Self::Number(number) => number as u32,
1439 Self::Star => 10,
1440 Self::Pound => 11,
1441 Self::A => 12,
1442 Self::B => 13,
1443 Self::C => 14,
1444 Self::D => 15,
1445 Self::Unknown(value) => value,
1446 }
1447 }
1448
1449 pub fn as_char(self) -> char {
1451 match self {
1452 Self::Number(n) if n <= 9 => char::from(b'0' + n),
1453 Self::Number(_) => '?',
1454 Self::Star => '*',
1455 Self::Pound => '#',
1456 Self::A => 'A',
1457 Self::B => 'B',
1458 Self::C => 'C',
1459 Self::D => 'D',
1460 Self::Unknown(_) => '?',
1461 }
1462 }
1463}
1464
1465impl From<u32> for Digit {
1466 fn from(value: u32) -> Self {
1467 Self::from_keypad(value)
1468 }
1469}
1470
1471impl From<Digit> for u32 {
1472 fn from(value: Digit) -> Self {
1473 value.keypad_value()
1474 }
1475}
1476
1477#[cfg(test)]
1478mod tests {
1479 use super::*;
1480
1481 #[test]
1482 fn protocol_versions_select_layout_profiles() {
1483 assert_eq!(ProtocolVersion::new(3).unwrap().layout(), LayoutProfile::V3);
1484 assert_eq!(
1485 ProtocolVersion::new(14).unwrap().layout(),
1486 LayoutProfile::V11
1487 );
1488 assert_eq!(ProtocolVersion::new(13).unwrap(), ProtocolVersion::V13);
1489 assert_eq!(ProtocolVersion::new(14).unwrap(), ProtocolVersion::V14);
1490 assert_eq!(
1491 ProtocolVersion::new(18).unwrap().layout(),
1492 LayoutProfile::V18
1493 );
1494 assert_eq!(
1495 ProtocolVersion::new(21).unwrap().layout(),
1496 LayoutProfile::V19
1497 );
1498 assert_eq!(
1499 ProtocolVersion::new(22).unwrap().layout(),
1500 LayoutProfile::V22
1501 );
1502 assert_eq!(
1503 ProtocolVersion::negotiate(99).unwrap(),
1504 ProtocolVersion::V22
1505 );
1506 assert!(ProtocolVersion::new(2).is_err());
1507 }
1508
1509 #[test]
1510 fn dynamic_station_layout_boundaries_follow_session_negotiation() {
1511 assert!(!ProtocolVersion::V8.uses_dynamic_general_ui());
1512 assert!(ProtocolVersion::V9.uses_dynamic_general_ui());
1513 assert!(
1514 !ProtocolVersion::new(14)
1515 .unwrap()
1516 .uses_dynamic_speed_dial_status()
1517 );
1518 assert!(ProtocolVersion::V15.uses_dynamic_speed_dial_status());
1519
1520 assert_eq!(
1521 ProtocolVersion::V15.dynamic_call_info_layout(),
1522 DynamicCallInfoLayout::Fields12
1523 );
1524 assert_eq!(
1525 ProtocolVersion::V16.dynamic_call_info_layout(),
1526 DynamicCallInfoLayout::Fields13
1527 );
1528 assert_eq!(
1529 ProtocolVersion::V18.dynamic_call_info_layout(),
1530 DynamicCallInfoLayout::Fields13
1531 );
1532 assert_eq!(
1533 ProtocolVersion::V19.dynamic_call_info_layout(),
1534 DynamicCallInfoLayout::Fields15
1535 );
1536
1537 let baseline = StationSessionContext::from(ProtocolVersion::V8);
1538 assert!(!baseline.uses_dynamic_general_ui());
1539 assert!(!baseline.uses_dynamic_feature_status());
1540 let negotiated =
1541 StationSessionContext::new(ProtocolVersion::V8, PhoneFeatures::DYNAMIC_MESSAGES);
1542 assert!(negotiated.uses_dynamic_general_ui());
1543 assert!(negotiated.uses_dynamic_feature_status());
1544 }
1545
1546 #[test]
1547 fn extensible_values_preserve_unknown_numbers() {
1548 let codec = Codec::from(0xfeed);
1549 assert_eq!(codec, Codec::Unknown(0xfeed));
1550 assert_eq!(codec.wire_value(), 0xfeed);
1551 let state = CallState::from(1000);
1552 assert_eq!(state.wire_value(), 1000);
1553 }
1554
1555 #[test]
1556 fn soft_key_events_are_template_positions() {
1557 assert_eq!(SoftKey::from(1), SoftKey::Redial);
1558 assert_eq!(SoftKey::from(13), SoftKey::Conference);
1559 assert_eq!(SoftKey::from(32), SoftKey::Dial);
1560 assert_eq!(SoftKey::from(201), SoftKey::Unknown(201));
1561 }
1562
1563 #[test]
1564 fn automatic_dtmf_uses_only_an_advertised_rfc2833_capability() {
1565 assert_eq!(
1566 DtmfMode::Auto.resolve(PhoneFeatures::RFC2833),
1567 DtmfMode::Rfc2833
1568 );
1569 assert_eq!(
1570 DtmfMode::Auto.telephone_event_payload(PhoneFeatures::RFC2833),
1571 RFC2833_TELEPHONE_EVENT_PAYLOAD
1572 );
1573 assert_eq!(
1574 DtmfMode::Auto.resolve(PhoneFeatures::empty()),
1575 DtmfMode::Skinny
1576 );
1577 assert_eq!(
1578 DtmfMode::Auto.telephone_event_payload(PhoneFeatures::empty()),
1579 0
1580 );
1581 assert_eq!(
1582 DtmfMode::Skinny.telephone_event_payload(PhoneFeatures::RFC2833),
1583 0
1584 );
1585 assert_eq!(
1586 DtmfMode::Rfc2833.telephone_event_payload(PhoneFeatures::empty()),
1587 RFC2833_TELEPHONE_EVENT_PAYLOAD
1588 );
1589 }
1590
1591 #[test]
1592 fn phone_feature_bits_match_the_three_register_feature_bytes() {
1593 let advertised = PhoneFeatures::from_bits_retain(0x8572_0000);
1597 assert!(advertised.contains(PhoneFeatures::PORT_REQUEST));
1598 assert!(advertised.contains(PhoneFeatures::UTF8));
1599 assert!(advertised.contains(PhoneFeatures::DYNAMIC_MESSAGES));
1600 assert!(advertised.contains(PhoneFeatures::RFC2833));
1601 assert!(advertised.contains(PhoneFeatures::ABBREVIATED_DIAL));
1602 assert!(!advertised.contains(PhoneFeatures::INTERNAL_CM_MEDIA));
1603 }
1604
1605 #[test]
1606 fn every_named_wire_enum_value_is_unique_and_round_trips() {
1607 macro_rules! assert_wire_enum {
1608 ($type:ty) => {{
1609 let mut values = std::collections::HashSet::new();
1610 for value in <$type>::ALL_KNOWN {
1611 assert!(
1612 values.insert(value.wire_value()),
1613 "duplicate {} value {value:?}",
1614 stringify!($type)
1615 );
1616 assert_eq!(<$type>::from(value.wire_value()), *value);
1617 assert!(value.is_known());
1618 }
1619 }};
1620 }
1621
1622 assert_wire_enum!(DeviceType);
1623 assert_wire_enum!(Codec);
1624 assert_wire_enum!(CallState);
1625 assert_wire_enum!(CallType);
1626 assert_wire_enum!(AlarmSeverity);
1627 assert_wire_enum!(MediaStatus);
1628 assert_wire_enum!(Stimulus);
1629 assert_wire_enum!(SoftKey);
1630 assert_wire_enum!(KeyMode);
1631 assert_wire_enum!(RingerMode);
1632 assert_wire_enum!(RingDuration);
1633 assert_wire_enum!(LampMode);
1634 assert_wire_enum!(Tone);
1635 assert_wire_enum!(ToneDirection);
1636 assert_wire_enum!(MediaPathId);
1637 assert_wire_enum!(MediaPathEvent);
1638 assert_wire_enum!(MediaPathCapability);
1639 assert_wire_enum!(MediaType);
1640 assert_wire_enum!(MediaTransport);
1641 assert_wire_enum!(QosDirection);
1642 assert_wire_enum!(QosReservationStyle);
1643 assert_wire_enum!(QosErrorCode);
1644 assert_wire_enum!(RsvpErrorCode);
1645 assert_wire_enum!(EndOfAnnouncementAck);
1646 assert_wire_enum!(AnnouncementPlayMode);
1647 assert_wire_enum!(AnnouncementPlayStatus);
1648 assert_wire_enum!(MessageWaitingResult);
1649 assert_wire_enum!(IpAddressType);
1650 assert_wire_enum!(ResetType);
1651 assert_wire_enum!(DtmfMode);
1652 assert_wire_enum!(CallForwardKind);
1653 assert_wire_enum!(CallPriority);
1654 assert_wire_enum!(NotificationPriority);
1655 assert_wire_enum!(CallInfoVisibility);
1656 assert_wire_enum!(CallSecurityState);
1657 assert_wire_enum!(BusyLampFieldState);
1658 assert_wire_enum!(SubscriptionCause);
1659 assert_wire_enum!(VideoFormat);
1660 assert_wire_enum!(MiscCommandType);
1661 assert_wire_enum!(EchoCancellation);
1662 assert_wire_enum!(SilenceSuppression);
1663 assert_wire_enum!(G723BitRate);
1664 assert_wire_enum!(UnregisterStatus);
1665 assert_wire_enum!(ButtonType);
1666 assert_wire_enum!(EncryptionMethod);
1667 assert_wire_enum!(EncryptionCapability);
1668 assert_wire_enum!(CallHistoryDisposition);
1669 assert_wire_enum!(SpeakerMode);
1670 assert_wire_enum!(MicrophoneMode);
1671 assert_wire_enum!(ConferenceResourceType);
1672 assert_wire_enum!(CreateConferenceResult);
1673 assert_wire_enum!(DeleteConferenceResult);
1674 assert_wire_enum!(ModifyConferenceResult);
1675 assert_wire_enum!(AddParticipantResult);
1676 assert_wire_enum!(AuditParticipantResult);
1677 }
1678
1679 #[test]
1680 fn codec_metadata_covers_static_and_cisco_dynamic_payloads() {
1681 assert_eq!(Codec::Pcmu.rtp_payload_type(), Some(0));
1682 assert_eq!(Codec::G711Ulaw56k.rtp_payload_type(), Some(0));
1683 assert_eq!(Codec::Pcma.rtp_payload_type(), Some(8));
1684 assert_eq!(Codec::G72248k.rtp_payload_type(), Some(9));
1685 assert_eq!(Codec::Wideband256k.rtp_payload_type(), Some(25));
1686 assert_eq!(Codec::Ilbc.rtp_payload_type(), Some(97));
1687 assert_eq!(Codec::G7221_32k.rtp_payload_type(), Some(102));
1688 assert_eq!(Codec::Opus.rtp_payload_type(), Some(107));
1689 assert_eq!(Codec::G726_32k.rtp_payload_type(), Some(112));
1690 assert_eq!(Codec::Wideband256k.sample_rate(), Some(16_000));
1691 assert_eq!(Codec::H264.kind(), CodecKind::Video);
1692 assert_eq!(Codec::ClearChannel.kind(), CodecKind::Data);
1693 }
1694}