Move 3 ASN1 dissectors to 'clean' group; move 1 PIDL dissector to 'dirty' group.
[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 /* The dynamic payload type which will be dissected as AMR */
81
82 static guint temp_dynamic_payload_type = 0;
83 static gint  amr_encoding_type         = 0;
84 static gint  pref_amr_mode             = AMR_NB;
85
86
87 /* Currently only octet aligned works */
88 /* static gboolean octet_aligned = TRUE; */
89
90 static const value_string amr_encoding_type_value[] = {
91     {0, "RFC 3267"},
92     {1, "RFC 3267 bandwidth-efficient mode"},
93     {2, "AMR IF 1"},
94     {3, "AMR IF 2"},
95     { 0,    NULL }
96 };
97
98
99 /* Table 1a of 3GPP TS 26.201*/
100 static const value_string amr_nb_codec_mode_vals[] = {
101     {0,            "AMR 4,75 kbit/s"},
102     {1,            "AMR 5,15 kbit/s"},
103     {2,            "AMR 5,90 kbit/s"},
104     {3,            "AMR 6,70 kbit/s (PDC-EFR)"},
105     {4,            "AMR 7,40 kbit/s (TDMA-EFR)"},
106     {5,            "AMR 7,95 kbit/s"},
107     {6,            "AMR 10,2 kbit/s"},
108     {7,            "AMR 12,2 kbit/s (GSM-EFR)"},
109     {AMR_NB_SID,   "AMR SID (Comfort Noise Frame)"},
110     {9,            "GSM-EFR SID"},
111     {10,           "TDMA-EFR SID "},
112     {11,           "PDC-EFR SID"},
113     {12,           "Illegal Frametype - for future use"},
114     {13,           "Illegal Frametype - for future use"},
115     {14,           "Illegal Frametype - for future use"},
116     {AMR_NO_TRANS, "No Data (No transmission/No reception)"},
117     { 0,    NULL }
118 };
119 static value_string_ext amr_nb_codec_mode_vals_ext = VALUE_STRING_EXT_INIT(amr_nb_codec_mode_vals);
120
121 static const value_string amr_wb_codec_mode_vals[] = {
122     {0,            "AMR-WB 6.60 kbit/s"},
123     {1,            "AMR-WB 8.85 kbit/s"},
124     {2,            "AMR-WB 12.65 kbit/s"},
125     {3,            "AMR-WB 14.25 kbit/s"},
126     {4,            "AMR-WB 15.85 kbit/s"},
127     {5,            "AMR-WB 18.25 kbit/s"},
128     {6,            "AMR-WB 19.85 kbit/s"},
129     {7,            "AMR-WB 23.05 kbit/s"},
130     {8,            "AMR-WB 23.85 kbit/s"},
131     {AMR_WB_SID,   "AMR-WB SID (Comfort Noise Frame)"},
132     {10,           "Illegal Frametype"},
133     {11,           "Illegal Frametype"},
134     {12,           "Illegal Frametype"},
135     {13,           "Illegal Frametype"},
136     {14,           "Speech lost"},
137     {AMR_NO_TRANS, "No Data (No transmission/No reception)"},
138     { 0,    NULL }
139 };
140
141 static value_string_ext amr_wb_codec_mode_vals_ext = VALUE_STRING_EXT_INIT(amr_wb_codec_mode_vals);
142
143 /* Ref 3GPP TS 26.101 table 1a for AMR-NB*/
144
145 /* From RFC3267 chapter 4.3.1
146 CMR (4 bits): Indicates a codec mode request sent to the speech
147       encoder at the site of the receiver of this payload.  The value of
148       the CMR field is set to the frame type index of the corresponding
149       speech mode being requested.  The frame type index may be 0-7 for
150       AMR, as defined in Table 1a in [2], or 0-8 for AMR-WB, as defined
151       in Table 1a in [3GPP TS 26.201].  CMR value 15 indicates that no
152       mode request is present, and other values are for future use.
153 */
154 static const value_string amr_nb_codec_mode_request_vals[] = {
155     {0,  "AMR 4,75 kbit/s"},
156     {1,  "AMR 5,15 kbit/s"},
157     {2,  "AMR 5,90 kbit/s"},
158     {3,  "AMR 6,70 kbit/s (PDC-EFR)"},
159     {4,  "AMR 7,40 kbit/s (TDMA-EFR)"},
160     {5,  "AMR 7,95 kbit/s"},
161     {6,  "AMR 10,2 kbit/s"},
162     {7,  "AMR 12,2 kbit/s (GSM-EFR)"},
163     {8,  "Illegal Frametype - For future use"},
164     {9,  "Illegal Frametype - For future use"},
165     {10, "Illegal Frametype - For future use"},
166     {11, "Illegal Frametype - For future use"},
167     {12, "Illegal Frametype - For future use"},
168     {13, "Illegal Frametype - For future use"},
169     {14, "Illegal Frametype - For future use"},
170     {15, "No mode request"},
171     { 0,    NULL }
172 };
173 static value_string_ext amr_nb_codec_mode_request_vals_ext = VALUE_STRING_EXT_INIT(amr_nb_codec_mode_request_vals);
174
175 /* Ref 3GPP TS 26.201 table 1a for AMR-WB*/
176 static const value_string amr_wb_codec_mode_request_vals[] = {
177     {0,  "AMR-WB 6.60 kbit/s"},
178     {1,  "AMR-WB 8.85 kbit/s"},
179     {2,  "AMR-WB 12.65 kbit/s"},
180     {3,  "AMR-WB 14.25 kbit/s"},
181     {4,  "AMR-WB 15.85 kbit/s"},
182     {5,  "AMR-WB 18.25 kbit/s"},
183     {6,  "AMR-WB 19.85 kbit/s"},
184     {7,  "AMR-WB 23.05 kbit/s"},
185     {8,  "AMR-WB 23.85 kbit/s"},
186     {9,  "Illegal Frametype - For future use"},
187     {10, "Illegal Frametype - For future use"},
188     {11, "Illegal Frametype - For future use"},
189     {12, "Illegal Frametype - For future use"},
190     {13, "Illegal Frametype - For future use"},
191     {14, "Illegal Frametype - For future use"},
192     {15, "No mode request"},
193     { 0,    NULL }
194 };
195 static value_string_ext amr_wb_codec_mode_request_vals_ext = VALUE_STRING_EXT_INIT(amr_wb_codec_mode_request_vals);
196
197 static const true_false_string toc_f_bit_vals = {
198     "Followed by another speech frame",
199     "Last frame in this payload"
200 };
201
202 static const true_false_string toc_q_bit_vals = {
203     "Ok",
204     "Severely damaged frame"
205 };
206
207 static const true_false_string amr_sti_vals = {
208     "SID_UPDATE",
209     "SID_FIRST"
210 };
211
212 /* See 3GPP TS 26.101 chapter 4 for AMR-NB IF1 */
213 static void
214 dissect_amr_nb_if1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
215     int         offset = 0;
216     guint8      octet;
217     proto_item *ti;
218
219     proto_tree_add_item(tree, hf_amr_nb_if1_ft, tvb, offset, 1, ENC_BIG_ENDIAN);
220     proto_tree_add_item(tree, hf_amr_if1_fqi,   tvb, offset, 1, ENC_BIG_ENDIAN);
221     octet = (tvb_get_guint8(tvb,offset) & 0xf0) >> 4;
222     if (octet == AMR_NB_SID) {
223         ti = proto_tree_add_item(tree, hf_amr_nb_if1_mode_req, tvb, offset+1, 1, ENC_BIG_ENDIAN);
224         if (tvb_get_guint8(tvb,offset+1) & 0x1f)
225             expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "Error:Spare bits not 0");
226         proto_tree_add_text(tree, tvb, offset+2, 5, "Speech data");
227         proto_tree_add_item(tree, hf_amr_if1_sti, tvb, offset+7, 1, ENC_BIG_ENDIAN);
228         proto_tree_add_item(tree, hf_amr_nb_if1_sti_mode_ind, tvb, offset+7, 1, ENC_BIG_ENDIAN);
229         return;
230     }
231
232     proto_tree_add_item(tree, hf_amr_nb_if1_mode_ind, tvb, offset, 1, ENC_BIG_ENDIAN);
233     offset += 1;
234     ti = proto_tree_add_item(tree, hf_amr_nb_if1_mode_req, tvb, offset, 1, ENC_BIG_ENDIAN);
235     if (tvb_get_guint8(tvb,offset) & 0x1f)
236         expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "Error:Spare bits not 0");
237     offset += 1;
238     proto_tree_add_text(tree, tvb, offset, -1, "Speech data");
239 }
240
241 /* See 3GPP TS 26.201 for AMR-WB */
242 static void
243 dissect_amr_wb_if1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
244     int         offset = 0;
245     guint8      octet;
246     proto_item *ti;
247
248     proto_tree_add_item(tree, hf_amr_wb_if1_ft, tvb, offset, 1, ENC_BIG_ENDIAN);
249     ti = proto_tree_add_item(tree, hf_amr_if1_fqi, tvb, offset, 1, ENC_BIG_ENDIAN);
250     if (tvb_get_guint8(tvb,offset) & 0x03)
251         expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN, "Error:Spare bits not 0");
252     octet = (tvb_get_guint8(tvb,offset) & 0xf0) >> 4;
253     if (octet == AMR_WB_SID) {
254         proto_tree_add_item(tree, hf_amr_wb_if1_mode_req, tvb, offset+1, 1, ENC_BIG_ENDIAN);
255         proto_tree_add_text(tree, tvb, offset+2, 4, "Speech data");
256         proto_tree_add_item(tree, hf_amr_if1_sti, tvb, offset+7, 1, ENC_BIG_ENDIAN);
257         proto_tree_add_item(tree, hf_amr_wb_if1_sti_mode_ind, tvb, offset+7, 1, ENC_BIG_ENDIAN);
258         return;
259     }
260
261     offset += 1;
262     proto_tree_add_item(tree, hf_amr_wb_if1_mode_ind, tvb, offset, 1, ENC_BIG_ENDIAN);
263     proto_tree_add_item(tree, hf_amr_wb_if1_mode_req, tvb, offset, 1, ENC_BIG_ENDIAN);
264     offset += 1;
265     proto_tree_add_text(tree, tvb, offset, -1, "Speech data");
266 }
267
268 static void
269 dissect_amr_nb_if2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
270     int    offset = 0;
271     guint8 octet;
272
273     proto_tree_add_item(tree, hf_amr_nb_if2_ft, tvb, offset, 1, ENC_BIG_ENDIAN);
274     octet = tvb_get_guint8(tvb,offset) & 0x0f;
275
276     if (octet == AMR_NB_SID) {
277         proto_tree_add_text(tree, tvb, offset+1, 3, "Speech data");
278         proto_tree_add_item(tree, hf_amr_if2_sti, tvb, offset+4, 1, ENC_BIG_ENDIAN);
279         proto_tree_add_item(tree, hf_amr_nb_if2_sti_mode_ind, tvb, offset+5, 1, ENC_BIG_ENDIAN);
280         return;
281     }
282     if (octet == AMR_NO_TRANS)
283         return;
284     proto_tree_add_text(tree, tvb, offset+1, -1, "Speech data");
285
286     col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
287             val_to_str_ext(octet, &amr_nb_codec_mode_request_vals_ext, "Unknown (%d)" ));
288 }
289
290 static void
291 dissect_amr_wb_if2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
292     int    offset = 0;
293     guint8 octet;
294
295     proto_tree_add_item(tree, hf_amr_wb_if2_ft, tvb, offset, 1, ENC_BIG_ENDIAN);
296     octet = (tvb_get_guint8(tvb,offset) & 0xf0) >> 4;
297
298     if (octet == AMR_WB_SID) {
299         proto_tree_add_text(tree, tvb, offset+1, 4, "Speech data");
300         proto_tree_add_item(tree, hf_amr_if2_sti, tvb, offset+5, 1, ENC_BIG_ENDIAN);
301         proto_tree_add_item(tree, hf_amr_wb_if2_sti_mode_ind, tvb, offset+5, 1, ENC_BIG_ENDIAN);
302         return;
303     }
304     if (octet == AMR_NO_TRANS)
305         return;
306     proto_tree_add_text(tree, tvb, offset+1, -1, "Speech data");
307
308     col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
309             val_to_str_ext(octet, &amr_wb_codec_mode_request_vals_ext, "Unknown (%d)" ));
310 }
311
312 static void
313 dissect_amr_be(tvbuff_t *tvb, packet_info *pinfo _U_, proto_tree *tree, gint amr_mode) {
314     proto_item *item;
315     int         ft;
316     int         bit_offset = 0;
317     int         bitcount;       /*bitcounter, MSB = bit 0, over bytes*/
318     int         bits_used_for_frames = 0;
319     int         bytes_needed_for_frames;
320     guint8      f_bit, q_bit;
321
322     /* Number of bits per frame for AMR-NB, see Table 1 RFC3267*/
323     /* Values taken for GSM-EFR SID, TDMA-EFR SID and PDC-EFR SID from 3GPP 26.101 Table A.1b */
324
325     /*               Frame type     0   1   2   3   4   5   6   7  8  9  10 11 12 13 14 15 */
326     unsigned char Framebits_NB[] = {95,103,118,134,148,159,204,244,39,43,38,37, 0, 0, 0, 0};
327
328     /* Number of bits per frame for AMR-WB, see 3GPP TS 26.201 Table 2*/
329     /*               Frame type     0   1   2   3   4   5   6   7   8   9  10 11 12 13 14 15 */
330     unsigned int Framebits_WB[] = {132,177,253,285,317,365,397,461,477, 40, 0, 0, 0, 0, 0, 0,};
331
332
333     /* Chapter 4.3 */
334
335     bitcount = 3;
336     if (amr_mode == AMR_NB)
337         proto_tree_add_bits_item(tree, hf_amr_nb_cmr, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
338     else
339         proto_tree_add_bits_item(tree, hf_amr_wb_cmr, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
340
341     bit_offset += 4;
342     /* In bandwidth-efficient mode, a ToC entry takes the following format:
343      *
344      *    0 1 2 3 4 5
345      *   +-+-+-+-+-+-+
346      *   |F|  FT   |Q|
347      *   +-+-+-+-+-+-+
348      *
349      *   F (1 bit): If set to 1, indicates that this frame is followed by
350      *      another speech frame in this payload; if set to 0, indicates that
351      *      this frame is the last frame in this payload.
352      *
353      *   FT (4 bits): Frame type index, indicating either the AMR or AMR-WB
354      *      speech coding mode or comfort noise (SID) mode of the
355      *      corresponding frame carried in this payload.
356      */
357     do {
358         /* Check F bit */
359         bitcount += 1;
360         f_bit = tvb_get_bits8(tvb, bit_offset, 1);
361         proto_tree_add_bits_item(tree, hf_amr_toc_f, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
362         bit_offset += 1;
363         ft = tvb_get_bits8(tvb, bit_offset, 4);
364         if (amr_mode == AMR_NB)
365             item = proto_tree_add_bits_item(tree, hf_amr_nb_toc_ft, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
366         else
367             item = proto_tree_add_bits_item(tree, hf_amr_wb_toc_ft, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
368
369         bit_offset += 4;
370         bitcount   += 4;
371         if (amr_mode == AMR_NB)
372             bits_used_for_frames += Framebits_NB[ft];
373         else
374             bits_used_for_frames += Framebits_WB[ft];
375         /* Check Q bit */
376         q_bit = tvb_get_bits8(tvb, bit_offset, 1);
377         proto_tree_add_bits_item(tree, hf_amr_toc_q, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
378         bit_offset += 1;
379         bitcount   += 1;
380         if (q_bit == 1)
381             proto_item_append_text(item, " / Frame OK");
382         else
383             proto_item_append_text(item, " / Frame damaged");
384     } while ((f_bit == 1) && (tvb_reported_length_remaining(tvb, bitcount/8) > 2));
385
386     if (bits_used_for_frames > 0)
387         bytes_needed_for_frames = 1 + (bitcount+bits_used_for_frames)/8-bitcount/8;
388     else
389         bytes_needed_for_frames = 0;
390
391     /* Check if we have enough data available for our frames */
392     if (tvb_reported_length_remaining(tvb, bitcount/8) < bytes_needed_for_frames) {
393         item = proto_tree_add_text(tree, tvb, bitcount/8, bytes_needed_for_frames, "Error:");
394         proto_item_append_text(item, " %d Bytes available, %d would be needed!",
395                        tvb_reported_length_remaining(tvb, bitcount/8),
396                        bytes_needed_for_frames);
397         expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Not enough data for the frames according to TOC");
398     }
399     else {
400         item = proto_tree_add_text(tree, tvb, bitcount/8, bytes_needed_for_frames, "Frame Data");
401         proto_item_append_text(item, " (%d Bytes)",bytes_needed_for_frames);
402     }
403
404     bitcount += bits_used_for_frames;
405
406     if (tvb_reported_length_remaining(tvb, (bitcount+8)/8) > 0) {
407         item = proto_tree_add_text(tree, tvb, bitcount/8, tvb_reported_length_remaining(tvb, bitcount/8), "Error:");
408         proto_item_append_text(item, " %d Bytes remaining - should be 0!",tvb_reported_length_remaining(tvb, (bitcount+8)/8));
409         expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Superfluous data remaining");
410
411         /* Now check the paddings */
412         if (bitcount%8 != 0) {
413             if ( (1 << (8 -(bitcount%8)-1)) & tvb_get_guint8(tvb,bitcount/8) )
414                 proto_tree_add_text(tree, tvb, bitcount/8, 1, "Padding bits correct");
415             else {
416                 item = proto_tree_add_text(tree, tvb, bitcount/8, 1, "Padding bits error");
417                 expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Padding bits error - MUST be 0");
418             }
419         }
420     }
421 }
422
423 /* Code to actually dissect the packets */
424 static void
425 dissect_amr_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint amr_mode)
426 {
427     int         offset     = 0;
428     int         bit_offset = 0;
429     guint8      octet;
430     proto_item *item;
431     gboolean    first_time;
432
433 /* Set up structures needed to add the protocol subtree and manage it */
434     proto_item *ti,*toc_item;
435     proto_tree *amr_tree, *toc_tree;
436
437     ti = proto_tree_add_item(tree, proto_amr, tvb, 0, -1, ENC_NA);
438     amr_tree = proto_item_add_subtree(ti, ett_amr);
439
440     proto_tree_add_text(amr_tree, tvb, offset, -1, "Payload decoded as %s",
441                 val_to_str(amr_encoding_type, amr_encoding_type_value, "Unknown value - Error"));
442
443     switch (amr_encoding_type) {
444     case 0: /* RFC 3267 Byte aligned */
445         break;
446     case 1: /* RFC 3267 Bandwidth-efficient */
447         dissect_amr_be(tvb, pinfo, amr_tree, amr_mode);
448         return;
449     case 2: /* AMR IF1 */
450         if (amr_mode == AMR_NB)
451             dissect_amr_nb_if1(tvb, pinfo, amr_tree);
452         else
453             dissect_amr_wb_if1(tvb, pinfo, amr_tree);
454         return;
455     case 3: /* AMR IF2 */
456         if (amr_mode == AMR_NB)
457             dissect_amr_nb_if2(tvb, pinfo, amr_tree);
458         else
459             dissect_amr_wb_if2(tvb, pinfo, amr_tree);
460         return;
461     default:
462         break;
463     }
464
465     if (amr_mode == AMR_NB)
466         proto_tree_add_bits_item(amr_tree, hf_amr_nb_cmr, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
467     else
468         proto_tree_add_bits_item(amr_tree, hf_amr_wb_cmr, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
469
470     bit_offset += 4;
471     octet = tvb_get_guint8(tvb,offset) & 0x0f;
472     if ( octet != 0  ) {
473         item = proto_tree_add_text(amr_tree, tvb, offset, -1,
474                        "Reserved != 0, wrongly encoded or not octet aligned."
475                        " Decoding as bandwidth-efficient mode");
476         PROTO_ITEM_SET_GENERATED(item);
477         return;
478
479     }
480
481     proto_tree_add_item(amr_tree, hf_amr_reserved, tvb, offset, 1, ENC_BIG_ENDIAN);
482     offset     += 1;
483     bit_offset += 4;
484     /*
485      *  A ToC entry takes the following format in octet-aligned mode:
486      *
487      *    0 1 2 3 4 5 6 7
488      *   +-+-+-+-+-+-+-+-+
489      *   |F|  FT   |Q|P|P|
490      *   +-+-+-+-+-+-+-+-+
491      *
492      *   F (1 bit): see definition in Section 4.3.2.
493      *
494      *   FT (4 bits unsigned integer): see definition in Section 4.3.2.
495      *
496      *   Q (1 bit): see definition in Section 4.3.2.
497      *
498      *   P bits: padding bits, MUST be set to zero.
499      */
500     octet = tvb_get_guint8(tvb,offset);
501     toc_item = proto_tree_add_text(amr_tree, tvb, offset, -1, "Payload Table of Contents");
502     toc_tree = proto_item_add_subtree(toc_item, ett_amr_toc);
503
504     first_time = TRUE;
505     while ((( octet& 0x80 ) == 0x80) || (first_time == TRUE)) {
506         first_time = FALSE;
507         octet = tvb_get_guint8(tvb,offset);
508
509         proto_tree_add_bits_item(toc_tree, hf_amr_toc_f, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
510         bit_offset += 1;
511         if (amr_mode == AMR_NB)
512             proto_tree_add_bits_item(toc_tree, hf_amr_nb_toc_ft, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
513         else
514             proto_tree_add_bits_item(toc_tree, hf_amr_wb_toc_ft, tvb, bit_offset, 4, ENC_BIG_ENDIAN);
515         bit_offset += 4;
516         proto_tree_add_bits_item(toc_tree, hf_amr_toc_q, tvb, bit_offset, 1, ENC_BIG_ENDIAN);
517         bit_offset += 1;
518         /* 2 pading bits */
519         bit_offset += 2;
520         offset     += 1;
521     }
522
523 }
524
525 /* Code to actually dissect the packets */
526 static void
527 dissect_amr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
528 {
529
530 /* Make entries in Protocol column and Info column on summary display */
531     col_set_str(pinfo->cinfo, COL_PROTOCOL, "AMR");
532
533     dissect_amr_common(tvb, pinfo, tree, pref_amr_mode);
534 }
535
536 static void
537 dissect_amr_wb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
538 {
539
540 /* Make entries in Protocol column and Info column on summary display */
541     col_set_str(pinfo->cinfo, COL_PROTOCOL, "AMR-WB");
542     dissect_amr_common(tvb, pinfo, tree, AMR_WB);
543 }
544
545
546 typedef struct _amr_capability_t {
547     const gchar     *id;
548     const gchar     *name;
549     new_dissector_t  content_pdu;
550 } amr_capability_t;
551
552 static amr_capability_t amr_capability_tab[] = {
553     /* ITU-T H.241 (05/2006), 8.3 H.264 capabilities */
554     { "GenericCapability/0.0.8.245.1.1.1",              "H.245 - GSM AMR Capability Identifier", NULL },
555     { "GenericCapability/0.0.8.245.1.1.1/collapsing/0", "maxAl-sduAudioFrames",                  NULL },
556     { "GenericCapability/0.0.8.245.1.1.1/collapsing/1", "bitRate",                               NULL },
557     { "GenericCapability/0.0.8.245.1.1.1/collapsing/2", "gsmAmrComfortNoise",                    NULL },
558     { "GenericCapability/0.0.8.245.1.1.1/collapsing/3", "gsmEfrComfortNoise",                    NULL },
559     { "GenericCapability/0.0.8.245.1.1.1/collapsing/4", "is-641ComfortNoise",                    NULL },
560     { "GenericCapability/0.0.8.245.1.1.1/collapsing/5", "pdcEFRComfortNoise",                    NULL },
561     /* ITU-T Rec. G.722.2/Annex F (11/2002) */
562     { "GenericCapability/0.0.7.7222.1.0/collapsing/0",  "maxAl-sduFrames",                       NULL },
563     { "GenericCapability/0.0.7.7222.1.0/collapsing/1",  "bitRate",                               NULL },
564     { "GenericCapability/0.0.7.7222.1.0/collapsing/2",  "octetAlign",                            NULL },
565     { "GenericCapability/0.0.7.7222.1.0/collapsing/3",  "modeSet",                               NULL },
566     { "GenericCapability/0.0.7.7222.1.0/collapsing/4",  "modeChangePeriod",                      NULL },
567     { "GenericCapability/0.0.7.7222.1.0/collapsing/5",  "modeChangeNeighbour",                   NULL },
568     { "GenericCapability/0.0.7.7222.1.0/collapsing/6",  "crc",                                   NULL },
569     { "GenericCapability/0.0.7.7222.1.0/collapsing/7",  "robustSorting",                         NULL },
570     { "GenericCapability/0.0.7.7222.1.0/collapsing/8",  "interleaving",                          NULL },
571     { NULL, NULL, NULL },
572 };
573
574 static amr_capability_t *find_cap(const gchar *id) {
575     amr_capability_t *ftr = NULL;
576     amr_capability_t *f;
577
578     for (f=amr_capability_tab; f->id; f++) {
579         if (!strcmp(id, f->id)) {
580             ftr = f;
581             break;
582         }
583     }
584     return ftr;
585 }
586
587 static void
588 dissect_amr_name(tvbuff_t *tvb _U_, packet_info *pinfo, proto_tree *tree)
589 {
590     asn1_ctx_t       *actx;
591
592     actx = get_asn1_ctx(pinfo->private_data);
593     DISSECTOR_ASSERT(actx != NULL);
594     if (tree && actx != NULL) {
595         amr_capability_t *ftr;
596         ftr = find_cap(pinfo->match_string);
597         if (ftr) {
598             proto_item_append_text(actx->created_item, " - %s", ftr->name);
599             proto_item_append_text(proto_item_get_parent(proto_tree_get_parent(tree)), ": %s", ftr->name);
600         } else {
601             proto_item_append_text(actx->created_item, " - unknown(%s)", pinfo->match_string);
602         }
603     }
604 }
605
606 void proto_reg_handoff_amr(void);
607
608 void
609 proto_register_amr(void)
610 {
611     module_t *amr_module;
612
613     static hf_register_info hf[] = {
614         { &hf_amr_nb_cmr,
615             { "CMR",           "amr.nb.cmr",
616             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_request_vals_ext, 0x0,
617             "codec mode request", HFILL }
618         },
619         { &hf_amr_wb_cmr,
620             { "CMR",           "amr.wb.cmr",
621             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_request_vals_ext, 0x0,
622             "codec mode request", HFILL }
623         },
624         { &hf_amr_reserved,
625             { "Reserved",           "amr.reserved",
626             FT_UINT8, BASE_DEC, NULL, 0x0f,
627             "Reserved bits", HFILL }
628         },
629         { &hf_amr_toc_f,
630             { "F bit",           "amr.toc.f",
631             FT_BOOLEAN, BASE_NONE, TFS(&toc_f_bit_vals), 0x0,
632             NULL, HFILL }
633         },
634         { &hf_amr_nb_toc_ft,
635             { "FT bits",           "amr.nb.toc.ft",
636             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_request_vals_ext, 0x0,
637             "Frame type index", HFILL }
638         },
639         { &hf_amr_wb_toc_ft,
640             { "FT bits",           "amr.wb.toc.ft",
641             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_request_vals_ext, 0x0,
642             "Frame type index", HFILL }
643         },
644         { &hf_amr_toc_q,
645             { "Q bit",           "amr.toc.q",
646             FT_BOOLEAN, BASE_NONE, TFS(&toc_q_bit_vals), 0x0,
647             "Frame quality indicator bit", HFILL }
648         },
649         { &hf_amr_nb_if1_ft,
650             { "Frame Type",           "amr.nb.if1.ft",
651             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_vals_ext, 0xf0,
652             NULL, HFILL }
653         },
654         { &hf_amr_wb_if1_ft,
655             { "Frame Type",           "amr.wb.if1.ft",
656             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_vals_ext, 0xf0,
657             NULL, HFILL }
658         },
659         { &hf_amr_nb_if1_mode_req,
660             { "Mode Type request",           "amr.nb.if1.modereq",
661             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_request_vals_ext, 0xe0,
662             NULL, HFILL }
663         },
664         { &hf_amr_wb_if1_mode_req,
665             { "Mode Type request",           "amr.wb.if1.modereq",
666             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_request_vals_ext, 0x0f,
667             NULL, HFILL }
668         },
669         { &hf_amr_if1_sti,
670             { "SID Type Indicator",           "amr.if1.sti",
671             FT_BOOLEAN, 8, TFS(&amr_sti_vals), 0x10,
672             NULL, HFILL }
673         },
674         { &hf_amr_nb_if1_sti_mode_ind,
675             { "Mode Type indication",           "amr.nb.if1.stimodeind",
676             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_vals_ext, 0x0e,
677             NULL, HFILL }
678         },
679         { &hf_amr_wb_if1_sti_mode_ind,
680             { "Mode Type indication",           "amr.wb.if1.stimodeind",
681             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_vals_ext, 0x0f,
682             NULL, HFILL }
683         },
684         { &hf_amr_nb_if1_mode_ind,
685             { "Mode Type indication",           "amr.nb.if1.modeind",
686             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_vals_ext, 0x07,
687             NULL, HFILL }
688         },
689         { &hf_amr_wb_if1_mode_ind,
690             { "Mode Type indication",           "amr.wb.if1.modeind",
691             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_vals_ext, 0xf0,
692             NULL, HFILL }
693         },
694         { &hf_amr_nb_if2_ft,
695             { "Frame Type",           "amr.nb.if2.ft",
696             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_vals_ext, 0x0f,
697             NULL, HFILL }
698         },
699         { &hf_amr_wb_if2_ft,
700             { "Frame Type",           "amr.wb.if2.ft",
701             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_vals_ext, 0xf0,
702             NULL, HFILL }
703         },
704         { &hf_amr_if2_sti,
705             { "SID Type Indicator",           "amr.if2.sti",
706             FT_BOOLEAN, 8, TFS(&amr_sti_vals), 0x80,
707             NULL, HFILL }
708         },
709         { &hf_amr_nb_if2_sti_mode_ind,
710             { "Mode Type indication",           "amr.nb.if2.stimodeind",
711             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_nb_codec_mode_vals_ext, 0x07,
712             NULL, HFILL }
713         },
714         { &hf_amr_wb_if2_sti_mode_ind,
715             { "Mode Type indication",           "amr.wb.if2.stimodeind",
716             FT_UINT8, BASE_DEC|BASE_EXT_STRING, &amr_wb_codec_mode_vals_ext, 0x78,
717             NULL, HFILL }
718         },
719         { &hf_amr_if1_fqi,
720             { "FQI",           "amr.fqi",
721             FT_BOOLEAN, 8, TFS(&toc_q_bit_vals), 0x08,
722             "Frame quality indicator bit", HFILL }
723         },
724     };
725
726 /* Setup protocol subtree array */
727     static gint *ett[] = {
728         &ett_amr,
729         &ett_amr_toc,
730     };
731     static const enum_val_t encoding_types[] = {
732         {"RFC 3267 Byte aligned", "RFC 3267 octet aligned", 0},
733         {"RFC 3267 Bandwidth-efficient", "RFC 3267 BW-efficient", 1},
734         {"AMR IF1", "AMR IF1", 2},
735         {"AMR IF2", "AMR IF2", 3},
736         {NULL, NULL, -1}
737     };
738
739     static const enum_val_t modes[] = {
740         {"AMR-NB", "Narrowband AMR", AMR_NB},
741         {"AMR-WB", "Wideband AMR", AMR_WB},
742         {NULL, NULL, -1}
743     };
744
745 /* Register the protocol name and description */
746     proto_amr = proto_register_protocol("Adaptive Multi-Rate","AMR", "amr");
747
748 /* Required function calls to register the header fields and subtrees used */
749     proto_register_field_array(proto_amr, hf, array_length(hf));
750     proto_register_subtree_array(ett, array_length(ett));
751     /* Register a configuration option for port */
752
753     amr_module = prefs_register_protocol(proto_amr, proto_reg_handoff_amr);
754
755     prefs_register_uint_preference(amr_module, "dynamic.payload.type",
756                        "AMR dynamic payload type",
757                        "The dynamic payload type which will be interpreted as AMR"
758                        "; The value must be greater than 95",
759                        10,
760                        &temp_dynamic_payload_type);
761
762     prefs_register_enum_preference(amr_module, "encoding.version",
763                        "Type of AMR encoding of the payload",
764                        "Type of AMR encoding of the payload",
765                        &amr_encoding_type, encoding_types, FALSE);
766
767     prefs_register_enum_preference(amr_module, "mode",
768                        "The AMR mode",
769                        "The AMR mode",
770                        &pref_amr_mode, modes, AMR_NB);
771
772     register_dissector("amr", dissect_amr, proto_amr);
773     register_dissector("amr-wb", dissect_amr_wb, proto_amr);
774     register_dissector("amr_if1_nb", dissect_amr_nb_if1, proto_amr);
775     register_dissector("amr_if1_wb", dissect_amr_wb_if1, proto_amr);
776     register_dissector("amr_if2_nb", dissect_amr_nb_if2, proto_amr);
777     register_dissector("amr_if2_wb", dissect_amr_wb_if2, proto_amr);
778
779     oid_add_from_string("G.722.2 (AMR-WB) audio capability","0.0.7.7222.1.0");
780 }
781
782 /* Register the protocol with Wireshark */
783 void
784 proto_reg_handoff_amr(void)
785 {
786     static dissector_handle_t amr_handle;
787     static guint              dynamic_payload_type;
788     static gboolean           amr_prefs_initialized = FALSE;
789
790     if (!amr_prefs_initialized) {
791         dissector_handle_t  amr_name_handle;
792         dissector_handle_t  amr_wb_handle;
793         amr_capability_t   *ftr;
794
795         amr_handle    = find_dissector("amr");
796         amr_wb_handle = find_dissector("amr-wb");
797         dissector_add_string("rtp_dyn_payload_type","AMR", amr_handle);
798         dissector_add_string("rtp_dyn_payload_type","AMR-WB", amr_wb_handle);
799
800         /*
801          * Register H.245 Generic parameter name(s)
802          */
803         amr_name_handle = create_dissector_handle(dissect_amr_name, proto_amr);
804         for (ftr=amr_capability_tab; ftr->id; ftr++) {
805             if (ftr->name)
806                 dissector_add_string("h245.gef.name", ftr->id, amr_name_handle);
807             if (ftr->content_pdu)
808                 dissector_add_string("h245.gef.content", ftr->id,
809                              new_create_dissector_handle(ftr->content_pdu, proto_amr));
810         }
811         /*  Activate the next line for testing with the randpkt tool
812             dissector_add_uint("udp.port", 55555, amr_handle);
813         */
814         amr_prefs_initialized = TRUE;
815     } else {
816         if ( dynamic_payload_type > 95 )
817             dissector_delete_uint("rtp.pt", dynamic_payload_type, amr_handle);
818     }
819
820     dynamic_payload_type = temp_dynamic_payload_type;
821
822     if ( dynamic_payload_type > 95 ) {
823         dissector_add_uint("rtp.pt", dynamic_payload_type, amr_handle);
824     }
825 }
826
827 /*
828  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
829  *
830  * Local variables:
831  * c-basic-offset: 4
832  * tab-width: 8
833  * indent-tabs-mode: nil
834  * End:
835  *
836  * vi: set shiftwidth=4 tabstop=8 expandtab:
837  * :indentSize=4:tabSize=8:noTabs=true:
838  */