MSWSP: add two more Property Sets
[wireshark-wip.git] / epan / dissectors / packet-amr.c
blob3f15a4d5df7b804a904ed4a452859f3708c477b7
1 /* packet-amr.c
2 * Routines for AMR dissection
3 * Copyright 2005-2008, Anders Broman <anders.broman[at]ericsson.com>
5 * $Id$
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.
25 * References:
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
30 #include "config.h"
32 #include <glib.h>
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>
41 #define AMR_NB_SID 8
42 #define AMR_WB_SID 9
43 #define AMR_NO_TRANS 15
45 #define AMR_NB 0
46 #define AMR_WB 1
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[] = {
96 {0, "RFC 3267"},
97 {1, "RFC 3267 bandwidth-efficient mode"},
98 {2, "AMR IF 1"},
99 {3, "AMR IF 2"},
100 { 0, NULL }
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)"},
115 {9, "GSM-EFR SID"},
116 {10, "TDMA-EFR SID "},
117 {11, "PDC-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)"},
122 { 0, NULL }
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"},
141 {14, "Speech lost"},
142 {AMR_NO_TRANS, "No Data (No transmission/No reception)"},
143 { 0, NULL }
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"},
176 { 0, NULL }
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"},
198 { 0, NULL }
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 = {
208 "Ok",
209 "Severely damaged frame"
212 static const true_false_string amr_sti_vals = {
213 "SID_UPDATE",
214 "SID_FIRST"
217 /* See 3GPP TS 26.101 chapter 4 for AMR-NB IF1 */
218 static void
219 dissect_amr_nb_if1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
220 int offset = 0;
221 guint8 octet;
222 proto_item *ti;
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);
234 return;
237 proto_tree_add_item(tree, hf_amr_nb_if1_mode_ind, tvb, offset, 1, ENC_BIG_ENDIAN);
238 offset += 1;
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);
242 offset += 1;
243 proto_tree_add_text(tree, tvb, offset, -1, "Speech data");
246 /* See 3GPP TS 26.201 for AMR-WB */
247 static void
248 dissect_amr_wb_if1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
249 int offset = 0;
250 guint8 octet;
251 proto_item *ti;
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);
263 return;
266 offset += 1;
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);
269 offset += 1;
270 proto_tree_add_text(tree, tvb, offset, -1, "Speech data");
273 static void
274 dissect_amr_nb_if2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
275 int offset = 0;
276 guint8 octet;
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);
285 return;
287 if (octet == AMR_NO_TRANS)
288 return;
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)" ));
295 static void
296 dissect_amr_wb_if2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
297 int offset = 0;
298 guint8 octet;
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);
307 return;
309 if (octet == AMR_NO_TRANS)
310 return;
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)" ));
317 static void
318 dissect_amr_be(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint amr_mode) {
319 proto_item *item;
320 int ft;
321 int bit_offset = 0;
322 int bitcount; /*bitcounter, MSB = bit 0, over bytes*/
323 int bits_used_for_frames = 0;
324 int bytes_needed_for_frames;
325 guint8 f_bit, q_bit;
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,};
338 /* Chapter 4.3 */
340 bitcount = 3;
341 if (amr_mode == AMR_NB)
342 proto_tree_add_bits_item(tree, hf_amr_nb_cmr, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
343 else
344 proto_tree_add_bits_item(tree, hf_amr_wb_cmr, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
346 bit_offset += 4;
347 /* In bandwidth-efficient mode, a ToC entry takes the following format:
349 * 0 1 2 3 4 5
350 * +-+-+-+-+-+-+
351 * |F| FT |Q|
352 * +-+-+-+-+-+-+
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.
362 do {
363 /* Check F bit */
364 bitcount += 1;
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);
367 bit_offset += 1;
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);
371 else
372 item = proto_tree_add_bits_item(tree, hf_amr_wb_toc_ft, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
374 bit_offset += 4;
375 bitcount += 4;
376 if (amr_mode == AMR_NB)
377 bits_used_for_frames += Framebits_NB[ft];
378 else
379 bits_used_for_frames += Framebits_WB[ft];
380 /* Check Q bit */
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);
383 bit_offset += 1;
384 bitcount += 1;
385 if (q_bit == 1)
386 proto_item_append_text(item, " / Frame OK");
387 else
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;
393 else
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);
404 else {
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");
420 else {
421 proto_tree_add_expert(tree, pinfo, &ei_amr_padding_bits_not0, tvb,
422 bitcount/8, 1);
428 /* Code to actually dissect the packets */
429 static void
430 dissect_amr_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint amr_mode)
432 int offset = 0;
433 int bit_offset = 0;
434 guint8 octet;
435 proto_item *item;
436 gboolean first_time;
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 */
450 break;
451 case 1: /* RFC 3267 Bandwidth-efficient */
452 dissect_amr_be(tvb, pinfo, amr_tree, amr_mode);
453 return;
454 case 2: /* AMR IF1 */
455 if (amr_mode == AMR_NB)
456 dissect_amr_nb_if1(tvb, pinfo, amr_tree);
457 else
458 dissect_amr_wb_if1(tvb, pinfo, amr_tree);
459 return;
460 case 3: /* AMR IF2 */
461 if (amr_mode == AMR_NB)
462 dissect_amr_nb_if2(tvb, pinfo, amr_tree);
463 else
464 dissect_amr_wb_if2(tvb, pinfo, amr_tree);
465 return;
466 default:
467 break;
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);
472 else
473 proto_tree_add_bits_item(amr_tree, hf_amr_wb_cmr, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
475 bit_offset += 4;
476 octet = tvb_get_guint8(tvb,offset) & 0x0f;
477 if ( octet != 0 ) {
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);
482 return;
486 proto_tree_add_item(amr_tree, hf_amr_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
487 offset += 1;
488 bit_offset += 4;
490 * A ToC entry takes the following format in octet-aligned mode:
492 * 0 1 2 3 4 5 6 7
493 * +-+-+-+-+-+-+-+-+
494 * |F| FT |Q|P|P|
495 * +-+-+-+-+-+-+-+-+
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);
509 first_time = TRUE;
510 while ((( octet& 0x80 ) == 0x80) || (first_time == TRUE)) {
511 first_time = FALSE;
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);
515 bit_offset += 1;
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);
518 else
519 proto_tree_add_bits_item(toc_tree, hf_amr_wb_toc_ft, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
520 bit_offset += 4;
521 proto_tree_add_bits_item(toc_tree, hf_amr_toc_q, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
522 bit_offset += 1;
523 /* 2 pading bits */
524 bit_offset += 2;
525 offset += 1;
530 /* Code to actually dissect the packets */
531 static void
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);
541 static void
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 {
552 const gchar *id;
553 const gchar *name;
554 new_dissector_t content_pdu;
555 } amr_capability_t;
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;
581 amr_capability_t *f;
583 for (f=amr_capability_tab; f->id; f++) {
584 if (!strcmp(id, f->id)) {
585 ftr = f;
586 break;
589 return ftr;
592 static int
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);
601 if (ftr) {
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);
604 } else {
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);
614 void
615 proto_register_amr(void)
617 module_t *amr_module;
618 expert_module_t* expert_amr;
620 static hf_register_info hf[] = {
621 { &hf_amr_nb_cmr,
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 }
626 { &hf_amr_wb_cmr,
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 }
631 { &hf_amr_reserved,
632 { "Reserved", "amr.reserved",
633 FT_UINT8, BASE_DEC, NULL, 0x0f,
634 "Reserved bits", HFILL }
636 { &hf_amr_toc_f,
637 { "F bit", "amr.toc.f",
638 FT_BOOLEAN, BASE_NONE, TFS(&toc_f_bit_vals), 0x0,
639 NULL, HFILL }
641 { &hf_amr_nb_toc_ft,
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 }
646 { &hf_amr_wb_toc_ft,
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 }
651 { &hf_amr_toc_q,
652 { "Q bit", "amr.toc.q",
653 FT_BOOLEAN, BASE_NONE, TFS(&toc_q_bit_vals), 0x0,
654 "Frame quality indicator bit", HFILL }
656 { &hf_amr_nb_if1_ft,
657 { "Frame Type", "amr.nb.if1.ft",
658 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_vals_ext, 0xf0,
659 NULL, HFILL }
661 { &hf_amr_wb_if1_ft,
662 { "Frame Type", "amr.wb.if1.ft",
663 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_vals_ext, 0xf0,
664 NULL, HFILL }
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,
669 NULL, HFILL }
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,
674 NULL, HFILL }
676 { &hf_amr_if1_sti,
677 { "SID Type Indicator", "amr.if1.sti",
678 FT_BOOLEAN, 8, TFS(&amr_sti_vals), 0x10,
679 NULL, HFILL }
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,
684 NULL, HFILL }
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,
689 NULL, HFILL }
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,
694 NULL, HFILL }
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,
699 NULL, HFILL }
701 { &hf_amr_nb_if2_ft,
702 { "Frame Type", "amr.nb.if2.ft",
703 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_vals_ext, 0x0f,
704 NULL, HFILL }
706 { &hf_amr_wb_if2_ft,
707 { "Frame Type", "amr.wb.if2.ft",
708 FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_vals_ext, 0xf0,
709 NULL, HFILL }
711 { &hf_amr_if2_sti,
712 { "SID Type Indicator", "amr.if2.sti",
713 FT_BOOLEAN, 8, TFS(&amr_sti_vals), 0x80,
714 NULL, HFILL }
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,
719 NULL, HFILL }
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,
724 NULL, HFILL }
726 { &hf_amr_if1_fqi,
727 { "FQI", "amr.fqi",
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[] = {
735 &ett_amr,
736 &ett_amr_toc,
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},
751 {NULL, NULL, -1}
754 static const enum_val_t modes[] = {
755 {"AMR-NB", "Narrowband AMR", AMR_NB},
756 {"AMR-WB", "Wideband AMR", AMR_WB},
757 {NULL, NULL, -1}
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",
785 "The AMR mode",
786 "The AMR 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 */
800 void
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++) {
822 if (ftr->name)
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;
832 } else {
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
847 * Local variables:
848 * c-basic-offset: 4
849 * tab-width: 8
850 * indent-tabs-mode: nil
851 * End:
853 * vi: set shiftwidth=4 tabstop=8 expandtab:
854 * :indentSize=4:tabSize=8:noTabs=true: