2 * Routines for AMR dissection
3 * Copyright 2005-2008, Anders Broman <anders.broman[at]ericsson.com>
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * RFC 3267 http://www.ietf.org/rfc/rfc3267.txt?number=3267
27 * 3GPP TS 26.101 for AMR-NB, 3GPP TS 26.201 for AMR-WB
34 #include <epan/packet.h>
35 #include <epan/expert.h>
36 #include <epan/oids.h>
37 #include <epan/asn1.h>
39 #include <epan/prefs.h>
43 #define AMR_NO_TRANS 15
48 /* Initialize the protocol and registered fields */
49 static int proto_amr = -1;
50 static int hf_amr_nb_cmr = -1;
51 static int hf_amr_wb_cmr = -1;
52 static int hf_amr_reserved = -1;
53 static int hf_amr_toc_f = -1;
54 static int hf_amr_nb_toc_ft = -1;
55 static int hf_amr_wb_toc_ft = -1;
56 static int hf_amr_toc_q = -1;
58 static int hf_amr_nb_if1_ft = -1;
59 static int hf_amr_wb_if1_ft = -1;
60 static int hf_amr_if1_fqi = -1;
61 static int hf_amr_nb_if1_mode_req = -1;
62 static int hf_amr_wb_if1_mode_req = -1;
63 static int hf_amr_if1_sti = -1;
64 static int hf_amr_nb_if1_mode_ind = -1;
65 static int hf_amr_wb_if1_mode_ind = -1;
66 static int hf_amr_nb_if1_sti_mode_ind = -1;
67 static int hf_amr_wb_if1_sti_mode_ind = -1;
68 static int hf_amr_if2_sti = -1;
69 static int hf_amr_nb_if2_sti_mode_ind = -1;
70 static int hf_amr_wb_if2_sti_mode_ind = -1;
72 static int hf_amr_nb_if2_ft = -1;
73 static int hf_amr_wb_if2_ft = -1;
76 /* Initialize the subtree pointers */
77 static int ett_amr = -1;
78 static int ett_amr_toc = -1;
80 /* The dynamic payload type which will be dissected as AMR */
82 static guint temp_dynamic_payload_type = 0;
83 static gint amr_encoding_type = 0;
84 static gint pref_amr_mode = AMR_NB;
87 /* Currently only octet aligned works */
88 /* static gboolean octet_aligned = TRUE; */
90 static const value_string amr_encoding_type_value[] = {
92 {1, "RFC 3267 bandwidth-efficient mode"},
99 /* Table 1a of 3GPP TS 26.201*/
100 static const value_string amr_nb_codec_mode_vals[] = {
101 {0, "AMR 4,75 kbit/s"},
102 {1, "AMR 5,15 kbit/s"},
103 {2, "AMR 5,90 kbit/s"},
104 {3, "AMR 6,70 kbit/s (PDC-EFR)"},
105 {4, "AMR 7,40 kbit/s (TDMA-EFR)"},
106 {5, "AMR 7,95 kbit/s"},
107 {6, "AMR 10,2 kbit/s"},
108 {7, "AMR 12,2 kbit/s (GSM-EFR)"},
109 {AMR_NB_SID, "AMR SID (Comfort Noise Frame)"},
111 {10, "TDMA-EFR SID "},
113 {12, "Illegal Frametype - for future use"},
114 {13, "Illegal Frametype - for future use"},
115 {14, "Illegal Frametype - for future use"},
116 {AMR_NO_TRANS, "No Data (No transmission/No reception)"},
119 static value_string_ext amr_nb_codec_mode_vals_ext = VALUE_STRING_EXT_INIT(amr_nb_codec_mode_vals);
121 static const value_string amr_wb_codec_mode_vals[] = {
122 {0, "AMR-WB 6.60 kbit/s"},
123 {1, "AMR-WB 8.85 kbit/s"},
124 {2, "AMR-WB 12.65 kbit/s"},
125 {3, "AMR-WB 14.25 kbit/s"},
126 {4, "AMR-WB 15.85 kbit/s"},
127 {5, "AMR-WB 18.25 kbit/s"},
128 {6, "AMR-WB 19.85 kbit/s"},
129 {7, "AMR-WB 23.05 kbit/s"},
130 {8, "AMR-WB 23.85 kbit/s"},
131 {AMR_WB_SID, "AMR-WB SID (Comfort Noise Frame)"},
132 {10, "Illegal Frametype"},
133 {11, "Illegal Frametype"},
134 {12, "Illegal Frametype"},
135 {13, "Illegal Frametype"},
137 {AMR_NO_TRANS, "No Data (No transmission/No reception)"},
141 static value_string_ext amr_wb_codec_mode_vals_ext = VALUE_STRING_EXT_INIT(amr_wb_codec_mode_vals);
143 /* Ref 3GPP TS 26.101 table 1a for AMR-NB*/
145 /* From RFC3267 chapter 4.3.1
146 CMR (4 bits): Indicates a codec mode request sent to the speech
147 encoder at the site of the receiver of this payload. The value of
148 the CMR field is set to the frame type index of the corresponding
149 speech mode being requested. The frame type index may be 0-7 for
150 AMR, as defined in Table 1a in [2], or 0-8 for AMR-WB, as defined
151 in Table 1a in [3GPP TS 26.201]. CMR value 15 indicates that no
152 mode request is present, and other values are for future use.
154 static const value_string amr_nb_codec_mode_request_vals[] = {
155 {0, "AMR 4,75 kbit/s"},
156 {1, "AMR 5,15 kbit/s"},
157 {2, "AMR 5,90 kbit/s"},
158 {3, "AMR 6,70 kbit/s (PDC-EFR)"},
159 {4, "AMR 7,40 kbit/s (TDMA-EFR)"},
160 {5, "AMR 7,95 kbit/s"},
161 {6, "AMR 10,2 kbit/s"},
162 {7, "AMR 12,2 kbit/s (GSM-EFR)"},
163 {8, "Illegal Frametype - For future use"},
164 {9, "Illegal Frametype - For future use"},
165 {10, "Illegal Frametype - For future use"},
166 {11, "Illegal Frametype - For future use"},
167 {12, "Illegal Frametype - For future use"},
168 {13, "Illegal Frametype - For future use"},
169 {14, "Illegal Frametype - For future use"},
170 {15, "No mode request"},
173 static value_string_ext amr_nb_codec_mode_request_vals_ext = VALUE_STRING_EXT_INIT(amr_nb_codec_mode_request_vals);
175 /* Ref 3GPP TS 26.201 table 1a for AMR-WB*/
176 static const value_string amr_wb_codec_mode_request_vals[] = {
177 {0, "AMR-WB 6.60 kbit/s"},
178 {1, "AMR-WB 8.85 kbit/s"},
179 {2, "AMR-WB 12.65 kbit/s"},
180 {3, "AMR-WB 14.25 kbit/s"},
181 {4, "AMR-WB 15.85 kbit/s"},
182 {5, "AMR-WB 18.25 kbit/s"},
183 {6, "AMR-WB 19.85 kbit/s"},
184 {7, "AMR-WB 23.05 kbit/s"},
185 {8, "AMR-WB 23.85 kbit/s"},
186 {9, "Illegal Frametype - For future use"},
187 {10, "Illegal Frametype - For future use"},
188 {11, "Illegal Frametype - For future use"},
189 {12, "Illegal Frametype - For future use"},
190 {13, "Illegal Frametype - For future use"},
191 {14, "Illegal Frametype - For future use"},
192 {15, "No mode request"},
195 static value_string_ext amr_wb_codec_mode_request_vals_ext = VALUE_STRING_EXT_INIT(amr_wb_codec_mode_request_vals);
197 static const true_false_string toc_f_bit_vals = {
198 "Followed by another speech frame",
199 "Last frame in this payload"
202 static const true_false_string toc_q_bit_vals = {
204 "Severely damaged frame"
207 static const true_false_string amr_sti_vals = {
212 /* See 3GPP TS 26.101 chapter 4 for AMR-NB IF1 */
214 dissect_amr_nb_if1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
219 proto_tree_add_item(tree, hf_amr_nb_if1_ft, tvb, offset, 1, ENC_BIG_ENDIAN);
220 proto_tree_add_item(tree, hf_amr_if1_fqi, tvb, offset, 1, ENC_BIG_ENDIAN);
221 octet = (tvb_get_guint8(tvb,offset) & 0xf0) >> 4;
222 if (octet == AMR_NB_SID) {
223 ti = proto_tree_add_item(tree, hf_amr_nb_if1_mode_req, tvb, offset+1, 1, ENC_BIG_ENDIAN);
224 if (tvb_get_guint8(tvb,offset+1) & 0x1f)
225 expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "Error:Spare bits not 0");
226 proto_tree_add_text(tree, tvb, offset+2, 5, "Speech data");
227 proto_tree_add_item(tree, hf_amr_if1_sti, tvb, offset+7, 1, ENC_BIG_ENDIAN);
228 proto_tree_add_item(tree, hf_amr_nb_if1_sti_mode_ind, tvb, offset+7, 1, ENC_BIG_ENDIAN);
232 proto_tree_add_item(tree, hf_amr_nb_if1_mode_ind, tvb, offset, 1, ENC_BIG_ENDIAN);
234 ti = proto_tree_add_item(tree, hf_amr_nb_if1_mode_req, tvb, offset, 1, ENC_BIG_ENDIAN);
235 if (tvb_get_guint8(tvb,offset) & 0x1f)
236 expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "Error:Spare bits not 0");
238 proto_tree_add_text(tree, tvb, offset, -1, "Speech data");
241 /* See 3GPP TS 26.201 for AMR-WB */
243 dissect_amr_wb_if1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
248 proto_tree_add_item(tree, hf_amr_wb_if1_ft, tvb, offset, 1, ENC_BIG_ENDIAN);
249 ti = proto_tree_add_item(tree, hf_amr_if1_fqi, tvb, offset, 1, ENC_BIG_ENDIAN);
250 if (tvb_get_guint8(tvb,offset) & 0x03)
251 expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "Error:Spare bits not 0");
252 octet = (tvb_get_guint8(tvb,offset) & 0xf0) >> 4;
253 if (octet == AMR_WB_SID) {
254 proto_tree_add_item(tree, hf_amr_wb_if1_mode_req, tvb, offset+1, 1, ENC_BIG_ENDIAN);
255 proto_tree_add_text(tree, tvb, offset+2, 4, "Speech data");
256 proto_tree_add_item(tree, hf_amr_if1_sti, tvb, offset+7, 1, ENC_BIG_ENDIAN);
257 proto_tree_add_item(tree, hf_amr_wb_if1_sti_mode_ind, tvb, offset+7, 1, ENC_BIG_ENDIAN);
262 proto_tree_add_item(tree, hf_amr_wb_if1_mode_ind, tvb, offset, 1, ENC_BIG_ENDIAN);
263 proto_tree_add_item(tree, hf_amr_wb_if1_mode_req, tvb, offset, 1, ENC_BIG_ENDIAN);
265 proto_tree_add_text(tree, tvb, offset, -1, "Speech data");
269 dissect_amr_nb_if2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
273 proto_tree_add_item(tree, hf_amr_nb_if2_ft, tvb, offset, 1, ENC_BIG_ENDIAN);
274 octet = tvb_get_guint8(tvb,offset) & 0x0f;
276 if (octet == AMR_NB_SID) {
277 proto_tree_add_text(tree, tvb, offset+1, 3, "Speech data");
278 proto_tree_add_item(tree, hf_amr_if2_sti, tvb, offset+4, 1, ENC_BIG_ENDIAN);
279 proto_tree_add_item(tree, hf_amr_nb_if2_sti_mode_ind, tvb, offset+5, 1, ENC_BIG_ENDIAN);
282 if (octet == AMR_NO_TRANS)
284 proto_tree_add_text(tree, tvb, offset+1, -1, "Speech data");
286 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
287 val_to_str_ext(octet, &amr_nb_codec_mode_request_vals_ext, "Unknown (%d)" ));
291 dissect_amr_wb_if2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
295 proto_tree_add_item(tree, hf_amr_wb_if2_ft, tvb, offset, 1, ENC_BIG_ENDIAN);
296 octet = (tvb_get_guint8(tvb,offset) & 0xf0) >> 4;
298 if (octet == AMR_WB_SID) {
299 proto_tree_add_text(tree, tvb, offset+1, 4, "Speech data");
300 proto_tree_add_item(tree, hf_amr_if2_sti, tvb, offset+5, 1, ENC_BIG_ENDIAN);
301 proto_tree_add_item(tree, hf_amr_wb_if2_sti_mode_ind, tvb, offset+5, 1, ENC_BIG_ENDIAN);
304 if (octet == AMR_NO_TRANS)
306 proto_tree_add_text(tree, tvb, offset+1, -1, "Speech data");
308 col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
309 val_to_str_ext(octet, &amr_wb_codec_mode_request_vals_ext, "Unknown (%d)" ));
313 dissect_amr_be(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint amr_mode) {
317 int bitcount; /*bitcounter, MSB = bit 0, over bytes*/
318 int bits_used_for_frames = 0;
319 int bytes_needed_for_frames;
322 /* Number of bits per frame for AMR-NB, see Table 1 RFC3267*/
323 /* Values taken for GSM-EFR SID, TDMA-EFR SID and PDC-EFR SID from 3GPP 26.101 Table A.1b */
325 /* Frame type 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
326 unsigned char Framebits_NB[] = {95,103,118,134,148,159,204,244,39,43,38,37, 0, 0, 0, 0};
328 /* Number of bits per frame for AMR-WB, see 3GPP TS 26.201 Table 2*/
329 /* Frame type 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
330 unsigned int Framebits_WB[] = {132,177,253,285,317,365,397,461,477, 40, 0, 0, 0, 0, 0, 0,};
336 if (amr_mode == AMR_NB)
337 proto_tree_add_bits_item(tree, hf_amr_nb_cmr, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
339 proto_tree_add_bits_item(tree, hf_amr_wb_cmr, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
342 /* In bandwidth-efficient mode, a ToC entry takes the following format:
349 * F (1 bit): If set to 1, indicates that this frame is followed by
350 * another speech frame in this payload; if set to 0, indicates that
351 * this frame is the last frame in this payload.
353 * FT (4 bits): Frame type index, indicating either the AMR or AMR-WB
354 * speech coding mode or comfort noise (SID) mode of the
355 * corresponding frame carried in this payload.
360 f_bit = tvb_get_bits8(tvb, bit_offset, 1);
361 proto_tree_add_bits_item(tree, hf_amr_toc_f, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
363 ft = tvb_get_bits8(tvb, bit_offset, 4);
364 if (amr_mode == AMR_NB)
365 item = proto_tree_add_bits_item(tree, hf_amr_nb_toc_ft, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
367 item = proto_tree_add_bits_item(tree, hf_amr_wb_toc_ft, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
371 if (amr_mode == AMR_NB)
372 bits_used_for_frames += Framebits_NB[ft];
374 bits_used_for_frames += Framebits_WB[ft];
376 q_bit = tvb_get_bits8(tvb, bit_offset, 1);
377 proto_tree_add_bits_item(tree, hf_amr_toc_q, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
381 proto_item_append_text(item, " / Frame OK");
383 proto_item_append_text(item, " / Frame damaged");
384 } while ((f_bit == 1) && (tvb_reported_length_remaining(tvb, bitcount/8) > 2));
386 if (bits_used_for_frames > 0)
387 bytes_needed_for_frames = 1 + (bitcount+bits_used_for_frames)/8-bitcount/8;
389 bytes_needed_for_frames = 0;
391 /* Check if we have enough data available for our frames */
392 if (tvb_reported_length_remaining(tvb, bitcount/8) < bytes_needed_for_frames) {
393 item = proto_tree_add_text(tree, tvb, bitcount/8, bytes_needed_for_frames, "Error:");
394 proto_item_append_text(item, " %d Bytes available, %d would be needed!",
395 tvb_reported_length_remaining(tvb, bitcount/8),
396 bytes_needed_for_frames);
397 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Not enough data for the frames according to TOC");
400 item = proto_tree_add_text(tree, tvb, bitcount/8, bytes_needed_for_frames, "Frame Data");
401 proto_item_append_text(item, " (%d Bytes)",bytes_needed_for_frames);
404 bitcount += bits_used_for_frames;
406 if (tvb_reported_length_remaining(tvb, (bitcount+8)/8) > 0) {
407 item = proto_tree_add_text(tree, tvb, bitcount/8, tvb_reported_length_remaining(tvb, bitcount/8), "Error:");
408 proto_item_append_text(item, " %d Bytes remaining - should be 0!",tvb_reported_length_remaining(tvb, (bitcount+8)/8));
409 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Superfluous data remaining");
411 /* Now check the paddings */
412 if (bitcount%8 != 0) {
413 if ( (1 << (8 -(bitcount%8)-1)) & tvb_get_guint8(tvb,bitcount/8) )
414 proto_tree_add_text(tree, tvb, bitcount/8, 1, "Padding bits correct");
416 item = proto_tree_add_text(tree, tvb, bitcount/8, 1, "Padding bits error");
417 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Padding bits error - MUST be 0");
423 /* Code to actually dissect the packets */
425 dissect_amr_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint amr_mode)
433 /* Set up structures needed to add the protocol subtree and manage it */
434 proto_item *ti,*toc_item;
435 proto_tree *amr_tree, *toc_tree;
437 ti = proto_tree_add_item(tree, proto_amr, tvb, 0, -1, ENC_NA);
438 amr_tree = proto_item_add_subtree(ti, ett_amr);
440 proto_tree_add_text(amr_tree, tvb, offset, -1, "Payload decoded as %s",
441 val_to_str(amr_encoding_type, amr_encoding_type_value, "Unknown value - Error"));
443 switch (amr_encoding_type) {
444 case 0: /* RFC 3267 Byte aligned */
446 case 1: /* RFC 3267 Bandwidth-efficient */
447 dissect_amr_be(tvb, pinfo, amr_tree, amr_mode);
449 case 2: /* AMR IF1 */
450 if (amr_mode == AMR_NB)
451 dissect_amr_nb_if1(tvb, pinfo, amr_tree);
453 dissect_amr_wb_if1(tvb, pinfo, amr_tree);
455 case 3: /* AMR IF2 */
456 if (amr_mode == AMR_NB)
457 dissect_amr_nb_if2(tvb, pinfo, amr_tree);
459 dissect_amr_wb_if2(tvb, pinfo, amr_tree);
465 if (amr_mode == AMR_NB)
466 proto_tree_add_bits_item(amr_tree, hf_amr_nb_cmr, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
468 proto_tree_add_bits_item(amr_tree, hf_amr_wb_cmr, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
471 octet = tvb_get_guint8(tvb,offset) & 0x0f;
473 item = proto_tree_add_text(amr_tree, tvb, offset, -1,
474 "Reserved != 0, wrongly encoded or not octet aligned."
475 " Decoding as bandwidth-efficient mode");
476 PROTO_ITEM_SET_GENERATED(item);
481 proto_tree_add_item(amr_tree, hf_amr_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
485 * A ToC entry takes the following format in octet-aligned mode:
492 * F (1 bit): see definition in Section 4.3.2.
494 * FT (4 bits unsigned integer): see definition in Section 4.3.2.
496 * Q (1 bit): see definition in Section 4.3.2.
498 * P bits: padding bits, MUST be set to zero.
500 octet = tvb_get_guint8(tvb,offset);
501 toc_item = proto_tree_add_text(amr_tree, tvb, offset, -1, "Payload Table of Contents");
502 toc_tree = proto_item_add_subtree(toc_item, ett_amr_toc);
505 while ((( octet& 0x80 ) == 0x80) || (first_time == TRUE)) {
507 octet = tvb_get_guint8(tvb,offset);
509 proto_tree_add_bits_item(toc_tree, hf_amr_toc_f, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
511 if (amr_mode == AMR_NB)
512 proto_tree_add_bits_item(toc_tree, hf_amr_nb_toc_ft, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
514 proto_tree_add_bits_item(toc_tree, hf_amr_wb_toc_ft, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
516 proto_tree_add_bits_item(toc_tree, hf_amr_toc_q, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
525 /* Code to actually dissect the packets */
527 dissect_amr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
530 /* Make entries in Protocol column and Info column on summary display */
531 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AMR");
533 dissect_amr_common(tvb, pinfo, tree, pref_amr_mode);
537 dissect_amr_wb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
540 /* Make entries in Protocol column and Info column on summary display */
541 col_set_str(pinfo->cinfo, COL_PROTOCOL, "AMR-WB");
542 dissect_amr_common(tvb, pinfo, tree, AMR_WB);
546 typedef struct _amr_capability_t {
549 new_dissector_t content_pdu;
552 static amr_capability_t amr_capability_tab[] = {
553 /* ITU-T H.241 (05/2006), 8.3 H.264 capabilities */
554 { "GenericCapability/0.0.8.245.1.1.1", "H.245 - GSM AMR Capability Identifier", NULL },
555 { "GenericCapability/0.0.8.245.1.1.1/collapsing/0", "maxAl-sduAudioFrames", NULL },
556 { "GenericCapability/0.0.8.245.1.1.1/collapsing/1", "bitRate", NULL },
557 { "GenericCapability/0.0.8.245.1.1.1/collapsing/2", "gsmAmrComfortNoise", NULL },
558 { "GenericCapability/0.0.8.245.1.1.1/collapsing/3", "gsmEfrComfortNoise", NULL },
559 { "GenericCapability/0.0.8.245.1.1.1/collapsing/4", "is-641ComfortNoise", NULL },
560 { "GenericCapability/0.0.8.245.1.1.1/collapsing/5", "pdcEFRComfortNoise", NULL },
561 /* ITU-T Rec. G.722.2/Annex F (11/2002) */
562 { "GenericCapability/0.0.7.7222.1.0/collapsing/0", "maxAl-sduFrames", NULL },
563 { "GenericCapability/0.0.7.7222.1.0/collapsing/1", "bitRate", NULL },
564 { "GenericCapability/0.0.7.7222.1.0/collapsing/2", "octetAlign", NULL },
565 { "GenericCapability/0.0.7.7222.1.0/collapsing/3", "modeSet", NULL },
566 { "GenericCapability/0.0.7.7222.1.0/collapsing/4", "modeChangePeriod", NULL },
567 { "GenericCapability/0.0.7.7222.1.0/collapsing/5", "modeChangeNeighbour", NULL },
568 { "GenericCapability/0.0.7.7222.1.0/collapsing/6", "crc", NULL },
569 { "GenericCapability/0.0.7.7222.1.0/collapsing/7", "robustSorting", NULL },
570 { "GenericCapability/0.0.7.7222.1.0/collapsing/8", "interleaving", NULL },
571 { NULL, NULL, NULL },
574 static amr_capability_t *find_cap(const gchar *id) {
575 amr_capability_t *ftr = NULL;
578 for (f=amr_capability_tab; f->id; f++) {
579 if (!strcmp(id, f->id)) {
588 dissect_amr_name(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree)
592 actx = get_asn1_ctx(pinfo->private_data);
593 DISSECTOR_ASSERT(actx != NULL);
594 if (tree && actx != NULL) {
595 amr_capability_t *ftr;
596 ftr = find_cap(pinfo->match_string);
598 proto_item_append_text(actx->created_item, " - %s", ftr->name);
599 proto_item_append_text(proto_item_get_parent(proto_tree_get_parent(tree)), ": %s", ftr->name);
601 proto_item_append_text(actx->created_item, " - unknown(%s)", pinfo->match_string);
606 void proto_reg_handoff_amr(void);
609 proto_register_amr(void)
611 module_t *amr_module;
613 static hf_register_info hf[] = {
615 { "CMR", "amr.nb.cmr",
616 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_request_vals_ext, 0x0,
617 "codec mode request", HFILL }
620 { "CMR", "amr.wb.cmr",
621 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_request_vals_ext, 0x0,
622 "codec mode request", HFILL }
625 { "Reserved", "amr.reserved",
626 FT_UINT8, BASE_DEC, NULL, 0x0f,
627 "Reserved bits", HFILL }
630 { "F bit", "amr.toc.f",
631 FT_BOOLEAN, BASE_NONE, TFS(&toc_f_bit_vals), 0x0,
635 { "FT bits", "amr.nb.toc.ft",
636 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_request_vals_ext, 0x0,
637 "Frame type index", HFILL }
640 { "FT bits", "amr.wb.toc.ft",
641 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_request_vals_ext, 0x0,
642 "Frame type index", HFILL }
645 { "Q bit", "amr.toc.q",
646 FT_BOOLEAN, BASE_NONE, TFS(&toc_q_bit_vals), 0x0,
647 "Frame quality indicator bit", HFILL }
650 { "Frame Type", "amr.nb.if1.ft",
651 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_vals_ext, 0xf0,
655 { "Frame Type", "amr.wb.if1.ft",
656 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_vals_ext, 0xf0,
659 { &hf_amr_nb_if1_mode_req,
660 { "Mode Type request", "amr.nb.if1.modereq",
661 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_request_vals_ext, 0xe0,
664 { &hf_amr_wb_if1_mode_req,
665 { "Mode Type request", "amr.wb.if1.modereq",
666 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_request_vals_ext, 0x0f,
670 { "SID Type Indicator", "amr.if1.sti",
671 FT_BOOLEAN, 8, TFS(&amr_sti_vals), 0x10,
674 { &hf_amr_nb_if1_sti_mode_ind,
675 { "Mode Type indication", "amr.nb.if1.stimodeind",
676 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_vals_ext, 0x0e,
679 { &hf_amr_wb_if1_sti_mode_ind,
680 { "Mode Type indication", "amr.wb.if1.stimodeind",
681 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_vals_ext, 0x0f,
684 { &hf_amr_nb_if1_mode_ind,
685 { "Mode Type indication", "amr.nb.if1.modeind",
686 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_vals_ext, 0x07,
689 { &hf_amr_wb_if1_mode_ind,
690 { "Mode Type indication", "amr.wb.if1.modeind",
691 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_vals_ext, 0xf0,
695 { "Frame Type", "amr.nb.if2.ft",
696 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_vals_ext, 0x0f,
700 { "Frame Type", "amr.wb.if2.ft",
701 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_vals_ext, 0xf0,
705 { "SID Type Indicator", "amr.if2.sti",
706 FT_BOOLEAN, 8, TFS(&amr_sti_vals), 0x80,
709 { &hf_amr_nb_if2_sti_mode_ind,
710 { "Mode Type indication", "amr.nb.if2.stimodeind",
711 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_vals_ext, 0x07,
714 { &hf_amr_wb_if2_sti_mode_ind,
715 { "Mode Type indication", "amr.wb.if2.stimodeind",
716 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_vals_ext, 0x78,
721 FT_BOOLEAN, 8, TFS(&toc_q_bit_vals), 0x08,
722 "Frame quality indicator bit", HFILL }
726 /* Setup protocol subtree array */
727 static gint *ett[] = {
731 static const enum_val_t encoding_types[] = {
732 {"RFC 3267 Byte aligned", "RFC 3267 octet aligned", 0},
733 {"RFC 3267 Bandwidth-efficient", "RFC 3267 BW-efficient", 1},
734 {"AMR IF1", "AMR IF1", 2},
735 {"AMR IF2", "AMR IF2", 3},
739 static const enum_val_t modes[] = {
740 {"AMR-NB", "Narrowband AMR", AMR_NB},
741 {"AMR-WB", "Wideband AMR", AMR_WB},
745 /* Register the protocol name and description */
746 proto_amr = proto_register_protocol("Adaptive Multi-Rate","AMR", "amr");
748 /* Required function calls to register the header fields and subtrees used */
749 proto_register_field_array(proto_amr, hf, array_length(hf));
750 proto_register_subtree_array(ett, array_length(ett));
751 /* Register a configuration option for port */
753 amr_module = prefs_register_protocol(proto_amr, proto_reg_handoff_amr);
755 prefs_register_uint_preference(amr_module, "dynamic.payload.type",
756 "AMR dynamic payload type",
757 "The dynamic payload type which will be interpreted as AMR"
758 "; The value must be greater than 95",
760 &temp_dynamic_payload_type);
762 prefs_register_enum_preference(amr_module, "encoding.version",
763 "Type of AMR encoding of the payload",
764 "Type of AMR encoding of the payload",
765 &amr_encoding_type, encoding_types, FALSE);
767 prefs_register_enum_preference(amr_module, "mode",
770 &pref_amr_mode, modes, AMR_NB);
772 register_dissector("amr", dissect_amr, proto_amr);
773 register_dissector("amr-wb", dissect_amr_wb, proto_amr);
774 register_dissector("amr_if1_nb", dissect_amr_nb_if1, proto_amr);
775 register_dissector("amr_if1_wb", dissect_amr_wb_if1, proto_amr);
776 register_dissector("amr_if2_nb", dissect_amr_nb_if2, proto_amr);
777 register_dissector("amr_if2_wb", dissect_amr_wb_if2, proto_amr);
779 oid_add_from_string("G.722.2 (AMR-WB) audio capability","0.0.7.7222.1.0");
782 /* Register the protocol with Wireshark */
784 proto_reg_handoff_amr(void)
786 static dissector_handle_t amr_handle;
787 static guint dynamic_payload_type;
788 static gboolean amr_prefs_initialized = FALSE;
790 if (!amr_prefs_initialized) {
791 dissector_handle_t amr_name_handle;
792 dissector_handle_t amr_wb_handle;
793 amr_capability_t *ftr;
795 amr_handle = find_dissector("amr");
796 amr_wb_handle = find_dissector("amr-wb");
797 dissector_add_string("rtp_dyn_payload_type","AMR", amr_handle);
798 dissector_add_string("rtp_dyn_payload_type","AMR-WB", amr_wb_handle);
801 * Register H.245 Generic parameter name(s)
803 amr_name_handle = create_dissector_handle(dissect_amr_name, proto_amr);
804 for (ftr=amr_capability_tab; ftr->id; ftr++) {
806 dissector_add_string("h245.gef.name", ftr->id, amr_name_handle);
807 if (ftr->content_pdu)
808 dissector_add_string("h245.gef.content", ftr->id,
809 new_create_dissector_handle(ftr->content_pdu, proto_amr));
811 /* Activate the next line for testing with the randpkt tool
812 dissector_add_uint("udp.port", 55555, amr_handle);
814 amr_prefs_initialized = TRUE;
816 if ( dynamic_payload_type > 95 )
817 dissector_delete_uint("rtp.pt", dynamic_payload_type, amr_handle);
820 dynamic_payload_type = temp_dynamic_payload_type;
822 if ( dynamic_payload_type > 95 ) {
823 dissector_add_uint("rtp.pt", dynamic_payload_type, amr_handle);
828 * Editor modelines - http://www.wireshark.org/tools/modelines.html
833 * indent-tabs-mode: nil
836 * vi: set shiftwidth=4 tabstop=8 expandtab:
837 * :indentSize=4:tabSize=8:noTabs=true: