6a4326568b48378bef1b2eb64022a2335db74eee
[obnox/wireshark/wip.git] / epan / dissectors / packet-umts_fp.c
1 /* Routines for UMTS FP disassembly
2  *
3  * Martin Mathieson
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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <epan/packet.h>
31 #include <epan/expert.h>
32
33 #include "packet-umts_fp.h"
34
35 /* TODO:
36    - remaining message types
37    - verify header & payload CRCs
38    - look for (and report as expert info) spare extension bytes
39 */
40
41 /* Initialize the protocol and registered fields. */
42 int proto_fp = -1;
43
44 static int hf_fp_channel_type = -1;
45 static int hf_fp_direction = -1;
46 static int hf_fp_header_crc = -1;
47 static int hf_fp_ft = -1;
48 static int hf_fp_cfn = -1;
49 static int hf_fp_pch_cfn = -1;
50 static int hf_fp_pch_toa = -1;
51 static int hf_fp_cfn_control = -1;
52 static int hf_fp_toa = -1;
53 static int hf_fp_tfi = -1;
54 static int hf_fp_usch_tfi = -1;
55 static int hf_fp_cpch_tfi = -1;
56 static int hf_fp_propagation_delay = -1;
57 static int hf_fp_tb = -1;
58 static int hf_fp_received_sync_ul_timing_deviation = -1;
59 static int hf_fp_pch_pi = -1;
60 static int hf_fp_pch_tfi = -1;
61 static int hf_fp_fach_tfi = -1;
62 static int hf_fp_transmit_power_level = -1;
63 static int hf_fp_paging_indication_bitmap = -1;
64 static int hf_fp_pdsch_set_id = -1;
65 static int hf_fp_rx_timing_deviation = -1;
66 static int hf_fp_dch_control_frame_type = -1;
67 static int hf_fp_dch_rx_timing_deviation = -1;
68 static int hf_fp_quality_estimate = -1;
69 static int hf_fp_payload_crc = -1;
70 static int hf_fp_edch_header_crc = -1;
71 static int hf_fp_edch_fsn = -1;
72 static int hf_fp_edch_subframe = -1;
73 static int hf_fp_edch_number_of_subframes = -1;
74 static int hf_fp_edch_harq_retransmissions = -1;
75 static int hf_fp_edch_subframe_number = -1;
76 static int hf_fp_edch_number_of_mac_es_pdus = -1;
77 static int hf_fp_edch_ddi = -1;
78 static int hf_fp_edch_subframe_header = -1;
79 static int hf_fp_edch_number_of_mac_d_pdus = -1;
80 static int hf_fp_edch_pdu_padding = -1;
81 static int hf_fp_edch_tsn = -1;
82 static int hf_fp_edch_mac_es_pdu = -1;
83 static int hf_fp_cmch_pi = -1;
84 static int hf_fp_user_buffer_size = -1;
85 static int hf_fp_hsdsch_credits = -1;
86 static int hf_fp_hsdsch_max_macd_pdu_len = -1;
87 static int hf_fp_hsdsch_interval = -1;
88 static int hf_fp_hsdsch_repetition_period = -1;
89 static int hf_fp_hsdsch_data_padding = -1;
90 static int hf_fp_hsdsch_new_ie_flags = -1;
91 static int hf_fp_hsdsch_new_ie_flag[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
92 static int hf_fp_hsdsch_drt = -1;
93 static int hf_fp_timing_advance = -1;
94 static int hf_fp_num_of_pdu = -1;
95 static int hf_fp_mac_d_pdu_len = -1;
96 static int hf_fp_mac_d_pdu = -1;
97 static int hf_fp_data = -1;
98 static int hf_fp_crcis = -1;
99 static int hf_fp_crci[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
100 static int hf_fp_common_control_frame_type = -1;
101 static int hf_fp_t1 = -1;
102 static int hf_fp_t2 = -1;
103 static int hf_fp_t3 = -1;
104 static int hf_fp_ul_sir_target = -1;
105 static int hf_fp_pusch_set_id = -1;
106 static int hf_fp_activation_cfn = -1;
107 static int hf_fp_duration = -1;
108 static int hf_fp_power_offset = -1;
109 static int hf_fp_code_number = -1;
110 static int hf_fp_spreading_factor = -1;
111 static int hf_fp_mc_info = -1;
112 static int hf_fp_rach_new_ie_flags = -1;
113 static int hf_fp_rach_new_ie_flag[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
114 static int hf_fp_cell_portion_id = -1;
115 static int hf_fp_radio_interface_parameter_update_flag[5] = {-1, -1, -1, -1, -1};
116 static int hf_fp_dpc_mode = -1;
117 static int hf_fp_tpc_po = -1;
118 static int hf_fp_multiple_rl_set_indicator = -1;
119 static int hf_fp_max_ue_tx_pow = -1;
120 static int hf_fp_congestion_status = -1;
121
122 /* Subtrees. */
123 static int ett_fp = -1;
124 static int ett_fp_data = -1;
125 static int ett_fp_crcis = -1;
126 static int ett_fp_edch_subframe_header = -1;
127 static int ett_fp_edch_subframe = -1;
128 static int ett_fp_hsdsch_new_ie_flags = -1;
129 static int ett_fp_rach_new_ie_flags = -1;
130
131
132 /* E-DCH channel header information */
133 struct subframe_info
134 {
135     guint8  subframe_number;
136     guint8  number_of_mac_es_pdus;
137     guint8  ddi[64];
138     guint16 number_of_mac_d_pdus[64];
139 };
140
141
142 static const value_string channel_type_vals[] =
143 {
144     { CHANNEL_RACH_FDD,     "RACH_FDD" },
145     { CHANNEL_RACH_TDD,     "RACH_TDD" },
146     { CHANNEL_FACH_FDD,     "FACH_FDD" },
147     { CHANNEL_FACH_TDD,     "FACH_TDD" },
148     { CHANNEL_DSCH_FDD,     "DSCH_FDD" },
149     { CHANNEL_DSCH_TDD,     "DSCH_TDD" },
150     { CHANNEL_USCH_TDD_384, "USCH_TDD_384" },
151     { CHANNEL_USCH_TDD_128, "USCH_TDD_128" },
152     { CHANNEL_PCH,          "PCH" },
153     { CHANNEL_CPCH,         "CPCH" },
154     { CHANNEL_BCH,          "BCH" },
155     { CHANNEL_DCH,          "DCH" },
156     { CHANNEL_HSDSCH,       "HSDSCH" },
157     { CHANNEL_IUR_CPCHF,    "IUR CPCHF" },
158     { CHANNEL_IUR_FACH,     "IUR FACH" },
159     { CHANNEL_IUR_DSCH,     "IUR DSCH" },
160     { CHANNEL_EDCH,         "EDCH" },
161     { CHANNEL_RACH_TDD_128, "RACH_TDD_128" },
162     { 0, NULL }
163 };
164
165 static const value_string data_control_vals[] = {
166     { 0,   "Data" },
167     { 1,   "Control" },
168     { 0,   NULL },
169 };
170
171 static const value_string direction_vals[] = {
172     { 0,   "Downlink" },
173     { 1,   "Uplink" },
174     { 0,   NULL },
175 };
176
177 static const value_string crci_vals[] = {
178     { 0,   "Correct" },
179     { 1,   "Not correct" },
180     { 0,   NULL },
181 };
182
183 static const value_string paging_indication_vals[] = {
184     { 0,   "no PI-bitmap in payload" },
185     { 1,   "PI-bitmap in payload" },
186     { 0,   NULL },
187 };
188
189 static const value_string spreading_factor_vals[] = {
190     {0,    "4"},
191     {1,    "8"},
192     {2,    "16"},
193     {3,    "32"},
194     {4,    "64"},
195     {5,    "128"},
196     {6,    "256"},
197     {0,    NULL }
198 };
199
200 static const value_string congestion_status_vals[] = {
201     {0,    "No TNL congestion"},
202     {1,    "Reserved for future use"},
203     {2,    "TNL congestion - detected by delay build-up"},
204     {3,    "TNL congestion - detected by frame loss"},
205     {0,    NULL }
206 };
207
208
209 /* DCH control types */
210 #define DCH_OUTER_LOOP_POWER_CONTROL            1
211 #define DCH_TIMING_ADJUSTMENT                   2
212 #define DCH_DL_SYNCHRONISATION                  3
213 #define DCH_UL_SYNCHRONISATION                  4
214
215 #define DCH_DL_NODE_SYNCHRONISATION             6
216 #define DCH_UL_NODE_SYNCHRONISATION             7
217 #define DCH_RX_TIMING_DEVIATION                 8
218 #define DCH_RADIO_INTERFACE_PARAMETER_UPDATE    9
219 #define DCH_TIMING_ADVANCE                      10
220 #define DCH_TNL_CONGESTION_INDICATION           11
221
222 static const value_string dch_control_frame_type_vals[] = {
223     { DCH_OUTER_LOOP_POWER_CONTROL,         "OUTER LOOP POWER CONTROL" },
224     { DCH_TIMING_ADJUSTMENT,                "TIMING ADJUSTMENT" },
225     { DCH_DL_SYNCHRONISATION,               "DL SYNCHRONISATION" },
226     { DCH_UL_SYNCHRONISATION,               "UL SYNCHRONISATION" },
227     { 5,                                    "Reserved Value" },
228     { DCH_DL_NODE_SYNCHRONISATION,          "DL NODE SYNCHRONISATION" },
229     { DCH_UL_NODE_SYNCHRONISATION,          "UL NODE SYNCHRONISATION" },
230     { DCH_RX_TIMING_DEVIATION,              "RX TIMING DEVIATION" },
231     { DCH_RADIO_INTERFACE_PARAMETER_UPDATE, "RADIO INTERFACE PARAMETER UPDATE" },
232     { DCH_TIMING_ADVANCE,                   "TIMING ADVANCE" },
233     { DCH_TNL_CONGESTION_INDICATION,        "TNL CONGESTION INDICATION" },
234     { 0,   NULL },
235 };
236
237
238 /* Common channel control types */
239 #define COMMON_OUTER_LOOP_POWER_CONTROL         1
240 #define COMMON_TIMING_ADJUSTMENT                2
241 #define COMMON_DL_SYNCHRONISATION               3
242 #define COMMON_UL_SYNCHRONISATION               4
243
244 #define COMMON_DL_NODE_SYNCHRONISATION          6
245 #define COMMON_UL_NODE_SYNCHRONISATION          7
246 #define COMMON_DYNAMIC_PUSCH_ASSIGNMENT         8
247 #define COMMON_TIMING_ADVANCE                   9
248 #define COMMON_HS_DSCH_Capacity_Request         10
249 #define COMMON_HS_DSCH_Capacity_Allocation      11
250
251 static const value_string common_control_frame_type_vals[] = {
252     { COMMON_OUTER_LOOP_POWER_CONTROL,         "OUTER LOOP POWER CONTROL" },
253     { COMMON_TIMING_ADJUSTMENT,                "TIMING ADJUSTMENT" },
254     { COMMON_DL_SYNCHRONISATION,               "DL SYNCHRONISATION" },
255     { COMMON_UL_SYNCHRONISATION,               "UL SYNCHRONISATION" },
256     { 5,                                       "Reserved Value" },
257     { COMMON_DL_NODE_SYNCHRONISATION,          "DL NODE SYNCHRONISATION" },
258     { COMMON_UL_NODE_SYNCHRONISATION,          "UL NODE SYNCHRONISATION" },
259     { COMMON_DYNAMIC_PUSCH_ASSIGNMENT,         "DYNAMIC PUSCH ASSIGNMENT" },
260     { COMMON_TIMING_ADVANCE,                   "TIMING ADVANCE" },
261     { COMMON_HS_DSCH_Capacity_Request,         "HS-DSCH Capacity Request" },
262     { COMMON_HS_DSCH_Capacity_Allocation,      "HS-DSCH Capacity Allocation" },
263     { 0,   NULL },
264 };
265
266 /* Dissect message parts */
267 static int dissect_tb_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
268                            int offset, struct _fp_info *p_fp_info, int *num_tbs);
269 static int dissect_macd_pdu_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
270                                  int offset, guint16 length, guint8 number_of_pdus);
271 static int dissect_crci_bits(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
272                              int num_tbs, int offset);
273
274 /* Dissect common control messages */
275 static void dissect_common_timing_adjustment(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
276                                              int offset, struct _fp_info *p_fp_info);
277 static void dissect_common_dl_node_synchronisation(packet_info *pinfo, proto_tree *tree,
278                                                    tvbuff_t *tvb, int offset);
279 static void dissect_common_ul_node_synchronisation(packet_info *pinfo, proto_tree *tree,
280                                                    tvbuff_t *tvb, int offset);
281 static void dissect_common_dl_syncronisation(packet_info *pinfo, proto_tree *tree,
282                                              tvbuff_t *tvb, int offset,
283                                              struct _fp_info *p_fp_info);
284 static void dissect_common_ul_syncronisation(packet_info *pinfo, proto_tree *tree,
285                                              tvbuff_t *tvb, int offset,
286                                              struct _fp_info *p_fp_info);
287 static void dissect_common_timing_advance(packet_info *pinfo, proto_tree *tree,
288                                           tvbuff_t *tvb, int offset);
289 static void dissect_hsdpa_capacity_request(packet_info *pinfo, proto_tree *tree,
290                                            tvbuff_t *tvb, int offset);
291 static void dissect_hsdpa_capacity_allocation(packet_info *pinfo, proto_tree *tree,
292                                               tvbuff_t *tvb, int offset);
293 static void dissect_common_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
294                                    int offset, struct _fp_info *p_fp_info);
295 static void dissect_common_dynamic_pusch_assignment(packet_info *pinfo, proto_tree *tree,
296                                                     tvbuff_t *tvb, int offset);
297
298 /* Dissect common channel types */
299 static void dissect_rach_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
300                                       int offset, struct _fp_info *p_fp_info);
301 static void dissect_fach_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
302                                       int offset, struct _fp_info *p_fp_info);
303 static void dissect_dsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
304                                       int offset, struct _fp_info *p_fp_info);
305 static void dissect_usch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
306                                       int offset, struct _fp_info *p_fp_info);
307 static void dissect_pch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
308                                      int offset, struct _fp_info *p_fp_info);
309 static void dissect_cpch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
310                                       int offset, struct _fp_info *p_fp_info);
311 static void dissect_iur_dsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
312                                           int offset, struct _fp_info *p_fp_info _U_);
313 static void dissect_hsdsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
314                                         int offset, struct _fp_info *p_fp_info);
315
316
317 /* Dissect DCH control messages */
318 static void dissect_dch_timing_adjustment(proto_tree *tree, packet_info *pinfo,
319                                           tvbuff_t *tvb, int offset);
320 static void dissect_dch_rx_timing_deviation(proto_tree *tree, tvbuff_t *tvb, int offset);
321 static void dissect_dch_dl_synchronisation(proto_tree *tree, packet_info *pinfo,
322                                            tvbuff_t *tvb, int offset);
323 static void dissect_dch_ul_synchronisation(proto_tree *tree, packet_info *pinfo,
324                                            tvbuff_t *tvb, int offset);
325 static void dissect_dch_outer_loop_power_control(proto_tree *tree, packet_info *pinfo,
326                                                  tvbuff_t *tvb, int offset);
327 static void dissect_dch_dl_node_synchronisation(proto_tree *tree, packet_info *pinfo,
328                                                 tvbuff_t *tvb, int offset);
329 static void dissect_dch_ul_node_synchronisation(proto_tree *tree, packet_info *pinfo,
330                                                 tvbuff_t *tvb, int offset);
331 static void dissect_dch_radio_interface_parameter_update(proto_tree *tree, packet_info *pinfo,
332                                                          tvbuff_t *tvb, int offset);
333 static void dissect_dch_timing_advance(proto_tree *tree, packet_info *pinfo,
334                                        tvbuff_t *tvb, int offset);
335 static void dissect_dch_tnl_congestion_indication(proto_tree *tree, packet_info *pinfo,
336                                                   tvbuff_t *tvb, int offset);
337
338
339 static void dissect_dch_control_frame(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb,
340                                       int offset);
341
342
343 /* Dissect a DCH channel */
344 static void dissect_dch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
345                                      int offset, struct _fp_info *p_fp_info);
346
347 /* Dissect dedicated channels */
348 static void dissect_e_dch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
349                                 int offset, struct _fp_info *p_fp_info);
350 static void dissect_fp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
351
352 void proto_register_fp(void);
353 void proto_reg_handoff_fp(void);
354
355
356
357
358 /* Dissect the TBs of a data frame */
359 int dissect_tb_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
360                     int offset, struct _fp_info *p_fp_info, int *num_tbs)
361 {
362     int chan;
363     int bit_offset = 0;
364     guint data_bits = 0;
365     proto_item *ti = NULL;
366     proto_tree *data_tree = NULL;
367
368     if (tree)
369     {
370         /* Add data subtree */
371         ti =  proto_tree_add_string_format(tree, hf_fp_data, tvb, offset, 0,
372                                            "",
373                                            "TB data for %u chans",
374                                            p_fp_info->num_chans);
375         data_tree = proto_item_add_subtree(ti, ett_fp_data);
376     }
377
378     /* Now for the TB data */
379     for (chan=0; chan < p_fp_info->num_chans; chan++)
380     {
381         int n;
382         for (n=0; n < p_fp_info->chan_num_tbs[chan]; n++)
383         {
384             proto_item *ti;
385             if (data_tree)
386             {
387                 ti = proto_tree_add_item(data_tree, hf_fp_tb, tvb,
388                                          offset + (bit_offset/8),
389                                          ((bit_offset % 8) + p_fp_info->chan_tf_size[chan] + 7) / 8,
390                                          FALSE);
391                 proto_item_append_text(ti, " (chan %u, tb %u, %u bits)",
392                                        chan+1, n+1, p_fp_info->chan_tf_size[chan]);
393             }
394             (*num_tbs)++;
395
396             /* Advance bit offset */
397             bit_offset += p_fp_info->chan_tf_size[chan];
398             data_bits += p_fp_info->chan_tf_size[chan];
399
400             /* Pad out to next byte */
401             if (bit_offset % 8)
402             {
403                 bit_offset += (8 - (bit_offset % 8));
404             }
405         }
406     }
407
408     if (check_col(pinfo->cinfo, COL_INFO))
409     {
410         col_append_fstr(pinfo->cinfo, COL_INFO, "(%u bits in %u tbs)",
411                         data_bits, *num_tbs);
412     }
413
414     /* Data tree should cover entire length */
415     if (data_tree)
416     {
417         proto_item_set_len(data_tree, bit_offset/8);
418         proto_item_append_text(ti, " (%u bits in %u tbs)", data_bits, *num_tbs);
419     }
420
421     /* Move offset past TBs (we know its already padded out to next byte) */
422     offset += (bit_offset / 8);
423
424     return offset;
425 }
426
427
428 /* Dissect the MAC-d PDUs of an HS-DSCH frame */
429 int dissect_macd_pdu_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
430                           int offset, guint16 length, guint8 number_of_pdus)
431 {
432     int pdu;
433     int bit_offset = 0;
434     proto_item *ti = NULL;
435     proto_tree *data_tree = NULL;
436
437     /* Add data subtree */
438     if (tree)
439     {
440         ti =  proto_tree_add_string_format(tree, hf_fp_data, tvb, offset, 0,
441                                            "",
442                                            "%u MAC-d PDUs of %u bits",
443                                            number_of_pdus,
444                                            length);
445         data_tree = proto_item_add_subtree(ti, ett_fp_data);
446     }
447
448     /* Now for the PDUs */
449     for (pdu=0; pdu < number_of_pdus; pdu++)
450     {
451         proto_item *ti;
452
453         if (data_tree)
454         {
455             /* Show 4 bits padding at start of PDU */
456             proto_tree_add_item(data_tree, hf_fp_hsdsch_data_padding, tvb, offset+(bit_offset/8), 1, FALSE);
457         }
458         bit_offset += 4;
459
460         /* Data bytes! */
461         if (data_tree)
462         {
463             ti = proto_tree_add_item(data_tree, hf_fp_mac_d_pdu, tvb,
464                                      offset + (bit_offset/8),
465                                      ((bit_offset % 8) + length + 7) / 8,
466                                      FALSE);
467             proto_item_append_text(ti, " (PDU %u)", pdu+1);
468         }
469
470         /* Advance bit offset */
471         bit_offset += length;
472
473         /* Pad out to next byte */
474         if (bit_offset % 8)
475         {
476             bit_offset += (8 - (bit_offset % 8));
477         }
478     }
479
480     /* Data tree should cover entire length */
481     proto_item_set_len(data_tree, bit_offset/8);
482
483     /* Move offset past PDUs (we know its already padded out to next byte) */
484     offset += (bit_offset / 8);
485
486     /* Show summary in info column */
487     if (check_col(pinfo->cinfo, COL_INFO))
488     {
489         col_append_fstr(pinfo->cinfo, COL_INFO, "   %u PDUs of %u bits",
490                         number_of_pdus, length);
491     }
492
493     return offset;
494 }
495
496
497 /* Dissect CRCI bits (uplink) */
498 int dissect_crci_bits(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
499                       int num_tbs, int offset)
500 {
501     int n;
502     proto_item *ti = NULL;
503     proto_tree *crcis_tree = NULL;
504     guint errors = 0;
505
506     /* Add CRCIs subtree */
507     if (tree)
508     {
509         ti =  proto_tree_add_string_format(tree, hf_fp_crcis, tvb, offset, 0,
510                                            "",
511                                            "CRCI bits for %u tbs",
512                                            num_tbs);
513         crcis_tree = proto_item_add_subtree(ti, ett_fp_crcis);
514     }
515
516     /* CRCIs */
517     for (n=0; n < num_tbs; n++)
518     {
519         int bit = (tvb_get_guint8(tvb, offset+(n/8)) >> (7-(n%8))) & 0x01;
520         proto_tree_add_item(crcis_tree, hf_fp_crci[n%8], tvb, offset+(n/8),
521                             1, FALSE);
522
523         if (bit == 1)
524         {
525             errors++;
526             expert_add_info_format(pinfo, ti,
527                                    PI_CHECKSUM, PI_WARN,
528                                    "CRCI error bit set for TB");
529         }
530     }
531
532     if (tree)
533     {
534         /* Highlight range of bytes covered by indicator bits */
535         proto_item_set_len(ti, (num_tbs+7) / 8);
536
537         /* Show error count in root text */
538         proto_item_append_text(ti, " (%u errors)", errors);
539     }
540
541     offset += ((num_tbs+7) / 8);
542     return offset;
543 }
544
545
546
547 /***********************************************************/
548 /* Common control message types                            */
549
550 void dissect_common_timing_adjustment(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
551                                       int offset, struct _fp_info *p_fp_info)
552 {
553     if (p_fp_info->channel != CHANNEL_PCH)
554     {
555         guint8 cfn;
556         gint16 toa;
557
558         /* CFN control */
559         cfn = tvb_get_guint8(tvb, offset);
560         proto_tree_add_item(tree, hf_fp_cfn_control, tvb, offset, 1, FALSE);
561         offset++;
562
563         /* ToA */
564         toa = tvb_get_ntohs(tvb, offset);
565         proto_tree_add_item(tree, hf_fp_toa, tvb, offset, 2, FALSE);
566         offset++;
567
568         if (check_col(pinfo->cinfo, COL_INFO))
569         {
570             col_append_fstr(pinfo->cinfo, COL_INFO, "   CFN=%u, ToA=%d", cfn, toa);
571         }
572     }
573     else
574     {
575         guint16 cfn;
576         gint32 toa;
577
578         /* PCH CFN is 12 bits */
579         cfn = (tvb_get_ntohs(tvb, offset) >> 4);
580         proto_tree_add_item(tree, hf_fp_pch_cfn, tvb, offset, 2, FALSE);
581         offset += 2;
582
583         /* 4 bits of padding follow... */
584
585         /* 20 bits of ToA (followed by 4 padding bits) */
586         toa = ((int)(tvb_get_ntoh24(tvb, offset) << 8)) / 4096;
587         proto_tree_add_int(tree, hf_fp_pch_toa, tvb, offset, 3, toa);
588
589         if (check_col(pinfo->cinfo, COL_INFO))
590         {
591             col_append_fstr(pinfo->cinfo, COL_INFO, "   CFN=%u, ToA=%d", cfn, toa);
592         }
593     }
594 }
595
596 void dissect_common_dl_node_synchronisation(packet_info *pinfo, proto_tree *tree,
597                                             tvbuff_t *tvb, int offset)
598 {
599     /* T1 */
600     guint32 t1 = tvb_get_ntoh24(tvb, offset);
601     proto_tree_add_item(tree, hf_fp_t1, tvb, offset, 3, FALSE);
602
603     if (check_col(pinfo->cinfo, COL_INFO))
604     {
605         col_append_fstr(pinfo->cinfo, COL_INFO, "   T1=%u", t1);
606     }
607 }
608
609 void dissect_common_ul_node_synchronisation(packet_info *pinfo, proto_tree *tree,
610                                             tvbuff_t *tvb, int offset)
611 {
612     guint32 t1, t2, t3;
613
614     /* T1 */
615     t1 = tvb_get_ntoh24(tvb, offset);
616     proto_tree_add_item(tree, hf_fp_t1, tvb, offset, 3, FALSE);
617     offset += 3;
618
619     /* T2 */
620     t2 = tvb_get_ntoh24(tvb, offset);
621     proto_tree_add_item(tree, hf_fp_t2, tvb, offset, 3, FALSE);
622     offset += 3;
623
624     /* T3 */
625     t3 = tvb_get_ntoh24(tvb, offset);
626     proto_tree_add_item(tree, hf_fp_t3, tvb, offset, 3, FALSE);
627     offset += 3;
628
629     if (check_col(pinfo->cinfo, COL_INFO))
630     {
631         col_append_fstr(pinfo->cinfo, COL_INFO, "   T1=%u T2=%u, T3=%u",
632                         t1, t2, t3);
633     }
634 }
635
636 void dissect_common_dl_syncronisation(packet_info *pinfo, proto_tree *tree,
637                                       tvbuff_t *tvb, int offset, struct _fp_info *p_fp_info)
638 {
639     guint16 cfn;
640
641     if (p_fp_info->channel != CHANNEL_PCH)
642     {
643         /* CFN control */
644         cfn = tvb_get_guint8(tvb, offset);
645         proto_tree_add_item(tree, hf_fp_cfn_control, tvb, offset, 1, FALSE);
646     }
647     else
648     {
649         /* PCH CFN is 12 bits */
650         cfn = (tvb_get_ntohs(tvb, offset) >> 4);
651         proto_tree_add_item(tree, hf_fp_pch_cfn, tvb, offset, 2, FALSE);
652
653         /* 4 bits of padding follow... */
654     }
655
656     if (check_col(pinfo->cinfo, COL_INFO))
657     {
658         col_append_fstr(pinfo->cinfo, COL_INFO, "   CFN=%u", cfn);
659     }
660 }
661
662 void dissect_common_ul_syncronisation(packet_info *pinfo, proto_tree *tree,
663                                       tvbuff_t *tvb, int offset, struct _fp_info *p_fp_info)
664 {
665     dissect_common_timing_adjustment(pinfo, tree, tvb, offset, p_fp_info);
666 }
667
668 void dissect_common_timing_advance(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset)
669 {
670     guint8 cfn;
671     guint8 timing_advance;
672
673     /* CFN control */
674     cfn = tvb_get_guint8(tvb, offset);
675     proto_tree_add_item(tree, hf_fp_cfn_control, tvb, offset, 1, FALSE);
676     offset++;
677
678     /* Timing Advance */
679     timing_advance = (tvb_get_guint8(tvb, offset) & 0x3f) * 4;
680     proto_tree_add_uint(tree, hf_fp_timing_advance, tvb, offset, 1, timing_advance*4);
681     offset++;
682
683     if (check_col(pinfo->cinfo, COL_INFO))
684     {
685         col_append_fstr(pinfo->cinfo, COL_INFO, " CFN = %u, TA = %u",
686                         cfn, timing_advance);
687     }
688 }
689
690 void dissect_hsdpa_capacity_request(packet_info *pinfo, proto_tree *tree,
691                                     tvbuff_t *tvb, int offset)
692 {
693     guint8 priority;
694     guint16 user_buffer_size;
695
696     /* CmCH-PI */
697     priority = (tvb_get_guint8(tvb, offset) & 0x0f);
698     proto_tree_add_item(tree, hf_fp_cmch_pi, tvb, offset, 1, FALSE);
699     offset++;
700
701     /* User buffer size */
702     user_buffer_size = tvb_get_ntohs(tvb, offset);
703     proto_tree_add_item(tree, hf_fp_user_buffer_size, tvb, offset, 2, FALSE);
704     offset += 2;
705
706     if (check_col(pinfo->cinfo, COL_INFO))
707     {
708         col_append_fstr(pinfo->cinfo, COL_INFO, "      CmCH-PI=%u  User-Buffer-Size=%u",
709                         priority, user_buffer_size);
710     }
711
712     /* TODO: Spare extension may follow */
713 }
714
715 void dissect_hsdpa_capacity_allocation(packet_info *pinfo, proto_tree *tree,
716                                        tvbuff_t *tvb, int offset)
717 {
718     proto_item *ti;
719     guint16 max_pdu_length;
720     guint8 repetition_period;
721     guint8 interval;
722     guint16 credits;
723
724     /* CmCH-PI */
725     proto_tree_add_item(tree, hf_fp_cmch_pi, tvb, offset, 1, FALSE);
726     offset++;
727
728     /* Max MAC-d PDU length (13 bits) */
729     max_pdu_length = (tvb_get_ntohs(tvb, offset) >> 3);
730     proto_tree_add_item(tree, hf_fp_hsdsch_max_macd_pdu_len, tvb, offset, 2, FALSE);
731     offset++;
732
733     /* HS-DSCH credits (11 bits) */
734     credits = (tvb_get_ntohs(tvb, offset) & 0x07ff);
735     ti = proto_tree_add_item(tree, hf_fp_hsdsch_credits, tvb, offset, 2, FALSE);
736     offset += 2;
737     if (credits == 0)
738     {
739         proto_item_append_text(ti, " (stop transmission)");
740     }
741     if (credits == 2047)
742     {
743         proto_item_append_text(ti, " (unlimited)");
744     }
745
746     /* HS-DSCH Interval */
747     interval = tvb_get_guint8(tvb, offset);
748     ti = proto_tree_add_uint(tree, hf_fp_hsdsch_interval, tvb, offset, 1, interval*10);
749     offset++;
750     if (interval == 0)
751     {
752         proto_item_append_text(ti, " (none of the credits shall be used)");
753     }
754
755     /* HS-DSCH Repetition period */
756     repetition_period = tvb_get_guint8(tvb, offset);
757     ti = proto_tree_add_item(tree, hf_fp_hsdsch_repetition_period, tvb, offset, 1, FALSE);
758     offset++;
759     if (repetition_period == 0)
760     {
761         proto_item_append_text(ti, " (unlimited repetition period)");
762     }
763
764     if (check_col(pinfo->cinfo, COL_INFO))
765     {
766         col_append_fstr(pinfo->cinfo, COL_INFO,
767                         "   Max-PDU-len=%u  Credits=%u  Interval=%u  Rep-Period=%u",
768                         max_pdu_length, credits, interval, repetition_period);
769     }
770
771     /* TODO: Spare extension may follow */
772 }
773
774
775 void dissect_common_dynamic_pusch_assignment(packet_info *pinfo, proto_tree *tree,
776                                              tvbuff_t *tvb, int offset)
777 {
778     guint8 pusch_set_id;
779     guint8 activation_cfn;
780     guint8 duration;
781
782     /* PUSCH Set Id */
783     pusch_set_id = tvb_get_guint8(tvb, offset);
784     proto_tree_add_item(tree, hf_fp_pusch_set_id, tvb, offset, 1, FALSE);
785     offset++;
786
787     /* Activation CFN */
788     activation_cfn = tvb_get_guint8(tvb, offset);
789     proto_tree_add_item(tree, hf_fp_activation_cfn, tvb, offset, 1, FALSE);
790     offset++;
791
792     /* Duration */
793     duration = tvb_get_guint8(tvb, offset) * 10;
794     proto_tree_add_uint(tree, hf_fp_duration, tvb, offset, 1, duration);
795
796     if (check_col(pinfo->cinfo, COL_INFO))
797     {
798         col_append_fstr(pinfo->cinfo, COL_INFO,
799                         "   PUSCH Set Id=%u  Activation CFN=%u  Duration=%u",
800                         pusch_set_id, activation_cfn, duration);
801     }
802 }
803
804
805
806
807
808 /* Dissect the control part of a common channel message */
809 void dissect_common_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
810                             int offset, struct _fp_info *p_fp_info)
811 {
812     /* Common control frame type */
813     guint8 control_frame_type = tvb_get_guint8(tvb, offset);
814     proto_tree_add_item(tree, hf_fp_common_control_frame_type, tvb, offset, 1, FALSE);
815     offset++;
816
817     if (check_col(pinfo->cinfo, COL_INFO))
818     {
819         col_append_str(pinfo->cinfo, COL_INFO,
820                        val_to_str(control_frame_type, common_control_frame_type_vals, "Unknown"));
821     }
822
823     /* Frame-type specific dissection */
824     switch (control_frame_type)
825     {
826         case COMMON_OUTER_LOOP_POWER_CONTROL:
827             break;
828         case COMMON_TIMING_ADJUSTMENT:
829             dissect_common_timing_adjustment(pinfo, tree, tvb, offset, p_fp_info);
830             break;
831         case COMMON_DL_SYNCHRONISATION:
832             dissect_common_dl_syncronisation(pinfo, tree, tvb, offset, p_fp_info);
833             break;
834         case COMMON_UL_SYNCHRONISATION:
835             dissect_common_ul_syncronisation(pinfo, tree, tvb, offset, p_fp_info);
836             break;
837         case COMMON_DL_NODE_SYNCHRONISATION:
838             dissect_common_dl_node_synchronisation(pinfo, tree, tvb, offset);
839             break;
840         case COMMON_UL_NODE_SYNCHRONISATION:
841             dissect_common_ul_node_synchronisation(pinfo, tree, tvb, offset);
842             break;
843         case COMMON_DYNAMIC_PUSCH_ASSIGNMENT:
844             dissect_common_dynamic_pusch_assignment(pinfo, tree, tvb, offset);
845             break;
846         case COMMON_TIMING_ADVANCE:
847             dissect_common_timing_advance(pinfo, tree, tvb, offset);
848             break;
849         case COMMON_HS_DSCH_Capacity_Request:
850             dissect_hsdpa_capacity_request(pinfo, tree, tvb, offset);
851             break;
852         case COMMON_HS_DSCH_Capacity_Allocation:
853             dissect_hsdpa_capacity_allocation(pinfo, tree, tvb, offset);
854             break;
855
856         default:
857             break;
858     }
859 }
860
861
862
863 /**************************/
864 /* Dissect a RACH channel */
865 void dissect_rach_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
866                                int offset, struct _fp_info *p_fp_info)
867 {
868     gboolean is_control_frame;
869
870     /* Header CRC */
871     proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
872
873     /* Frame Type */
874     is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
875     proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
876     offset++;
877
878     if (check_col(pinfo->cinfo, COL_INFO))
879     {
880         col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
881     }
882
883     if (is_control_frame)
884     {
885         dissect_common_control(tvb, pinfo, tree, offset, p_fp_info);
886     }
887     else
888     {
889         int num_tbs = 0;
890         guint8 cfn;
891
892         /* DATA */
893
894         /* CFN */
895         cfn = tvb_get_guint8(tvb, offset);
896         proto_tree_add_item(tree, hf_fp_cfn, tvb, offset, 1, FALSE);
897         offset++;
898
899         if (check_col(pinfo->cinfo, COL_INFO))
900         {
901             col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn);
902         }
903
904         /* TFI */
905         proto_tree_add_item(tree, hf_fp_tfi, tvb, offset, 1, FALSE);
906         offset++;
907
908         if (p_fp_info->channel == CHANNEL_RACH_FDD)
909         {
910             /* Propagation delay */
911             proto_tree_add_uint(tree, hf_fp_propagation_delay, tvb, offset, 1,
912                                 tvb_get_guint8(tvb, offset) * 3);
913             offset++;
914         }
915
916         if (p_fp_info->channel == CHANNEL_RACH_TDD)
917         {
918             /* Rx Timing Deviation */
919             proto_tree_add_item(tree, hf_fp_rx_timing_deviation, tvb, offset, 1, FALSE);
920             offset++;
921         }
922
923         if (p_fp_info->channel == CHANNEL_RACH_TDD_128)
924         {
925             /* Received SYNC UL Timing Deviation */
926             proto_tree_add_item(tree, hf_fp_received_sync_ul_timing_deviation, tvb, offset, 1, FALSE);
927             offset++;
928         }
929
930         /* TB data */
931         offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &num_tbs);
932
933         /* CRCIs */
934         offset = dissect_crci_bits(tvb, pinfo, tree, num_tbs, offset);
935
936         /* Info introduced in R6 */
937         if (p_fp_info->release == 6)
938         {
939             int n;
940             guint8 flags;
941             guint8 flag_bytes = 0;
942
943             /* New IE flags */
944             do
945             {
946                 proto_item *new_ie_flags_ti;
947                 proto_tree *new_ie_flags_tree;
948                 guint ies_found = 0;
949
950                 /* Add new IE flags subtree */
951                 new_ie_flags_ti = proto_tree_add_string_format(tree, hf_fp_rach_new_ie_flags, tvb, offset, 1,
952                                                               "", "New IE flags");
953                 new_ie_flags_tree = proto_item_add_subtree(new_ie_flags_ti, ett_fp_rach_new_ie_flags);
954
955                 /* Read next byte */
956                 flags = tvb_get_guint8(tvb, offset);
957                 flag_bytes++;
958
959                 /* Dissect individual bits */
960                 for (n=0; n < 8; n++)
961                 {
962                     proto_tree_add_item(new_ie_flags_tree, hf_fp_rach_new_ie_flag[n], tvb, offset, 1, FALSE);
963                     if ((flags >> (7-n)) & 0x01)
964                     {
965                         ies_found++;
966                     }
967                 }
968                 offset++;
969
970                 proto_item_append_text(new_ie_flags_ti, " (%u IEs found)", ies_found);
971
972                 /* Last bit set will indicate another flags byte follows... */
973             } while (0); /*((flags & 0x01) && (flag_bytes < 31));*/
974
975             /* Cell portion ID */
976             proto_tree_add_item(tree, hf_fp_cell_portion_id, tvb, offset, 1, FALSE);
977             offset++;
978         }
979
980         /* Payload CRC */
981         proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
982         offset += 2;
983     }
984 }
985
986
987 /**************************/
988 /* Dissect a FACH channel */
989 void dissect_fach_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
990                                int offset, struct _fp_info *p_fp_info)
991 {
992     gboolean is_control_frame;
993
994     /* Header CRC */
995     proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
996
997     /* Frame Type */
998     is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
999     proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
1000     offset++;
1001
1002     if (check_col(pinfo->cinfo, COL_INFO))
1003     {
1004         col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
1005     }
1006
1007     if (is_control_frame)
1008     {
1009         dissect_common_control(tvb, pinfo, tree, offset, p_fp_info);
1010     }
1011     else
1012     {
1013         int num_tbs = 0;
1014         guint8 cfn;
1015
1016         /* DATA */
1017
1018         /* CFN */
1019         cfn = tvb_get_guint8(tvb, offset);
1020         proto_tree_add_item(tree, hf_fp_cfn, tvb, offset, 1, FALSE);
1021         offset++;
1022
1023         if (check_col(pinfo->cinfo, COL_INFO))
1024         {
1025             col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn);
1026         }
1027
1028         /* TFI */
1029         proto_tree_add_item(tree, hf_fp_fach_tfi, tvb, offset, 1, FALSE);
1030         offset++;
1031
1032         /* Transmit power level */
1033         proto_tree_add_float(tree, hf_fp_transmit_power_level, tvb, offset, 1,
1034                              (float)(int)(tvb_get_guint8(tvb, offset)) / 10);
1035         offset++;
1036
1037         /* TB data */
1038         offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &num_tbs);
1039
1040         /* Payload CRC */
1041         proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
1042         offset += 2;
1043     }
1044 }
1045
1046
1047 /**************************/
1048 /* Dissect a DSCH channel */
1049 void dissect_dsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1050                                int offset, struct _fp_info *p_fp_info)
1051 {
1052     gboolean is_control_frame;
1053
1054     /* Header CRC */
1055     proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
1056
1057     /* Frame Type */
1058     is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
1059     proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
1060     offset++;
1061
1062     if (check_col(pinfo->cinfo, COL_INFO))
1063     {
1064         col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
1065     }
1066
1067     if (is_control_frame)
1068     {
1069         dissect_common_control(tvb, pinfo, tree, offset, p_fp_info);
1070     }
1071     else
1072     {
1073         int num_tbs = 0;
1074         guint8 cfn;
1075
1076         /* DATA */
1077
1078         /* CFN */
1079         cfn = tvb_get_guint8(tvb, offset);
1080         proto_tree_add_item(tree, hf_fp_cfn, tvb, offset, 1, FALSE);
1081         offset++;
1082
1083         if (check_col(pinfo->cinfo, COL_INFO))
1084         {
1085             col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn);
1086         }
1087
1088         /* TFI */
1089         proto_tree_add_item(tree, hf_fp_tfi, tvb, offset, 1, FALSE);
1090         offset++;
1091
1092
1093         /* Other fields depend upon release & FDD/TDD settings */
1094         if (((p_fp_info->release == 99) || (p_fp_info->release == 4)) &&
1095              (p_fp_info->channel == CHANNEL_DSCH_FDD))
1096         {
1097             /* Power offset */
1098             proto_tree_add_float(tree, hf_fp_power_offset, tvb, offset, 1,
1099                                  (float)(-32.0) +
1100                                   ((float)(tvb_get_guint8(tvb, offset)) * (float)(0.25)));
1101             offset++;
1102
1103             /* Code number */
1104             proto_tree_add_item(tree, hf_fp_code_number, tvb, offset, 1, FALSE);
1105             offset++;
1106
1107             /* Spreading Factor (3 bits) */
1108             proto_tree_add_item(tree, hf_fp_spreading_factor, tvb, offset, 1, FALSE);
1109
1110             /* MC info (4 bits)*/
1111             proto_tree_add_item(tree, hf_fp_mc_info, tvb, offset, 1, FALSE);
1112
1113             /* Last bit of this byte is spare */
1114             offset++;
1115         }
1116         else
1117         {
1118             /* Normal case */
1119
1120             /* PDSCH Set Id */
1121             proto_tree_add_item(tree, hf_fp_pdsch_set_id, tvb, offset, 1, FALSE);
1122             offset++;
1123     
1124             /* Transmit power level */
1125             proto_tree_add_float(tree, hf_fp_transmit_power_level, tvb, offset, 1,
1126                                  (float)(tvb_get_guint8(tvb, offset)) / 10);
1127             offset++;
1128         }
1129
1130         /* TB data */
1131         offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &num_tbs);
1132
1133         /* Payload CRC */
1134         proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
1135         offset += 2;
1136     }
1137 }
1138
1139
1140 /**************************/
1141 /* Dissect a USCH channel */
1142 void dissect_usch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1143                                int offset, struct _fp_info *p_fp_info)
1144 {
1145     gboolean is_control_frame;
1146
1147     /* Header CRC */
1148     proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
1149
1150     /* Frame Type */
1151     is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
1152     proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
1153     offset++;
1154
1155     if (check_col(pinfo->cinfo, COL_INFO))
1156     {
1157         col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
1158     }
1159
1160     if (is_control_frame)
1161     {
1162         dissect_common_control(tvb, pinfo, tree, offset, p_fp_info);
1163     }
1164     else
1165     {
1166         int num_tbs = 0;
1167         guint cfn;
1168
1169         /* DATA */
1170
1171         /* CFN */
1172         cfn = tvb_get_guint8(tvb, offset);
1173         proto_tree_add_item(tree, hf_fp_cfn, tvb, offset, 1, FALSE);
1174         offset++;
1175
1176         if (check_col(pinfo->cinfo, COL_INFO))
1177         {
1178             col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn);
1179         }
1180
1181         /* TFI */
1182         proto_tree_add_item(tree, hf_fp_usch_tfi, tvb, offset, 1, FALSE);
1183         offset++;
1184
1185         /* Rx Timing Deviation */
1186         proto_tree_add_item(tree, hf_fp_rx_timing_deviation, tvb, offset, 1, FALSE);
1187         offset++;
1188
1189         /* TB data */
1190         offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &num_tbs);
1191
1192         /* QE */
1193         proto_tree_add_item(tree, hf_fp_quality_estimate, tvb, offset, 1, FALSE);
1194         offset++;
1195
1196         /* CRCIs */
1197         offset = dissect_crci_bits(tvb, pinfo, tree, num_tbs, offset);
1198
1199         /* Payload CRC */
1200         proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
1201         offset += 2;
1202     }
1203 }
1204
1205
1206
1207 /**************************/
1208 /* Dissect a PCH channel  */
1209 void dissect_pch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1210                               int offset, struct _fp_info *p_fp_info)
1211 {
1212     gboolean is_control_frame;
1213     guint16  pch_cfn;
1214     gboolean paging_indication;
1215
1216     /* Header CRC */
1217     proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
1218
1219     /* Frame Type */
1220     is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
1221     proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
1222     offset++;
1223
1224     if (check_col(pinfo->cinfo, COL_INFO))
1225     {
1226         col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
1227     }
1228
1229     if (is_control_frame)
1230     {
1231         dissect_common_control(tvb, pinfo, tree, offset, p_fp_info);
1232     }
1233     else
1234     {
1235         int num_tbs = 0;
1236
1237         /* DATA */
1238
1239         /* 12-bit CFN value */
1240         proto_tree_add_item(tree, hf_fp_pch_cfn, tvb, offset, 2, FALSE);
1241         pch_cfn = (tvb_get_ntohs(tvb, offset) & 0xfff0) >> 4;
1242         offset++;
1243
1244         if (check_col(pinfo->cinfo, COL_INFO))
1245         {
1246             col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%04u ", pch_cfn);
1247         }
1248
1249         /* Paging indication */
1250         proto_tree_add_item(tree, hf_fp_pch_pi, tvb, offset, 1, FALSE);
1251         paging_indication = tvb_get_guint8(tvb, offset) & 0x01;
1252         offset++;
1253
1254         /* 5-bit TFI */
1255         proto_tree_add_item(tree, hf_fp_pch_tfi, tvb, offset, 1, FALSE);
1256         offset++;
1257
1258         /* Optional paging indications */
1259         if (paging_indication)
1260         {
1261             proto_item *ti;
1262             ti = proto_tree_add_item(tree, hf_fp_paging_indication_bitmap, tvb,
1263                                      offset,
1264                                      (p_fp_info->paging_indications+7) / 8,
1265                                      FALSE);
1266             proto_item_append_text(ti, " (%u bits)", p_fp_info->paging_indications);
1267             offset += ((p_fp_info->paging_indications+7) / 8);
1268         }
1269
1270         /* TB data */
1271         offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &num_tbs);
1272
1273         /* Payload CRC */
1274         proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
1275         offset += 2;
1276     }
1277 }
1278
1279
1280 /**************************/
1281 /* Dissect a CPCH channel */
1282 void dissect_cpch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1283                                int offset, struct _fp_info *p_fp_info)
1284 {
1285     gboolean is_control_frame;
1286
1287     /* Header CRC */
1288     proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
1289
1290     /* Frame Type */
1291     is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
1292     proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
1293     offset++;
1294
1295     if (check_col(pinfo->cinfo, COL_INFO))
1296     {
1297         col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
1298     }
1299
1300     if (is_control_frame)
1301     {
1302         dissect_common_control(tvb, pinfo, tree, offset, p_fp_info);
1303     }
1304     else
1305     {
1306         int num_tbs = 0;
1307         guint cfn;
1308
1309         /* DATA */
1310
1311         /* CFN */
1312         cfn = tvb_get_guint8(tvb, offset);
1313         proto_tree_add_item(tree, hf_fp_cfn, tvb, offset, 1, FALSE);
1314         offset++;
1315
1316         if (check_col(pinfo->cinfo, COL_INFO))
1317         {
1318             col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn);
1319         }
1320
1321         /* TFI */
1322         proto_tree_add_item(tree, hf_fp_cpch_tfi, tvb, offset, 1, FALSE);
1323         offset++;
1324
1325         /* Propagation delay */
1326         proto_tree_add_uint(tree, hf_fp_propagation_delay, tvb, offset, 1,
1327                             tvb_get_guint8(tvb, offset) * 3);
1328         offset++;
1329
1330         /* TB data */
1331         offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &num_tbs);
1332
1333         /* CRCIs */
1334         offset = dissect_crci_bits(tvb, pinfo, tree, num_tbs, offset);
1335
1336         /* Payload CRC */
1337         proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
1338         offset += 2;
1339     }
1340 }
1341
1342 /********************************/
1343 /* Dissect an IUR DSCH channel  */
1344 void dissect_iur_dsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1345                                    int offset, struct _fp_info *p_fp_info _U_)
1346 {
1347     gboolean is_control_frame;
1348
1349     /* Header CRC */
1350     proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
1351
1352     /* Frame Type */
1353     is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
1354     proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
1355     offset++;
1356
1357     if (check_col(pinfo->cinfo, COL_INFO))
1358     {
1359         col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
1360     }
1361
1362     if (is_control_frame)
1363     {
1364         dissect_common_control(tvb, pinfo, tree, offset, p_fp_info);
1365     }
1366     else
1367     {
1368         /* TODO: DATA */
1369     }
1370 }
1371
1372
1373
1374
1375 /************************/
1376 /* DCH control messages */
1377
1378 void dissect_dch_timing_adjustment(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset)
1379 {
1380     guint8 control_cfn;
1381     gint16 toa;
1382
1383     /* CFN control */
1384     control_cfn = tvb_get_guint8(tvb, offset);
1385     proto_tree_add_item(tree, hf_fp_cfn_control, tvb, offset, 1, FALSE);
1386     offset++;
1387
1388     /* ToA */
1389     toa = tvb_get_ntohs(tvb, offset);
1390     proto_tree_add_item(tree, hf_fp_toa, tvb, offset, 2, FALSE);
1391     offset += 2;
1392
1393     if (check_col(pinfo->cinfo, COL_INFO))
1394     {
1395         col_append_fstr(pinfo->cinfo, COL_INFO,
1396                         " CFN = %u, ToA = %d", control_cfn, toa);
1397     }
1398 }
1399
1400 void dissect_dch_rx_timing_deviation(proto_tree *tree, tvbuff_t *tvb, int offset)
1401 {
1402     /* CFN control */
1403     proto_tree_add_item(tree, hf_fp_cfn_control, tvb, offset, 1, FALSE);
1404     offset++;
1405
1406     /* Rx Timing Deviation */
1407     proto_tree_add_item(tree, hf_fp_dch_rx_timing_deviation, tvb, offset, 1, FALSE);
1408     offset++;
1409 }
1410
1411 void dissect_dch_dl_synchronisation(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset)
1412 {
1413     /* CFN control */
1414     guint cfn = tvb_get_guint8(tvb, offset);
1415     proto_tree_add_item(tree, hf_fp_cfn_control, tvb, offset, 1, FALSE);
1416     offset++;
1417
1418     if (check_col(pinfo->cinfo, COL_INFO))
1419     {
1420         col_append_fstr(pinfo->cinfo, COL_INFO, " CFN = %u", cfn);
1421     }
1422 }
1423
1424 void dissect_dch_ul_synchronisation(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset)
1425 {
1426     guint8 cfn;
1427     gint16 toa;
1428
1429     /* CFN control */
1430     cfn = tvb_get_guint8(tvb, offset);
1431     proto_tree_add_item(tree, hf_fp_cfn_control, tvb, offset, 1, FALSE);
1432     offset++;
1433
1434     /* ToA */
1435     toa = tvb_get_ntohs(tvb, offset);
1436     proto_tree_add_item(tree, hf_fp_toa, tvb, offset, 2, FALSE);
1437     offset += 2;
1438
1439     if (check_col(pinfo->cinfo, COL_INFO))
1440     {
1441         col_append_fstr(pinfo->cinfo, COL_INFO, " CFN = %u, ToA = %d",
1442                         cfn, toa);
1443     }
1444 }
1445
1446 void dissect_dch_outer_loop_power_control(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset)
1447 {
1448     /* SIR target */
1449     float target = -8.2 + (0.1 * (float)(tvb_get_guint8(tvb, offset)));
1450     proto_tree_add_float(tree, hf_fp_ul_sir_target, tvb, offset, 1, target);
1451
1452     if (check_col(pinfo->cinfo, COL_INFO))
1453     {
1454         col_append_fstr(pinfo->cinfo, COL_INFO, "SIR Target = %f", target);
1455     }
1456 }
1457
1458 void dissect_dch_dl_node_synchronisation(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset)
1459 {
1460     dissect_common_dl_node_synchronisation(pinfo, tree, tvb, offset);
1461 }
1462
1463 void dissect_dch_ul_node_synchronisation(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset)
1464 {
1465     dissect_common_ul_node_synchronisation(pinfo, tree, tvb, offset);
1466 }
1467
1468 void dissect_dch_radio_interface_parameter_update(proto_tree *tree, packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
1469 {
1470     int n;
1471     guint8 cfn;
1472     guint8 value;
1473
1474     /* Show defined flags in these 2 bytes */
1475     for (n=4; n >= 0; n--)
1476     {
1477         proto_tree_add_item(tree, hf_fp_radio_interface_parameter_update_flag[n], tvb, offset, 2, FALSE);
1478     }
1479     offset += 2;
1480
1481     /* CFN  */
1482     cfn = tvb_get_guint8(tvb, offset);
1483     proto_tree_add_item(tree, hf_fp_cfn, tvb, offset, 1, FALSE);
1484     offset++;
1485
1486     /* DPC mode */
1487     proto_tree_add_item(tree, hf_fp_dpc_mode, tvb, offset, 1, FALSE);
1488
1489     /* TPC PO */
1490     proto_tree_add_item(tree, hf_fp_tpc_po, tvb, offset, 1, FALSE);
1491     offset++;
1492
1493     /* Multiple RL sets indicator */
1494     proto_tree_add_item(tree, hf_fp_multiple_rl_set_indicator, tvb, offset, 1, FALSE);
1495     offset += 2;
1496
1497     /* MAX_UE_TX_POW */
1498     value = (tvb_get_guint8(tvb, offset) & 0x7f);
1499     proto_tree_add_int(tree, hf_fp_max_ue_tx_pow, tvb, offset, 1, -55 + value);
1500
1501     /* TODO: spare extension */
1502 }
1503
1504 void dissect_dch_timing_advance(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset)
1505 {
1506     dissect_common_timing_advance(pinfo, tree, tvb, offset);
1507 }
1508
1509 void dissect_dch_tnl_congestion_indication(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset)
1510 {
1511     guint8 status = (tvb_get_guint8(tvb, offset) & 0x03);
1512
1513     /* Congestion status */
1514     proto_tree_add_int(tree, hf_fp_congestion_status, tvb, offset, 1, FALSE);
1515
1516     if (check_col(pinfo->cinfo, COL_INFO))
1517     {
1518         col_append_fstr(pinfo->cinfo, COL_INFO, " status = %s",
1519                         val_to_str(status, congestion_status_vals, "unknown"));
1520     }
1521 }
1522
1523
1524
1525
1526 /* DCH control frame */
1527 void dissect_dch_control_frame(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset)
1528 {
1529     /* Control frame type */
1530     guint8 control_frame_type = tvb_get_guint8(tvb, offset);
1531     proto_tree_add_item(tree, hf_fp_dch_control_frame_type, tvb, offset, 1, FALSE);
1532     offset++;
1533
1534     if (check_col(pinfo->cinfo, COL_INFO))
1535     {
1536         col_append_str(pinfo->cinfo, COL_INFO,
1537                        val_to_str(control_frame_type,
1538                                   dch_control_frame_type_vals, "Unknown"));
1539     }
1540
1541     switch (control_frame_type)
1542     {
1543         case DCH_TIMING_ADJUSTMENT:
1544             dissect_dch_timing_adjustment(tree, pinfo, tvb, offset);
1545             break;
1546         case DCH_RX_TIMING_DEVIATION:
1547             dissect_dch_rx_timing_deviation(tree, tvb, offset);
1548             break;
1549         case DCH_DL_SYNCHRONISATION:
1550             dissect_dch_dl_synchronisation(tree, pinfo, tvb, offset);
1551             break;
1552         case DCH_UL_SYNCHRONISATION:
1553             dissect_dch_ul_synchronisation(tree, pinfo, tvb, offset);
1554             break;
1555         case DCH_OUTER_LOOP_POWER_CONTROL:
1556             dissect_dch_outer_loop_power_control(tree, pinfo, tvb, offset);
1557             break;
1558         case DCH_DL_NODE_SYNCHRONISATION:
1559             dissect_dch_dl_node_synchronisation(tree, pinfo, tvb, offset);
1560             break;
1561         case DCH_UL_NODE_SYNCHRONISATION:
1562             dissect_dch_ul_node_synchronisation(tree, pinfo, tvb, offset);
1563             break;
1564         case DCH_RADIO_INTERFACE_PARAMETER_UPDATE:
1565             dissect_dch_radio_interface_parameter_update(tree, pinfo, tvb, offset);
1566             break;
1567         case DCH_TIMING_ADVANCE:
1568             dissect_dch_timing_advance(tree, pinfo, tvb, offset);
1569             break;
1570         case DCH_TNL_CONGESTION_INDICATION:
1571             dissect_dch_tnl_congestion_indication(tree, pinfo, tvb, offset);
1572             break;
1573     }
1574 }
1575
1576 /*******************************/
1577 /* Dissect a DCH channel       */
1578 void dissect_dch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1579                               int offset, struct _fp_info *p_fp_info)
1580 {
1581     gboolean is_control_frame;
1582     guint8   cfn;
1583
1584     /* Header CRC */
1585     proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
1586
1587     /* Frame Type */
1588     is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
1589     proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
1590     offset++;
1591
1592     if (check_col(pinfo->cinfo, COL_INFO))
1593     {
1594         col_append_str(pinfo->cinfo, COL_INFO,
1595                        is_control_frame ? " [Control] " : 
1596                                           ((p_fp_info->is_uplink) ? " [ULData] " :
1597                                                                     " [DLData] " ));
1598     }
1599
1600     if (is_control_frame)
1601     {
1602         /* DCH control frame */
1603         dissect_dch_control_frame(tree, pinfo, tvb, offset);
1604     }
1605     else
1606     {
1607         /************************/
1608         /* DCH data here        */
1609         int chan;
1610         int num_tbs = 0;
1611
1612         /* CFN */
1613         proto_tree_add_item(tree, hf_fp_cfn, tvb, offset, 1, FALSE);
1614         cfn = tvb_get_guint8(tvb, offset);
1615         offset++;
1616
1617         if (check_col(pinfo->cinfo, COL_INFO))
1618         {
1619             col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn);
1620         }
1621
1622         /* One TFI for each channel */
1623         for (chan=0; chan < p_fp_info->num_chans; chan++)
1624         {
1625             proto_tree_add_item(tree, hf_fp_tfi, tvb, offset, 1, FALSE);
1626             offset++;
1627         }
1628
1629         /* Dissect TB data */
1630         offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &num_tbs);
1631
1632         /* QE (uplink only) */
1633         if (p_fp_info->is_uplink)
1634         {
1635             proto_tree_add_item(tree, hf_fp_quality_estimate, tvb, offset, 1, FALSE);
1636             offset++;
1637         }
1638
1639         /* CRCI bits (uplink only) */
1640         if (p_fp_info->is_uplink)
1641         {
1642             offset = dissect_crci_bits(tvb, pinfo, tree, num_tbs, offset);
1643         }
1644
1645         /* Payload CRC (optional) */
1646         if (p_fp_info->dch_crc_present)
1647         {
1648             proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
1649         }
1650     }
1651 }
1652
1653
1654
1655 /**********************************/
1656 /* Dissect an E-DCH channel       */
1657 void dissect_e_dch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1658                                 int offset, struct _fp_info *p_fp_info)
1659 {
1660     gboolean is_control_frame;
1661     guint8   number_of_subframes;
1662     guint8   cfn;
1663     int      n;
1664     struct   subframe_info subframes[8];
1665
1666     /* Header CRC */
1667     proto_tree_add_item(tree, hf_fp_edch_header_crc, tvb, offset, 2, FALSE);
1668
1669     /* Frame Type */
1670     is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
1671     proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
1672     offset++;
1673
1674     if (check_col(pinfo->cinfo, COL_INFO))
1675     {
1676         col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
1677     }
1678
1679     if (is_control_frame)
1680     {
1681         /* DCH control frame */
1682         dissect_dch_control_frame(tree, pinfo, tvb, offset);
1683     }
1684     else
1685     {
1686         /********************************/
1687         /* E-DCH data here        */
1688
1689         guint  bit_offset = 0;
1690         guint  total_bits = 0;
1691
1692         /* FSN */
1693         proto_tree_add_item(tree, hf_fp_edch_fsn, tvb, offset, 1, FALSE);
1694         offset++;
1695
1696         /* Number of subframes.
1697            This was 3 bits in early releases, is 4 bits offset by 1 in later releases  */
1698         if ((p_fp_info->dct2000_variant % 256) > 1)
1699         {
1700             /* Use 4 bits plus offset of 1 */
1701             number_of_subframes = (tvb_get_guint8(tvb, offset) & 0x0f) + 1;
1702         }
1703         else
1704         {
1705             /* Use 3 bits only */
1706             number_of_subframes = (tvb_get_guint8(tvb, offset) & 0x07);
1707         }
1708         proto_tree_add_uint(tree, hf_fp_edch_number_of_subframes, tvb, offset, 1,
1709                             number_of_subframes);
1710
1711         offset++;
1712
1713         /* CFN */
1714         cfn = tvb_get_guint8(tvb, offset);
1715         proto_tree_add_item(tree, hf_fp_cfn, tvb, offset, 1, FALSE);
1716         offset++;
1717
1718         /* EDCH subframe header list */
1719         for (n=0; n < number_of_subframes; n++)
1720         {
1721             int i;
1722             proto_item *subframe_header_ti;
1723             proto_tree *subframe_header_tree;
1724
1725             /* Add subframe header subtree */
1726             subframe_header_ti = proto_tree_add_string_format(tree, hf_fp_edch_subframe_header, tvb, offset, 0,
1727                                                               "", "Subframe");
1728             subframe_header_tree = proto_item_add_subtree(subframe_header_ti, ett_fp_edch_subframe_header);
1729
1730             /* Number of HARQ Retransmissions */
1731             proto_tree_add_item(subframe_header_tree, hf_fp_edch_harq_retransmissions, tvb,
1732                                 offset, 1, FALSE);
1733
1734             /* Subframe number */
1735             subframes[n].subframe_number = (tvb_get_guint8(tvb, offset) & 0x07);
1736             proto_tree_add_item(subframe_header_tree, hf_fp_edch_subframe_number, tvb,
1737                                 offset, 1, FALSE);
1738             offset++;
1739
1740             /* Number of MAC-es PDUs */
1741             subframes[n].number_of_mac_es_pdus = (tvb_get_guint8(tvb, offset) & 0xf0) >> 4;
1742             proto_tree_add_item(subframe_header_tree, hf_fp_edch_number_of_mac_es_pdus,
1743                                 tvb, offset, 1, FALSE);
1744             bit_offset = 4;
1745
1746             proto_item_append_text(subframe_header_ti, " %u header (%u MAC-es PDUs)",
1747                                    subframes[n].subframe_number,
1748                                    subframes[n].number_of_mac_es_pdus);
1749
1750             /* Details of each MAC-es PDU */
1751             for (i=0; i < subframes[n].number_of_mac_es_pdus; i++)
1752             {
1753                 guint8 ddi;
1754                 int    ddi_offset;
1755                 guint8 n_pdus;
1756                 int    n_pdus_offset;
1757
1758                 /* DDI (6 bits) */
1759                 ddi_offset = offset + (bit_offset / 8);
1760
1761                 switch (bit_offset%8)
1762                 {
1763                     case 0:
1764                         ddi = (tvb_get_guint8(tvb, ddi_offset) >> 2);
1765                         break;
1766                     case 2:
1767                         ddi = (tvb_get_guint8(tvb, ddi_offset) & 0x3f);
1768                         break;
1769                     case 4:
1770                         ddi = (tvb_get_ntohs(tvb, ddi_offset) >> 6) & 0x003f;
1771                         break;
1772                     case 6:
1773                         ddi = (tvb_get_ntohs(tvb, ddi_offset) >> 4) & 0x003f;
1774                         break;
1775                     default:
1776                         /* Can't get here, but avoid warning */
1777                         return;
1778                 }
1779
1780                 proto_tree_add_uint(subframe_header_tree, hf_fp_edch_ddi, tvb, ddi_offset,
1781                                     ((bit_offset%8) <= 2) ? 1 : 2, ddi);
1782
1783                 subframes[n].ddi[i] = ddi;
1784                 bit_offset += 6;
1785
1786                 /* Number of MAC-d PDUs (6 bits) */
1787                 n_pdus_offset = offset + (bit_offset / 8);
1788                 switch (bit_offset%8)
1789                 {
1790                     case 0:
1791                         n_pdus = (tvb_get_guint8(tvb, n_pdus_offset) >> 2);
1792                         break;
1793                     case 2:
1794                         n_pdus = (tvb_get_guint8(tvb, n_pdus_offset) & 0x3f);
1795                         break;
1796                     case 4:
1797                         n_pdus = (tvb_get_ntohs(tvb, n_pdus_offset) >> 6) & 0x003f;
1798                         break;
1799                     case 6:
1800                         n_pdus = (tvb_get_ntohs(tvb, n_pdus_offset) >> 4) & 0x003f;
1801                         break;
1802                     default:
1803                         /* Can't get here, but avoid warning */
1804                         return;
1805                 }
1806                 proto_tree_add_uint(subframe_header_tree, hf_fp_edch_number_of_mac_d_pdus, tvb, n_pdus_offset,
1807                                     ((bit_offset%8) <= 2) ? 1 : 2, n_pdus);
1808
1809                 subframes[n].number_of_mac_d_pdus[i] = n_pdus;
1810                 bit_offset += 6;
1811             }
1812
1813             /* Tree should cover entire subframe header */
1814             proto_item_set_len(subframe_header_ti, bit_offset/8);
1815
1816             offset += ((bit_offset+7)/8);
1817         }
1818
1819         /* EDCH subframes */
1820         bit_offset = 0;
1821         for (n=0; n < number_of_subframes; n++)
1822         {
1823             int i;
1824             proto_item *subframe_ti;
1825             proto_tree *subframe_tree;
1826             guint bits_in_subframe = 0;
1827             guint mac_d_pdus_in_subframe = 0;
1828
1829             bit_offset = 0;
1830
1831             /* Add subframe subtree */
1832             subframe_ti = proto_tree_add_string_format(tree, hf_fp_edch_subframe, tvb, offset, 0,
1833                                                        "", "Subframe %u data", subframes[n].subframe_number);
1834             subframe_tree = proto_item_add_subtree(subframe_ti, ett_fp_edch_subframe);
1835
1836             for (i=0; i < subframes[n].number_of_mac_es_pdus; i++)
1837             {
1838                 int         m;
1839                 guint16     size = 0;
1840                 guint       send_size;
1841                 proto_item  *ti;
1842
1843                 /* Look up mac-d pdu size for this ddi */
1844                 for (m=0; m < p_fp_info->no_ddi_entries; m++)
1845                 {
1846                     if (subframes[n].ddi[i] == p_fp_info->edch_ddi[m])
1847                     {
1848                         size = p_fp_info->edch_macd_pdu_size[m];
1849                         break;
1850                     }
1851                 }
1852
1853                 if (m == p_fp_info->no_ddi_entries)
1854                 {
1855                     /* Not found.  Oops */
1856                     return;
1857                 }
1858
1859                 /* Send MAC-dd PDUs together as one MAC-es PDU */
1860                 send_size = size * subframes[n].number_of_mac_d_pdus[i];
1861
1862                 /* 2 bits spare */
1863                 proto_tree_add_item(subframe_tree, hf_fp_edch_pdu_padding, tvb,
1864                                     offset + (bit_offset/8),
1865                                     1, FALSE);
1866                 bit_offset += 2;
1867
1868                 /* TSN */
1869                 proto_tree_add_item(subframe_tree, hf_fp_edch_tsn, tvb,
1870                                     offset + (bit_offset/8),
1871                                     1, FALSE);
1872                 bit_offset += 6;
1873
1874                 /* PDU */
1875                 if (subframe_tree)
1876                 {
1877                     ti = proto_tree_add_item(subframe_tree, hf_fp_edch_mac_es_pdu, tvb,
1878                                              offset + (bit_offset/8),
1879                                              ((bit_offset % 8) + send_size + 7) / 8,
1880                                              FALSE);
1881                     proto_item_append_text(ti, " (%u * %u = %u bits, subframe %d)",
1882                                            size, subframes[n].number_of_mac_d_pdus[i],
1883                                            send_size, n);
1884                 }
1885                 bits_in_subframe += send_size;
1886                 mac_d_pdus_in_subframe += subframes[n].number_of_mac_d_pdus[i];
1887
1888                 bit_offset += send_size;
1889
1890                 /* Pad out to next byte */
1891                 if (bit_offset % 8)
1892                 {
1893                     bit_offset += (8 - (bit_offset % 8));
1894                 }
1895             }
1896
1897             if (tree)
1898             {
1899                 /* Tree should cover entire subframe */
1900                 proto_item_set_len(subframe_ti, bit_offset/8);
1901     
1902                 /* Append summary info to subframe label */
1903                 proto_item_append_text(subframe_ti, " (%u bits in %u MAC-d PDUs)",
1904                                        bits_in_subframe, mac_d_pdus_in_subframe);
1905             }
1906             total_bits += bits_in_subframe;
1907
1908             offset += (bit_offset/8);
1909         }
1910
1911         /* Report number of subframes in info column */
1912         if (check_col(pinfo->cinfo, COL_INFO))
1913         {
1914             col_append_fstr(pinfo->cinfo, COL_INFO,
1915                             " CFN = %03u   (%u bits in %u subframes)",
1916                             cfn, total_bits, number_of_subframes);
1917         }
1918
1919         /* Payload CRC (optional) */
1920         /* TODO: is this test correct...? */
1921         /* if (p_fp_info->dch_crc_present) */
1922         if (tvb_length_remaining(tvb, offset) == 2)
1923         {
1924             proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
1925         }
1926     }
1927 }
1928
1929
1930 /***********************************/
1931 /* Dissect an HSDSCH channel       */
1932 void dissect_hsdsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1933                                  int offset, struct _fp_info *p_fp_info)
1934 {
1935     gboolean is_control_frame;
1936
1937     /* Header CRC */
1938     proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
1939
1940     /* Frame Type */
1941     is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
1942     proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
1943     offset++;
1944
1945     if (check_col(pinfo->cinfo, COL_INFO))
1946     {
1947         col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
1948     }
1949
1950     if (is_control_frame)
1951     {
1952         dissect_common_control(tvb, pinfo, tree, offset, p_fp_info);
1953     }
1954     else
1955     {
1956         guint8 number_of_pdus;
1957         guint16 pdu_length;
1958
1959         /********************************/
1960         /* HS-DCH data here             */
1961
1962         /* CmCH-PI */
1963         proto_tree_add_item(tree, hf_fp_cmch_pi, tvb, offset, 1, FALSE);
1964         offset++;
1965
1966         /* MAC-d PDU Length (13 bits) */
1967         pdu_length = (tvb_get_ntohs(tvb, offset) >> 3);
1968         proto_tree_add_item(tree, hf_fp_mac_d_pdu_len, tvb, offset, 2, FALSE);
1969         offset += 2;
1970
1971         /* Num of PDU */
1972         number_of_pdus = tvb_get_guint8(tvb, offset);
1973         proto_tree_add_item(tree, hf_fp_num_of_pdu, tvb, offset, 1, FALSE);
1974         offset++;
1975
1976         /* User buffer size */
1977         proto_tree_add_item(tree, hf_fp_user_buffer_size, tvb, offset, 2, FALSE);
1978         offset += 2;
1979
1980         /* MAC-d PDUs */
1981         offset = dissect_macd_pdu_data(tvb, pinfo, tree, offset, pdu_length,
1982                                        number_of_pdus);
1983
1984         /* Extra R6 stuff */
1985         if (p_fp_info->release == 6)
1986         {
1987             int n;
1988             guint8 flags;
1989             guint8 flag_bytes = 0;
1990
1991             /* New IE flags */
1992             do
1993             {
1994                 proto_item *new_ie_flags_ti;
1995                 proto_tree *new_ie_flags_tree;
1996                 guint ies_found = 0;
1997
1998                 /* Add new IE flags subtree */
1999                 new_ie_flags_ti = proto_tree_add_string_format(tree, hf_fp_hsdsch_new_ie_flags, tvb, offset, 1,
2000                                                               "", "New IE flags");
2001                 new_ie_flags_tree = proto_item_add_subtree(new_ie_flags_ti, ett_fp_hsdsch_new_ie_flags);
2002
2003                 /* Read next byte */
2004                 flags = tvb_get_guint8(tvb, offset);
2005                 flag_bytes++;
2006
2007                 /* Dissect individual bits */
2008                 for (n=0; n < 8; n++)
2009                 {
2010                     proto_tree_add_item(new_ie_flags_tree, hf_fp_hsdsch_new_ie_flag[n], tvb, offset, 1, FALSE);
2011                     if ((flags >> (7-n)) & 0x01)
2012                     {
2013                         ies_found++;
2014                     }
2015                 }
2016                 offset++;
2017
2018                 proto_item_append_text(new_ie_flags_ti, " (%u IEs found)", ies_found);
2019
2020                 /* Last bit set will indicate another flags byte follows... */
2021             } while (0); /*((flags & 0x01) && (flag_bytes < 31));*/
2022
2023             if (1) /*(flags & 0x8) */
2024             {
2025                 /* DRT is shown as mandatory in the diagram (3GPP TS 25.435 V6.3.0),
2026                    but the description below it states that
2027                    it should depend upon the first bit.  The detailed description of
2028                    New IE flags doesn't agree, so treat as mandatory for now... */
2029                 proto_tree_add_item(tree, hf_fp_hsdsch_drt, tvb, offset, 2, FALSE);
2030                 offset += 2;
2031             }
2032         }
2033
2034         /* TODO: may be spare extension to skip */
2035
2036         /* Payload CRC */
2037         proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
2038     }
2039 }
2040
2041
2042
2043
2044 /*****************************/
2045 /* Main dissection function. */
2046 void dissect_fp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
2047 {
2048     proto_tree       *fp_tree;
2049     proto_item       *ti;
2050     gint             offset = 0;
2051     struct _fp_info  *p_fp_info;
2052
2053     /* Append this protocol name rather than replace. */
2054     if (check_col(pinfo->cinfo, COL_PROTOCOL))
2055         col_set_str(pinfo->cinfo, COL_PROTOCOL, "FP");
2056
2057     /* Create fp tree. */
2058     ti = proto_tree_add_item(tree, proto_fp, tvb, offset, -1, FALSE);
2059     fp_tree = proto_item_add_subtree(ti, ett_fp);
2060
2061     /* Look for packet info! */
2062     p_fp_info = p_get_proto_data(pinfo->fd, proto_fp);
2063
2064     /* Can't dissect anything without it... */
2065     if (p_fp_info == NULL)
2066     {
2067         return;
2068     }
2069
2070     /* Show channel type in info column, tree */
2071     if (check_col(pinfo->cinfo, COL_INFO))
2072     {
2073         col_set_str(pinfo->cinfo, COL_INFO,
2074                     val_to_str(p_fp_info->channel,
2075                                channel_type_vals,
2076                                "Unknown channel type"));
2077     }
2078     proto_item_append_text(ti, " (%s)",
2079                            val_to_str(p_fp_info->channel,
2080                                       channel_type_vals,
2081                                       "Unknown channel type"));
2082
2083     /* Add channel type as a generated field */
2084     ti = proto_tree_add_uint(fp_tree, hf_fp_channel_type, tvb, 0, 0, p_fp_info->channel);
2085     PROTO_ITEM_SET_GENERATED(ti);
2086
2087     /* Add link direction as a generated field */
2088     ti = proto_tree_add_uint(fp_tree, hf_fp_direction, tvb, 0, 0, p_fp_info->is_uplink);
2089     PROTO_ITEM_SET_GENERATED(ti);
2090
2091
2092     /*************************************/
2093     /* Dissect according to channel type */
2094     switch (p_fp_info->channel)
2095     {
2096         case CHANNEL_RACH_TDD:
2097         case CHANNEL_RACH_TDD_128:
2098         case CHANNEL_RACH_FDD:
2099             dissect_rach_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
2100             break;
2101         case CHANNEL_DCH:
2102             dissect_dch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
2103             break;
2104         case CHANNEL_FACH_FDD:
2105         case CHANNEL_FACH_TDD:
2106             dissect_fach_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
2107             break;
2108         case CHANNEL_DSCH_FDD:
2109         case CHANNEL_DSCH_TDD:
2110             dissect_dsch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
2111             break;
2112         case CHANNEL_USCH_TDD_128:
2113         case CHANNEL_USCH_TDD_384:
2114             dissect_usch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
2115             break;
2116         case CHANNEL_PCH:
2117             dissect_pch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
2118             break;
2119         case CHANNEL_CPCH:
2120             dissect_cpch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
2121             break;
2122             break;
2123         case CHANNEL_BCH:
2124             /* TODO? */
2125             break;
2126         case CHANNEL_HSDSCH:
2127             dissect_hsdsch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
2128             break;
2129         case CHANNEL_IUR_CPCHF:
2130             break;
2131         case CHANNEL_IUR_FACH:
2132             break;
2133         case CHANNEL_IUR_DSCH:
2134             dissect_iur_dsch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
2135             break;
2136         case CHANNEL_EDCH:
2137             dissect_e_dch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
2138             break;
2139
2140         default:
2141             break;
2142     }
2143 }
2144
2145 void proto_register_fp(void)
2146 {
2147     static hf_register_info hf[] =
2148     {
2149         { &hf_fp_channel_type,
2150             { "Channel Type",
2151               "fp.channel-type", FT_UINT8, BASE_HEX, VALS(channel_type_vals), 0x0,
2152               "Channel Type", HFILL
2153             }
2154         },
2155         { &hf_fp_direction,
2156             { "Direction",
2157               "fp.direction", FT_UINT8, BASE_HEX, VALS(direction_vals), 0x0,
2158               "Link direction", HFILL
2159             }
2160         },
2161         { &hf_fp_header_crc,
2162             { "Header CRC",
2163               "fp.header-crc", FT_UINT8, BASE_HEX, NULL, 0xfe,
2164               "Header CRC", HFILL
2165             }
2166         },
2167         { &hf_fp_ft,
2168             { "Frame Type",
2169               "fp.ft", FT_UINT8, BASE_HEX, VALS(data_control_vals), 0x01,
2170               "Frame Type", HFILL
2171             }
2172         },
2173         { &hf_fp_cfn,
2174             { "CFN",
2175               "fp.cfn", FT_UINT8, BASE_DEC, NULL, 0x0,
2176               "Connection Frame Number", HFILL
2177             }
2178         },
2179         { &hf_fp_pch_cfn,
2180             { "CFN (PCH)",
2181               "fp.pch.cfn", FT_UINT16, BASE_DEC, NULL, 0xfff0,
2182               "PCH Connection Frame Number", HFILL
2183             }
2184         },
2185         { &hf_fp_pch_toa,
2186             { "ToA (PCH)",
2187               "fp.pch.toa", FT_INT24, BASE_DEC, NULL, 0x0,
2188               "PCH Time of Arrival", HFILL
2189             }
2190         },
2191         { &hf_fp_cfn_control,
2192             { "CFN control",
2193               "fp.cfn-control", FT_UINT8, BASE_DEC, NULL, 0x0,
2194               "Connection Frame Number Control", HFILL
2195             }
2196         },
2197         { &hf_fp_toa,
2198             { "ToA",
2199               "fp.cfn-control", FT_INT16, BASE_DEC, NULL, 0x0,
2200               "Time of arrival (units are 125 microseconds)", HFILL
2201             }
2202         },
2203         { &hf_fp_tb,
2204             { "TB",
2205               "fp.tb", FT_NONE, BASE_NONE, NULL, 0x0,
2206               "Transport Block", HFILL
2207             }
2208         },
2209         { &hf_fp_tfi,
2210             { "TFI",
2211               "fp.tfi", FT_UINT8, BASE_DEC, NULL, 0x0,
2212               "Transport Format Indicator", HFILL
2213             }
2214         },
2215         { &hf_fp_usch_tfi,
2216             { "TFI",
2217               "fp.usch.tfi", FT_UINT8, BASE_DEC, NULL, 0x1f,
2218               "USCH Transport Format Indicator", HFILL
2219             }
2220         },
2221         { &hf_fp_cpch_tfi,
2222             { "TFI",
2223               "fp.cpch.tfi", FT_UINT8, BASE_DEC, NULL, 0x1f,
2224               "CPCH Transport Format Indicator", HFILL
2225             }
2226         },
2227         { &hf_fp_propagation_delay,
2228             { "Propagation Delay",
2229               "fp.propagation-delay", FT_UINT8, BASE_DEC, NULL, 0x0,
2230               "Propagation Delay", HFILL
2231             }
2232         },
2233         { &hf_fp_dch_control_frame_type,
2234             { "Control Frame Type",
2235               "fp.dch.control.frame-type", FT_UINT8, BASE_HEX, VALS(dch_control_frame_type_vals), 0x0,
2236               "DCH Control Frame Type", HFILL
2237             }
2238         },
2239         { &hf_fp_dch_rx_timing_deviation,
2240             { "Rx Timing Deviation",
2241               "fp.dch.control.rx-timing-deviation", FT_UINT8, BASE_DEC, 0, 0x0,
2242               "DCH Rx Timing Deviation", HFILL
2243             }
2244         },
2245         { &hf_fp_quality_estimate,
2246             { "Quality Estimate",
2247               "fp.dch.quality-estimate", FT_UINT8, BASE_DEC, 0, 0x0,
2248               "Quality Estimate", HFILL
2249             }
2250         },
2251         { &hf_fp_payload_crc,
2252             { "Payload CRC",
2253               "fp.payload-crc", FT_UINT16, BASE_HEX, 0, 0x0,
2254               "Payload CRC", HFILL
2255             }
2256         },
2257         { &hf_fp_common_control_frame_type,
2258             { "Control Frame Type",
2259               "fp.common.control.frame-type", FT_UINT8, BASE_HEX, VALS(common_control_frame_type_vals), 0x0,
2260               "Common Control Frame Type", HFILL
2261             }
2262         },
2263         { &hf_fp_crci[0],
2264             { "CRCI",
2265               "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x80,
2266               "CRC correctness indicator", HFILL
2267             }
2268         },
2269         { &hf_fp_crci[1],
2270             { "CRCI",
2271               "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x40,
2272               "CRC correctness indicator", HFILL
2273             }
2274         },
2275         { &hf_fp_crci[2],
2276             { "CRCI",
2277               "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x20,
2278               "CRC correctness indicator", HFILL
2279             }
2280         },
2281         { &hf_fp_crci[3],
2282             { "CRCI",
2283               "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x10,
2284               "CRC correctness indicator", HFILL
2285             }
2286         },
2287         { &hf_fp_crci[4],
2288             { "CRCI",
2289               "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x08,
2290               "CRC correctness indicator", HFILL
2291             }
2292         },
2293         { &hf_fp_crci[5],
2294             { "CRCI",
2295               "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x04,
2296               "CRC correctness indicator", HFILL
2297             }
2298         },
2299         { &hf_fp_crci[6],
2300             { "CRCI",
2301               "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x02,
2302               "CRC correctness indicator", HFILL
2303             }
2304         },
2305         { &hf_fp_crci[7],
2306             { "CRCI",
2307               "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x01,
2308               "CRC correctness indicator", HFILL
2309             }
2310         },
2311         { &hf_fp_received_sync_ul_timing_deviation,
2312             { "Received SYNC UL Timing Deviation",
2313               "fp.rx-sync-ul-timing-deviation", FT_UINT8, BASE_DEC, 0, 0x0,
2314               "Received SYNC UL Timing Deviation", HFILL
2315             }
2316         },
2317         { &hf_fp_pch_pi,
2318             { "Paging Indication",
2319               "fp.pch.pi", FT_UINT8, BASE_DEC, VALS(paging_indication_vals), 0x01,
2320               "Indicates if the PI Bitmap is present", HFILL
2321             }
2322         },
2323         { &hf_fp_pch_tfi,
2324             { "TFI",
2325               "fp.pch.tfi", FT_UINT8, BASE_DEC, 0, 0x1f,
2326               "PCH Transport Format Indicator", HFILL
2327             }
2328         },
2329         { &hf_fp_fach_tfi,
2330             { "TFI",
2331               "fp.fach.tfi", FT_UINT8, BASE_DEC, 0, 0x1f,
2332               "FACH Transport Format Indicator", HFILL
2333             }
2334         },
2335         { &hf_fp_transmit_power_level,
2336             { "Transmit Power Level",
2337               "fp.transmit-power-level", FT_FLOAT, BASE_DEC, 0, 0x0,
2338               "Transmit Power Level (dB)", HFILL
2339             }
2340         },
2341         { &hf_fp_pdsch_set_id,
2342             { "PDSCH Set Id",
2343               "fp.pdsch-set-id", FT_UINT8, BASE_DEC, 0, 0x0,
2344               "A pointer to the PDSCH Set which shall be used to transmit", HFILL
2345             }
2346         },
2347         { &hf_fp_paging_indication_bitmap,
2348             { "Paging Indications bitmap",
2349               "fp.pch.pi-bitmap", FT_NONE, BASE_NONE, NULL, 0x0,
2350               "Paging Indication bitmap", HFILL
2351             }
2352         },
2353         { &hf_fp_rx_timing_deviation,
2354             { "Rx Timing Deviation",
2355               "fp.common.control.rx-timing-deviation", FT_UINT8, BASE_DEC, 0, 0x0,
2356               "Common Rx Timing Deviation", HFILL
2357             }
2358         },
2359         { &hf_fp_edch_header_crc,
2360             { "E-DCH Header CRC",
2361               "fp.edch.header-crc", FT_UINT16, BASE_HEX, 0, 0xfef,
2362               "E-DCH Header CRC", HFILL
2363             }
2364         },
2365         { &hf_fp_edch_fsn,
2366             { "FSN",
2367               "fp.edch.fsn", FT_UINT8, BASE_DEC, 0, 0x0f,
2368               "E-DCH Frame Sequence Number", HFILL
2369             }
2370         },
2371         { &hf_fp_edch_number_of_subframes,
2372             { "No of subframes",
2373               "fp.edch.no-of-subframes", FT_UINT8, BASE_DEC, 0, 0x0f,
2374               "E-DCH Number of subframes", HFILL
2375             }
2376         },
2377         { &hf_fp_edch_harq_retransmissions,
2378             { "No of HARQ Retransmissions",
2379               "fp.edch.no-of-harq-retransmissions", FT_UINT8, BASE_DEC, 0, 0x78,
2380               "E-DCH Number of HARQ retransmissions", HFILL
2381             }
2382         },
2383         { &hf_fp_edch_subframe_number,
2384             { "Subframe number",
2385               "fp.edch.subframe-number", FT_UINT8, BASE_DEC, 0, 0x07,
2386               "E-DCH Subframe number", HFILL
2387             }
2388         },
2389         { &hf_fp_edch_number_of_mac_es_pdus,
2390             { "Number of Mac-es PDUs",
2391               "fp.edch.number-of-mac-es-pdus", FT_UINT8, BASE_DEC, 0, 0xf0,
2392               "Number of Mac-es PDUs", HFILL
2393             }
2394         },
2395         { &hf_fp_edch_ddi,
2396             { "DDI",
2397               "fp.edch.ddi", FT_UINT8, BASE_DEC, 0, 0x0,
2398               "E-DCH Data Description Indicator", HFILL
2399             }
2400         },
2401         { &hf_fp_edch_subframe,
2402             { "Subframe",
2403               "fp.edch.subframe", FT_STRING, BASE_NONE, NULL, 0x0,
2404               "EDCH Subframe", HFILL
2405             }
2406         },
2407         { &hf_fp_edch_subframe_header,
2408             { "Subframe header",
2409               "fp.edch.subframe-header", FT_STRING, BASE_NONE, NULL, 0x0,
2410               "EDCH Subframe header", HFILL
2411             }
2412         },
2413         { &hf_fp_edch_number_of_mac_d_pdus,
2414             { "Number of Mac-d PDUs",
2415               "fp.edch.number-of-mac-d-pdus", FT_UINT8, BASE_DEC, 0, 0x0,
2416               "Number of Mac-d PDUs", HFILL
2417             }
2418         },
2419         { &hf_fp_edch_pdu_padding,
2420             { "Padding",
2421               "fp.edch-data-padding", FT_UINT8, BASE_DEC, 0, 0xc0,
2422               "E-DCH padding before PDU", HFILL
2423             }
2424         },
2425         { &hf_fp_edch_tsn,
2426             { "TSN",
2427               "fp.edch-tsn", FT_UINT8, BASE_DEC, 0, 0x3f,
2428               "E-DCH Transmission Sequence Number", HFILL
2429             }
2430         },
2431         { &hf_fp_edch_mac_es_pdu,
2432             { "MAC-es PDU",
2433               "fp.edch.mac-es-pdu", FT_NONE, BASE_NONE, NULL, 0x0,
2434               "MAC-es PDU", HFILL
2435             }
2436         },
2437         { &hf_fp_cmch_pi,
2438             { "CmCH-PI",
2439               "fp.cmch-pi", FT_UINT8, BASE_DEC, 0, 0x0f,
2440               "Common Transport Channel Priority Indicator", HFILL
2441             }
2442         },
2443         { &hf_fp_user_buffer_size,
2444             { "User buffer size",
2445               "fp.user-buffer-size", FT_UINT16, BASE_DEC, 0, 0x0,
2446               "User buffer size in octets", HFILL
2447             }
2448         },
2449         { &hf_fp_hsdsch_credits,
2450             { "HS-DSCH Credits",
2451               "fp.hsdsch-credits", FT_UINT16, BASE_DEC, 0, 0x07ff,
2452               "HS-DSCH Credits", HFILL
2453             }
2454         },
2455         { &hf_fp_hsdsch_max_macd_pdu_len,
2456             { "Max MAC-d PDU Length",
2457               "fp.hsdsch.max-macd-pdu-len", FT_UINT16, BASE_DEC, 0, 0xfff8,
2458               "Maximum MAC-d PDU Length in bits", HFILL
2459             }
2460         },
2461         { &hf_fp_hsdsch_interval,
2462             { "HS-DSCH Interval in milliseconds",
2463               "fp.hsdsch-interval", FT_UINT8, BASE_DEC, 0, 0x0,
2464               "HS-DSCH Interval in milliseconds", HFILL
2465             }
2466         },
2467         { &hf_fp_hsdsch_repetition_period,
2468             { "HS-DSCH Repetition Period",
2469               "fp.hsdsch-repetition-period", FT_UINT8, BASE_DEC, 0, 0x0,
2470               "HS-DSCH Repetition Period in milliseconds", HFILL
2471             }
2472         },
2473         { &hf_fp_hsdsch_data_padding,
2474             { "Padding",
2475               "fp.hsdsch-data-padding", FT_UINT8, BASE_DEC, 0, 0xf0,
2476               "HS-DSCH Repetition Period in milliseconds", HFILL
2477             }
2478         },
2479         { &hf_fp_hsdsch_new_ie_flags,
2480             { "New IEs flags",
2481               "fp.hsdsch.new-ie-flags", FT_STRING, BASE_NONE, 0, 0x0,
2482               "New IEs flags", HFILL
2483             }
2484         },
2485         { &hf_fp_hsdsch_new_ie_flag[0],
2486             { "DRT IE present",
2487               "fp.hsdsch.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x80,
2488               "DRT IE present", HFILL
2489             }
2490         },
2491         { &hf_fp_hsdsch_new_ie_flag[1],
2492             { "New IE present",
2493               "fp.hsdsch.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x40,
2494               "New IE present", HFILL
2495             }
2496         },
2497         { &hf_fp_hsdsch_new_ie_flag[2],
2498             { "New IE present",
2499               "fp.hsdsch.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x20,
2500               "New IE present", HFILL
2501             }
2502         },
2503         { &hf_fp_hsdsch_new_ie_flag[3],
2504             { "New IE present",
2505               "fp.hsdsch.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x10,
2506               "New IE present", HFILL
2507             }
2508         },
2509         { &hf_fp_hsdsch_new_ie_flag[4],
2510             { "New IE present",
2511               "fp.hsdsch.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x08,
2512               "New IE present", HFILL
2513             }
2514         },
2515         { &hf_fp_hsdsch_new_ie_flag[5],
2516             { "New IE present",
2517               "fp.hsdsch.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x04,
2518               "New IE present", HFILL
2519             }
2520         },
2521         { &hf_fp_hsdsch_new_ie_flag[6],
2522             { "New IE present",
2523               "fp.hsdsch.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x02,
2524               "New IE present", HFILL
2525             }
2526         },
2527         { &hf_fp_hsdsch_new_ie_flag[7],
2528             { "Another new IE flags byte",
2529               "fp.hsdsch.new-ie-flags-byte", FT_UINT8, BASE_DEC, 0, 0x01,
2530               "Another new IE flagsbyte", HFILL
2531             }
2532         },
2533         { &hf_fp_hsdsch_drt,
2534             { "DRT",
2535               "fp.hsdsch.drt", FT_UINT8, BASE_DEC, 0, 0xf0,
2536               "Delay Reference Time", HFILL
2537             }
2538         },
2539         { &hf_fp_timing_advance,
2540             { "Timing advance",
2541               "fp.timing-advance", FT_UINT8, BASE_DEC, 0, 0x3f,
2542               "Timing advance in chips", HFILL
2543             }
2544         },
2545         { &hf_fp_num_of_pdu,
2546             { "Number of PDUs",
2547               "fp.hsdsch.num-of-pdu", FT_UINT8, BASE_DEC, 0, 0x0,
2548               "Number of PDUs in the payload", HFILL
2549             }
2550         },
2551         { &hf_fp_mac_d_pdu_len,
2552             { "MAC-d PDU Length",
2553               "fp.hsdsch.mac-d-pdu-len", FT_UINT16, BASE_DEC, 0, 0xfff8,
2554               "MAC-d PDU Length in bits", HFILL
2555             }
2556         },
2557         { &hf_fp_mac_d_pdu,
2558             { "MAC-d PDU",
2559               "fp.mac-d-pdu", FT_NONE, BASE_NONE, NULL, 0x0,
2560               "MAC-d PDU", HFILL
2561             }
2562         },
2563         { &hf_fp_data,
2564             { "Data",
2565               "fp.data", FT_STRING, BASE_NONE, NULL, 0x0,
2566               "Data", HFILL
2567             }
2568         },
2569         { &hf_fp_crcis,
2570             { "CRCIs",
2571               "fp.crcis", FT_STRING, BASE_NONE, NULL, 0x0,
2572               "CRC Indicators for uplink TBs", HFILL
2573             }
2574         },
2575         { &hf_fp_t1,
2576             { "T1",
2577               "fp.t1", FT_UINT24, BASE_DEC, NULL, 0x0,
2578               "RNC frame number indicating time it sends frame", HFILL
2579             }
2580         },
2581         { &hf_fp_t2,
2582             { "T2",
2583               "fp.t2", FT_UINT24, BASE_DEC, NULL, 0x0,
2584               "NodeB frame number indicating time it received DL Sync", HFILL
2585             }
2586         },
2587         { &hf_fp_t3,
2588             { "T3",
2589               "fp.t3", FT_UINT24, BASE_DEC, NULL, 0x0,
2590               "NodeB frame number indicating time it sends frame", HFILL
2591             }
2592         },
2593         { &hf_fp_ul_sir_target,
2594             { "UL_SIR_TARGET",
2595               "fp.ul-sir_target", FT_FLOAT, BASE_DEC, 0, 0x0,
2596               "Value (in dB) of the SIR target to be used by the UL inner loop power control", HFILL
2597             }
2598         },
2599         { &hf_fp_pusch_set_id,
2600             { "PUSCH Set Id",
2601               "fp.pusch-set-id", FT_UINT8, BASE_DEC, NULL, 0x0,
2602               "Identifies PUSCH Set from those configured in NodeB", HFILL
2603             }
2604         },
2605         { &hf_fp_activation_cfn,
2606             { "Activation CFN",
2607               "fp.activation-cfn", FT_UINT8, BASE_DEC, NULL, 0x0,
2608               "Activation Connection Frame Number", HFILL
2609             }
2610         },
2611         { &hf_fp_duration,
2612             { "Duration (ms)",
2613               "fp.pusch-set-id", FT_UINT8, BASE_DEC, NULL, 0x0,
2614               "Duration of the activation period of the PUSCH Set", HFILL
2615             }
2616         },
2617         { &hf_fp_power_offset,
2618             { "Power offset",
2619               "fp.power-offset", FT_FLOAT, BASE_NONE, NULL, 0x0,
2620               "Power offset (in dB)", HFILL
2621             }
2622         },
2623         { &hf_fp_code_number,
2624             { "Code number",
2625               "fp.code-number", FT_UINT8, BASE_DEC, NULL, 0x0,
2626               "Code number", HFILL
2627             }
2628         },
2629         { &hf_fp_spreading_factor,
2630             { "Spreading factor",
2631               "fp.spreading-factor", FT_UINT8, BASE_DEC, VALS(spreading_factor_vals), 0xf0,
2632               "Spreading factor", HFILL
2633             }
2634         },
2635         { &hf_fp_mc_info,
2636             { "MC info",
2637               "fp.mc-info", FT_UINT8, BASE_DEC, NULL, 0x0e,
2638               "MC info", HFILL
2639             }
2640         },
2641         { &hf_fp_rach_new_ie_flags,
2642             { "New IEs flags",
2643               "fp.rach.new-ie-flags", FT_STRING, BASE_NONE, 0, 0x0,
2644               "New IEs flags", HFILL
2645             }
2646         },
2647         { &hf_fp_rach_new_ie_flag[0],
2648             { "New IE present",
2649               "fp.rach.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x80,
2650               "New IE present", HFILL
2651             }
2652         },
2653         { &hf_fp_rach_new_ie_flag[1],
2654             { "New IE present",
2655               "fp.rach.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x40,
2656               "New IE present", HFILL
2657             }
2658         },
2659         { &hf_fp_rach_new_ie_flag[2],
2660             { "New IE present",
2661               "fp.rach.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x20,
2662               "New IE present", HFILL
2663             }
2664         },
2665         { &hf_fp_rach_new_ie_flag[3],
2666             { "New IE present",
2667               "fp.rach.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x10,
2668               "New IE present", HFILL
2669             }
2670         },
2671         { &hf_fp_rach_new_ie_flag[4],
2672             { "New IE present",
2673               "fp.rach.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x08,
2674               "New IE present", HFILL
2675             }
2676         },
2677         { &hf_fp_rach_new_ie_flag[5],
2678             { "New IE present",
2679               "fp.rach.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x04,
2680               "New IE present", HFILL
2681             }
2682         },
2683         { &hf_fp_rach_new_ie_flag[6],
2684             { "New IE present",
2685               "fp.rach.new-ie-flag", FT_UINT8, BASE_DEC, 0, 0x02,
2686               "New IE present", HFILL
2687             }
2688         },
2689         { &hf_fp_rach_new_ie_flag[7],
2690             { "Another new IE flags byte",
2691               "fp.rach.new-ie-flags-byte", FT_UINT8, BASE_DEC, 0, 0x01,
2692               "Another new IE flags byte", HFILL
2693             }
2694         },
2695         { &hf_fp_cell_portion_id,
2696             { "Cell Portion ID",
2697               "fp.cell-portion-id", FT_UINT8, BASE_DEC, NULL, 0x3f,
2698               "Cell Portion ID", HFILL
2699             }
2700         },
2701
2702         { &hf_fp_radio_interface_parameter_update_flag[0],
2703             { "CFN valid",
2704               "fp.radio_interface_param.cfn-valid", FT_UINT16, BASE_DEC, 0, 0x0001,
2705               "CFN valid", HFILL
2706             }
2707         },
2708         { &hf_fp_radio_interface_parameter_update_flag[1],
2709             { "TPC PO valid",
2710               "fp.radio_interface_param.tpc-po-valid", FT_UINT16, BASE_DEC, 0, 0x0002,
2711               "TPC PO valid", HFILL
2712             }
2713         },
2714         { &hf_fp_radio_interface_parameter_update_flag[2],
2715             { "DPC mode valid",
2716               "fp.radio_interface_param.dpc-mode-valid", FT_UINT16, BASE_DEC, 0, 0x0004,
2717               "DPC mode valid", HFILL
2718             }
2719         },
2720         { &hf_fp_radio_interface_parameter_update_flag[3],
2721             { "RL sets indicator valid",
2722               "fp.radio_interface_param.rl-sets-indicator-valid", FT_UINT16, BASE_DEC, 0, 0x0020,
2723               "RI valid", HFILL
2724             }
2725         },
2726         { &hf_fp_radio_interface_parameter_update_flag[4],
2727             { "MAX_UE_TX_POW valid",
2728               "fp.radio_interface_param.max-ue-tx-pow-valid", FT_UINT16, BASE_DEC, 0, 0x0040,
2729               "MAX UE TX POW valid", HFILL
2730             }
2731         },
2732         { &hf_fp_dpc_mode,
2733             { "DPC Mode",
2734               "fp.dpc-mode", FT_UINT8, BASE_DEC, NULL, 0x20,
2735               "DPC Mode to be applied in the uplink", HFILL
2736             }
2737         },
2738         { &hf_fp_tpc_po,
2739             { "TPC PO",
2740               "fp.tpc-po", FT_UINT8, BASE_DEC, NULL, 0x1f,
2741               "TPC PO", HFILL
2742             }
2743         },
2744         { &hf_fp_multiple_rl_set_indicator,
2745             { "Multiple RL sets indicator",
2746               "fp.multiple-rl-sets-indicator", FT_UINT8, BASE_DEC, NULL, 0x80,
2747               "Multiple RL sets indicator", HFILL
2748             }
2749         },
2750         { &hf_fp_max_ue_tx_pow,
2751             { "MAX_UE_TX_POW",
2752               "fp.max-ue-tx-pow", FT_INT8, BASE_DEC, NULL, 0x0,
2753               "Max UE TX POW (dBm)", HFILL
2754             }
2755         },
2756         { &hf_fp_congestion_status,
2757             { "Congestion Status",
2758               "fp.congestion-status", FT_UINT8, BASE_DEC, VALS(congestion_status_vals), 0x03,
2759               "Congestion Status", HFILL
2760             }
2761         },
2762
2763     };
2764
2765
2766     static gint *ett[] =
2767     {
2768         &ett_fp,
2769         &ett_fp_data,
2770         &ett_fp_crcis,
2771         &ett_fp_edch_subframe_header,
2772         &ett_fp_edch_subframe,
2773         &ett_fp_hsdsch_new_ie_flags,
2774         &ett_fp_rach_new_ie_flags
2775     };
2776
2777     /* Register protocol. */
2778     proto_fp = proto_register_protocol("FP", "FP", "fp");
2779     proto_register_field_array(proto_fp, hf, array_length(hf));
2780     proto_register_subtree_array(ett, array_length(ett));
2781
2782     /* Allow other dissectors to find this one by name. */
2783     register_dissector("fp", dissect_fp, proto_fp);
2784 }
2785
2786
2787 void proto_reg_handoff_fp(void)
2788 {
2789 }
2790