1 /* Routines for UMTS FP disassembly
5 * $Id: packet-fp.c 18196 2006-05-21 04:49:01Z sahlberg $
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version 2
14 * of the License, or (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
30 #include <epan/packet.h>
31 #include <epan/expert.h>
33 #include "packet-umts_fp.h"
36 - remaining message types
37 - verify header & payload CRCs
38 - look for (and report as expert info) spare extension bytes
41 /* Initialize the protocol and registered fields. */
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_propagation_delay = -1;
56 static int hf_fp_tb = -1;
57 static int hf_fp_received_sync_ul_timing_deviation = -1;
58 static int hf_fp_pch_pi = -1;
59 static int hf_fp_pch_tfi = -1;
60 static int hf_fp_fach_tfi = -1;
61 static int hf_fp_transmit_power_level = -1;
62 static int hf_fp_paging_indication_bitmap = -1;
63 static int hf_fp_pdsch_set_id = -1;
64 static int hf_fp_rx_timing_deviation = -1;
65 static int hf_fp_dch_control_frame_type = -1;
66 static int hf_fp_dch_rx_timing_deviation = -1;
67 static int hf_fp_quality_estimate = -1;
68 static int hf_fp_payload_crc = -1;
69 static int hf_fp_edch_header_crc = -1;
70 static int hf_fp_edch_fsn = -1;
71 static int hf_fp_edch_subframe = -1;
72 static int hf_fp_edch_number_of_subframes = -1;
73 static int hf_fp_edch_harq_retransmissions = -1;
74 static int hf_fp_edch_subframe_number = -1;
75 static int hf_fp_edch_number_of_mac_es_pdus = -1;
76 static int hf_fp_edch_ddi = -1;
77 static int hf_fp_edch_subframe_header = -1;
78 static int hf_fp_edch_number_of_mac_d_pdus = -1;
79 static int hf_fp_edch_pdu_padding = -1;
80 static int hf_fp_edch_tsn = -1;
81 static int hf_fp_edch_mac_es_pdu = -1;
82 static int hf_fp_cmch_pi = -1;
83 static int hf_fp_user_buffer_size = -1;
84 static int hf_fp_hsdsch_credits = -1;
85 static int hf_fp_hsdsch_max_macd_pdu_len = -1;
86 static int hf_fp_hsdsch_interval = -1;
87 static int hf_fp_hsdsch_repetition_period = -1;
88 static int hf_fp_hsdsch_data_padding = -1;
89 static int hf_fp_hsdsch_new_ie_flags[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
90 static int hf_fp_hsdsch_drt = -1;
91 static int hf_fp_timing_advance = -1;
92 static int hf_fp_num_of_pdu = -1;
93 static int hf_fp_mac_d_pdu_len = -1;
94 static int hf_fp_mac_d_pdu = -1;
95 static int hf_fp_data = -1;
96 static int hf_fp_crcis = -1;
97 static int hf_fp_crci[8] = {-1, -1, -1, -1, -1, -1, -1, -1};
98 static int hf_fp_common_control_frame_type = -1;
99 static int hf_fp_t1 = -1;
100 static int hf_fp_t2 = -1;
101 static int hf_fp_t3 = -1;
102 static int hf_fp_ul_sir_target = -1;
105 static int ett_fp = -1;
106 static int ett_fp_data = -1;
107 static int ett_fp_crcis = -1;
108 static int ett_fp_edch_subframe_header = -1;
109 static int ett_fp_edch_subframe = -1;
112 /* E-DCH channel header information */
115 guint8 subframe_number;
116 guint8 number_of_mac_es_pdus;
118 guint16 number_of_mac_d_pdus[64];
122 static const value_string channel_type_vals[] =
124 { CHANNEL_RACH_FDD, "RACH_FDD" },
125 { CHANNEL_RACH_TDD, "RACH_TDD" },
126 { CHANNEL_FACH_FDD, "FACH_FDD" },
127 { CHANNEL_FACH_TDD, "FACH_TDD" },
128 { CHANNEL_DSCH_FDD, "DSCH_FDD" },
129 { CHANNEL_DSCH_TDD, "DSCH_TDD" },
130 { CHANNEL_USCH_TDD_384, "USCH_TDD_384" },
131 { CHANNEL_USCH_TDD_128, "USCH_TDD_128" },
132 { CHANNEL_PCH, "PCH" },
133 { CHANNEL_CPCH, "CPCH" },
134 { CHANNEL_BCH, "BCH" },
135 { CHANNEL_DCH, "DCH" },
136 { CHANNEL_HSDSCH, "HSDSCH" },
137 { CHANNEL_IUR_CPCHF, "IUR CPCHF" },
138 { CHANNEL_IUR_FACH, "IUR FACH" },
139 { CHANNEL_IUR_DSCH, "IUR DSCH" },
140 { CHANNEL_EDCH, "EDCH" },
141 { CHANNEL_RACH_TDD_128, "RACH_TDD_128" },
145 static const value_string data_control_vals[] = {
151 static const value_string direction_vals[] = {
157 static const value_string crci_vals[] = {
159 { 1, "Not correct" },
163 static const value_string paging_indication_vals[] = {
164 { 0, "no PI-bitmap in payload" },
165 { 1, "PI-bitmap in payload" },
170 /* DCH control types */
171 #define DCH_OUTER_LOOP_POWER_CONTROL 1
172 #define DCH_TIMING_ADJUSTMENT 2
173 #define DCH_DL_SYNCHRONISATION 3
174 #define DCH_UL_SYNCHRONISATION 4
176 #define DCH_DL_NODE_SYNCHRONISATION 6
177 #define DCH_UL_NODE_SYNCHRONISATION 7
178 #define DCH_RX_TIMING_DEVIATION 8
179 #define DCH_RADIO_INTERFACE_PARAMETER_UPDATE 9
180 #define DCH_TIMING_ADVANCE 10
181 #define DCH_TNL_CONGESTION_INDICATION 11
183 static const value_string dch_control_frame_type_vals[] = {
184 { DCH_OUTER_LOOP_POWER_CONTROL, "OUTER LOOP POWER CONTROL" },
185 { DCH_TIMING_ADJUSTMENT, "TIMING ADJUSTMENT" },
186 { DCH_DL_SYNCHRONISATION, "DL SYNCHRONISATION" },
187 { DCH_UL_SYNCHRONISATION, "UL SYNCHRONISATION" },
188 { 5, "Reserved Value" },
189 { DCH_DL_NODE_SYNCHRONISATION, "DL NODE SYNCHRONISATION" },
190 { DCH_UL_NODE_SYNCHRONISATION, "UL NODE SYNCHRONISATION" },
191 { DCH_RX_TIMING_DEVIATION, "RX TIMING DEVIATION" },
192 { DCH_RADIO_INTERFACE_PARAMETER_UPDATE, "RADIO INTERFACE PARAMETER UPDATE" },
193 { DCH_TIMING_ADVANCE, "TIMING ADVANCE" },
194 { DCH_TNL_CONGESTION_INDICATION, "TNL CONGESTION INDICATION" },
199 /* Common channel control types */
200 #define COMMON_OUTER_LOOP_POWER_CONTROL 1
201 #define COMMON_TIMING_ADJUSTMENT 2
202 #define COMMON_DL_SYNCHRONISATION 3
203 #define COMMON_UL_SYNCHRONISATION 4
205 #define COMMON_DL_NODE_SYNCHRONISATION 6
206 #define COMMON_UL_NODE_SYNCHRONISATION 7
207 #define COMMON_DYNAMIC_PUSCH_ASSIGNMENT 8
208 #define COMMON_TIMING_ADVANCE 9
209 #define COMMON_HS_DSCH_Capacity_Request 10
210 #define COMMON_HS_DSCH_Capacity_Allocation 11
212 static const value_string common_control_frame_type_vals[] = {
213 { COMMON_OUTER_LOOP_POWER_CONTROL, "OUTER LOOP POWER CONTROL" },
214 { COMMON_TIMING_ADJUSTMENT, "TIMING ADJUSTMENT" },
215 { COMMON_DL_SYNCHRONISATION, "DL SYNCHRONISATION" },
216 { COMMON_UL_SYNCHRONISATION, "UL SYNCHRONISATION" },
217 { 5, "Reserved Value" },
218 { COMMON_DL_NODE_SYNCHRONISATION, "DL NODE SYNCHRONISATION" },
219 { COMMON_UL_NODE_SYNCHRONISATION, "UL NODE SYNCHRONISATION" },
220 { COMMON_DYNAMIC_PUSCH_ASSIGNMENT, "DYNAMIC PUSCH ASSIGNMENT" },
221 { COMMON_TIMING_ADVANCE, "TIMING ADVANCE" },
222 { COMMON_HS_DSCH_Capacity_Request, "HS-DSCH Capacity Request" },
223 { COMMON_HS_DSCH_Capacity_Allocation, "HS-DSCH Capacity Allocation" },
227 /* Dissect message parts */
228 static int dissect_tb_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
229 int offset, struct _fp_info *p_fp_info, int *num_tbs);
230 static int dissect_macd_pdu_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
231 int offset, guint16 length, guint8 number_of_pdus);
232 static int dissect_crci_bits(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
233 int num_tbs, int offset);
235 /* Dissect common control messages */
236 static void dissect_common_timing_adjustment(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
237 int offset, struct _fp_info *p_fp_info);
238 static void dissect_common_dl_node_synchronisation(packet_info *pinfo, proto_tree *tree,
239 tvbuff_t *tvb, int offset);
240 static void dissect_common_ul_node_synchronisation(packet_info *pinfo, proto_tree *tree,
241 tvbuff_t *tvb, int offset);
242 static void dissect_common_dl_syncronisation(packet_info *pinfo, proto_tree *tree,
243 tvbuff_t *tvb, int offset,
244 struct _fp_info *p_fp_info);
245 static void dissect_common_ul_syncronisation(packet_info *pinfo, proto_tree *tree,
246 tvbuff_t *tvb, int offset,
247 struct _fp_info *p_fp_info);
248 static void dissect_common_timing_advance(proto_tree *tree, tvbuff_t *tvb, int offset);
249 static void dissect_hsdpa_capacity_request(packet_info *pinfo, proto_tree *tree,
250 tvbuff_t *tvb, int offset);
251 static void dissect_hsdpa_capacity_allocation(packet_info *pinfo, proto_tree *tree,
252 tvbuff_t *tvb, int offset);
253 static void dissect_common_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
254 int offset, struct _fp_info *p_fp_info);
256 /* Dissect common channel types */
257 static void dissect_rach_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
258 int offset, struct _fp_info *p_fp_info);
259 static void dissect_fach_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
260 int offset, struct _fp_info *p_fp_info);
261 static void dissect_dsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
262 int offset, struct _fp_info *p_fp_info);
263 static void dissect_usch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
264 int offset, struct _fp_info *p_fp_info);
265 static void dissect_pch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
266 int offset, struct _fp_info *p_fp_info);
267 static void dissect_iur_dsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
268 int offset, struct _fp_info *p_fp_info _U_);
269 static void dissect_hsdsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
270 int offset, struct _fp_info *p_fp_info);
273 /* Dissect DCH control messages */
274 static void dissect_dch_timing_adjustment(proto_tree *tree, packet_info *pinfo,
275 tvbuff_t *tvb, int offset);
276 static void dissect_dch_rx_timing_deviation(proto_tree *tree, tvbuff_t *tvb, int offset);
277 static void dissect_dch_dl_synchronisation(proto_tree *tree, packet_info *pinfo,
278 tvbuff_t *tvb, int offset);
279 static void dissect_dch_ul_synchronisation(proto_tree *tree, packet_info *pinfo,
280 tvbuff_t *tvb, int offset);
281 static void dissect_dch_dl_node_synchronisation(proto_tree *tree, packet_info *pinfo,
282 tvbuff_t *tvb, int offset);
283 static void dissect_dch_ul_node_synchronisation(proto_tree *tree, packet_info *pinfo,
284 tvbuff_t *tvb, int offset);
287 /* Dissect a DCH channel */
288 static void dissect_dch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
289 int offset, struct _fp_info *p_fp_info);
291 /* Dissect dedicated channels */
292 static void dissect_e_dch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
293 int offset, struct _fp_info *p_fp_info);
294 static void dissect_fp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree);
296 void proto_register_fp(void);
297 void proto_reg_handoff_fp(void);
302 /* Dissect the TBs of a data frame */
303 int dissect_tb_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
304 int offset, struct _fp_info *p_fp_info, int *num_tbs)
310 proto_tree *data_tree;
312 /* Add data subtree */
313 ti = proto_tree_add_string_format(tree, hf_fp_data, tvb, offset, 0,
315 "TB data for %u chans",
316 p_fp_info->num_chans);
317 data_tree = proto_item_add_subtree(ti, ett_fp_data);
320 /* Now for the TB data */
321 for (chan=0; chan < p_fp_info->num_chans; chan++)
324 for (n=0; n < p_fp_info->chan_num_tbs[chan]; n++)
327 ti = proto_tree_add_item(data_tree, hf_fp_tb, tvb,
328 offset + (bit_offset/8),
329 ((bit_offset % 8) + p_fp_info->chan_tf_size[chan] + 7) / 8,
331 proto_item_append_text(ti, " (chan %u, tb %u, %u bits)",
332 chan+1, n+1, p_fp_info->chan_tf_size[chan]);
335 /* Advance bit offset */
336 bit_offset += p_fp_info->chan_tf_size[chan];
337 data_bits += p_fp_info->chan_tf_size[chan];
339 /* Pad out to next byte */
342 bit_offset += (8 - (bit_offset % 8));
347 if (check_col(pinfo->cinfo, COL_INFO))
349 col_append_fstr(pinfo->cinfo, COL_INFO, "(%u bits in %u tbs)",
350 data_bits, *num_tbs);
353 /* Data tree should cover entire length */
354 proto_item_set_len(data_tree, bit_offset/8);
355 proto_item_append_text(ti, " (total %u tbs)", *num_tbs);
357 /* Move offset past TBs (we know its already padded out to next byte) */
358 offset += (bit_offset / 8);
364 /* Dissect the MAC-d PDUs of an HS-DSCH frame */
365 int dissect_macd_pdu_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
366 int offset, guint16 length, guint8 number_of_pdus)
371 proto_tree *data_tree;
373 /* Add data subtree */
374 ti = proto_tree_add_string_format(tree, hf_fp_data, tvb, offset, 0,
376 "%u MAC-d PDUs of %u bits",
379 data_tree = proto_item_add_subtree(ti, ett_fp_data);
381 /* Now for the PDUs */
382 for (pdu=0; pdu < number_of_pdus; pdu++)
386 /* Show 4 bits padding at start of PDU */
387 proto_tree_add_item(data_tree, hf_fp_hsdsch_data_padding, tvb, offset+(bit_offset/8), 1, FALSE);
390 ti = proto_tree_add_item(data_tree, hf_fp_mac_d_pdu, tvb,
391 offset + (bit_offset/8),
392 ((bit_offset % 8) + length + 7) / 8,
394 proto_item_append_text(ti, " (PDU %u)", pdu+1);
396 /* Advance bit offset */
397 bit_offset += length;
399 /* Pad out to next byte */
402 bit_offset += (8 - (bit_offset % 8));
406 /* Data tree should cover entire length */
407 proto_item_set_len(data_tree, bit_offset/8);
409 /* Move offset past PDUs (we know its already padded out to next byte) */
410 offset += (bit_offset / 8);
412 /* Show summary in info column */
413 if (check_col(pinfo->cinfo, COL_INFO))
415 col_append_fstr(pinfo->cinfo, COL_INFO, " %u PDUs of %u bits",
416 number_of_pdus, length);
423 /* Dissect CRCI bits (uplink) */
424 int dissect_crci_bits(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
425 int num_tbs, int offset)
429 proto_tree *crcis_tree;
432 /* Add CRCIs subtree */
433 ti = proto_tree_add_string_format(tree, hf_fp_crcis, tvb, offset, 0,
435 "CRCI bits for %u tbs",
437 crcis_tree = proto_item_add_subtree(ti, ett_fp_crcis);
440 for (n=0; n < num_tbs; n++)
442 int bit = (tvb_get_guint8(tvb, offset+(n/8)) >> (7-(n%8))) & 0x01;
443 proto_tree_add_item(crcis_tree, hf_fp_crci[n%8], tvb, offset+(n/8),
449 expert_add_info_format(pinfo, ti,
450 PI_CHECKSUM, PI_WARN,
451 "CRCI error bit set for TB %u", n+1);
455 /* Highlight range of bytes covered by indicator bits */
456 proto_item_set_len(ti, (num_tbs+7) / 8);
458 /* Show error count in root text */
459 proto_item_append_text(ti, " (%u errors)", errors);
461 offset += ((num_tbs+7) / 8);
467 /***********************************************************/
468 /* Common control message types */
470 void dissect_common_timing_adjustment(packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb,
471 int offset, struct _fp_info *p_fp_info)
473 if (p_fp_info->channel != CHANNEL_PCH)
479 cfn = tvb_get_guint8(tvb, offset);
480 proto_tree_add_item(tree, hf_fp_cfn_control, tvb, offset, 1, FALSE);
484 toa = tvb_get_ntohs(tvb, offset);
485 proto_tree_add_item(tree, hf_fp_toa, tvb, offset, 2, FALSE);
488 if (check_col(pinfo->cinfo, COL_INFO))
490 col_append_fstr(pinfo->cinfo, COL_INFO, " CFN=%u, ToA=%d", cfn, toa);
498 /* PCH CFN is 12 bits */
499 cfn = (tvb_get_ntohs(tvb, offset) >> 4);
500 proto_tree_add_item(tree, hf_fp_pch_cfn, tvb, offset, 2, FALSE);
503 /* 4 bits of padding follow... */
505 /* 20 bits of ToA (followed by 4 padding bits) */
506 toa = ((int)(tvb_get_ntoh24(tvb, offset) << 8)) / 4096;
507 proto_tree_add_int(tree, hf_fp_pch_toa, tvb, offset, 3, toa);
509 if (check_col(pinfo->cinfo, COL_INFO))
511 col_append_fstr(pinfo->cinfo, COL_INFO, " CFN=%u, ToA=%d", cfn, toa);
516 void dissect_common_dl_node_synchronisation(packet_info *pinfo, proto_tree *tree,
517 tvbuff_t *tvb, int offset)
520 guint32 t1 = tvb_get_ntoh24(tvb, offset);
521 proto_tree_add_item(tree, hf_fp_t1, tvb, offset, 3, FALSE);
523 if (check_col(pinfo->cinfo, COL_INFO))
525 col_append_fstr(pinfo->cinfo, COL_INFO, " T1=%u", t1);
529 void dissect_common_ul_node_synchronisation(packet_info *pinfo, proto_tree *tree,
530 tvbuff_t *tvb, int offset)
535 t1 = tvb_get_ntoh24(tvb, offset);
536 proto_tree_add_item(tree, hf_fp_t1, tvb, offset, 3, FALSE);
540 t2 = tvb_get_ntoh24(tvb, offset);
541 proto_tree_add_item(tree, hf_fp_t2, tvb, offset, 3, FALSE);
545 t3 = tvb_get_ntoh24(tvb, offset);
546 proto_tree_add_item(tree, hf_fp_t3, tvb, offset, 3, FALSE);
549 if (check_col(pinfo->cinfo, COL_INFO))
551 col_append_fstr(pinfo->cinfo, COL_INFO, " T1=%u T2=%u, T3=%u",
556 void dissect_common_dl_syncronisation(packet_info *pinfo, proto_tree *tree,
557 tvbuff_t *tvb, int offset, struct _fp_info *p_fp_info)
561 if (p_fp_info->channel != CHANNEL_PCH)
564 cfn = tvb_get_guint8(tvb, offset);
565 proto_tree_add_item(tree, hf_fp_cfn_control, tvb, offset, 1, FALSE);
569 /* PCH CFN is 12 bits */
570 cfn = (tvb_get_ntohs(tvb, offset) >> 4);
571 proto_tree_add_item(tree, hf_fp_pch_cfn, tvb, offset, 2, FALSE);
573 /* 4 bits of padding follow... */
576 if (check_col(pinfo->cinfo, COL_INFO))
578 col_append_fstr(pinfo->cinfo, COL_INFO, " CFN=%u", cfn);
582 void dissect_common_ul_syncronisation(packet_info *pinfo, proto_tree *tree,
583 tvbuff_t *tvb, int offset, struct _fp_info *p_fp_info)
585 dissect_common_timing_adjustment(pinfo, tree, tvb, offset, p_fp_info);
588 void dissect_common_timing_advance(proto_tree *tree, tvbuff_t *tvb, int offset)
590 guint8 timing_advance;
593 proto_tree_add_item(tree, hf_fp_cfn_control, tvb, offset, 1, FALSE);
597 timing_advance = (tvb_get_guint8(tvb, offset) & 0x3f);
598 proto_tree_add_uint(tree, hf_fp_timing_advance, tvb, offset, 1, timing_advance*4);
602 void dissect_hsdpa_capacity_request(packet_info *pinfo, proto_tree *tree,
603 tvbuff_t *tvb, int offset)
606 guint16 user_buffer_size;
609 priority = (tvb_get_guint8(tvb, offset) & 0x0f);
610 proto_tree_add_item(tree, hf_fp_cmch_pi, tvb, offset, 1, FALSE);
613 /* User buffer size */
614 user_buffer_size = tvb_get_ntohs(tvb, offset);
615 proto_tree_add_item(tree, hf_fp_user_buffer_size, tvb, offset, 2, FALSE);
618 if (check_col(pinfo->cinfo, COL_INFO))
620 col_append_fstr(pinfo->cinfo, COL_INFO, " CmCH-PI=%u User-Buffer-Size=%u",
621 priority, user_buffer_size);
624 /* TODO: Spare extension may follow */
627 void dissect_hsdpa_capacity_allocation(packet_info *pinfo, proto_tree *tree,
628 tvbuff_t *tvb, int offset)
631 guint16 max_pdu_length;
632 guint8 repetition_period;
637 proto_tree_add_item(tree, hf_fp_cmch_pi, tvb, offset, 1, FALSE);
640 /* Max MAC-d PDU length (13 bits) */
641 max_pdu_length = (tvb_get_ntohs(tvb, offset) >> 3);
642 proto_tree_add_item(tree, hf_fp_hsdsch_max_macd_pdu_len, tvb, offset, 2, FALSE);
645 /* HS-DSCH credits (11 bits) */
646 credits = (tvb_get_ntohs(tvb, offset) & 0x07ff);
647 ti = proto_tree_add_item(tree, hf_fp_hsdsch_credits, tvb, offset, 2, FALSE);
651 proto_item_append_text(ti, " (stop transmission)");
655 proto_item_append_text(ti, " (unlimited)");
658 /* HS-DSCH Interval */
659 interval = tvb_get_guint8(tvb, offset);
660 ti = proto_tree_add_uint(tree, hf_fp_hsdsch_interval, tvb, offset, 1, interval*10);
664 proto_item_append_text(ti, " (none of the credits shall be used)");
667 /* HS-DSCH Repetition period */
668 repetition_period = tvb_get_guint8(tvb, offset);
669 ti = proto_tree_add_item(tree, hf_fp_hsdsch_repetition_period, tvb, offset, 1, FALSE);
671 if (repetition_period == 0)
673 proto_item_append_text(ti, " (unlimited repetition period)");
676 if (check_col(pinfo->cinfo, COL_INFO))
678 col_append_fstr(pinfo->cinfo, COL_INFO,
679 " Max-PDU-len=%u Credits=%u Interval=%u Rep-Period=%u",
680 max_pdu_length, credits, interval, repetition_period);
683 /* TODO: Spare extension may follow */
687 /* Dissect the control part of a common channel message */
688 void dissect_common_control(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
689 int offset, struct _fp_info *p_fp_info)
691 /* Common control frame type */
692 guint8 control_frame_type = tvb_get_guint8(tvb, offset);
693 proto_tree_add_item(tree, hf_fp_common_control_frame_type, tvb, offset, 1, FALSE);
696 if (check_col(pinfo->cinfo, COL_INFO))
698 col_append_str(pinfo->cinfo, COL_INFO,
699 val_to_str(control_frame_type, common_control_frame_type_vals, "Unknown"));
702 /* Frame-type specific dissection */
703 switch (control_frame_type)
705 case COMMON_OUTER_LOOP_POWER_CONTROL:
707 case COMMON_TIMING_ADJUSTMENT:
708 dissect_common_timing_adjustment(pinfo, tree, tvb, offset, p_fp_info);
710 case COMMON_DL_SYNCHRONISATION:
711 dissect_common_dl_syncronisation(pinfo, tree, tvb, offset, p_fp_info);
713 case COMMON_UL_SYNCHRONISATION:
714 dissect_common_ul_syncronisation(pinfo, tree, tvb, offset, p_fp_info);
716 case COMMON_DL_NODE_SYNCHRONISATION:
717 dissect_common_dl_node_synchronisation(pinfo, tree, tvb, offset);
719 case COMMON_UL_NODE_SYNCHRONISATION:
720 dissect_common_ul_node_synchronisation(pinfo, tree, tvb, offset);
722 case COMMON_DYNAMIC_PUSCH_ASSIGNMENT:
725 case COMMON_TIMING_ADVANCE:
726 dissect_common_timing_advance(tree, tvb, offset);
728 case COMMON_HS_DSCH_Capacity_Request:
729 dissect_hsdpa_capacity_request(pinfo, tree, tvb, offset);
731 case COMMON_HS_DSCH_Capacity_Allocation:
732 dissect_hsdpa_capacity_allocation(pinfo, tree, tvb, offset);
742 /**************************/
743 /* Dissect a RACH channel */
744 void dissect_rach_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
745 int offset, struct _fp_info *p_fp_info)
747 gboolean is_control_frame;
750 proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
753 is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
754 proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
757 if (check_col(pinfo->cinfo, COL_INFO))
759 col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
762 if (is_control_frame)
764 dissect_common_control(tvb, pinfo, tree, offset, p_fp_info);
774 cfn = tvb_get_guint8(tvb, offset);
775 proto_tree_add_item(tree, hf_fp_cfn, tvb, offset, 1, FALSE);
778 if (check_col(pinfo->cinfo, COL_INFO))
780 col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn);
784 proto_tree_add_item(tree, hf_fp_tfi, tvb, offset, 1, FALSE);
787 if (p_fp_info->channel == CHANNEL_RACH_FDD)
789 /* Propagation delay */
790 proto_tree_add_item(tree, hf_fp_propagation_delay, tvb, offset, 1, FALSE);
794 if (p_fp_info->channel == CHANNEL_RACH_TDD)
796 /* RX Timing Deviation */
799 if (p_fp_info->channel == CHANNEL_RACH_TDD_128)
801 /* Received SYNC UL Timing Deviation */
802 proto_tree_add_item(tree, hf_fp_received_sync_ul_timing_deviation, tvb, offset, 1, FALSE);
807 offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &num_tbs);
810 offset = dissect_crci_bits(tvb, pinfo, tree, num_tbs, offset);
813 proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
819 /**************************/
820 /* Dissect a FACH channel */
821 void dissect_fach_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
822 int offset, struct _fp_info *p_fp_info)
824 gboolean is_control_frame;
827 proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
830 is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
831 proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
834 if (check_col(pinfo->cinfo, COL_INFO))
836 col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
839 if (is_control_frame)
841 dissect_common_control(tvb, pinfo, tree, offset, p_fp_info);
851 cfn = tvb_get_guint8(tvb, offset);
852 proto_tree_add_item(tree, hf_fp_cfn, tvb, offset, 1, FALSE);
855 if (check_col(pinfo->cinfo, COL_INFO))
857 col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn);
861 proto_tree_add_item(tree, hf_fp_fach_tfi, tvb, offset, 1, FALSE);
864 /* Transmit power level. TODO: units are 0.1dB */
865 proto_tree_add_item(tree, hf_fp_transmit_power_level, tvb, offset, 1, FALSE);
869 offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &num_tbs);
872 proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
878 /**************************/
879 /* Dissect a DSCH channel */
880 void dissect_dsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
881 int offset, struct _fp_info *p_fp_info)
883 gboolean is_control_frame;
886 proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
889 is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
890 proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
893 if (check_col(pinfo->cinfo, COL_INFO))
895 col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
898 if (is_control_frame)
900 dissect_common_control(tvb, pinfo, tree, offset, p_fp_info);
910 cfn = tvb_get_guint8(tvb, offset);
911 proto_tree_add_item(tree, hf_fp_cfn, tvb, offset, 1, FALSE);
914 if (check_col(pinfo->cinfo, COL_INFO))
916 col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn);
920 proto_tree_add_item(tree, hf_fp_tfi, tvb, offset, 1, FALSE);
924 proto_tree_add_item(tree, hf_fp_pdsch_set_id, tvb, offset, 1, FALSE);
927 /* Transmit power level. TODO: units are 0.1dB */
928 proto_tree_add_item(tree, hf_fp_transmit_power_level, tvb, offset, 1, FALSE);
932 offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &num_tbs);
935 proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
941 /**************************/
942 /* Dissect a USCH channel */
943 void dissect_usch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
944 int offset, struct _fp_info *p_fp_info)
946 gboolean is_control_frame;
949 proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
952 is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
953 proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
956 if (check_col(pinfo->cinfo, COL_INFO))
958 col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
961 if (is_control_frame)
963 dissect_common_control(tvb, pinfo, tree, offset, p_fp_info);
973 cfn = tvb_get_guint8(tvb, offset);
974 proto_tree_add_item(tree, hf_fp_cfn, tvb, offset, 1, FALSE);
977 if (check_col(pinfo->cinfo, COL_INFO))
979 col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn);
983 proto_tree_add_item(tree, hf_fp_usch_tfi, tvb, offset, 1, FALSE);
986 /* Rx Timing Deviation */
987 proto_tree_add_item(tree, hf_fp_rx_timing_deviation, tvb, offset, 1, FALSE);
991 offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &num_tbs);
994 proto_tree_add_item(tree, hf_fp_quality_estimate, tvb, offset, 1, FALSE);
998 offset = dissect_crci_bits(tvb, pinfo, tree, num_tbs, offset);
1001 proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
1008 /**************************/
1009 /* Dissect a PCH channel */
1010 void dissect_pch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1011 int offset, struct _fp_info *p_fp_info)
1013 gboolean is_control_frame;
1015 gboolean paging_indication;
1018 proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
1021 is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
1022 proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
1025 if (check_col(pinfo->cinfo, COL_INFO))
1027 col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
1030 if (is_control_frame)
1032 dissect_common_control(tvb, pinfo, tree, offset, p_fp_info);
1040 /* 12-bit CFN value */
1041 proto_tree_add_item(tree, hf_fp_pch_cfn, tvb, offset, 2, FALSE);
1042 pch_cfn = (tvb_get_ntohs(tvb, offset) & 0xfff0) >> 4;
1045 if (check_col(pinfo->cinfo, COL_INFO))
1047 col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%04u ", pch_cfn);
1050 /* Paging indication */
1051 proto_tree_add_item(tree, hf_fp_pch_pi, tvb, offset, 1, FALSE);
1052 paging_indication = tvb_get_guint8(tvb, offset) & 0x01;
1056 proto_tree_add_item(tree, hf_fp_pch_tfi, tvb, offset, 1, FALSE);
1059 /* Optional paging indications */
1060 if (paging_indication)
1063 ti = proto_tree_add_item(tree, hf_fp_paging_indication_bitmap, tvb,
1065 (p_fp_info->paging_indications+7) / 8,
1067 proto_item_append_text(ti, " (%u bits)", p_fp_info->paging_indications);
1071 offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &num_tbs);
1074 proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
1080 /********************************/
1081 /* Dissect an IUR DSCH channel */
1082 void dissect_iur_dsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1083 int offset, struct _fp_info *p_fp_info _U_)
1085 gboolean is_control_frame;
1088 proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
1091 is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
1092 proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
1095 if (check_col(pinfo->cinfo, COL_INFO))
1097 col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
1101 if (is_control_frame)
1103 dissect_common_control(tvb, pinfo, tree, offset, p_fp_info);
1114 /************************/
1115 /* DCH control messages */
1117 void dissect_dch_timing_adjustment(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset)
1123 control_cfn = tvb_get_guint8(tvb, offset);
1124 proto_tree_add_item(tree, hf_fp_cfn_control, tvb, offset, 1, FALSE);
1128 toa = tvb_get_ntohs(tvb, offset);
1129 proto_tree_add_item(tree, hf_fp_toa, tvb, offset, 2, FALSE);
1132 if (check_col(pinfo->cinfo, COL_INFO))
1134 col_append_fstr(pinfo->cinfo, COL_INFO,
1135 " CFN = %u, ToA = %d", control_cfn, toa);
1139 void dissect_dch_rx_timing_deviation(proto_tree *tree, tvbuff_t *tvb, int offset)
1142 proto_tree_add_item(tree, hf_fp_cfn_control, tvb, offset, 1, FALSE);
1145 /* Rx Timing Deviation */
1146 proto_tree_add_item(tree, hf_fp_dch_rx_timing_deviation, tvb, offset, 1, FALSE);
1150 void dissect_dch_dl_synchronisation(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset)
1153 guint cfn = tvb_get_guint8(tvb, offset);
1154 proto_tree_add_item(tree, hf_fp_cfn_control, tvb, offset, 1, FALSE);
1157 if (check_col(pinfo->cinfo, COL_INFO))
1159 col_append_fstr(pinfo->cinfo, COL_INFO, " CFN = %u", cfn);
1163 void dissect_dch_ul_synchronisation(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset)
1169 cfn = tvb_get_guint8(tvb, offset);
1170 proto_tree_add_item(tree, hf_fp_cfn_control, tvb, offset, 1, FALSE);
1174 toa = tvb_get_ntohs(tvb, offset);
1175 proto_tree_add_item(tree, hf_fp_toa, tvb, offset, 2, FALSE);
1178 if (check_col(pinfo->cinfo, COL_INFO))
1180 col_append_fstr(pinfo->cinfo, COL_INFO, " CFN = %u, ToA = %d",
1185 void dissect_dch_outer_loop_power_control(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset)
1188 float target = -8.2 + (0.1*(float)tvb_get_guint8(tvb, offset));
1189 proto_tree_add_float(tree, hf_fp_ul_sir_target, tvb, offset, 1, target);
1191 if (check_col(pinfo->cinfo, COL_INFO))
1193 col_append_fstr(pinfo->cinfo, COL_INFO, "SIR Target = %f", target);
1197 void dissect_dch_dl_node_synchronisation(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset)
1199 dissect_common_dl_node_synchronisation(pinfo, tree, tvb, offset);
1202 void dissect_dch_ul_node_synchronisation(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, int offset)
1204 dissect_common_ul_node_synchronisation(pinfo, tree, tvb, offset);
1209 /*******************************/
1210 /* Dissect a DCH channel */
1211 void dissect_dch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1212 int offset, struct _fp_info *p_fp_info)
1214 gboolean is_control_frame;
1215 guint8 control_frame_type;
1219 proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
1222 is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
1223 proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
1226 if (check_col(pinfo->cinfo, COL_INFO))
1228 col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
1231 if (is_control_frame)
1233 /* DCH control frame */
1235 /* Control frame type */
1236 control_frame_type = tvb_get_guint8(tvb, offset);
1237 proto_tree_add_item(tree, hf_fp_dch_control_frame_type, tvb, offset, 1, FALSE);
1240 if (check_col(pinfo->cinfo, COL_INFO))
1242 col_append_str(pinfo->cinfo, COL_INFO,
1243 val_to_str(control_frame_type,
1244 dch_control_frame_type_vals, "Unknown"));
1247 switch (control_frame_type)
1249 case DCH_TIMING_ADJUSTMENT:
1250 dissect_dch_timing_adjustment(tree, pinfo, tvb, offset);
1252 case DCH_RX_TIMING_DEVIATION:
1253 dissect_dch_rx_timing_deviation(tree, tvb, offset);
1255 case DCH_DL_SYNCHRONISATION:
1256 dissect_dch_dl_synchronisation(tree, pinfo, tvb, offset);
1258 case DCH_UL_SYNCHRONISATION:
1259 dissect_dch_ul_synchronisation(tree, pinfo, tvb, offset);
1261 case DCH_OUTER_LOOP_POWER_CONTROL:
1262 dissect_dch_outer_loop_power_control(tree, pinfo, tvb, offset);
1264 case DCH_DL_NODE_SYNCHRONISATION:
1265 dissect_dch_dl_node_synchronisation(tree, pinfo, tvb, offset);
1267 case DCH_UL_NODE_SYNCHRONISATION:
1268 dissect_dch_ul_node_synchronisation(tree, pinfo, tvb, offset);
1270 case DCH_RADIO_INTERFACE_PARAMETER_UPDATE:
1271 case DCH_TIMING_ADVANCE:
1272 case DCH_TNL_CONGESTION_INDICATION:
1279 /************************/
1285 proto_tree_add_item(tree, hf_fp_cfn, tvb, offset, 1, FALSE);
1286 cfn = tvb_get_guint8(tvb, offset);
1289 if (check_col(pinfo->cinfo, COL_INFO))
1291 col_append_fstr(pinfo->cinfo, COL_INFO, "CFN=%03u ", cfn);
1294 /* One TFI for each channel */
1295 for (chan=0; chan < p_fp_info->num_chans; chan++)
1297 proto_tree_add_item(tree, hf_fp_tfi, tvb, offset, 1, FALSE);
1301 /* Dissect TB data */
1302 offset = dissect_tb_data(tvb, pinfo, tree, offset, p_fp_info, &num_tbs);
1304 /* QE (uplink only) */
1305 if (p_fp_info->is_uplink)
1307 proto_tree_add_item(tree, hf_fp_quality_estimate, tvb, offset, 1, FALSE);
1311 /* CRCI bits (uplink only) */
1312 if (p_fp_info->is_uplink)
1314 offset = dissect_crci_bits(tvb, pinfo, tree, num_tbs, offset);
1317 /* Payload CRC (optional) */
1318 if (p_fp_info->dch_crc_present)
1320 proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
1327 /**********************************/
1328 /* Dissect an E-DCH channel */
1329 void dissect_e_dch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1330 int offset, struct _fp_info *p_fp_info)
1332 gboolean is_control_frame;
1333 guint8 number_of_subframes;
1336 struct subframe_info subframes[8];
1339 proto_tree_add_item(tree, hf_fp_edch_header_crc, tvb, offset, 2, FALSE);
1342 is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
1343 proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
1346 if (check_col(pinfo->cinfo, COL_INFO))
1348 col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
1351 if (is_control_frame)
1353 /* TODO: will this be seen? */
1357 /********************************/
1358 /* E-DCH data here */
1360 guint bit_offset = 0;
1361 guint total_bits = 0;
1364 proto_tree_add_item(tree, hf_fp_edch_fsn, tvb, offset, 1, FALSE);
1367 /* Number of subframes (was 3, now 4 bits) */
1368 number_of_subframes = (tvb_get_guint8(tvb, offset) & 0x0f);
1369 proto_tree_add_item(tree, hf_fp_edch_number_of_subframes, tvb, offset, 1, FALSE);
1373 cfn = tvb_get_guint8(tvb, offset);
1374 proto_tree_add_item(tree, hf_fp_cfn, tvb, offset, 1, FALSE);
1377 /* EDCH subframe header list */
1378 for (n=0; n < number_of_subframes; n++)
1381 proto_item *subframe_header_ti;
1382 proto_tree *subframe_header_tree;
1384 /* Add subframe header subtree */
1385 subframe_header_ti = proto_tree_add_string_format(tree, hf_fp_edch_subframe_header, tvb, offset, 0,
1387 subframe_header_tree = proto_item_add_subtree(subframe_header_ti, ett_fp_edch_subframe_header);
1389 /* Number of HARQ Retransmissions */
1390 proto_tree_add_item(subframe_header_tree, hf_fp_edch_harq_retransmissions, tvb,
1393 /* Subframe number */
1394 subframes[n].subframe_number = (tvb_get_guint8(tvb, offset) & 0x07);
1395 proto_tree_add_item(subframe_header_tree, hf_fp_edch_subframe_number, tvb,
1399 /* Number of MAC-es PDUs */
1400 subframes[n].number_of_mac_es_pdus = (tvb_get_guint8(tvb, offset) & 0xf0) >> 4;
1401 proto_tree_add_item(subframe_header_tree, hf_fp_edch_number_of_mac_es_pdus,
1402 tvb, offset, 1, FALSE);
1405 proto_item_append_text(subframe_header_ti, " %u header (%u MAC-es PDUs)",
1406 subframes[n].subframe_number,
1407 subframes[n].number_of_mac_es_pdus);
1409 /* Details of each MAC-es PDU */
1410 for (i=0; i < subframes[n].number_of_mac_es_pdus; i++)
1418 ddi_offset = offset + (bit_offset / 8);
1420 switch (bit_offset%8)
1423 ddi = (tvb_get_guint8(tvb, ddi_offset) >> 2);
1426 ddi = (tvb_get_guint8(tvb, ddi_offset) & 0x3f);
1429 ddi = (tvb_get_ntohs(tvb, ddi_offset) >> 6) & 0x003f;
1432 ddi = (tvb_get_ntohs(tvb, ddi_offset) >> 4) & 0x003f;
1435 /* Can't get here, but avoid warning */
1439 proto_tree_add_uint(subframe_header_tree, hf_fp_edch_ddi, tvb, ddi_offset,
1440 ((bit_offset%8) <= 2) ? 1 : 2, ddi);
1442 subframes[n].ddi[i] = ddi;
1445 /* Number of MAC-d PDUs (6 bits) */
1446 n_pdus_offset = offset + (bit_offset / 8);
1447 switch (bit_offset%8)
1450 n_pdus = (tvb_get_guint8(tvb, n_pdus_offset) >> 2);
1453 n_pdus = (tvb_get_guint8(tvb, n_pdus_offset) & 0x3f);
1456 n_pdus = (tvb_get_ntohs(tvb, n_pdus_offset) >> 6) & 0x003f;
1459 n_pdus = (tvb_get_ntohs(tvb, n_pdus_offset) >> 4) & 0x003f;
1462 /* Can't get here, but avoid warning */
1465 proto_tree_add_uint(subframe_header_tree, hf_fp_edch_number_of_mac_d_pdus, tvb, n_pdus_offset,
1466 ((bit_offset%8) <= 2) ? 1 : 2, n_pdus);
1468 subframes[n].number_of_mac_d_pdus[i] = n_pdus;
1472 /* Tree should cover entire subframe header */
1473 proto_item_set_len(subframe_header_ti, bit_offset/8);
1475 offset += ((bit_offset+7)/8);
1478 /* EDCH subframes */
1480 for (n=0; n < number_of_subframes; n++)
1483 proto_item *subframe_ti;
1484 proto_tree *subframe_tree;
1485 guint bits_in_subframe = 0;
1486 guint mac_d_pdus_in_subframe = 0;
1490 /* Add subframe subtree */
1491 subframe_ti = proto_tree_add_string_format(tree, hf_fp_edch_subframe, tvb, offset, 0,
1492 "", "Subframe %u data", subframes[n].subframe_number);
1493 subframe_tree = proto_item_add_subtree(subframe_ti, ett_fp_edch_subframe);
1495 for (i=0; i < subframes[n].number_of_mac_es_pdus; i++)
1502 /* Look up mac-d pdu size for this ddi */
1503 for (m=0; m < p_fp_info->no_ddi_entries; m++)
1505 if (subframes[n].ddi[i] == p_fp_info->edch_ddi[m])
1507 size = p_fp_info->edch_macd_pdu_size[m];
1512 if (m == p_fp_info->no_ddi_entries)
1514 /* Not found. Oops */
1518 /* Send MAC-dd PDUs together as one MAC-es PDU */
1519 send_size = size * subframes[n].number_of_mac_d_pdus[i];
1522 proto_tree_add_item(subframe_tree, hf_fp_edch_pdu_padding, tvb,
1523 offset + (bit_offset/8),
1528 proto_tree_add_item(subframe_tree, hf_fp_edch_tsn, tvb,
1529 offset + (bit_offset/8),
1534 ti = proto_tree_add_item(subframe_tree, hf_fp_edch_mac_es_pdu, tvb,
1535 offset + (bit_offset/8),
1536 ((bit_offset % 8) + send_size + 7) / 8,
1538 proto_item_append_text(ti, " (%u * %u = %u bits, subframe %d)",
1539 size, subframes[n].number_of_mac_d_pdus[i],
1541 bits_in_subframe += send_size;
1542 mac_d_pdus_in_subframe += subframes[n].number_of_mac_d_pdus[i];
1544 bit_offset += send_size;
1546 /* Pad out to next byte */
1549 bit_offset += (8 - (bit_offset % 8));
1553 /* Tree should cover entire subframe */
1554 proto_item_set_len(subframe_ti, bit_offset/8);
1556 /* Append summary info to subframe label */
1557 proto_item_append_text(subframe_ti, " (%u bits in %u MAC-d PDUs)",
1558 bits_in_subframe, mac_d_pdus_in_subframe);
1559 total_bits += bits_in_subframe;
1561 offset += (bit_offset/8);
1564 /* Report number of subframes in info column */
1565 if (check_col(pinfo->cinfo, COL_INFO))
1567 col_append_fstr(pinfo->cinfo, COL_INFO,
1568 " CFN = %03u (%u bits in %u subframes)",
1569 cfn, total_bits, number_of_subframes);
1572 /* Payload CRC (optional) */
1573 /* TODO: is this test correct...? */
1574 if (p_fp_info->dch_crc_present)
1576 proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
1582 /***********************************/
1583 /* Dissect an HSDSCH channel */
1584 void dissect_hsdsch_channel_info(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
1585 int offset, struct _fp_info *p_fp_info)
1587 gboolean is_control_frame;
1590 proto_tree_add_item(tree, hf_fp_header_crc, tvb, offset, 1, FALSE);
1593 is_control_frame = tvb_get_guint8(tvb, offset) & 0x01;
1594 proto_tree_add_item(tree, hf_fp_ft, tvb, offset, 1, FALSE);
1597 if (check_col(pinfo->cinfo, COL_INFO))
1599 col_append_str(pinfo->cinfo, COL_INFO, is_control_frame ? " [Control] " : " [Data] ");
1602 if (is_control_frame)
1604 dissect_common_control(tvb, pinfo, tree, offset, p_fp_info);
1608 guint8 number_of_pdus;
1611 /********************************/
1612 /* HS-DCH data here */
1615 proto_tree_add_item(tree, hf_fp_cmch_pi, tvb, offset, 1, FALSE);
1618 /* MAC-d PDU Length (13 bits) */
1619 pdu_length = (tvb_get_ntohs(tvb, offset) >> 3);
1620 proto_tree_add_item(tree, hf_fp_mac_d_pdu_len, tvb, offset, 2, FALSE);
1624 number_of_pdus = tvb_get_guint8(tvb, offset);
1625 proto_tree_add_item(tree, hf_fp_num_of_pdu, tvb, offset, 1, FALSE);
1628 /* User buffer size */
1629 proto_tree_add_item(tree, hf_fp_user_buffer_size, tvb, offset, 2, FALSE);
1633 offset = dissect_macd_pdu_data(tvb, pinfo, tree, offset, pdu_length,
1636 /* Extra R6 stuff */
1637 if (p_fp_info->release == 6)
1641 guint8 flag_bytes = 0;
1646 /* Read next byte */
1647 flags = tvb_get_guint8(tvb, offset);
1650 /* Dissect individual bits */
1651 for (n=0; n < 8; n++)
1653 proto_tree_add_item(tree, hf_fp_hsdsch_new_ie_flags[n], tvb, offset, 1, FALSE);
1657 /* Last bit set will indicate another flags byte follows... */
1658 } while (0); /*((flags & 0x01) && (flag_bytes < 31));*/
1660 if (1) /*(flags & 0x8) */
1662 /* DRT is shown as mandatory in the diagram (3GPP TS 25.435 V6.3.0),
1663 but the description below it states that
1664 it should depend upon the first bit. The detailed description of
1665 New IE flags doesn't agree, so treat as mandatory for now... */
1666 proto_tree_add_item(tree, hf_fp_hsdsch_drt, tvb, offset, 2, FALSE);
1671 /* TODO: may be spare extension to skip */
1674 proto_tree_add_item(tree, hf_fp_payload_crc, tvb, offset, 2, FALSE);
1681 /*****************************/
1682 /* Main dissection function. */
1683 void dissect_fp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
1685 proto_tree *fp_tree;
1688 struct _fp_info *p_fp_info;
1690 /* Append this protocol name rather than replace. */
1691 if (check_col(pinfo->cinfo, COL_PROTOCOL))
1692 col_set_str(pinfo->cinfo, COL_PROTOCOL, "FP");
1694 /* Create fp tree. */
1695 ti = proto_tree_add_item(tree, proto_fp, tvb, offset, -1, FALSE);
1696 fp_tree = proto_item_add_subtree(ti, ett_fp);
1698 /* Look for packet info! */
1699 p_fp_info = p_get_proto_data(pinfo->fd, proto_fp);
1701 /* Can't dissect anything without it... */
1702 if (p_fp_info == NULL)
1707 /* Show channel type in info column, tree */
1708 if (check_col(pinfo->cinfo, COL_INFO))
1710 col_set_str(pinfo->cinfo, COL_INFO,
1711 val_to_str(p_fp_info->channel,
1713 "Unknown channel type"));
1715 proto_item_append_text(ti, " (%s)",
1716 val_to_str(p_fp_info->channel,
1718 "Unknown channel type"));
1720 /* Add channel type as a generated field */
1721 ti = proto_tree_add_uint(fp_tree, hf_fp_channel_type, tvb, 0, 0, p_fp_info->channel);
1722 PROTO_ITEM_SET_GENERATED(ti);
1724 /* Add link direction as a generated field */
1725 ti = proto_tree_add_uint(fp_tree, hf_fp_direction, tvb, 0, 0, p_fp_info->is_uplink);
1726 PROTO_ITEM_SET_GENERATED(ti);
1729 /*************************************/
1730 /* Dissect according to channel type */
1731 switch (p_fp_info->channel)
1733 case CHANNEL_RACH_TDD:
1734 case CHANNEL_RACH_TDD_128:
1735 case CHANNEL_RACH_FDD:
1736 dissect_rach_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
1739 dissect_dch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
1741 case CHANNEL_FACH_FDD:
1742 case CHANNEL_FACH_TDD:
1743 dissect_fach_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
1745 case CHANNEL_DSCH_FDD:
1746 case CHANNEL_DSCH_TDD:
1747 dissect_dsch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
1749 case CHANNEL_USCH_TDD_128:
1750 case CHANNEL_USCH_TDD_384:
1751 dissect_usch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
1754 dissect_pch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
1762 case CHANNEL_HSDSCH:
1763 dissect_hsdsch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
1765 case CHANNEL_IUR_CPCHF:
1767 case CHANNEL_IUR_FACH:
1769 case CHANNEL_IUR_DSCH:
1770 dissect_iur_dsch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
1773 dissect_e_dch_channel_info(tvb, pinfo, fp_tree, offset, p_fp_info);
1781 void proto_register_fp(void)
1783 static hf_register_info hf[] =
1785 { &hf_fp_channel_type,
1787 "fp.channel-type", FT_UINT8, BASE_HEX, VALS(channel_type_vals), 0x0,
1788 "Channel Type", HFILL
1793 "fp.direction", FT_UINT8, BASE_HEX, VALS(direction_vals), 0x0,
1794 "Link direction", HFILL
1797 { &hf_fp_header_crc,
1799 "fp.header-crc", FT_UINT8, BASE_HEX, NULL, 0xfe,
1805 "fp.ft", FT_UINT8, BASE_HEX, VALS(data_control_vals), 0x01,
1811 "fp.cfn", FT_UINT8, BASE_DEC, NULL, 0x0,
1812 "Connection Frame Number", HFILL
1817 "fp.pch.cfn", FT_UINT16, BASE_DEC, NULL, 0xfff0,
1818 "PCH Connection Frame Number", HFILL
1823 "fp.pch.toa", FT_INT24, BASE_DEC, NULL, 0x0,
1824 "PCH Time of Arrival", HFILL
1827 { &hf_fp_cfn_control,
1829 "fp.cfn-control", FT_UINT8, BASE_DEC, NULL, 0x0,
1830 "Connection Frame Number Control", HFILL
1835 "fp.cfn-control", FT_INT16, BASE_DEC, NULL, 0x0,
1836 "Connection Frame Number Control", HFILL
1841 "fp.tb", FT_NONE, BASE_NONE, NULL, 0x0,
1847 "fp.tfi", FT_UINT8, BASE_DEC, NULL, 0x0,
1848 "Transport Format Indicator", HFILL
1853 "fp.usch.tfi", FT_UINT8, BASE_DEC, NULL, 0x1f,
1854 "USCH Transport Format Indicator", HFILL
1857 { &hf_fp_propagation_delay,
1858 { "Propagation Delay",
1859 "fp.propagation-delay", FT_UINT8, BASE_DEC, NULL, 0x0,
1860 "Propagation Delay", HFILL
1863 { &hf_fp_dch_control_frame_type,
1864 { "Control Frame Type",
1865 "fp.dch.control.frame-type", FT_UINT8, BASE_HEX, VALS(dch_control_frame_type_vals), 0x0,
1866 "DCH Control Frame Type", HFILL
1869 { &hf_fp_dch_rx_timing_deviation,
1870 { "Rx Timing Deviation",
1871 "fp.dch.control.rx-timing-deviation", FT_UINT8, BASE_DEC, 0, 0x0,
1872 "DCH Rx Timing Deviation", HFILL
1875 { &hf_fp_quality_estimate,
1876 { "Quality Estimate",
1877 "fp.dch.quality-estimate", FT_UINT8, BASE_DEC, 0, 0x0,
1878 "Quality Estimate", HFILL
1881 { &hf_fp_payload_crc,
1883 "fp.payload-crc", FT_UINT16, BASE_HEX, 0, 0x0,
1884 "Payload CRC", HFILL
1887 { &hf_fp_common_control_frame_type,
1888 { "Control Frame Type",
1889 "fp.common.control.frame-type", FT_UINT8, BASE_HEX, VALS(common_control_frame_type_vals), 0x0,
1890 "Common Control Frame Type", HFILL
1895 "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x80,
1896 "CRC correctness indicator", HFILL
1901 "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x40,
1902 "CRC correctness indicator", HFILL
1907 "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x20,
1908 "CRC correctness indicator", HFILL
1913 "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x10,
1914 "CRC correctness indicator", HFILL
1919 "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x08,
1920 "CRC correctness indicator", HFILL
1925 "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x04,
1926 "CRC correctness indicator", HFILL
1931 "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x02,
1932 "CRC correctness indicator", HFILL
1937 "fp.crci", FT_UINT8, BASE_HEX, VALS(crci_vals), 0x01,
1938 "CRC correctness indicator", HFILL
1941 { &hf_fp_received_sync_ul_timing_deviation,
1942 { "Received SYNC UL Timing Deviation",
1943 "fp.rx-sync-ul-timing-deviation", FT_UINT8, BASE_DEC, 0, 0x0,
1944 "Received SYNC UL Timing Deviation", HFILL
1948 { "Paging Indication",
1949 "fp.pch.pi", FT_UINT8, BASE_DEC, VALS(paging_indication_vals), 0x01,
1950 "Indicates if the PI Bitmap is present", HFILL
1955 "fp.pch.tfi", FT_UINT8, BASE_DEC, 0, 0x1f,
1956 "PCH Transport Format Indicator", HFILL
1961 "fp.fach.tfi", FT_UINT8, BASE_DEC, 0, 0x1f,
1962 "Transport Format Indicator", HFILL
1965 { &hf_fp_transmit_power_level,
1966 { "Transmit Power Level",
1967 "fp.transmit-power-level", FT_UINT8, BASE_DEC, 0, 0x0,
1968 "Transmit Power Level", HFILL
1971 { &hf_fp_pdsch_set_id,
1973 "fp.pdsch-set-id", FT_UINT8, BASE_DEC, 0, 0x0,
1974 "A pointer to the PDSCH Set which shall be used to transmit", HFILL
1977 { &hf_fp_paging_indication_bitmap,
1978 { "Paging Indications bitmap",
1979 "fp.pch.pi-bitmap", FT_NONE, BASE_NONE, NULL, 0x0,
1980 "Paging Indication bitmap", HFILL
1983 { &hf_fp_rx_timing_deviation,
1984 { "Rx Timing Deviation",
1985 "fp.common.control.rx-timing-deviation", FT_UINT8, BASE_DEC, 0, 0x0,
1986 "Common Rx Timing Deviation", HFILL
1989 { &hf_fp_edch_header_crc,
1990 { "E-DCH Header CRC",
1991 "fp.edch.header-crc", FT_UINT16, BASE_HEX, 0, 0xfef,
1992 "E-DCH Header CRC", HFILL
1997 "fp.edch.fsn", FT_UINT8, BASE_DEC, 0, 0x0f,
1998 "E-DCH Frame Sequence Number", HFILL
2001 { &hf_fp_edch_number_of_subframes,
2002 { "No of subframes",
2003 "fp.edch.no-of-subframes", FT_UINT8, BASE_DEC, 0, 0x0f,
2004 "E-DCH Number of subframes", HFILL
2007 { &hf_fp_edch_harq_retransmissions,
2008 { "No of HARQ Retransmissions",
2009 "fp.edch.no-of-harq-retransmissions", FT_UINT8, BASE_DEC, 0, 0x78,
2010 "E-DCH Number of HARQ retransmissions", HFILL
2013 { &hf_fp_edch_subframe_number,
2014 { "Subframe number",
2015 "fp.edch.subframe-number", FT_UINT8, BASE_DEC, 0, 0x07,
2016 "E-DCH Subframe number", HFILL
2019 { &hf_fp_edch_number_of_mac_es_pdus,
2020 { "Number of Mac-es PDUs",
2021 "fp.edch.number-of-mac-es-pdus", FT_UINT8, BASE_DEC, 0, 0xf0,
2022 "Number of Mac-es PDUs", HFILL
2027 "fp.edch.ddi", FT_UINT8, BASE_DEC, 0, 0x0,
2028 "E-DCH Data Description Indicator", HFILL
2031 { &hf_fp_edch_subframe,
2033 "fp.edch.subframe", FT_STRING, BASE_NONE, NULL, 0x0,
2034 "EDCH Subframe", HFILL
2037 { &hf_fp_edch_subframe_header,
2038 { "Subframe header",
2039 "fp.edch.subframe-header", FT_STRING, BASE_NONE, NULL, 0x0,
2040 "EDCH Subframe header", HFILL
2043 { &hf_fp_edch_number_of_mac_d_pdus,
2044 { "Number of Mac-d PDUs",
2045 "fp.edch.number-of-mac-d-pdus", FT_UINT8, BASE_DEC, 0, 0x0,
2046 "Number of Mac-d PDUs", HFILL
2049 { &hf_fp_edch_pdu_padding,
2051 "fp.edch-data-padding", FT_UINT8, BASE_DEC, 0, 0xc0,
2052 "E-DCH padding before PDU", HFILL
2057 "fp.edch-tsn", FT_UINT8, BASE_DEC, 0, 0x3f,
2058 "E-DCH Transmission Sequence Number", HFILL
2061 { &hf_fp_edch_mac_es_pdu,
2063 "fp.edch.mac-es-pdu", FT_NONE, BASE_NONE, NULL, 0x0,
2069 "fp.cmch-pi", FT_UINT8, BASE_DEC, 0, 0x0f,
2070 "Common Transport Channel Priority Indicator", HFILL
2073 { &hf_fp_user_buffer_size,
2074 { "User buffer size",
2075 "fp.user-buffer-size", FT_UINT16, BASE_DEC, 0, 0x0,
2076 "User buffer size in octets", HFILL
2079 { &hf_fp_hsdsch_credits,
2080 { "HS-DSCH Credits",
2081 "fp.hsdsch-credits", FT_UINT16, BASE_DEC, 0, 0x07ff,
2082 "HS-DSCH Credits", HFILL
2085 { &hf_fp_hsdsch_max_macd_pdu_len,
2086 { "Max MAC-d PDU Length",
2087 "fp.hsdsch.max-macd-pdu-len", FT_UINT16, BASE_DEC, 0, 0xfff8,
2088 "Maximum MAC-d PDU Length in bits", HFILL
2091 { &hf_fp_hsdsch_interval,
2092 { "HS-DSCH Interval in milliseconds",
2093 "fp.hsdsch-interval", FT_UINT8, BASE_DEC, 0, 0x0,
2094 "HS-DSCH Interval in milliseconds", HFILL
2097 { &hf_fp_hsdsch_repetition_period,
2098 { "HS-DSCH Repetition Period",
2099 "fp.hsdsch-repetition-period", FT_UINT8, BASE_DEC, 0, 0x0,
2100 "HS-DSCH Repetition Period in milliseconds", HFILL
2103 { &hf_fp_hsdsch_data_padding,
2105 "fp.hsdsch-data-padding", FT_UINT8, BASE_DEC, 0, 0xf0,
2106 "HS-DSCH Repetition Period in milliseconds", HFILL
2109 { &hf_fp_hsdsch_new_ie_flags[0],
2111 "fp.hsdsch.new-ie-flags", FT_UINT8, BASE_DEC, 0, 0x80,
2112 "DRT present", HFILL
2115 { &hf_fp_hsdsch_new_ie_flags[1],
2117 "fp.hsdsch.new-ie-flags", FT_UINT8, BASE_DEC, 0, 0x40,
2118 "New IE present", HFILL
2121 { &hf_fp_hsdsch_new_ie_flags[2],
2123 "fp.hsdsch.new-ie-flags", FT_UINT8, BASE_DEC, 0, 0x20,
2124 "New IE present", HFILL
2127 { &hf_fp_hsdsch_new_ie_flags[3],
2129 "fp.hsdsch.new-ie-flags", FT_UINT8, BASE_DEC, 0, 0x10,
2130 "New IE present", HFILL
2133 { &hf_fp_hsdsch_new_ie_flags[4],
2135 "fp.hsdsch.new-ie-flags", FT_UINT8, BASE_DEC, 0, 0x08,
2136 "New IE present", HFILL
2139 { &hf_fp_hsdsch_new_ie_flags[5],
2141 "fp.hsdsch.new-ie-flags", FT_UINT8, BASE_DEC, 0, 0x04,
2142 "New IE present", HFILL
2145 { &hf_fp_hsdsch_new_ie_flags[6],
2147 "fp.hsdsch.new-ie-flags", FT_UINT8, BASE_DEC, 0, 0x02,
2148 "New IE present", HFILL
2151 { &hf_fp_hsdsch_new_ie_flags[7],
2153 "fp.hsdsch.new-ie-flags", FT_UINT8, BASE_DEC, 0, 0x01,
2154 "New IE present", HFILL
2157 { &hf_fp_hsdsch_drt,
2159 "fp.hsdsch.drt", FT_UINT8, BASE_DEC, 0, 0xf0,
2160 "Delay Reference Time", HFILL
2163 { &hf_fp_timing_advance,
2165 "fp.timing-advance", FT_UINT8, BASE_DEC, 0, 0x3f,
2166 "Timing advance in chips", HFILL
2169 { &hf_fp_num_of_pdu,
2171 "fp.hsdsch.num-of-pdu", FT_UINT8, BASE_DEC, 0, 0x0,
2172 "Number of PDUs in the payload", HFILL
2175 { &hf_fp_mac_d_pdu_len,
2176 { "MAC-d PDU Length",
2177 "fp.hsdsch.mac-d-pdu-len", FT_UINT16, BASE_DEC, 0, 0xfff8,
2178 "MAC-d PDU Length in bits", HFILL
2183 "fp.mac-d-pdu", FT_NONE, BASE_NONE, NULL, 0x0,
2189 "fp.data", FT_STRING, BASE_NONE, NULL, 0x0,
2195 "fp.crcis", FT_STRING, BASE_NONE, NULL, 0x0,
2196 "CRC Indicators for uplink TBs", HFILL
2201 "fp.t1", FT_UINT24, BASE_DEC, NULL, 0x0,
2202 "RNC frame number indicating time it sends frame", HFILL
2207 "fp.t2", FT_UINT24, BASE_DEC, NULL, 0x0,
2208 "NodeB frame number indicating time it received DL Sync", HFILL
2213 "fp.t3", FT_UINT24, BASE_DEC, NULL, 0x0,
2214 "NodeB frame number indicating time it sends frame", HFILL
2217 { &hf_fp_ul_sir_target,
2219 "fp.ul-sir_target", FT_FLOAT, BASE_DEC, 0, 0x0,
2220 "Value (in dB) of the SIR target to be used by the UL inner loop power control", HFILL
2226 static gint *ett[] =
2231 &ett_fp_edch_subframe_header,
2232 &ett_fp_edch_subframe
2235 /* Register protocol. */
2236 proto_fp = proto_register_protocol("FP", "FP", "fp");
2237 proto_register_field_array(proto_fp, hf, array_length(hf));
2238 proto_register_subtree_array(ett, array_length(ett));
2240 /* Allow other dissectors to find this one by name. */
2241 register_dissector("fp", dissect_fp, proto_fp);
2245 void proto_reg_handoff_fp(void)