Have asn1_ctx_t passed into the "h245.gef.name" and "h245.gef.content" subdissectors...
[metze/wireshark/wip.git] / epan / dissectors / packet-amr.c
1 /* packet-amr.c
2  * Routines for AMR dissection
3  * Copyright 2005-2008, Anders Broman <anders.broman[at]ericsson.com>
4  *
5  * $Id$
6  *
7  * Wireshark - Network traffic analyzer
8  * By Gerald Combs <gerald@wireshark.org>
9  * Copyright 1998 Gerald Combs
10  *
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.
15  *
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.
20  *
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.
24  *
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
28  */
29
30 #include "config.h"
31
32 #include <glib.h>
33
34 #include <epan/packet.h>
35 #include <epan/expert.h>
36 #include <epan/oids.h>
37 #include <epan/asn1.h>
38
39 #include <epan/prefs.h>
40
41 #define AMR_NB_SID 8
42 #define AMR_WB_SID 9
43 #define AMR_NO_TRANS 15
44
45 #define AMR_NB 0
46 #define AMR_WB 1
47
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;
57
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;
71
72 static int hf_amr_nb_if2_ft = -1;
73 static int hf_amr_wb_if2_ft = -1;
74
75
76 /* Initialize the subtree pointers */
77 static int ett_amr = -1;
78 static int ett_amr_toc = -1;
79
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;
84
85 /* The dynamic payload type which will be dissected as AMR */
86
87 static guint temp_dynamic_payload_type = 0;
88 static gint  amr_encoding_type         = 0;
89 static gint  pref_amr_mode             = AMR_NB;
90
91
92 /* Currently only octet aligned works */
93 /* static gboolean octet_aligned = TRUE; */
94
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 }
101 };
102
103
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 }
123 };
124 static value_string_ext amr_nb_codec_mode_vals_ext = VALUE_STRING_EXT_INIT(amr_nb_codec_mode_vals);
125
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 }
144 };
145
146 static value_string_ext amr_wb_codec_mode_vals_ext = VALUE_STRING_EXT_INIT(amr_wb_codec_mode_vals);
147
148 /* Ref 3GPP TS 26.101 table 1a for AMR-NB*/
149
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.
158 */
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 }
177 };
178 static value_string_ext amr_nb_codec_mode_request_vals_ext = VALUE_STRING_EXT_INIT(amr_nb_codec_mode_request_vals);
179
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 }
199 };
200 static value_string_ext amr_wb_codec_mode_request_vals_ext = VALUE_STRING_EXT_INIT(amr_wb_codec_mode_request_vals);
201
202 static const true_false_string toc_f_bit_vals = {
203     "Followed by another speech frame",
204     "Last frame in this payload"
205 };
206
207 static const true_false_string toc_q_bit_vals = {
208     "Ok",
209     "Severely damaged frame"
210 };
211
212 static const true_false_string amr_sti_vals = {
213     "SID_UPDATE",
214     "SID_FIRST"
215 };
216
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;
223
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;
235     }
236
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");
244 }
245
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;
252
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;
264     }
265
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");
271 }
272
273 static void
274 dissect_amr_nb_if2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
275     int    offset = 0;
276     guint8 octet;
277
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;
280
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;
286     }
287     if (octet == AMR_NO_TRANS)
288         return;
289     proto_tree_add_text(tree, tvb, offset+1, -1, "Speech data");
290
291     col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
292             val_to_str_ext(octet, &amr_nb_codec_mode_request_vals_ext, "Unknown (%d)" ));
293 }
294
295 static void
296 dissect_amr_wb_if2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
297     int    offset = 0;
298     guint8 octet;
299
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;
302
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;
308     }
309     if (octet == AMR_NO_TRANS)
310         return;
311     proto_tree_add_text(tree, tvb, offset+1, -1, "Speech data");
312
313     col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
314             val_to_str_ext(octet, &amr_wb_codec_mode_request_vals_ext, "Unknown (%d)" ));
315 }
316
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;
326
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 */
329
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};
332
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,};
336
337
338     /* Chapter 4.3 */
339
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);
345
346     bit_offset += 4;
347     /* In bandwidth-efficient mode, a ToC entry takes the following format:
348      *
349      *    0 1 2 3 4 5
350      *   +-+-+-+-+-+-+
351      *   |F|  FT   |Q|
352      *   +-+-+-+-+-+-+
353      *
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.
357      *
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.
361      */
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);
373
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));
390
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;
395
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);
403     }
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);
407     }
408
409     bitcount += bits_used_for_frames;
410
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);
415
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);
423             }
424         }
425     }
426 }
427
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)
431 {
432     int         offset     = 0;
433     int         bit_offset = 0;
434     guint8      octet;
435     proto_item *item;
436     gboolean    first_time;
437
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;
441
442     ti = proto_tree_add_item(tree, proto_amr, tvb, 0, -1, ENC_NA);
443     amr_tree = proto_item_add_subtree(ti, ett_amr);
444
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"));
447
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;
468     }
469
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);
474
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;
483
484     }
485
486     proto_tree_add_item(amr_tree, hf_amr_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
487     offset     += 1;
488     bit_offset += 4;
489     /*
490      *  A ToC entry takes the following format in octet-aligned mode:
491      *
492      *    0 1 2 3 4 5 6 7
493      *   +-+-+-+-+-+-+-+-+
494      *   |F|  FT   |Q|P|P|
495      *   +-+-+-+-+-+-+-+-+
496      *
497      *   F (1 bit): see definition in Section 4.3.2.
498      *
499      *   FT (4 bits unsigned integer): see definition in Section 4.3.2.
500      *
501      *   Q (1 bit): see definition in Section 4.3.2.
502      *
503      *   P bits: padding bits, MUST be set to zero.
504      */
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);
508
509     first_time = TRUE;
510     while ((( octet& 0x80 ) == 0x80) || (first_time == TRUE)) {
511         first_time = FALSE;
512         octet = tvb_get_guint8(tvb,offset);
513
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;
526     }
527
528 }
529
530 /* Code to actually dissect the packets */
531 static void
532 dissect_amr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
533 {
534
535 /* Make entries in Protocol column and Info column on summary display */
536     col_set_str(pinfo->cinfo, COL_PROTOCOL, "AMR");
537
538     dissect_amr_common(tvb, pinfo, tree, pref_amr_mode);
539 }
540
541 static void
542 dissect_amr_wb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
543 {
544
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);
548 }
549
550
551 typedef struct _amr_capability_t {
552     const gchar     *id;
553     const gchar     *name;
554     new_dissector_t  content_pdu;
555 } amr_capability_t;
556
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 },
577 };
578
579 static amr_capability_t *find_cap(const gchar *id) {
580     amr_capability_t *ftr = NULL;
581     amr_capability_t *f;
582
583     for (f=amr_capability_tab; f->id; f++) {
584         if (!strcmp(id, f->id)) {
585             ftr = f;
586             break;
587         }
588     }
589     return ftr;
590 }
591
592 static int
593 dissect_amr_name(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree, void* data)
594 {
595     asn1_ctx_t *actx = get_asn1_ctx(data);
596
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);
606         }
607     }
608
609     return tvb_length(tvb);
610 }
611
612 void proto_reg_handoff_amr(void);
613
614 void
615 proto_register_amr(void)
616 {
617     module_t *amr_module;
618     expert_module_t* expert_amr;
619
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 }
625         },
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 }
630         },
631         { &hf_amr_reserved,
632             { "Reserved",           "amr.reserved",
633             FT_UINT8, BASE_DEC, NULL, 0x0f,
634             "Reserved bits", HFILL }
635         },
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 }
640         },
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 }
645         },
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 }
650         },
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 }
655         },
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 }
660         },
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 }
665         },
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 }
670         },
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 }
675         },
676         { &hf_amr_if1_sti,
677             { "SID Type Indicator",           "amr.if1.sti",
678             FT_BOOLEAN, 8, TFS(&amr_sti_vals), 0x10,
679             NULL, HFILL }
680         },
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 }
685         },
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 }
690         },
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 }
695         },
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 }
700         },
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 }
705         },
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 }
710         },
711         { &hf_amr_if2_sti,
712             { "SID Type Indicator",           "amr.if2.sti",
713             FT_BOOLEAN, 8, TFS(&amr_sti_vals), 0x80,
714             NULL, HFILL }
715         },
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 }
720         },
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 }
725         },
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 }
730         },
731     };
732
733 /* Setup protocol subtree array */
734     static gint *ett[] = {
735         &ett_amr,
736         &ett_amr_toc,
737     };
738
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 }},
744     };
745
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}
752     };
753
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}
758     };
759
760 /* Register the protocol name and description */
761     proto_amr = proto_register_protocol("Adaptive Multi-Rate","AMR", "amr");
762
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 */
769
770     amr_module = prefs_register_protocol(proto_amr, proto_reg_handoff_amr);
771
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",
776                        10,
777                        &temp_dynamic_payload_type);
778
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);
783
784     prefs_register_enum_preference(amr_module, "mode",
785                        "The AMR mode",
786                        "The AMR mode",
787                        &pref_amr_mode, modes, AMR_NB);
788
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);
795
796     oid_add_from_string("G.722.2 (AMR-WB) audio capability","0.0.7.7222.1.0");
797 }
798
799 /* Register the protocol with Wireshark */
800 void
801 proto_reg_handoff_amr(void)
802 {
803     static dissector_handle_t amr_handle;
804     static guint              dynamic_payload_type;
805     static gboolean           amr_prefs_initialized = FALSE;
806
807     if (!amr_prefs_initialized) {
808         dissector_handle_t  amr_name_handle;
809         dissector_handle_t  amr_wb_handle;
810         amr_capability_t   *ftr;
811
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);
816
817         /*
818          * Register H.245 Generic parameter name(s)
819          */
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));
827         }
828         /*  Activate the next line for testing with the randpkt tool
829             dissector_add_uint("udp.port", 55555, amr_handle);
830         */
831         amr_prefs_initialized = TRUE;
832     } else {
833         if ( dynamic_payload_type > 95 )
834             dissector_delete_uint("rtp.pt", dynamic_payload_type, amr_handle);
835     }
836
837     dynamic_payload_type = temp_dynamic_payload_type;
838
839     if ( dynamic_payload_type > 95 ) {
840         dissector_add_uint("rtp.pt", dynamic_payload_type, amr_handle);
841     }
842 }
843
844 /*
845  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
846  *
847  * Local variables:
848  * c-basic-offset: 4
849  * tab-width: 8
850  * indent-tabs-mode: nil
851  * End:
852  *
853  * vi: set shiftwidth=4 tabstop=8 expandtab:
854  * :indentSize=4:tabSize=8:noTabs=true:
855  */