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 static expert_field ei_amr_spare_bit_not0
= EI_INIT
;
81 static expert_field ei_amr_not_enough_data_for_frames
= EI_INIT
;
82 static expert_field ei_amr_superfluous_data
= EI_INIT
;
83 static expert_field ei_amr_padding_bits_not0
= EI_INIT
;
85 /* The dynamic payload type which will be dissected as AMR */
87 static guint temp_dynamic_payload_type
= 0;
88 static gint amr_encoding_type
= 0;
89 static gint pref_amr_mode
= AMR_NB
;
92 /* Currently only octet aligned works */
93 /* static gboolean octet_aligned = TRUE; */
95 static const value_string amr_encoding_type_value
[] = {
97 {1, "RFC 3267 bandwidth-efficient mode"},
104 /* Table 1a of 3GPP TS 26.201*/
105 static const value_string amr_nb_codec_mode_vals
[] = {
106 {0, "AMR 4,75 kbit/s"},
107 {1, "AMR 5,15 kbit/s"},
108 {2, "AMR 5,90 kbit/s"},
109 {3, "AMR 6,70 kbit/s (PDC-EFR)"},
110 {4, "AMR 7,40 kbit/s (TDMA-EFR)"},
111 {5, "AMR 7,95 kbit/s"},
112 {6, "AMR 10,2 kbit/s"},
113 {7, "AMR 12,2 kbit/s (GSM-EFR)"},
114 {AMR_NB_SID
, "AMR SID (Comfort Noise Frame)"},
116 {10, "TDMA-EFR SID "},
118 {12, "Illegal Frametype - for future use"},
119 {13, "Illegal Frametype - for future use"},
120 {14, "Illegal Frametype - for future use"},
121 {AMR_NO_TRANS
, "No Data (No transmission/No reception)"},
124 static value_string_ext amr_nb_codec_mode_vals_ext
= VALUE_STRING_EXT_INIT(amr_nb_codec_mode_vals
);
126 static const value_string amr_wb_codec_mode_vals
[] = {
127 {0, "AMR-WB 6.60 kbit/s"},
128 {1, "AMR-WB 8.85 kbit/s"},
129 {2, "AMR-WB 12.65 kbit/s"},
130 {3, "AMR-WB 14.25 kbit/s"},
131 {4, "AMR-WB 15.85 kbit/s"},
132 {5, "AMR-WB 18.25 kbit/s"},
133 {6, "AMR-WB 19.85 kbit/s"},
134 {7, "AMR-WB 23.05 kbit/s"},
135 {8, "AMR-WB 23.85 kbit/s"},
136 {AMR_WB_SID
, "AMR-WB SID (Comfort Noise Frame)"},
137 {10, "Illegal Frametype"},
138 {11, "Illegal Frametype"},
139 {12, "Illegal Frametype"},
140 {13, "Illegal Frametype"},
142 {AMR_NO_TRANS
, "No Data (No transmission/No reception)"},
146 static value_string_ext amr_wb_codec_mode_vals_ext
= VALUE_STRING_EXT_INIT(amr_wb_codec_mode_vals
);
148 /* Ref 3GPP TS 26.101 table 1a for AMR-NB*/
150 /* From RFC3267 chapter 4.3.1
151 CMR (4 bits): Indicates a codec mode request sent to the speech
152 encoder at the site of the receiver of this payload. The value of
153 the CMR field is set to the frame type index of the corresponding
154 speech mode being requested. The frame type index may be 0-7 for
155 AMR, as defined in Table 1a in [2], or 0-8 for AMR-WB, as defined
156 in Table 1a in [3GPP TS 26.201]. CMR value 15 indicates that no
157 mode request is present, and other values are for future use.
159 static const value_string amr_nb_codec_mode_request_vals
[] = {
160 {0, "AMR 4,75 kbit/s"},
161 {1, "AMR 5,15 kbit/s"},
162 {2, "AMR 5,90 kbit/s"},
163 {3, "AMR 6,70 kbit/s (PDC-EFR)"},
164 {4, "AMR 7,40 kbit/s (TDMA-EFR)"},
165 {5, "AMR 7,95 kbit/s"},
166 {6, "AMR 10,2 kbit/s"},
167 {7, "AMR 12,2 kbit/s (GSM-EFR)"},
168 {8, "Illegal Frametype - For future use"},
169 {9, "Illegal Frametype - For future use"},
170 {10, "Illegal Frametype - For future use"},
171 {11, "Illegal Frametype - For future use"},
172 {12, "Illegal Frametype - For future use"},
173 {13, "Illegal Frametype - For future use"},
174 {14, "Illegal Frametype - For future use"},
175 {15, "No mode request"},
178 static value_string_ext amr_nb_codec_mode_request_vals_ext
= VALUE_STRING_EXT_INIT(amr_nb_codec_mode_request_vals
);
180 /* Ref 3GPP TS 26.201 table 1a for AMR-WB*/
181 static const value_string amr_wb_codec_mode_request_vals
[] = {
182 {0, "AMR-WB 6.60 kbit/s"},
183 {1, "AMR-WB 8.85 kbit/s"},
184 {2, "AMR-WB 12.65 kbit/s"},
185 {3, "AMR-WB 14.25 kbit/s"},
186 {4, "AMR-WB 15.85 kbit/s"},
187 {5, "AMR-WB 18.25 kbit/s"},
188 {6, "AMR-WB 19.85 kbit/s"},
189 {7, "AMR-WB 23.05 kbit/s"},
190 {8, "AMR-WB 23.85 kbit/s"},
191 {9, "Illegal Frametype - For future use"},
192 {10, "Illegal Frametype - For future use"},
193 {11, "Illegal Frametype - For future use"},
194 {12, "Illegal Frametype - For future use"},
195 {13, "Illegal Frametype - For future use"},
196 {14, "Illegal Frametype - For future use"},
197 {15, "No mode request"},
200 static value_string_ext amr_wb_codec_mode_request_vals_ext
= VALUE_STRING_EXT_INIT(amr_wb_codec_mode_request_vals
);
202 static const true_false_string toc_f_bit_vals
= {
203 "Followed by another speech frame",
204 "Last frame in this payload"
207 static const true_false_string toc_q_bit_vals
= {
209 "Severely damaged frame"
212 static const true_false_string amr_sti_vals
= {
217 /* See 3GPP TS 26.101 chapter 4 for AMR-NB IF1 */
219 dissect_amr_nb_if1(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
) {
224 proto_tree_add_item(tree
, hf_amr_nb_if1_ft
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
225 proto_tree_add_item(tree
, hf_amr_if1_fqi
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
226 octet
= (tvb_get_guint8(tvb
,offset
) & 0xf0) >> 4;
227 if (octet
== AMR_NB_SID
) {
228 ti
= proto_tree_add_item(tree
, hf_amr_nb_if1_mode_req
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
229 if (tvb_get_guint8(tvb
,offset
+1) & 0x1f)
230 expert_add_info(pinfo
, ti
, &ei_amr_spare_bit_not0
);
231 proto_tree_add_text(tree
, tvb
, offset
+2, 5, "Speech data");
232 proto_tree_add_item(tree
, hf_amr_if1_sti
, tvb
, offset
+7, 1, ENC_BIG_ENDIAN
);
233 proto_tree_add_item(tree
, hf_amr_nb_if1_sti_mode_ind
, tvb
, offset
+7, 1, ENC_BIG_ENDIAN
);
237 proto_tree_add_item(tree
, hf_amr_nb_if1_mode_ind
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
239 ti
= proto_tree_add_item(tree
, hf_amr_nb_if1_mode_req
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
240 if (tvb_get_guint8(tvb
,offset
) & 0x1f)
241 expert_add_info(pinfo
, ti
, &ei_amr_spare_bit_not0
);
243 proto_tree_add_text(tree
, tvb
, offset
, -1, "Speech data");
246 /* See 3GPP TS 26.201 for AMR-WB */
248 dissect_amr_wb_if1(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
) {
253 proto_tree_add_item(tree
, hf_amr_wb_if1_ft
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
254 ti
= proto_tree_add_item(tree
, hf_amr_if1_fqi
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
255 if (tvb_get_guint8(tvb
,offset
) & 0x03)
256 expert_add_info(pinfo
, ti
, &ei_amr_spare_bit_not0
);
257 octet
= (tvb_get_guint8(tvb
,offset
) & 0xf0) >> 4;
258 if (octet
== AMR_WB_SID
) {
259 proto_tree_add_item(tree
, hf_amr_wb_if1_mode_req
, tvb
, offset
+1, 1, ENC_BIG_ENDIAN
);
260 proto_tree_add_text(tree
, tvb
, offset
+2, 4, "Speech data");
261 proto_tree_add_item(tree
, hf_amr_if1_sti
, tvb
, offset
+7, 1, ENC_BIG_ENDIAN
);
262 proto_tree_add_item(tree
, hf_amr_wb_if1_sti_mode_ind
, tvb
, offset
+7, 1, ENC_BIG_ENDIAN
);
267 proto_tree_add_item(tree
, hf_amr_wb_if1_mode_ind
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
268 proto_tree_add_item(tree
, hf_amr_wb_if1_mode_req
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
270 proto_tree_add_text(tree
, tvb
, offset
, -1, "Speech data");
274 dissect_amr_nb_if2(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
) {
278 proto_tree_add_item(tree
, hf_amr_nb_if2_ft
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
279 octet
= tvb_get_guint8(tvb
,offset
) & 0x0f;
281 if (octet
== AMR_NB_SID
) {
282 proto_tree_add_text(tree
, tvb
, offset
+1, 3, "Speech data");
283 proto_tree_add_item(tree
, hf_amr_if2_sti
, tvb
, offset
+4, 1, ENC_BIG_ENDIAN
);
284 proto_tree_add_item(tree
, hf_amr_nb_if2_sti_mode_ind
, tvb
, offset
+5, 1, ENC_BIG_ENDIAN
);
287 if (octet
== AMR_NO_TRANS
)
289 proto_tree_add_text(tree
, tvb
, offset
+1, -1, "Speech data");
291 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s ",
292 val_to_str_ext(octet
, &amr_nb_codec_mode_request_vals_ext
, "Unknown (%d)" ));
296 dissect_amr_wb_if2(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
) {
300 proto_tree_add_item(tree
, hf_amr_wb_if2_ft
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
301 octet
= (tvb_get_guint8(tvb
,offset
) & 0xf0) >> 4;
303 if (octet
== AMR_WB_SID
) {
304 proto_tree_add_text(tree
, tvb
, offset
+1, 4, "Speech data");
305 proto_tree_add_item(tree
, hf_amr_if2_sti
, tvb
, offset
+5, 1, ENC_BIG_ENDIAN
);
306 proto_tree_add_item(tree
, hf_amr_wb_if2_sti_mode_ind
, tvb
, offset
+5, 1, ENC_BIG_ENDIAN
);
309 if (octet
== AMR_NO_TRANS
)
311 proto_tree_add_text(tree
, tvb
, offset
+1, -1, "Speech data");
313 col_append_fstr(pinfo
->cinfo
, COL_INFO
, "%s ",
314 val_to_str_ext(octet
, &amr_wb_codec_mode_request_vals_ext
, "Unknown (%d)" ));
318 dissect_amr_be(tvbuff_t
*tvb
, packet_info
*pinfo _U_
, proto_tree
*tree
, gint amr_mode
) {
322 int bitcount
; /*bitcounter, MSB = bit 0, over bytes*/
323 int bits_used_for_frames
= 0;
324 int bytes_needed_for_frames
;
327 /* Number of bits per frame for AMR-NB, see Table 1 RFC3267*/
328 /* Values taken for GSM-EFR SID, TDMA-EFR SID and PDC-EFR SID from 3GPP 26.101 Table A.1b */
330 /* Frame type 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
331 unsigned char Framebits_NB
[] = {95,103,118,134,148,159,204,244,39,43,38,37, 0, 0, 0, 0};
333 /* Number of bits per frame for AMR-WB, see 3GPP TS 26.201 Table 2*/
334 /* Frame type 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 */
335 unsigned int Framebits_WB
[] = {132,177,253,285,317,365,397,461,477, 40, 0, 0, 0, 0, 0, 0,};
341 if (amr_mode
== AMR_NB
)
342 proto_tree_add_bits_item(tree
, hf_amr_nb_cmr
, tvb
, bit_offset
, 4, ENC_BIG_ENDIAN
);
344 proto_tree_add_bits_item(tree
, hf_amr_wb_cmr
, tvb
, bit_offset
, 4, ENC_BIG_ENDIAN
);
347 /* In bandwidth-efficient mode, a ToC entry takes the following format:
354 * F (1 bit): If set to 1, indicates that this frame is followed by
355 * another speech frame in this payload; if set to 0, indicates that
356 * this frame is the last frame in this payload.
358 * FT (4 bits): Frame type index, indicating either the AMR or AMR-WB
359 * speech coding mode or comfort noise (SID) mode of the
360 * corresponding frame carried in this payload.
365 f_bit
= tvb_get_bits8(tvb
, bit_offset
, 1);
366 proto_tree_add_bits_item(tree
, hf_amr_toc_f
, tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
);
368 ft
= tvb_get_bits8(tvb
, bit_offset
, 4);
369 if (amr_mode
== AMR_NB
)
370 item
= proto_tree_add_bits_item(tree
, hf_amr_nb_toc_ft
, tvb
, bit_offset
, 4, ENC_BIG_ENDIAN
);
372 item
= proto_tree_add_bits_item(tree
, hf_amr_wb_toc_ft
, tvb
, bit_offset
, 4, ENC_BIG_ENDIAN
);
376 if (amr_mode
== AMR_NB
)
377 bits_used_for_frames
+= Framebits_NB
[ft
];
379 bits_used_for_frames
+= Framebits_WB
[ft
];
381 q_bit
= tvb_get_bits8(tvb
, bit_offset
, 1);
382 proto_tree_add_bits_item(tree
, hf_amr_toc_q
, tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
);
386 proto_item_append_text(item
, " / Frame OK");
388 proto_item_append_text(item
, " / Frame damaged");
389 } while ((f_bit
== 1) && (tvb_reported_length_remaining(tvb
, bitcount
/8) > 2));
391 if (bits_used_for_frames
> 0)
392 bytes_needed_for_frames
= 1 + (bitcount
+bits_used_for_frames
)/8-bitcount
/8;
394 bytes_needed_for_frames
= 0;
396 /* Check if we have enough data available for our frames */
397 if (tvb_reported_length_remaining(tvb
, bitcount
/8) < bytes_needed_for_frames
) {
398 item
= proto_tree_add_text(tree
, tvb
, bitcount
/8, bytes_needed_for_frames
,
399 "Error: %d Bytes available, %d would be needed!",
400 tvb_reported_length_remaining(tvb
, bitcount
/8),
401 bytes_needed_for_frames
);
402 expert_add_info(pinfo
, item
, &ei_amr_not_enough_data_for_frames
);
405 item
= proto_tree_add_text(tree
, tvb
, bitcount
/8, bytes_needed_for_frames
, "Frame Data");
406 proto_item_append_text(item
, " (%d Bytes)",bytes_needed_for_frames
);
409 bitcount
+= bits_used_for_frames
;
411 if (tvb_reported_length_remaining(tvb
, (bitcount
+8)/8) > 0) {
412 item
= proto_tree_add_text(tree
, tvb
, bitcount
/8, tvb_reported_length_remaining(tvb
, bitcount
/8),
413 "Error: %d Bytes remaining - should be 0!",tvb_reported_length_remaining(tvb
, (bitcount
+8)/8));
414 expert_add_info(pinfo
, item
, &ei_amr_superfluous_data
);
416 /* Now check the paddings */
417 if (bitcount
%8 != 0) {
418 if ( (1 << (8 -(bitcount
%8)-1)) & tvb_get_guint8(tvb
,bitcount
/8) )
419 proto_tree_add_text(tree
, tvb
, bitcount
/8, 1, "Padding bits correct");
421 proto_tree_add_expert(tree
, pinfo
, &ei_amr_padding_bits_not0
, tvb
,
428 /* Code to actually dissect the packets */
430 dissect_amr_common(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
, gint amr_mode
)
438 /* Set up structures needed to add the protocol subtree and manage it */
439 proto_item
*ti
,*toc_item
;
440 proto_tree
*amr_tree
, *toc_tree
;
442 ti
= proto_tree_add_item(tree
, proto_amr
, tvb
, 0, -1, ENC_NA
);
443 amr_tree
= proto_item_add_subtree(ti
, ett_amr
);
445 proto_tree_add_text(amr_tree
, tvb
, offset
, -1, "Payload decoded as %s",
446 val_to_str_const(amr_encoding_type
, amr_encoding_type_value
, "Unknown value - Error"));
448 switch (amr_encoding_type
) {
449 case 0: /* RFC 3267 Byte aligned */
451 case 1: /* RFC 3267 Bandwidth-efficient */
452 dissect_amr_be(tvb
, pinfo
, amr_tree
, amr_mode
);
454 case 2: /* AMR IF1 */
455 if (amr_mode
== AMR_NB
)
456 dissect_amr_nb_if1(tvb
, pinfo
, amr_tree
);
458 dissect_amr_wb_if1(tvb
, pinfo
, amr_tree
);
460 case 3: /* AMR IF2 */
461 if (amr_mode
== AMR_NB
)
462 dissect_amr_nb_if2(tvb
, pinfo
, amr_tree
);
464 dissect_amr_wb_if2(tvb
, pinfo
, amr_tree
);
470 if (amr_mode
== AMR_NB
)
471 proto_tree_add_bits_item(amr_tree
, hf_amr_nb_cmr
, tvb
, bit_offset
, 4, ENC_BIG_ENDIAN
);
473 proto_tree_add_bits_item(amr_tree
, hf_amr_wb_cmr
, tvb
, bit_offset
, 4, ENC_BIG_ENDIAN
);
476 octet
= tvb_get_guint8(tvb
,offset
) & 0x0f;
478 item
= proto_tree_add_text(amr_tree
, tvb
, offset
, -1,
479 "Reserved != 0, wrongly encoded or not octet aligned."
480 " Decoding as bandwidth-efficient mode");
481 PROTO_ITEM_SET_GENERATED(item
);
486 proto_tree_add_item(amr_tree
, hf_amr_reserved
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
490 * A ToC entry takes the following format in octet-aligned mode:
497 * F (1 bit): see definition in Section 4.3.2.
499 * FT (4 bits unsigned integer): see definition in Section 4.3.2.
501 * Q (1 bit): see definition in Section 4.3.2.
503 * P bits: padding bits, MUST be set to zero.
505 octet
= tvb_get_guint8(tvb
,offset
);
506 toc_item
= proto_tree_add_text(amr_tree
, tvb
, offset
, -1, "Payload Table of Contents");
507 toc_tree
= proto_item_add_subtree(toc_item
, ett_amr_toc
);
510 while ((( octet
& 0x80 ) == 0x80) || (first_time
== TRUE
)) {
512 octet
= tvb_get_guint8(tvb
,offset
);
514 proto_tree_add_bits_item(toc_tree
, hf_amr_toc_f
, tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
);
516 if (amr_mode
== AMR_NB
)
517 proto_tree_add_bits_item(toc_tree
, hf_amr_nb_toc_ft
, tvb
, bit_offset
, 4, ENC_BIG_ENDIAN
);
519 proto_tree_add_bits_item(toc_tree
, hf_amr_wb_toc_ft
, tvb
, bit_offset
, 4, ENC_BIG_ENDIAN
);
521 proto_tree_add_bits_item(toc_tree
, hf_amr_toc_q
, tvb
, bit_offset
, 1, ENC_BIG_ENDIAN
);
530 /* Code to actually dissect the packets */
532 dissect_amr(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
535 /* Make entries in Protocol column and Info column on summary display */
536 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "AMR");
538 dissect_amr_common(tvb
, pinfo
, tree
, pref_amr_mode
);
542 dissect_amr_wb(tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*tree
)
545 /* Make entries in Protocol column and Info column on summary display */
546 col_set_str(pinfo
->cinfo
, COL_PROTOCOL
, "AMR-WB");
547 dissect_amr_common(tvb
, pinfo
, tree
, AMR_WB
);
551 typedef struct _amr_capability_t
{
554 new_dissector_t content_pdu
;
557 static amr_capability_t amr_capability_tab
[] = {
558 /* ITU-T H.241 (05/2006), 8.3 H.264 capabilities */
559 { "GenericCapability/0.0.8.245.1.1.1", "H.245 - GSM AMR Capability Identifier", NULL
},
560 { "GenericCapability/0.0.8.245.1.1.1/collapsing/0", "maxAl-sduAudioFrames", NULL
},
561 { "GenericCapability/0.0.8.245.1.1.1/collapsing/1", "bitRate", NULL
},
562 { "GenericCapability/0.0.8.245.1.1.1/collapsing/2", "gsmAmrComfortNoise", NULL
},
563 { "GenericCapability/0.0.8.245.1.1.1/collapsing/3", "gsmEfrComfortNoise", NULL
},
564 { "GenericCapability/0.0.8.245.1.1.1/collapsing/4", "is-641ComfortNoise", NULL
},
565 { "GenericCapability/0.0.8.245.1.1.1/collapsing/5", "pdcEFRComfortNoise", NULL
},
566 /* ITU-T Rec. G.722.2/Annex F (11/2002) */
567 { "GenericCapability/0.0.7.7222.1.0/collapsing/0", "maxAl-sduFrames", NULL
},
568 { "GenericCapability/0.0.7.7222.1.0/collapsing/1", "bitRate", NULL
},
569 { "GenericCapability/0.0.7.7222.1.0/collapsing/2", "octetAlign", NULL
},
570 { "GenericCapability/0.0.7.7222.1.0/collapsing/3", "modeSet", NULL
},
571 { "GenericCapability/0.0.7.7222.1.0/collapsing/4", "modeChangePeriod", NULL
},
572 { "GenericCapability/0.0.7.7222.1.0/collapsing/5", "modeChangeNeighbour", NULL
},
573 { "GenericCapability/0.0.7.7222.1.0/collapsing/6", "crc", NULL
},
574 { "GenericCapability/0.0.7.7222.1.0/collapsing/7", "robustSorting", NULL
},
575 { "GenericCapability/0.0.7.7222.1.0/collapsing/8", "interleaving", NULL
},
576 { NULL
, NULL
, NULL
},
579 static amr_capability_t
*find_cap(const gchar
*id
) {
580 amr_capability_t
*ftr
= NULL
;
583 for (f
=amr_capability_tab
; f
->id
; f
++) {
584 if (!strcmp(id
, f
->id
)) {
593 dissect_amr_name(tvbuff_t
*tvb _U_
, packet_info
*pinfo
, proto_tree
*tree
, void* data
)
595 asn1_ctx_t
*actx
= get_asn1_ctx(data
);
597 DISSECTOR_ASSERT(actx
!= NULL
);
598 if (tree
&& (actx
!= NULL
)) {
599 amr_capability_t
*ftr
;
600 ftr
= find_cap(pinfo
->match_string
);
602 proto_item_append_text(actx
->created_item
, " - %s", ftr
->name
);
603 proto_item_append_text(proto_item_get_parent(proto_tree_get_parent(tree
)), ": %s", ftr
->name
);
605 proto_item_append_text(actx
->created_item
, " - unknown(%s)", pinfo
->match_string
);
609 return tvb_length(tvb
);
612 void proto_reg_handoff_amr(void);
615 proto_register_amr(void)
617 module_t
*amr_module
;
618 expert_module_t
* expert_amr
;
620 static hf_register_info hf
[] = {
622 { "CMR", "amr.nb.cmr",
623 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_nb_codec_mode_request_vals_ext
, 0x0,
624 "codec mode request", HFILL
}
627 { "CMR", "amr.wb.cmr",
628 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_wb_codec_mode_request_vals_ext
, 0x0,
629 "codec mode request", HFILL
}
632 { "Reserved", "amr.reserved",
633 FT_UINT8
, BASE_DEC
, NULL
, 0x0f,
634 "Reserved bits", HFILL
}
637 { "F bit", "amr.toc.f",
638 FT_BOOLEAN
, BASE_NONE
, TFS(&toc_f_bit_vals
), 0x0,
642 { "FT bits", "amr.nb.toc.ft",
643 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_nb_codec_mode_vals_ext
, 0x0,
644 "Frame type index", HFILL
}
647 { "FT bits", "amr.wb.toc.ft",
648 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_wb_codec_mode_vals_ext
, 0x0,
649 "Frame type index", HFILL
}
652 { "Q bit", "amr.toc.q",
653 FT_BOOLEAN
, BASE_NONE
, TFS(&toc_q_bit_vals
), 0x0,
654 "Frame quality indicator bit", HFILL
}
657 { "Frame Type", "amr.nb.if1.ft",
658 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_nb_codec_mode_vals_ext
, 0xf0,
662 { "Frame Type", "amr.wb.if1.ft",
663 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_wb_codec_mode_vals_ext
, 0xf0,
666 { &hf_amr_nb_if1_mode_req
,
667 { "Mode Type request", "amr.nb.if1.modereq",
668 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_nb_codec_mode_request_vals_ext
, 0xe0,
671 { &hf_amr_wb_if1_mode_req
,
672 { "Mode Type request", "amr.wb.if1.modereq",
673 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_wb_codec_mode_request_vals_ext
, 0x0f,
677 { "SID Type Indicator", "amr.if1.sti",
678 FT_BOOLEAN
, 8, TFS(&amr_sti_vals
), 0x10,
681 { &hf_amr_nb_if1_sti_mode_ind
,
682 { "Mode Type indication", "amr.nb.if1.stimodeind",
683 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_nb_codec_mode_vals_ext
, 0x0e,
686 { &hf_amr_wb_if1_sti_mode_ind
,
687 { "Mode Type indication", "amr.wb.if1.stimodeind",
688 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_wb_codec_mode_vals_ext
, 0x0f,
691 { &hf_amr_nb_if1_mode_ind
,
692 { "Mode Type indication", "amr.nb.if1.modeind",
693 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_nb_codec_mode_vals_ext
, 0x07,
696 { &hf_amr_wb_if1_mode_ind
,
697 { "Mode Type indication", "amr.wb.if1.modeind",
698 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_wb_codec_mode_vals_ext
, 0xf0,
702 { "Frame Type", "amr.nb.if2.ft",
703 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_nb_codec_mode_vals_ext
, 0x0f,
707 { "Frame Type", "amr.wb.if2.ft",
708 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_wb_codec_mode_vals_ext
, 0xf0,
712 { "SID Type Indicator", "amr.if2.sti",
713 FT_BOOLEAN
, 8, TFS(&amr_sti_vals
), 0x80,
716 { &hf_amr_nb_if2_sti_mode_ind
,
717 { "Mode Type indication", "amr.nb.if2.stimodeind",
718 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_nb_codec_mode_vals_ext
, 0x07,
721 { &hf_amr_wb_if2_sti_mode_ind
,
722 { "Mode Type indication", "amr.wb.if2.stimodeind",
723 FT_UINT8
, BASE_DEC
|BASE_EXT_STRING
, &amr_wb_codec_mode_vals_ext
, 0x78,
728 FT_BOOLEAN
, 8, TFS(&toc_q_bit_vals
), 0x08,
729 "Frame quality indicator bit", HFILL
}
733 /* Setup protocol subtree array */
734 static gint
*ett
[] = {
739 static ei_register_info ei
[] = {
740 { &ei_amr_spare_bit_not0
, { "amr.spare_bit_not0", PI_PROTOCOL
, PI_WARN
, "Error:Spare bits not 0", EXPFILL
}},
741 { &ei_amr_not_enough_data_for_frames
, { "amr.not_enough_data_for_frames", PI_MALFORMED
, PI_ERROR
, "Not enough data for the frames according to TOC", EXPFILL
}},
742 { &ei_amr_superfluous_data
, { "amr.superfluous_data", PI_MALFORMED
, PI_ERROR
, "Superfluous data remaining", EXPFILL
}},
743 { &ei_amr_padding_bits_not0
, { "amr.padding_bits_not0", PI_MALFORMED
, PI_ERROR
, "Padding bits error - MUST be 0", EXPFILL
}},
746 static const enum_val_t encoding_types
[] = {
747 {"RFC 3267 Byte aligned", "RFC 3267 octet aligned", 0},
748 {"RFC 3267 Bandwidth-efficient", "RFC 3267 BW-efficient", 1},
749 {"AMR IF1", "AMR IF1", 2},
750 {"AMR IF2", "AMR IF2", 3},
754 static const enum_val_t modes
[] = {
755 {"AMR-NB", "Narrowband AMR", AMR_NB
},
756 {"AMR-WB", "Wideband AMR", AMR_WB
},
760 /* Register the protocol name and description */
761 proto_amr
= proto_register_protocol("Adaptive Multi-Rate","AMR", "amr");
763 /* Required function calls to register the header fields and subtrees used */
764 proto_register_field_array(proto_amr
, hf
, array_length(hf
));
765 proto_register_subtree_array(ett
, array_length(ett
));
766 expert_amr
= expert_register_protocol(proto_amr
);
767 expert_register_field_array(expert_amr
, ei
, array_length(ei
));
768 /* Register a configuration option for port */
770 amr_module
= prefs_register_protocol(proto_amr
, proto_reg_handoff_amr
);
772 prefs_register_uint_preference(amr_module
, "dynamic.payload.type",
773 "AMR dynamic payload type",
774 "The dynamic payload type which will be interpreted as AMR"
775 "; The value must be greater than 95",
777 &temp_dynamic_payload_type
);
779 prefs_register_enum_preference(amr_module
, "encoding.version",
780 "Type of AMR encoding of the payload",
781 "Type of AMR encoding of the payload",
782 &amr_encoding_type
, encoding_types
, FALSE
);
784 prefs_register_enum_preference(amr_module
, "mode",
787 &pref_amr_mode
, modes
, AMR_NB
);
789 register_dissector("amr", dissect_amr
, proto_amr
);
790 register_dissector("amr-wb", dissect_amr_wb
, proto_amr
);
791 register_dissector("amr_if1_nb", dissect_amr_nb_if1
, proto_amr
);
792 register_dissector("amr_if1_wb", dissect_amr_wb_if1
, proto_amr
);
793 register_dissector("amr_if2_nb", dissect_amr_nb_if2
, proto_amr
);
794 register_dissector("amr_if2_wb", dissect_amr_wb_if2
, proto_amr
);
796 oid_add_from_string("G.722.2 (AMR-WB) audio capability","0.0.7.7222.1.0");
799 /* Register the protocol with Wireshark */
801 proto_reg_handoff_amr(void)
803 static dissector_handle_t amr_handle
;
804 static guint dynamic_payload_type
;
805 static gboolean amr_prefs_initialized
= FALSE
;
807 if (!amr_prefs_initialized
) {
808 dissector_handle_t amr_name_handle
;
809 dissector_handle_t amr_wb_handle
;
810 amr_capability_t
*ftr
;
812 amr_handle
= find_dissector("amr");
813 amr_wb_handle
= find_dissector("amr-wb");
814 dissector_add_string("rtp_dyn_payload_type","AMR", amr_handle
);
815 dissector_add_string("rtp_dyn_payload_type","AMR-WB", amr_wb_handle
);
818 * Register H.245 Generic parameter name(s)
820 amr_name_handle
= new_create_dissector_handle(dissect_amr_name
, proto_amr
);
821 for (ftr
=amr_capability_tab
; ftr
->id
; ftr
++) {
823 dissector_add_string("h245.gef.name", ftr
->id
, amr_name_handle
);
824 if (ftr
->content_pdu
)
825 dissector_add_string("h245.gef.content", ftr
->id
,
826 new_create_dissector_handle(ftr
->content_pdu
, proto_amr
));
828 /* Activate the next line for testing with the randpkt tool
829 dissector_add_uint("udp.port", 55555, amr_handle);
831 amr_prefs_initialized
= TRUE
;
833 if ( dynamic_payload_type
> 95 )
834 dissector_delete_uint("rtp.pt", dynamic_payload_type
, amr_handle
);
837 dynamic_payload_type
= temp_dynamic_payload_type
;
839 if ( dynamic_payload_type
> 95 ) {
840 dissector_add_uint("rtp.pt", dynamic_payload_type
, amr_handle
);
845 * Editor modelines - http://www.wireshark.org/tools/modelines.html
850 * indent-tabs-mode: nil
853 * vi: set shiftwidth=4 tabstop=8 expandtab:
854 * :indentSize=4:tabSize=8:noTabs=true: